import fs from "node:fs/promises"; import path from "node:path"; const outDir = "/site"; const indexPath = "www.mewedding.vn/index.html"; const sourceDir = "www.mewedding.vn/source"; function decodeLocalAsset(rawUrl) { let url = rawUrl.split("?")[0]; url = url.replaceAll("\\ ", " "); url = url.replace(/^\.\.\//, ""); url = url.replace(/^\/+/, ""); try { return decodeURIComponent(url); } catch { return url; } } async function copyFilePreservingPath(relativePath) { const source = path.resolve(relativePath); const target = path.join(outDir, relativePath); await fs.mkdir(path.dirname(target), { recursive: true }); await fs.copyFile(source, target); } const html = await fs.readFile(indexPath, "utf8"); await fs.rm(outDir, { recursive: true, force: true }); await copyFilePreservingPath(indexPath); await fs.cp(sourceDir, path.join(outDir, sourceDir), { recursive: true }); const assetPattern = /(?:url\(["']?|src=["']|href=["']|"(?:dC|dw)"\s*:\s*")((?:\.\.\/|\/)w\.ladicdn\.com\/[^"')]+)/g; const assets = new Set(); for (const match of html.matchAll(assetPattern)) { assets.add(decodeLocalAsset(match[1])); } const missing = []; for (const asset of assets) { try { await fs.access(asset); await copyFilePreservingPath(asset); } catch { missing.push(asset); } } if (missing.length > 0) { console.error("Missing local assets:"); for (const asset of missing) console.error(`- ${asset}`); process.exit(1); } console.log(`Prepared static site with ${assets.size} local assets.`);