New URL redirection

This commit is contained in:
2025-11-30 22:30:46 +08:00
parent 83aaf333d6
commit 48fc7287a6
9 changed files with 102 additions and 153 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
github: ["MoeCinnamo"]
custom: ["https://afdian.com/a/MoeCinnamo"]

View File

@@ -4,22 +4,26 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<title></title>
<link rel="preload" href="/js/404.js" as="script">
<link rel="preload" href="/js/layout.js" as="script">
<link rel="preload" href="/js/i18n.js" as="script">
<link rel="preload" href="/css/layout.css" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="/css/404.css" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="/font-awesome/css/all.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="/img/background_v0.1.x.webp" as="image">
<link rel="preload" href="/font-awesome/webfonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font-awesome/webfonts/fa-regular-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font-awesome/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font-awesome/webfonts/fa-v4compatibility.woff2" as="font" type="font/woff2" crossorigin>
</head>
<body>
<script src="/js/404.js"></script>
<script>
(function () {
const path = window.location.pathname;
const isDirect404Access = path.includes('404.html');
if (isDirect404Access) {
window.location.replace('/');
} else {
const newPath = '/#' + path + window.location.search;
window.location.replace(newPath);
}
})();
</script>
</body>
</html>

View File

@@ -0,0 +1,16 @@
.container-index {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
height: 80%;
border-radius: 20px;
backdrop-filter: blur(3px);
background-color: rgba(255, 255, 255, 0.2);
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

BIN
docs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -4,6 +4,8 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<title></title>
<link rel="preload" href="/js/index.js" as="script">
<link rel="preload" href="/js/layout.js" as="script">

View File

@@ -28,7 +28,9 @@ function load404Page() {
buttonText.textContent = translations["404_Go_Home"];
button.appendChild(buttonText);
button.addEventListener("click", () => {
window.location.hash = "";
window.location.href = "/";
window.location.reload();
});
rightContainer.appendChild(button);
const langSelect = document.createElement("div");
@@ -55,48 +57,3 @@ function load404Page() {
container.appendChild(rightContainer);
page.appendChild(container);
}
// Load layout script
function loadLayoutScript404() {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = "/js/layout.js";
script.async = true;
script.onload = () => {
resolve();
script.remove();
};
script.onerror = () => {
const errorMsg = `Failed to load script: ${scriptUrl}`;
console.error(`[ScriptLoader] ${errorMsg}`);
reject(new Error(errorMsg));
};
document.body.appendChild(script);
});
}
// Initialize app
async function initializeApp() {
try {
await Promise.all([
loadLayoutScript404()
]);
await Promise.all([
loadScript("/js/i18n.js"),
loadCSSAsPromise("/css/layout.css"),
loadCSSAsPromise("/css/404.css"),
loadCSSAsPromise("/font-awesome/css/all.min.css")
])
createPage();
load404Page()
} catch (error) {
console.error('App initialization error:', error);
}
}
document.addEventListener('DOMContentLoaded', () => {
initializeApp();
});

View File

