147 lines
4.1 KiB
JavaScript
147 lines
4.1 KiB
JavaScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const repoRoot = process.cwd();
|
|
const websiteRoot = path.join(repoRoot, "website");
|
|
|
|
function listTopLevelHtml() {
|
|
return fs
|
|
.readdirSync(websiteRoot, { withFileTypes: true })
|
|
.filter((entry) => entry.isFile() && entry.name.endsWith(".html"))
|
|
.map((entry) => entry.name);
|
|
}
|
|
|
|
function destinationFor(filename) {
|
|
if (filename === "archive-speeches.html") {
|
|
return "speeches/index.html";
|
|
}
|
|
|
|
let match = filename.match(/^archive-speeches-rev-dr-sun-myung-moon-(.+)\.html$/);
|
|
if (match) {
|
|
return `speeches/rev-dr-sun-myung-moon/${match[1]}.html`;
|
|
}
|
|
|
|
match = filename.match(/^blog-category-speeches-of-rev-sun-myung-moon(?:-(.+))?\.html$/);
|
|
if (match) {
|
|
return `speeches/categories/rev-sun-myung-moon${match[1] ? `-${match[1]}` : ""}.html`;
|
|
}
|
|
|
|
if (filename === "blog-category-speeches-of-mrs-hak-ja-han-moon.html") {
|
|
return "speeches/categories/mrs-hak-ja-han-moon.html";
|
|
}
|
|
|
|
match = filename.match(/^blog-category-(.+)\.html$/);
|
|
if (match) {
|
|
return `blog/categories/${match[1]}.html`;
|
|
}
|
|
|
|
match = filename.match(/^blog-tag-(.+)\.html$/);
|
|
if (match) {
|
|
return `blog/tags/${match[1]}.html`;
|
|
}
|
|
|
|
match = filename.match(/^blog-(\d{4})-(\d{2})-(\d{2})-(.+)\.html$/);
|
|
if (match) {
|
|
return `blog/${match[1]}/${match[2]}/${match[3]}/${match[4]}.html`;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function splitUrl(value) {
|
|
const match = value.match(/^([^?#]*)([?#].*)?$/);
|
|
return { pathname: match?.[1] ?? value, suffix: match?.[2] ?? "" };
|
|
}
|
|
|
|
function stripLeadingParentDirs(value) {
|
|
return value.replace(/^(\.\/)?/, "").replace(/^(\.\.\/)+/, "");
|
|
}
|
|
|
|
function shouldSkipUrl(value) {
|
|
return (
|
|
value === "" ||
|
|
value.startsWith("#") ||
|
|
value.startsWith("/") ||
|
|
/^[a-z][a-z0-9+.-]*:/i.test(value)
|
|
);
|
|
}
|
|
|
|
function rewriteUrl(value, movedPaths) {
|
|
if (shouldSkipUrl(value)) {
|
|
return value;
|
|
}
|
|
|
|
const { pathname, suffix } = splitUrl(value);
|
|
const normalized = stripLeadingParentDirs(pathname);
|
|
|
|
if (normalized.startsWith("assets/") || normalized.startsWith("css/") || normalized.startsWith("js/")) {
|
|
return `/${normalized}${suffix}`;
|
|
}
|
|
|
|
if (movedPaths.has(normalized)) {
|
|
return `/${movedPaths.get(normalized)}${suffix}`;
|
|
}
|
|
|
|
if (normalized.endsWith(".html")) {
|
|
return `/${normalized}${suffix}`;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function rewriteHtml(html, movedPaths) {
|
|
let output = html.replace(
|
|
/\b(href|src|action)=(["'])([^"']+)\2/g,
|
|
(_match, attr, quote, value) => `${attr}=${quote}${rewriteUrl(value, movedPaths)}${quote}`
|
|
);
|
|
|
|
output = output.replace(/\burl\((["']?)(\.\.\/(?:assets|css|js)\/[^"')]+)\1\)/g, (_match, quote, value) => {
|
|
const rewritten = rewriteUrl(value, movedPaths);
|
|
return `url(${quote}${rewritten}${quote})`;
|
|
});
|
|
|
|
return output;
|
|
}
|
|
|
|
const movedPaths = new Map();
|
|
|
|
for (const filename of listTopLevelHtml()) {
|
|
const destination = destinationFor(filename);
|
|
if (destination) {
|
|
movedPaths.set(filename, destination);
|
|
}
|
|
}
|
|
|
|
for (const [filename, destination] of movedPaths) {
|
|
const sourcePath = path.join(websiteRoot, filename);
|
|
const destinationPath = path.join(websiteRoot, destination);
|
|
fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
|
|
fs.renameSync(sourcePath, destinationPath);
|
|
}
|
|
|
|
function walk(dir) {
|
|
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
const fullPath = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
return walk(fullPath);
|
|
}
|
|
return fullPath.endsWith(".html") || fullPath.endsWith(".md") ? [fullPath] : [];
|
|
});
|
|
}
|
|
|
|
let rewritten = 0;
|
|
|
|
for (const filePath of [...walk(websiteRoot), path.join(repoRoot, "README.md"), path.join(repoRoot, "docs", "SITE-STRUCTURE.md")]) {
|
|
if (!fs.existsSync(filePath)) {
|
|
continue;
|
|
}
|
|
const original = fs.readFileSync(filePath, "utf8");
|
|
const updated = rewriteHtml(original, movedPaths);
|
|
if (updated !== original) {
|
|
fs.writeFileSync(filePath, updated);
|
|
rewritten += 1;
|
|
}
|
|
}
|
|
|
|
console.log(`Moved ${movedPaths.size} HTML files into blog/ and speeches/.`);
|
|
console.log(`Rewrote links in ${rewritten} files.`);
|