From beb14bf8343d83537795ed24169e7359d9462a54 Mon Sep 17 00:00:00 2001 From: admin <572701190@qq.com> Date: Tue, 19 May 2026 22:52:34 +0800 Subject: [PATCH] fix reactive resume pdf download filename --- scripts/patch-reactive-resume-filename.sh | 88 ++++++++++++++++++++--- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/scripts/patch-reactive-resume-filename.sh b/scripts/patch-reactive-resume-filename.sh index d7ff0b1..b8a7f37 100755 --- a/scripts/patch-reactive-resume-filename.sh +++ b/scripts/patch-reactive-resume-filename.sh @@ -8,27 +8,97 @@ set -eu PUBLIC_FILE="/app/apps/web/.output/public/assets/file-D5WsIgJH.js" SSR_FILE="/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs" +SERVER_INDEX_FILE="/app/apps/web/.output/server/index.mjs" +PDF_FILENAME="ZhiboWang-Resume.pdf" +CACHE_BUST="rr-filename-20260519" cp "$PUBLIC_FILE" "$PUBLIC_FILE.bak-filename" 2>/dev/null || true cp "$SSR_FILE" "$SSR_FILE.bak-filename" 2>/dev/null || true +cp "$SERVER_INDEX_FILE" "$SERVER_INDEX_FILE.bak-filename" 2>/dev/null || true node - <<'NODE' const fs = require('fs'); +const crypto = require('crypto'); const publicFile = '/app/apps/web/.output/public/assets/file-D5WsIgJH.js'; +const ssrFile = '/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs'; +const serverIndexFile = '/app/apps/web/.output/server/index.mjs'; +const pdfFilename = 'ZhiboWang-Resume.pdf'; +const cacheBust = 'rr-filename-20260519'; + +function makeEtag(buffer) { + const digest = crypto.createHash('sha1').update(buffer).digest('base64').replace(/=+$/g, ''); + return `"${buffer.length.toString(16)}-${digest}"`; +} + +function patchStaticManifestEntry(source, urlPath, filePath) { + const buffer = fs.readFileSync(filePath); + const startMarker = `"${urlPath}": {`; + const start = source.indexOf(startMarker); + if (start === -1) throw new Error(`Static manifest entry not found for ${urlPath}`); + + const commaEnd = source.indexOf('\n\t},', start); + const objectEnd = source.indexOf('\n\t}', start); + const end = commaEnd === -1 ? objectEnd : Math.min(commaEnd, objectEnd); + if (end === -1) throw new Error(`Static manifest entry end not found for ${urlPath}`); + + let entry = source.slice(start, end); + entry = entry + .replace(/"etag": "(?:\\.|[^"\\])*"/, `"etag": ${JSON.stringify(makeEtag(buffer))}`) + .replace(/"mtime": "(?:\\.|[^"\\])*"/, `"mtime": ${JSON.stringify(new Date().toISOString())}`) + .replace(/"size": \d+/, `"size": ${buffer.length}`); + + return source.slice(0, start) + entry + source.slice(end); +} + +function patchPublicImporters() { + const assetsDir = '/app/apps/web/.output/public/assets'; + const files = fs + .readdirSync(assetsDir) + .filter((name) => name.endsWith('.js')) + .map((name) => `${assetsDir}/${name}`) + .filter((file) => fs.readFileSync(file, 'utf8').includes('file-D5WsIgJH.js')); + + for (const file of files) { + let source = fs.readFileSync(file, 'utf8'); + source = source.replace(/\.\/file-D5WsIgJH\.js(?:\?v=rr-filename-20260519)?/g, `./file-D5WsIgJH.js?v=${cacheBust}`); + fs.writeFileSync(file, source); + } + + return files; +} + let publicJs = fs.readFileSync(publicFile, 'utf8'); -publicJs = publicJs.replace( - /function t\(t,n\)\{return`\$\{e\(t\)\}\$\{n\?`\.\$\{n\}`:""\}`\}/, - 'function t(e,t){let n=(e||"resume").toString().trim()||"resume";return`${n}${t?`.${t}`:""}`}' -); +const publicReplacement = `function t(e,t){if(t==="pdf")return"${pdfFilename}";let n=(e||"resume").toString().trim()||"resume";return\`\${n}\${t?\`.\${t}\`:""}\`}`; +if (!publicJs.includes(publicReplacement)) { + const start = publicJs.indexOf('function t('); + const end = publicJs.indexOf('function n(', start); + if (start === -1 || end === -1) throw new Error('Public generateFilename marker not found'); + publicJs = publicJs.slice(0, start) + publicReplacement + publicJs.slice(end); +} fs.writeFileSync(publicFile, publicJs); -const ssrFile = '/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs'; let ssr = fs.readFileSync(ssrFile, 'utf8'); -ssr = ssr.replace( - /function generateFilename\(prefix, extension\) \{\n\s*return `\$\{slugify\(prefix\)\}\$\{extension \? `\.\$\{extension\}` : ""\}`;\n\}/, - 'function generateFilename(prefix, extension) {\n\tconst filename = (prefix || "resume").toString().trim() || "resume";\n\treturn `${filename}${extension ? `.${extension}` : ""}`;\n}' -); +const ssrReplacement = `function generateFilename(prefix, extension) {\n\tif (extension === "pdf") return "${pdfFilename}";\n\tconst filename = (prefix || "resume").toString().trim() || "resume";\n\treturn \`\${filename}\${extension ? \`.\${extension}\` : ""}\`;\n}`; +if (!ssr.includes(ssrReplacement)) { + const start = ssr.indexOf('function generateFilename('); + const end = ssr.indexOf('\nfunction downloadWithAnchor(', start); + if (start === -1 || end === -1) throw new Error('SSR generateFilename marker not found'); + ssr = ssr.slice(0, start) + ssrReplacement + ssr.slice(end); +} fs.writeFileSync(ssrFile, ssr); + +const importers = patchPublicImporters(); +let serverIndex = fs.readFileSync(serverIndexFile, 'utf8'); +serverIndex = patchStaticManifestEntry(serverIndex, '/assets/file-D5WsIgJH.js', publicFile); +for (const file of importers) { + const urlPath = `/assets/${file.split('/').pop()}`; + serverIndex = patchStaticManifestEntry(serverIndex, urlPath, file); +} +fs.writeFileSync(serverIndexFile, serverIndex); NODE + +node --check "$PUBLIC_FILE" >/dev/null +node --check "$SSR_FILE" >/dev/null +node --check "$SERVER_INDEX_FILE" >/dev/null SH