@@ -1,99 +1,20 @@
function route() {
const currentHash = window.location.hash;
const isDirectAccess = currentHash === "" || currentHash === "#" || currentHash === "#/";
if (isDirectAccess) {
const browserLang = getBrowserLanguage();
setHtmlLangAttribute(browserLang);
window.location.href = "#/" + browserLang + "/v0.1.x/index.html";
return;
async function handle404Page() {
await Promise.all([
loadScript("/js/404.js"),
loadCSSAsPromise("/css/404.css")
]);
const page = document.getElementById("page");
page.innerHTML = "";
load404Page();
}
loadPageContent(currentHash.substring(1));
}
async function loadPageContent(path) {
try {
const mdPath = convertHtmlPathToMdPath(path);
const markdownContent = await fetchMarkdownContent(mdPath);
renderMarkdownContent(markdownContent);
updatePageMetadata(path);
} catch (error) {
console.error("Failed to load page content: ", error);
renderErrorPage(error.message);
}
}
function convertHtmlPathToMdPath(htmlPath) {
let normalizedPath = htmlPath.startsWith('/') ? htmlPath.substring(1) : htmlPath;
const mdFilename = normalizedPath.replace(/\.html$/, '.md');
return `/markdown/${mdFilename}`;
}
async function fetchMarkdownContent(mdPath) {
const response = await fetch(mdPath);
if (!response.ok) {
throw new Error(`Unable to load file: ${mdPath} with status code: ${response.status}`);
}
return await response.text();
}
function renderMarkdownContent(markdownContent) {
if (typeof marked === 'undefined') {
throw new Error('Markdown parsing library marked is not loaded, please introduce marked-js first.');
}
const htmlContent = marked.parse(markdownContent);
const contentContainer = document.getElementById('content');
if (!contentContainer) {
throw new Error('Content container with id "content" not found.');
}
contentContainer.innerHTML = htmlContent;
handleInternalLinks();
}
function handleInternalLinks() {
const contentContainer = document.getElementById('content');
const links = contentContainer.querySelectorAll('a');
links.forEach(link => {
const href = link.getAttribute('href');
if (href && (href.endsWith('.md') || href.includes('/'))) {
link.addEventListener('click', (e) => {
e.preventDefault();
const htmlPath = href.replace(/\.md$/, '.html');
const normalizedPath = htmlPath.startsWith('/') ? htmlPath : '/' + htmlPath;
window.location.hash = normalizedPath;
route();
});
}
});
}
function updatePageMetadata(path) {
const pageTitle = path.split('/').pop().replace('.html', '').replace(/-/g, ' ');
document.title = `${capitalizeFirstLetter(pageTitle)}`;
}
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function renderErrorPage(message) {
const contentContainer = document.getElementById('content');
contentContainer.innerHTML = `
<div class="error-page">
<h1>页面加载失败</h1>
<p>${message}</p>
<button onclick="window.location.hash='#/'">返回首页</button>
</div>
`;
function handleIndex(lang) {
const page = document.getElementById("page");
page.style.background = "url('/img/background_v0.1.x.webp') no-repeat center center fixed";
page.style.backgroundSize = "cover";
const container = document.createElement("div");
container.classList.add("container-index");
page.appendChild(container);
}
// Load layout script
@@ -126,6 +47,7 @@ async function initializeApp() {
]);
await Promise.all([
loadScript("/js/i18n.js"),
loadScript("/js/route.js"),
loadCSSAsPromise("/css/layout.css"),
loadCSSAsPromise("/css/index.css"),
loadCSSAsPromise("/font-awesome/css/all.min.css")

1
docs/js/md5.min.js vendored
View File

@@ -1 +0,0 @@
!function (n) { "use strict"; function d(n, t) { var r = (65535 & n) + (65535 & t); return (n >> 16) + (t >> 16) + (r >> 16) << 16 | 65535 & r } function f(n, t, r, e, o, u) { return d((u = d(d(t, n), d(e, u))) << o | u >>> 32 - o, r) } function l(n, t, r, e, o, u, c) { return f(t & r | ~t & e, n, t, o, u, c) } function g(n, t, r, e, o, u, c) { return f(t & e | r & ~e, n, t, o, u, c) } function v(n, t, r, e, o, u, c) { return f(t ^ r ^ e, n, t, o, u, c) } function m(n, t, r, e, o, u, c) { return f(r ^ (t | ~e), n, t, o, u, c) } function c(n, t) { var r, e, o, u; n[t >> 5] |= 128 << t % 32, n[14 + (t + 64 >>> 9 << 4)] = t; for (var c = 1732584193, f = -271733879, i = -1732584194, a = 271733878, h = 0; h < n.length; h += 16)c = l(r = c, e = f, o = i, u = a, n[h], 7, -680876936), a = l(a, c, f, i, n[h + 1], 12, -389564586), i = l(i, a, c, f, n[h + 2], 17, 606105819), f = l(f, i, a, c, n[h + 3], 22, -1044525330), c = l(c, f, i, a, n[h + 4], 7, -176418897), a = l(a, c, f, i, n[h + 5], 12, 1200080426), i = l(i, a, c, f, n[h + 6], 17, -1473231341), f = l(f, i, a, c, n[h + 7], 22, -45705983), c = l(c, f, i, a, n[h + 8], 7, 1770035416), a = l(a, c, f, i, n[h + 9], 12, -1958414417), i = l(i, a, c, f, n[h + 10], 17, -42063), f = l(f, i, a, c, n[h + 11], 22, -1990404162), c = l(c, f, i, a, n[h + 12], 7, 1804603682), a = l(a, c, f, i, n[h + 13], 12, -40341101), i = l(i, a, c, f, n[h + 14], 17, -1502002290), c = g(c, f = l(f, i, a, c, n[h + 15], 22, 1236535329), i, a, n[h + 1], 5, -165796510), a = g(a, c, f, i, n[h + 6], 9, -1069501632), i = g(i, a, c, f, n[h + 11], 14, 643717713), f = g(f, i, a, c, n[h], 20, -373897302), c = g(c, f, i, a, n[h + 5], 5, -701558691), a = g(a, c, f, i, n[h + 10], 9, 38016083), i = g(i, a, c, f, n[h + 15], 14, -660478335), f = g(f, i, a, c, n[h + 4], 20, -405537848), c = g(c, f, i, a, n[h + 9], 5, 568446438), a = g(a, c, f, i, n[h + 14], 9, -1019803690), i = g(i, a, c, f, n[h + 3], 14, -187363961), f = g(f, i, a, c, n[h + 8], 20, 1163531501), c = g(c, f, i, a, n[h + 13], 5, -1444681467), a = g(a, c, f, i, n[h + 2], 9, -51403784), i = g(i, a, c, f, n[h + 7], 14, 1735328473), c = v(c, f = g(f, i, a, c, n[h + 12], 20, -1926607734), i, a, n[h + 5], 4, -378558), a = v(a, c, f, i, n[h + 8], 11, -2022574463), i = v(i, a, c, f, n[h + 11], 16, 1839030562), f = v(f, i, a, c, n[h + 14], 23, -35309556), c = v(c, f, i, a, n[h + 1], 4, -1530992060), a = v(a, c, f, i, n[h + 4], 11, 1272893353), i = v(i, a, c, f, n[h + 7], 16, -155497632), f = v(f, i, a, c, n[h + 10], 23, -1094730640), c = v(c, f, i, a, n[h + 13], 4, 681279174), a = v(a, c, f, i, n[h], 11, -358537222), i = v(i, a, c, f, n[h + 3], 16, -722521979), f = v(f, i, a, c, n[h + 6], 23, 76029189), c = v(c, f, i, a, n[h + 9], 4, -640364487), a = v(a, c, f, i, n[h + 12], 11, -421815835), i = v(i, a, c, f, n[h + 15], 16, 530742520), c = m(c, f = v(f, i, a, c, n[h + 2], 23, -995338651), i, a, n[h], 6, -198630844), a = m(a, c, f, i, n[h + 7], 10, 1126891415), i = m(i, a, c, f, n[h + 14], 15, -1416354905), f = m(f, i, a, c, n[h + 5], 21, -57434055), c = m(c, f, i, a, n[h + 12], 6, 1700485571), a = m(a, c, f, i, n[h + 3], 10, -1894986606), i = m(i, a, c, f, n[h + 10], 15, -1051523), f = m(f, i, a, c, n[h + 1], 21, -2054922799), c = m(c, f, i, a, n[h + 8], 6, 1873313359), a = m(a, c, f, i, n[h + 15], 10, -30611744), i = m(i, a, c, f, n[h + 6], 15, -1560198380), f = m(f, i, a, c, n[h + 13], 21, 1309151649), c = m(c, f, i, a, n[h + 4], 6, -145523070), a = m(a, c, f, i, n[h + 11], 10, -1120210379), i = m(i, a, c, f, n[h + 2], 15, 718787259), f = m(f, i, a, c, n[h + 9], 21, -343485551), c = d(c, r), f = d(f, e), i = d(i, o), a = d(a, u); return [c, f, i, a] } function i(n) { for (var t = "", r = 32 * n.length, e = 0; e < r; e += 8)t += String.fromCharCode(n[e >> 5] >>> e % 32 & 255); return t } function a(n) { var t = []; for (t[(n.length >> 2) - 1] = void 0, e = 0; e < t.length; e += 1)t[e] = 0; for (var r = 8 * n.length, e = 0; e < r; e += 8)t[e >> 5] |= (255 & n.charCodeAt(e / 8)) << e % 32; return t } function e(n) { for (var t, r = "0123456789abcdef", e = "", o = 0; o < n.length; o += 1)t = n.charCodeAt(o), e += r.charAt(t >>> 4 & 15) + r.charAt(15 & t); return e } function r(n) { return unescape(encodeURIComponent(n)) } function o(n) { return i(c(a(n = r(n)), 8 * n.length)) } function u(n, t) { return function (n, t) { var r, e = a(n), o = [], u = []; for (o[15] = u[15] = void 0, 16 < e.length && (e = c(e, 8 * n.length)), r = 0; r < 16; r += 1)o[r] = 909522486 ^ e[r], u[r] = 1549556828 ^ e[r]; return t = c(o.concat(a(t)), 512 + 8 * t.length), i(c(u.concat(t), 640)) }(r(n), r(t)) } function t(n, t, r) { return t ? r ? u(t, n) : e(u(t, n)) : r ? o(n) : e(o(n)) } "function" == typeof define && define.amd ? define(function () { return t }) : "object" == typeof module && module.exports ? module.exports = t : n.md5 = t }(this);

47
docs/js/route.js Normal file
View File

@@ -0,0 +1,47 @@
let isRouting = false;
function route() {
if (isRouting) return;
isRouting = true;
// Define route tables
const routeHandlers = {
'index.html': handleIndex,
};
const currentHash = window.location.hash.replace(/^#\/?/, '');
if (!currentHash || currentHash === "/") {
const browserLang = getBrowserLanguage();
window.location.href = `#/${browserLang}/index.html`;
setTimeout(() => {
isRouting = false;
}, 50);
return;
}
const match = currentHash.match(/^([^/]+)\/([^/]+\.html)(?:$|\?)/);
if (!match) {
handle404Page();
setTimeout(() => {
isRouting = false;
}, 50);
return;
}
const [_, lang, page] = match;
setHtmlLangAttribute(lang);
const handler = routeHandlers[page];
if (handler) {
handler(lang);
} else {
handle404Page();
}
setTimeout(() => {
isRouting = false;
}, 50);
}
window.addEventListener('hashchange', route);
window.addEventListener('popstate', route);