Feat: Add a script to generate Generator from a template
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
function InitPage() {
|
||||
$("#init-page").show();
|
||||
$("#result-page").hide();
|
||||
}
|
||||
|
||||
function Appear() {
|
||||
$("#init-page").hide();
|
||||
$("#result-page").show();
|
||||
}
|
||||
|
||||
function get{{ name }}() {
|
||||
Update();
|
||||
}
|
||||
|
||||
InitPage()
|
||||
@@ -0,0 +1,51 @@
|
||||
const canvas = document.getElementById("Matrix");
|
||||
const context = canvas.getContext("2d");
|
||||
|
||||
canvas.height = globalThis.innerHeight + 100;
|
||||
canvas.width = globalThis.innerWidth + 5;
|
||||
|
||||
const chars =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./*-+#$%^@!~?><:;[]{}=_αβΓγΔδεζηΘθικΛλμΞξΠπρΣσςτυΦφχΨψΩω×≦≧≠∞≒≡~∩∠∪∟⊿∫∮∵∴$¥〒¢£℃€℉╩◢ⅩⅨⅧⅦⅥⅤⅣⅢⅡⅠあいうえおがぎぐげござじずぜぞだぢつでづどにぬのばひぴぶへぺぼみゃょァゐゎè";
|
||||
|
||||
const fontSize = 16;
|
||||
const columns = canvas.width / fontSize;
|
||||
|
||||
const charArr = [];
|
||||
for (let i = 0; i < columns; i++) {
|
||||
charArr[i] = 1;
|
||||
}
|
||||
|
||||
let frame = 0;
|
||||
let str;
|
||||
|
||||
context.fillStyle = "rgba(0, 0, 0, 1)";
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
function Update() {
|
||||
context.fillStyle = "rgba(0, 0, 0, 0.05)";
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
if (frame == 0) {
|
||||
const a = parseInt(Math.random() * 255);
|
||||
str = `rgba(${a}, ${Math.abs(a - 127)}, ${Math.abs(a - 255)}, 0.9)`;
|
||||
}
|
||||
context.fillStyle = str;
|
||||
context.font = fontSize + "px monospace";
|
||||
|
||||
for (let i = 0; i < columns; i++) {
|
||||
const text = chars[Math.floor(Math.random() * chars.length)];
|
||||
context.fillText(text, i * fontSize, charArr[i] * fontSize);
|
||||
if (charArr[i] * fontSize > canvas.height && Math.random() > 0.90) {
|
||||
charArr[i] = 0;
|
||||
}
|
||||
charArr[i]++;
|
||||
}
|
||||
frame++;
|
||||
|
||||
if (frame <= 40 * (Math.floor(Math.random() * 10) + 3)) {
|
||||
requestAnimationFrame(Update); // 40 frames a cycle
|
||||
} else {
|
||||
frame = 0;
|
||||
Appear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
function copyResultImageToClipboard() {
|
||||
try {
|
||||
const root = document.documentElement;
|
||||
const backgroundColor = getComputedStyle(root).getPropertyValue('--bg-color');
|
||||
|
||||
htmlToImage.toBlob($("#result-page")[0], {
|
||||
skipFonts: true,
|
||||
preferredFontFormat: "woff2",
|
||||
backgroundColor: backgroundColor, // Set background color dynamically
|
||||
}).then((blob) => {
|
||||
navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
||||
showCopiedNotice();
|
||||
$title.parent().remove();
|
||||
}).catch((error) => {
|
||||
console.error("Error converting result page to image:", error);
|
||||
$title.parent().remove();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error copying result image to clipboard:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function showCopiedNotice() {
|
||||
const notice = $("<div>", {
|
||||
text: "Copied to clipboard!",
|
||||
css: {
|
||||
position: "fixed",
|
||||
bottom: "20px",
|
||||
right: "20px",
|
||||
padding: "10px 20px",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
||||
color: "#fff",
|
||||
borderRadius: "5px",
|
||||
zIndex: 1000,
|
||||
},
|
||||
});
|
||||
|
||||
$("body").append(notice);
|
||||
|
||||
setTimeout(() => {
|
||||
notice.fadeOut(300, () => {
|
||||
notice.remove();
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
const pre_cache_file_version = "pre-v1.0.0";
|
||||
const auto_cache_file_version = "auto-v1.0.0";
|
||||
|
||||
const ASSETS = [
|
||||
"/{{ repo_name }}/{{ folder_path }}/images/logo-192x192.png",
|
||||
"/{{ repo_name }}/{{ folder_path }}/images/logo-512x512.png",
|
||||
"/{{ repo_name }}/{{ folder_path }}/images/logo-180x180.png",
|
||||
"/{{ repo_name }}/{{ folder_path }}/images/logo-270x270.png",
|
||||
"/{{ repo_name }}/{{ folder_path }}/images/logo.jpg",
|
||||
|
||||
"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
|
||||
"https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js",
|
||||
];
|
||||
|
||||
const NEED_UPDATE = [
|
||||
"/{{ repo_name }}/{{ folder_path }}/",
|
||||
"/{{ repo_name }}/{{ folder_path }}/index.html",
|
||||
"/{{ repo_name }}/{{ folder_path }}/css/styles.css",
|
||||
"/{{ repo_name }}/{{ folder_path }}/js/{{ name }}.js",
|
||||
"/{{ repo_name }}/{{ folder_path }}/js/matrix.js",
|
||||
"/{{ repo_name }}/{{ folder_path }}/json/theme.json",
|
||||
"/{{ repo_name }}/{{ folder_path }}/json/manifest.json",
|
||||
];
|
||||
|
||||
const limit_cache_size = (name, size) => {
|
||||
caches.open(name).then((cache) => {
|
||||
cache.keys().then((keys) => {
|
||||
if (keys.length > size) {
|
||||
cache.delete(keys[0]).then(() => {
|
||||
limit_cache_size(name, size);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const is_in_array = (str, array) => {
|
||||
let path = "";
|
||||
|
||||
// Check the request's domain is the same as the current domain.
|
||||
if (str.indexOf(self.origin) === 0) {
|
||||
path = str.substring(self.origin.length); // Remove https://lifeadventurer.github.io
|
||||
} else {
|
||||
path = str; // outside request
|
||||
}
|
||||
|
||||
return array.indexOf(path) > -1;
|
||||
};
|
||||
|
||||
// install
|
||||
self.addEventListener("install", (event) => {
|
||||
self.skipWaiting();
|
||||
|
||||
//pre-cache files
|
||||
event.waitUntil(
|
||||
caches.open(pre_cache_file_version).then((cache) => {
|
||||
cache.addAll(ASSETS);
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
// activate
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((keys) => {
|
||||
return Promise.all(keys.map((key) => {
|
||||
if (
|
||||
pre_cache_file_version.indexOf(key) === -1 &&
|
||||
auto_cache_file_version.indexOf(key) === -1
|
||||
) {
|
||||
return caches.delete(key);
|
||||
}
|
||||
}));
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
// fetch event
|
||||
self.addEventListener("fetch", (event) => {
|
||||
if (is_in_array(event.request.url, ASSETS)) {
|
||||
// cache only strategy
|
||||
|
||||
event.respondWith(
|
||||
caches.match(event.request.url),
|
||||
);
|
||||
} else if (is_in_array(event.request.url, NEED_UPDATE)) {
|
||||
event.respondWith(
|
||||
fetch(event.request.url).then(async (response) => {
|
||||
if (response.ok) {
|
||||
const cache = await caches.open(auto_cache_file_version);
|
||||
cache.put(event.request.url, response.clone());
|
||||
return response;
|
||||
}
|
||||
|
||||
throw new Error("Network response was not ok.");
|
||||
}).catch(async (_error) => {
|
||||
const cache = await caches.open(auto_cache_file_version);
|
||||
return cache.match(event.request.url);
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const themeListContainer = document.querySelector("#themeList");
|
||||
const root = document.documentElement;
|
||||
|
||||
// Apply the saved theme if it exists
|
||||
applySavedTheme();
|
||||
|
||||
async function fetchThemes() {
|
||||
try {
|
||||
const response = await fetch("./json/themes.json");
|
||||
const themes = await response.json();
|
||||
populateThemeList(themes["themes"]);
|
||||
} catch (error) {
|
||||
console.error("Error fetching themes:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate theme list in modal
|
||||
function populateThemeList(themes) {
|
||||
themeListContainer.innerHTML = "";
|
||||
themes.forEach((theme) => {
|
||||
const themeItem = document.createElement("div");
|
||||
themeItem.className =
|
||||
"theme-item list-group-item d-flex justify-content-between align-items-center";
|
||||
themeItem.style.cursor = "pointer";
|
||||
themeItem.id = "themeItem";
|
||||
|
||||
// Add theme name
|
||||
const themeName = document.createElement("span");
|
||||
themeName.textContent = theme.name;
|
||||
themeItem.appendChild(themeName);
|
||||
|
||||
const colorPreivewContainer = document.createElement("div");
|
||||
colorPreivewContainer.className = "color-preview-container";
|
||||
|
||||
const propertyKeys = Object.keys(theme.properties);
|
||||
colorPreivewContainer.style.backgroundColor =
|
||||
theme.properties[propertyKeys[5]];
|
||||
|
||||
// Add color dots for visual preview
|
||||
const colorPreview = document.createElement("div");
|
||||
colorPreview.className = "color-preview";
|
||||
|
||||
Object.values(theme.properties).slice(0, 3).forEach((color) => {
|
||||
const colorDot = document.createElement("span");
|
||||
colorDot.style.backgroundColor = color;
|
||||
colorDot.className = "color-dot";
|
||||
colorPreview.appendChild(colorDot);
|
||||
});
|
||||
|
||||
colorPreivewContainer.appendChild(colorPreview);
|
||||
themeItem.appendChild(colorPreivewContainer);
|
||||
|
||||
// Apply theme on click
|
||||
themeItem.addEventListener("click", () => {
|
||||
applyTheme(theme.properties);
|
||||
saveThemeToLocalStorage(theme.name);
|
||||
});
|
||||
|
||||
themeListContainer.appendChild(themeItem);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply theme by setting CSS variables
|
||||
function applyTheme(properties) {
|
||||
Object.entries(properties).forEach(([key, value]) => {
|
||||
root.style.setProperty(`--${key}`, value);
|
||||
});
|
||||
}
|
||||
|
||||
function saveThemeToLocalStorage(themeName) {
|
||||
localStorage.setItem("selectedTheme", themeName);
|
||||
}
|
||||
|
||||
function applySavedTheme() {
|
||||
const savedThemeName = localStorage.getItem("selectedTheme");
|
||||
if (savedThemeName) {
|
||||
fetch("./json/themes.json")
|
||||
.then((response) => response.json())
|
||||
.then((themes) => {
|
||||
const theme = themes.themes.find((t) => t.name === savedThemeName);
|
||||
if (theme) {
|
||||
applyTheme(theme.properties);
|
||||
}
|
||||
})
|
||||
.catch((error) => console.error("Error fetching themes:", error));
|
||||
}
|
||||
}
|
||||
|
||||
fetchThemes();
|
||||
});
|
||||
Reference in New Issue
Block a user