Feat: Add a script to generate Generator from a template

This commit is contained in:
2025-03-28 22:30:01 +08:00
parent 4eb9212a23
commit fe09f879b2
15 changed files with 687 additions and 0 deletions
+15
View File
@@ -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()
+51
View File
@@ -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();
}
}
+45
View File
@@ -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);
}
+102
View File
@@ -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);
}),
);
}
});
+91
View File
@@ -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();
});