summaryrefslogtreecommitdiffstats
path: root/public/js/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/js/main.js')
-rw-r--r--public/js/main.js175
1 files changed, 175 insertions, 0 deletions
diff --git a/public/js/main.js b/public/js/main.js
new file mode 100644
index 0000000..c47a5b8
--- /dev/null
+++ b/public/js/main.js
@@ -0,0 +1,175 @@
+(() => {
+ // ns-hugo-imp:/home/danix/Programming/GIT/danix2-hugo-theme/assets/js/theme-toggle.js
+ (function() {
+ const STORAGE_KEY = "danix-theme";
+ const DARK_CLASS = "theme-dark";
+ const LIGHT_CLASS = "theme-light";
+ function init() {
+ const saved = localStorage.getItem(STORAGE_KEY);
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
+ const isDark = saved === null ? prefersDark : saved === "dark";
+ applyTheme(isDark ? "dark" : "light");
+ }
+ function applyTheme(theme) {
+ const html = document.documentElement;
+ html.classList.remove(DARK_CLASS, LIGHT_CLASS);
+ if (theme === "dark") {
+ html.classList.remove(LIGHT_CLASS);
+ localStorage.setItem(STORAGE_KEY, "dark");
+ } else {
+ html.classList.add(LIGHT_CLASS);
+ localStorage.setItem(STORAGE_KEY, "light");
+ }
+ }
+ function getCurrentTheme() {
+ return document.documentElement.classList.contains(LIGHT_CLASS) ? "light" : "dark";
+ }
+ function toggleTheme() {
+ const current = getCurrentTheme();
+ const next = current === "dark" ? "light" : "dark";
+ applyTheme(next);
+ window.dispatchEvent(new CustomEvent("theme-changed", { detail: { theme: next } }));
+ }
+ function setupToggleButton() {
+ const btn = document.getElementById("theme-toggle-btn");
+ if (btn) {
+ btn.addEventListener("click", toggleTheme);
+ updateToggleButtonLabel();
+ window.addEventListener("theme-changed", updateToggleButtonLabel);
+ }
+ }
+ function updateToggleButtonLabel() {
+ const btn = document.getElementById("theme-toggle-btn");
+ if (btn) {
+ const current = getCurrentTheme();
+ btn.textContent = current === "dark" ? "\u2600\uFE0F light" : "\u{1F319} dark";
+ }
+ }
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", function() {
+ init();
+ setupToggleButton();
+ });
+ } else {
+ init();
+ setupToggleButton();
+ }
+ window.ThemeToggle = {
+ toggle: toggleTheme,
+ set: applyTheme,
+ get: getCurrentTheme
+ };
+ })();
+
+ // ns-hugo-imp:/home/danix/Programming/GIT/danix2-hugo-theme/assets/js/matrix-rain.js
+ (function() {
+ const canvas = document.getElementById("matrix-canvas");
+ if (!canvas) return;
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
+ const ctx = canvas.getContext("2d");
+ const CHARS = "\u30A2\u30A4\u30A6\u30A8\u30AA\u30AB\u30AD\u30AF\u30B1\u30B3\u30B5\u30B7\u30B9\u30BB\u30BD\u30BF\u30C1\u30C4\u30C6\u30C8\u30CA\u30CB\u30CC\u30CD\u30CE\u30CF\u30D2\u30D5\u30D8\u30DB\u30DE\u30DF\u30E0\u30E1\u30E2\u30E4\u30E6\u30E8\u30E9\u30EA\u30EB\u30EC\u30ED\u30EF\u30F2\u30F30123456789ABCDEF<>/\\|{}[]$#@!";
+ const FS = 14;
+ let cols, drops, raf;
+ function init() {
+ canvas.width = canvas.offsetWidth;
+ canvas.height = canvas.offsetHeight;
+ cols = Math.floor(canvas.width / FS) + 1;
+ drops = Array.from({ length: cols }, () => Math.random() * -(canvas.height / FS));
+ }
+ function tick() {
+ const light = document.documentElement.classList.contains("theme-light");
+ ctx.fillStyle = light ? "rgba(240,244,248,0.07)" : "rgba(6,11,16,0.055)";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.font = `${FS}px "JetBrains Mono", monospace`;
+ for (let i = 0; i < cols; i++) {
+ const char = CHARS[Math.floor(Math.random() * CHARS.length)];
+ ctx.fillStyle = Math.random() > 0.96 ? light ? "#008f5a" : "#00ff88" : light ? "#7c3aed" : "#a855f7";
+ ctx.fillText(char, i * FS, drops[i] * FS);
+ if (drops[i] * FS > canvas.height && Math.random() > 0.975) {
+ drops[i] = Math.random() * -20;
+ }
+ drops[i] += 0.5;
+ }
+ raf = requestAnimationFrame(tick);
+ }
+ window.addEventListener("theme-changed", function() {
+ }, { passive: true });
+ init();
+ window.addEventListener("resize", () => {
+ cancelAnimationFrame(raf);
+ init();
+ tick();
+ }, { passive: true });
+ document.addEventListener("visibilitychange", () => {
+ if (document.hidden) {
+ cancelAnimationFrame(raf);
+ } else {
+ tick();
+ }
+ });
+ tick();
+ window.MatrixRain = { init, tick };
+ })();
+
+ // ns-hugo-imp:/home/danix/Programming/GIT/danix2-hugo-theme/assets/js/progress-bar.js
+ (function() {
+ const progressBar = document.querySelector(".reading-progress");
+ if (!progressBar) return;
+ const mainContent = document.querySelector("main");
+ if (!mainContent) return;
+ function updateProgress() {
+ const windowHeight = window.innerHeight;
+ const docHeight = document.documentElement.scrollHeight - windowHeight;
+ const scrolled = window.scrollY;
+ const percent = docHeight > 0 ? scrolled / docHeight * 100 : 0;
+ progressBar.style.width = percent + "%";
+ }
+ const contentHeight = mainContent.offsetHeight;
+ if (contentHeight > window.innerHeight * 1.5) {
+ document.body.classList.add("scrollable");
+ }
+ let ticking = false;
+ window.addEventListener("scroll", function() {
+ if (!ticking) {
+ requestAnimationFrame(updateProgress);
+ ticking = true;
+ setTimeout(() => {
+ ticking = false;
+ }, 100);
+ }
+ }, { passive: true });
+ updateProgress();
+ })();
+
+ // ns-hugo-imp:/home/danix/Programming/GIT/danix2-hugo-theme/assets/js/copy-code.js
+ (function() {
+ const codeBlocks = document.querySelectorAll("pre, .highlight");
+ codeBlocks.forEach((block) => {
+ const btn = document.createElement("button");
+ btn.className = "code-copy-btn";
+ btn.textContent = "copy";
+ btn.type = "button";
+ btn.setAttribute("aria-label", "Copy code");
+ const code = block.querySelector("code");
+ const text = code ? code.textContent : block.textContent;
+ btn.addEventListener("click", async function() {
+ try {
+ await navigator.clipboard.writeText(text);
+ const originalText = btn.textContent;
+ btn.textContent = "copied!";
+ btn.classList.add("copied");
+ setTimeout(() => {
+ btn.textContent = originalText;
+ btn.classList.remove("copied");
+ }, 2e3);
+ } catch (err) {
+ console.error("Failed to copy:", err);
+ btn.textContent = "error";
+ }
+ });
+ block.style.position = "relative";
+ block.appendChild(btn);
+ });
+ })();
+})();
+//# sourceMappingURL=main.js.map