UNPKG

zephyr-rspress-plugin

Version:

Rspress plugin for Zephyr

241 lines (240 loc) • 11.2 kB
"use strict"; var __webpack_require__ = {}; (()=>{ __webpack_require__.n = (module)=>{ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module; __webpack_require__.d(getter, { a: getter }); return getter; }; })(); (()=>{ __webpack_require__.d = (exports1, getters, values)=>{ var define = (defs, kind)=>{ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, { enumerable: true, [kind]: defs[key] }); }; define(getters, "get"); define(values, "value"); }; })(); (()=>{ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); })(); (()=>{ __webpack_require__.r = (exports1)=>{ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, { value: 'Module' }); Object.defineProperty(exports1, '__esModule', { value: true }); }; })(); var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { rewriteRspressModuleFederationAssets: ()=>rewriteRspressModuleFederationAssets }); const promises_namespaceObject = require("node:fs/promises"); const external_node_path_namespaceObject = require("node:path"); var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject); const external_zephyr_agent_namespaceObject = require("zephyr-agent"); const external_zephyr_edge_contract_namespaceObject = require("zephyr-edge-contract"); const BROWSER_MANIFEST = 'mf-manifest.json'; const MAX_HTML_REWRITE_CONCURRENCY = 16; const HTML_ASSET_ATTRIBUTE = /(<(?:link|script)\b[^>]*?\b(?:href|src)\s*=\s*["'])(https?:\/\/[^"']+)(["'])/gi; async function rewriteRspressModuleFederationAssets(outDir, files) { const normalizedFiles = new Set(files.map(toPortablePath)); if (!normalizedFiles.has(BROWSER_MANIFEST)) return; const browserManifest = await readManifest(outDir, BROWSER_MANIFEST); const nestedManifestFiles = [ ...normalizedFiles ].filter((file)=>file !== BROWSER_MANIFEST && file.endsWith('/mf-manifest.json')).sort(); const nestedManifests = new Map(); for (const file of nestedManifestFiles)nestedManifests.set(file, await readManifest(outDir, file)); const ssgManifest = selectSsgManifest(browserManifest, normalizedFiles, nestedManifests); const ssgManifestData = ssgManifest ? nestedManifests.get(ssgManifest) ?? null : null; const publicPaths = collectManifestPublicPaths(browserManifest, ssgManifestData); await rewriteHtmlAssetPrefixes(outDir, files, normalizedFiles, publicPaths); normalizeBrowserManifest(browserManifest, ssgManifest, ssgManifestData); await writeManifest(outDir, BROWSER_MANIFEST, browserManifest); if (ssgManifest && ssgManifestData) { normalizeSsgManifest(ssgManifestData); await writeManifest(outDir, ssgManifest, ssgManifestData); } } function collectManifestPublicPaths(browserManifest, ssgManifest) { const publicPaths = new Set(); for (const manifest of [ browserManifest, ssgManifest ])for (const value of [ manifest?.metaData?.publicPath, manifest?.metaData?.ssrPublicPath ]){ const prefix = normalizeHttpPrefix(value); if (prefix) publicPaths.add(prefix); } return [ ...publicPaths ].sort((left, right)=>right.length - left.length); } async function rewriteHtmlAssetPrefixes(outDir, files, emittedFiles, publicPaths) { await (0, external_zephyr_edge_contract_namespaceObject.forEachLimit)(files.filter((file)=>toPortablePath(file).endsWith('.html')).map((file)=>async ()=>{ const portableFile = toPortablePath(file); const filePath = await resolveOutputFile(outDir, file); const source = await (0, promises_namespaceObject.readFile)(filePath, 'utf8'); const rewritten = source.replace(HTML_ASSET_ATTRIBUTE, (match, prefix, absoluteUrl, quote)=>{ const asset = resolveEmittedAsset(absoluteUrl, publicPaths, emittedFiles); if (!asset) return match; return `${prefix}${relativeAssetUrl(portableFile, asset)}${quote}`; }); if (rewritten !== source) await (0, promises_namespaceObject.writeFile)(filePath, rewritten); }), MAX_HTML_REWRITE_CONCURRENCY); } function resolveEmittedAsset(absoluteUrl, publicPaths, emittedFiles) { const matchedPrefix = publicPaths.find((prefix)=>absoluteUrl.startsWith(prefix)); if (matchedPrefix) { const candidate = absoluteUrl.slice(matchedPrefix.length); if (emittedFiles.has(stripQueryAndHash(candidate))) return candidate; } let url; try { url = new URL(absoluteUrl); } catch { return null; } const pathname = url.pathname.replace(/^\/+/, ''); const candidates = [ pathname ]; const staticIndex = pathname.lastIndexOf('static/'); if (staticIndex > 0) candidates.push(pathname.slice(staticIndex)); const emitted = candidates.find((candidate)=>emittedFiles.has(candidate)); return emitted ? `${emitted}${url.search}${url.hash}` : null; } function relativeAssetUrl(htmlFile, asset) { const cleanAsset = stripQueryAndHash(asset); const suffix = asset.slice(cleanAsset.length); const htmlDirectory = external_node_path_default().posix.dirname(htmlFile); const relative = external_node_path_default().posix.relative('.' === htmlDirectory ? '' : htmlDirectory, cleanAsset); const prefixed = relative.startsWith('.') ? relative : `./${relative}`; return `${prefixed}${suffix}`; } function normalizeBrowserManifest(manifest, ssgManifest, ssgManifestData) { if (!manifest.metaData) return; setAutoPublicPathUnlessExplicit(manifest); delete manifest.metaData.ssrPublicPath; if (manifest.metaData.ssrRemoteEntry && ssgManifest) manifest.metaData.ssrRemoteEntry = { ...manifest.metaData.ssrRemoteEntry, path: getSsrRemoteEntryPath(ssgManifest, ssgManifestData) }; } function normalizeSsgManifest(manifest) { if (!manifest.metaData) return; setAutoPublicPathUnlessExplicit(manifest); delete manifest.metaData.ssrPublicPath; } function setAutoPublicPathUnlessExplicit(manifest) { const metadata = manifest.metaData; if (!metadata) return; if (metadata.getPublicPath && !Object.prototype.hasOwnProperty.call(metadata, 'publicPath')) return; metadata.publicPath = 'auto'; } function selectSsgManifest(browserManifest, files, nestedManifests) { const directCandidates = [ manifestFileFromPublicPath(browserManifest.metaData?.ssrPublicPath), manifestFileFromEntryPath(browserManifest.metaData?.ssrRemoteEntry?.path) ].filter((candidate)=>Boolean(candidate && files.has(candidate))); const uniqueDirect = [ ...new Set(directCandidates) ]; if (1 === uniqueDirect.length) return uniqueDirect[0] ?? null; if (uniqueDirect.length > 1) throw ambiguousSsgManifest(uniqueDirect); const discovered = [ ...nestedManifests.keys() ]; if (discovered.length <= 1) return discovered[0] ?? null; const expectedName = browserManifest.metaData?.ssrRemoteEntry?.name; const matching = expectedName ? discovered.filter((file)=>nestedManifests.get(file)?.metaData?.remoteEntry?.name === expectedName) : []; if (1 === matching.length) return matching[0] ?? null; throw ambiguousSsgManifest(matching.length > 1 ? matching : discovered); } function ambiguousSsgManifest(candidates) { return new external_zephyr_agent_namespaceObject.ZephyrError(external_zephyr_agent_namespaceObject.ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: `Rspress emitted ambiguous Module Federation SSG manifests: ${candidates.join(', ')}` }); } function getSsrRemoteEntryPath(ssgManifest, ssgManifestData) { const manifestDirectory = manifestDir(ssgManifest) ?? ''; const entryDirectory = normalizeManifestDir(ssgManifestData?.metaData?.remoteEntry?.path); return normalizeManifestDir(`${manifestDirectory}${entryDirectory ?? ''}`) ?? ''; } function normalizeHttpPrefix(value) { if (!value || !/^https?:\/\//i.test(value)) return null; return value.endsWith('/') ? value : `${value}/`; } function manifestFileFromPublicPath(value) { if (!value || !/^https?:\/\//i.test(value)) return null; try { const directory = normalizeManifestDir(new URL(value).pathname); return directory ? `${directory}mf-manifest.json` : null; } catch { return null; } } function manifestFileFromEntryPath(value) { const directory = normalizeManifestDir(value); return directory ? `${directory}mf-manifest.json` : null; } function manifestDir(file) { const index = file.lastIndexOf('/'); return index < 0 ? null : normalizeManifestDir(file.slice(0, index + 1)); } function normalizeManifestDir(value) { if (!value) return null; const normalized = toPortablePath(value).replace(/^\/+/, ''); const segments = normalized.split('/').filter((segment)=>segment && '.' !== segment); if (0 === segments.length || segments.includes('..')) return null; return `${segments.join('/')}/`; } function stripQueryAndHash(value) { return value.replace(/[?#].*$/, ''); } async function readManifest(outDir, file) { return JSON.parse(await (0, promises_namespaceObject.readFile)(await resolveOutputFile(outDir, file), 'utf8')); } async function writeManifest(outDir, file, manifest) { await (0, promises_namespaceObject.writeFile)(await resolveOutputFile(outDir, file), `${JSON.stringify(manifest, null, 2)}\n`); } async function resolveOutputFile(outDir, file) { const root = external_node_path_default().resolve(outDir); const resolved = external_node_path_default().resolve(root, file); if (resolved !== root && !resolved.startsWith(`${root}${external_node_path_default().sep}`)) throw invalidOutputPath(file); const [realRoot, realFile] = await Promise.all([ (0, promises_namespaceObject.realpath)(root), (0, promises_namespaceObject.realpath)(resolved) ]); if (realFile !== realRoot && !realFile.startsWith(`${realRoot}${external_node_path_default().sep}`)) throw invalidOutputPath(file); return resolved; } function invalidOutputPath(file) { return new external_zephyr_agent_namespaceObject.ZephyrError(external_zephyr_agent_namespaceObject.ZeErrors.ERR_DEPLOY_LOCAL_BUILD, { message: `Invalid Rspress output file path: ${file}` }); } function toPortablePath(file) { return file.replace(/\\/g, '/'); } exports.rewriteRspressModuleFederationAssets = __webpack_exports__.rewriteRspressModuleFederationAssets; for(var __rspack_i in __webpack_exports__)if (-1 === [ "rewriteRspressModuleFederationAssets" ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i]; Object.defineProperty(exports, '__esModule', { value: true }); //# sourceMappingURL=rewriteRspressModuleFederationAssets.js.map