vite-plugin-html-pages 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -42,6 +42,7 @@ interface HtPagesPluginOptions {
42
42
  mapOutputPath?: (page: HtPageInfo) => string;
43
43
  debug?: boolean;
44
44
  site?: string;
45
+ missingAssets?: 'error' | 'warn';
45
46
  rss?: {
46
47
  site: string;
47
48
  title?: string;
package/dist/index.js CHANGED
@@ -509,15 +509,138 @@ async function buildProcessedStaticAssets(args) {
509
509
  return out;
510
510
  }
511
511
 
512
- // src/plugin.ts
512
+ // src/html-asset-validator.ts
513
513
  import fs3 from "fs";
514
514
  import path6 from "path";
515
+ function stripQueryAndHash(url) {
516
+ return url.split("#")[0].split("?")[0];
517
+ }
518
+ function isLocalRootUrl(url) {
519
+ return !!url && url.startsWith("/") && !url.startsWith("//");
520
+ }
521
+ function fileExistsForPublicUrl(root, pagesDir, url) {
522
+ const clean = stripQueryAndHash(url).slice(1);
523
+ const fromSrc = path6.join(root, pagesDir, clean);
524
+ if (fs3.existsSync(fromSrc)) return true;
525
+ const fromPublic = path6.join(root, "public", clean);
526
+ if (fs3.existsSync(fromPublic)) return true;
527
+ return false;
528
+ }
529
+ function collectScriptSrcs(html) {
530
+ const out = [];
531
+ for (const match of html.matchAll(
532
+ /<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/gi
533
+ )) {
534
+ out.push(match[1]);
535
+ }
536
+ return out;
537
+ }
538
+ function collectStylesheetHrefs(html) {
539
+ const out = [];
540
+ for (const match of html.matchAll(
541
+ /<link\b[^>]*\brel=["']stylesheet["'][^>]*\bhref=["']([^"']+)["'][^>]*>/gi
542
+ )) {
543
+ out.push(match[1]);
544
+ }
545
+ return out;
546
+ }
547
+ function collectLiteralDynamicImports(html) {
548
+ const out = [];
549
+ for (const match of html.matchAll(
550
+ /import\s*\(\s*["']([^"'`]+)["']\s*\)/gi
551
+ )) {
552
+ out.push(match[1]);
553
+ }
554
+ return out;
555
+ }
556
+ function unique(values) {
557
+ return [...new Set(values)];
558
+ }
559
+ function formatPageLabel(pageLabel) {
560
+ return pageLabel ? ` (${pageLabel})` : "";
561
+ }
562
+ function missingAssetMessage(args) {
563
+ const { pluginName, kind, url, root, pagesDir, pageLabel } = args;
564
+ const clean = stripQueryAndHash(url).slice(1);
565
+ const pageSuffix = formatPageLabel(pageLabel);
566
+ return `[${pluginName}] Missing ${kind}${pageSuffix}: ${url}
567
+ Expected one of:
568
+ - ${path6.join(root, pagesDir, clean)}
569
+ - ${path6.join(root, "public", clean)}`;
570
+ }
571
+ function reportMissing(args) {
572
+ const message = missingAssetMessage(args);
573
+ if (args.mode === "warn") {
574
+ console.warn(`\u26A0\uFE0F ${message}`);
575
+ return;
576
+ }
577
+ throw new Error(message);
578
+ }
579
+ function validateHtmlAssetReferences(options) {
580
+ const {
581
+ root,
582
+ pagesDir,
583
+ html,
584
+ pluginName,
585
+ pageLabel,
586
+ missingAssets = "error"
587
+ } = options;
588
+ const scriptSrcs = unique(collectScriptSrcs(html)).filter(isLocalRootUrl);
589
+ const stylesheetHrefs = unique(collectStylesheetHrefs(html)).filter(isLocalRootUrl);
590
+ const literalDynamicImports = unique(collectLiteralDynamicImports(html)).filter(
591
+ isLocalRootUrl
592
+ );
593
+ for (const url of scriptSrcs) {
594
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
595
+ reportMissing({
596
+ mode: missingAssets,
597
+ pluginName,
598
+ kind: "JavaScript asset",
599
+ url,
600
+ root,
601
+ pagesDir,
602
+ pageLabel
603
+ });
604
+ }
605
+ }
606
+ for (const url of stylesheetHrefs) {
607
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
608
+ reportMissing({
609
+ mode: missingAssets,
610
+ pluginName,
611
+ kind: "stylesheet asset",
612
+ url,
613
+ root,
614
+ pagesDir,
615
+ pageLabel
616
+ });
617
+ }
618
+ }
619
+ for (const url of literalDynamicImports) {
620
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
621
+ console.warn(
622
+ `\u26A0\uFE0F ${missingAssetMessage({
623
+ pluginName,
624
+ kind: "literal dynamic import",
625
+ url,
626
+ root,
627
+ pagesDir,
628
+ pageLabel
629
+ })}`
630
+ );
631
+ }
632
+ }
633
+ }
634
+
635
+ // src/plugin.ts
636
+ import fs4 from "fs";
637
+ import path7 from "path";
515
638
  var hasWarnedESM = false;
516
639
  function warnIfNotESM(root) {
517
640
  try {
518
- const pkgPath = path6.join(root, "package.json");
519
- if (!fs3.existsSync(pkgPath)) return;
520
- const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf8"));
641
+ const pkgPath = path7.join(root, "package.json");
642
+ if (!fs4.existsSync(pkgPath)) return;
643
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf8"));
521
644
  if (pkg.type !== "module") {
522
645
  console.warn(
523
646
  `[${PLUGIN_NAME}] \u26A0\uFE0F It is recommended to add "type": "module" to your package.json for optimal performance and to avoid Node ESM warnings.`
@@ -666,7 +789,10 @@ function htPages(options = {}) {
666
789
  if (!server) return;
667
790
  logDebug(options.debug, "file changed", ctx.file);
668
791
  await loadDevPages();
669
- return void 0;
792
+ server.ws.send({
793
+ type: "full-reload"
794
+ });
795
+ return [];
670
796
  },
671
797
  async generateBundle(_, bundle) {
672
798
  try {
@@ -726,6 +852,14 @@ function htPages(options = {}) {
726
852
  );
727
853
  }
728
854
  const html = await renderPage(page, mod, false);
855
+ validateHtmlAssetReferences({
856
+ root,
857
+ pagesDir,
858
+ html,
859
+ pluginName: PLUGIN_NAME,
860
+ pageLabel: page.relativePath,
861
+ missingAssets: options.missingAssets ?? "error"
862
+ });
729
863
  this.emitFile({
730
864
  type: "asset",
731
865
  fileName: options.mapOutputPath?.(page) ?? page.fileName,
@@ -744,6 +878,14 @@ function htPages(options = {}) {
744
878
  );
745
879
  }
746
880
  const html = await renderPage(notFoundPage, mod, false);
881
+ validateHtmlAssetReferences({
882
+ root,
883
+ pagesDir,
884
+ html,
885
+ pluginName: PLUGIN_NAME,
886
+ pageLabel: notFoundPage.relativePath,
887
+ missingAssets: options.missingAssets ?? "error"
888
+ });
747
889
  this.emitFile({
748
890
  type: "asset",
749
891
  fileName: "404.html",
@@ -860,8 +1002,8 @@ ${rssItems}
860
1002
  }
861
1003
 
862
1004
  // src/fetch-cache.ts
863
- import fs4 from "fs/promises";
864
- import path7 from "path";
1005
+ import fs5 from "fs/promises";
1006
+ import path8 from "path";
865
1007
  import { createHash } from "crypto";
866
1008
  var memoryCache = /* @__PURE__ */ new Map();
867
1009
  function createDefaultCacheKey(input, init) {
@@ -874,7 +1016,7 @@ function createDefaultCacheKey(input, init) {
874
1016
  return createHash("sha256").update(raw).digest("hex");
875
1017
  }
876
1018
  function getCacheFilePath(cacheKey) {
877
- return path7.join(process.cwd(), CACHE_DIR_NAME, "fetch", `${cacheKey}.json`);
1019
+ return path8.join(process.cwd(), CACHE_DIR_NAME, "fetch", `${cacheKey}.json`);
878
1020
  }
879
1021
  function getEffectiveCacheMode(mode) {
880
1022
  if (mode === "memory" || mode === "fs" || mode === "none") {
@@ -912,10 +1054,10 @@ async function fetchWithCache(input, init, options = {}) {
912
1054
  }
913
1055
  const filePath = getCacheFilePath(cacheKey);
914
1056
  if (cacheMode === "fs") {
915
- await fs4.mkdir(path7.dirname(filePath), { recursive: true });
1057
+ await fs5.mkdir(path8.dirname(filePath), { recursive: true });
916
1058
  if (!options.forceRefresh) {
917
1059
  try {
918
- const raw = await fs4.readFile(filePath, "utf8");
1060
+ const raw = await fs5.readFile(filePath, "utf8");
919
1061
  const cached = JSON.parse(raw);
920
1062
  if (isFresh(cached, maxAge)) {
921
1063
  return toResponse(cached);
@@ -936,7 +1078,7 @@ async function fetchWithCache(input, init, options = {}) {
936
1078
  if (cacheMode === "memory") {
937
1079
  memoryCache.set(cacheKey, record);
938
1080
  } else if (cacheMode === "fs") {
939
- await fs4.writeFile(filePath, JSON.stringify(record), "utf8");
1081
+ await fs5.writeFile(filePath, JSON.stringify(record), "utf8");
940
1082
  }
941
1083
  return new Response(body, {
942
1084
  status: res.status,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts","../src/discover.ts","../src/path-utils.ts","../src/route-utils.ts","../src/constants.ts","../src/dev-server.ts","../src/errors.ts","../src/render-runtime.ts","../src/module-loader.ts","../src/page-index.ts","../src/static-assets.ts","../src/fetch-cache.ts"],"sourcesContent":["import pLimit from 'p-limit';\nimport type { Plugin, ViteDevServer } from 'vite';\n\nimport { discoverEntryPages } from './discover';\nimport { installDevServer } from './dev-server';\nimport { createPageModuleLoader, closePageModuleLoader } from './module-loader';\nimport { buildPageIndex } from './page-index';\nimport { renderPage } from './render-runtime';\nimport {\n buildProcessedStaticAssets,\n collectStaticAssets,\n copyStaticAssetSource,\n} from './static-assets';\n\nimport type { HtPageInfo, HtPageModule, HtPagesPluginOptions } from './types';\nimport { PLUGIN_NAME, VIRTUAL_BUILD_ENTRY_ID } from './constants';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nlet hasWarnedESM = false;\n\nfunction warnIfNotESM(root: string) {\n try {\n const pkgPath = path.join(root, 'package.json');\n\n if (!fs.existsSync(pkgPath)) return;\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n\n if (pkg.type !== 'module') {\n console.warn(\n `[${PLUGIN_NAME}] ⚠️ It is recommended to add \"type\": \"module\" to your package.json for optimal performance and to avoid Node ESM warnings.`,\n );\n }\n } catch {\n // silent — never break build\n }\n}\n\nfunction chunkArray<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) {\n out.push(items.slice(i, i + size));\n }\n return out;\n}\n\nexport function htPages(options: HtPagesPluginOptions = {}): Plugin {\n let root = process.cwd();\n let server: ViteDevServer | null = null;\n let devPages: HtPageInfo[] = [];\n\n const cleanUrls = options.cleanUrls ?? true;\n const pagesDir = options.pagesDir ?? 'src';\n const pageExtensions = options.pageExtensions?.length\n ? options.pageExtensions\n : ['.ht.js', '.html.js', '.ht.ts', '.html.ts'];\n\n function logDebug(enabled: boolean | undefined, ...args: unknown[]) {\n if (!enabled) return;\n console.log(`[${PLUGIN_NAME}]`, ...args);\n }\n\n async function loadDevPages(): Promise<HtPageInfo[]> {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n logDebug(\n options.debug,\n 'discovered entries',\n entries.map((e) => e.relativePath),\n );\n\n if (!server) return [];\n\n const loadModule = await createPageModuleLoader({\n mode: 'dev',\n root,\n server,\n });\n\n for (const entry of entries) {\n const mod = await loadModule(entry.entryPath, entry.relativePath);\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n devPages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n logDebug(\n options.debug,\n 'dev pages',\n devPages.map((p) => `${p.routePath} -> ${p.relativePath}`),\n );\n\n return devPages;\n }\n\n async function buildPagesPipeline() {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n const loadModule = await createPageModuleLoader({\n mode: 'build',\n root,\n });\n\n for (const entry of entries) {\n const mod = await loadModule(entry.entryPath, entry.relativePath);\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n const pages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n return { entries, modulesByEntry, pages };\n }\n\n return {\n name: PLUGIN_NAME,\n\n config(userConfig, env) {\n if (env.command !== 'build') return;\n\n const hasExplicitInput = userConfig.build?.rollupOptions?.input != null;\n if (hasExplicitInput) return;\n\n return {\n build: {\n rollupOptions: {\n input: VIRTUAL_BUILD_ENTRY_ID,\n },\n },\n };\n },\n\n resolveId(id) {\n if (id === VIRTUAL_BUILD_ENTRY_ID) return id;\n return null;\n },\n\n load(id) {\n if (id === VIRTUAL_BUILD_ENTRY_ID) {\n return 'export default {};';\n }\n return null;\n },\n\n configResolved(resolved) {\n root = resolved.root;\n\n if (!hasWarnedESM) {\n warnIfNotESM(root);\n hasWarnedESM = true;\n }\n },\n\n async buildStart() {\n const entries = await discoverEntryPages(root, options);\n\n for (const entry of entries) {\n this.addWatchFile(entry.entryPath);\n }\n\n const staticAssets = await collectStaticAssets({\n root,\n pagesDir,\n pageExtensions,\n });\n\n for (const asset of staticAssets) {\n this.addWatchFile(asset.absolutePath);\n }\n\n logDebug(\n options.debug,\n 'static assets',\n staticAssets.map((asset) => ({\n kind: asset.kind,\n input: asset.relativePathFromSrc,\n output: asset.outputFileName,\n })),\n );\n },\n\n configureServer(_server) {\n server = _server;\n\n installDevServer({\n server,\n getPages: async () => {\n if (devPages.length > 0) return devPages;\n return loadDevPages();\n },\n getEntries: async () => discoverEntryPages(root, options),\n });\n\n loadDevPages().catch((error) => {\n server?.config.logger.error(\n `[${PLUGIN_NAME}] loadDevPages failed: ${\n error instanceof Error ? error.stack ?? error.message : String(error)\n }`,\n );\n });\n },\n\n async handleHotUpdate(ctx) {\n if (!server) return;\n\n logDebug(options.debug, 'file changed', ctx.file);\n\n await loadDevPages();\n return undefined;\n },\n\n async generateBundle(_, bundle) {\n try {\n const { modulesByEntry, pages } = await buildPagesPipeline();\n\n const staticAssets = await collectStaticAssets({\n root,\n pagesDir,\n pageExtensions,\n });\n\n logDebug(\n options.debug,\n 'emitting pages',\n pages.map((p) => p.fileName),\n );\n\n logDebug(\n options.debug,\n 'emitting static assets',\n staticAssets.map((asset) => ({\n kind: asset.kind,\n input: asset.relativePathFromSrc,\n output: asset.outputFileName,\n })),\n );\n\n const limit = pLimit(options.renderConcurrency ?? 8);\n const batchSize =\n options.renderBatchSize ??\n Math.max(options.renderConcurrency ?? 8, 32);\n\n const processedOutputs = await buildProcessedStaticAssets({\n root,\n pagesDir,\n assets: staticAssets,\n minify: true,\n sourcemap: false,\n });\n\n for (const [fileName, source] of processedOutputs) {\n this.emitFile({\n type: 'asset',\n fileName,\n source,\n });\n }\n\n for (const asset of staticAssets) {\n if (asset.kind !== 'copy') continue;\n\n const source = await copyStaticAssetSource(asset);\n\n this.emitFile({\n type: 'asset',\n fileName: asset.outputFileName,\n source,\n });\n }\n\n for (const batch of chunkArray(pages, batchSize)) {\n await Promise.all(\n batch.map((page) =>\n limit(async () => {\n const mod = modulesByEntry.get(page.entryPath);\n\n if (!mod) {\n throw new Error(\n `[${PLUGIN_NAME}] Missing module for page entry: ${page.entryPath}`,\n );\n }\n\n const html = await renderPage(page, mod, false);\n\n this.emitFile({\n type: 'asset',\n fileName: options.mapOutputPath?.(page) ?? page.fileName,\n source: html,\n });\n }),\n ),\n );\n }\n\n const notFoundPage = pages.find((p) => p.routePath === '/404');\n\n if (notFoundPage) {\n const mod = modulesByEntry.get(notFoundPage.entryPath);\n\n if (!mod) {\n throw new Error(\n `[${PLUGIN_NAME}] Missing module for 404 page entry: ${notFoundPage.entryPath}`,\n );\n }\n\n const html = await renderPage(notFoundPage, mod, false);\n\n this.emitFile({\n type: 'asset',\n fileName: '404.html',\n source: html,\n });\n\n logDebug(options.debug, 'generated 404.html from user page');\n } else {\n const default404 = `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>404 - Page Not Found</title>\n <style>\n :root {\n color-scheme: light dark;\n }\n body {\n margin: 0;\n font-family: system-ui, sans-serif;\n min-height: 100vh;\n display: grid;\n place-items: center;\n padding: 2rem;\n }\n main {\n max-width: 40rem;\n text-align: center;\n }\n h1 {\n font-size: 3rem;\n margin: 0 0 1rem;\n }\n p {\n margin: 0.5rem 0;\n line-height: 1.5;\n }\n a {\n color: inherit;\n }\n </style>\n </head>\n <body>\n <main>\n <h1>404</h1>\n <p>Page not found.</p>\n <p><a href=\"/\">Go back home</a></p>\n </main>\n </body>\n</html>\n`;\n\n this.emitFile({\n type: 'asset',\n fileName: '404.html',\n source: default404,\n });\n\n logDebug(options.debug, 'generated default 404.html');\n }\n\n const sitemapBase = options.site ?? '';\n\n const sitemapRoutes = [...new Set(pages.map((p) => p.routePath))].filter(\n (route) => !route.includes(':') && !route.includes('*'),\n );\n\n if (sitemapBase && sitemapRoutes.length > 0) {\n const sitemap = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${sitemapRoutes\n .map((route) => ` <url><loc>${sitemapBase}${route}</loc></url>`)\n .join('\\n')}\\n</urlset>\\n`;\n\n this.emitFile({\n type: 'asset',\n fileName: 'sitemap.xml',\n source: sitemap,\n });\n\n logDebug(options.debug, 'generated sitemap.xml');\n }\n\n const rss = options.rss;\n\n if (rss?.site) {\n const routePrefix = rss.routePrefix ?? '/blog';\n \n const rssItems = pages\n .filter((page) => page.routePath.startsWith(routePrefix))\n .map((page) => {\n const url = `${rss.site}${page.routePath}`;\n \n return ` <item>\\n <title>${page.routePath}</title>\\n <link>${url}</link>\\n <guid>${url}</guid>\\n </item>`;\n })\n .join('\\n');\n \n const rssXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<rss version=\"2.0\">\\n<channel>\\n <title>${rss.title ?? PLUGIN_NAME}</title>\\n <link>${rss.site}</link>\\n <description>${rss.description ?? 'RSS feed'}</description>\\n${rssItems}\\n</channel>\\n</rss>\\n`;\n \n this.emitFile({\n type: 'asset',\n fileName: 'rss.xml',\n source: rssXml,\n });\n \n logDebug(options.debug, 'generated rss.xml');\n }\n\n for (const [fileName, output] of Object.entries(bundle)) {\n if (\n output.type === 'chunk' &&\n output.facadeModuleId === VIRTUAL_BUILD_ENTRY_ID\n ) {\n delete bundle[fileName];\n }\n }\n } finally {\n await closePageModuleLoader();\n }\n }\n };\n}\n\nexport default htPages;\n","import path from 'node:path';\nimport { normalizeFsPath, toPosix } from './path-utils';\nimport { getParamNames, isDynamicPage, toRoutePattern } from './route-utils';\nimport type { HtPageInfo, HtPagesPluginOptions } from './types';\nimport { PLUGIN_NAME } from './constants';\n\nfunction buildDefaultIncludeGlobs(\n pagesDir: string,\n pageExtensions: string[],\n): string[] {\n return pageExtensions.map((ext) => {\n const cleanExt = ext.startsWith('.') ? ext.slice(1) : ext;\n return `${pagesDir}/**/*.${cleanExt}`;\n });\n}\n\nexport async function discoverEntryPages(\n root: string,\n options: HtPagesPluginOptions,\n): Promise<HtPageInfo[]> {\n const fgModule = await import('fast-glob');\n const fg = (fgModule.default ?? fgModule) as typeof import('fast-glob');\n\n const pagesDir = options.pagesDir ?? 'src';\n const pageExtensions = options.pageExtensions?.length\n ? options.pageExtensions\n : ['.ht.js', '.html.js', '.ht.ts', '.html.ts'];\n\n const include = Array.isArray(options.include)\n ? options.include\n : options.include\n ? [options.include]\n : buildDefaultIncludeGlobs(pagesDir, pageExtensions);\n\n const exclude = Array.isArray(options.exclude)\n ? options.exclude\n : options.exclude\n ? [options.exclude]\n : [];\n\n const pagesRoot = normalizeFsPath(path.join(root, pagesDir));\n\n const files = await fg.glob(include, {\n cwd: root,\n ignore: exclude,\n absolute: true,\n });\n\n return files\n .sort()\n .map((absolutePath) => {\n const entryPath = normalizeFsPath(absolutePath);\n const relativePath = toPosix(path.relative(root, entryPath));\n const relativeFromPagesDir = toPosix(path.relative(pagesRoot, entryPath));\n\n if (\n relativeFromPagesDir.startsWith('../') ||\n relativeFromPagesDir === '..'\n ) {\n throw new Error(\n `[${PLUGIN_NAME}] Page is outside pagesDir: ${entryPath} (pagesDir: ${pagesDir})`,\n );\n }\n\n const dynamic = isDynamicPage(relativeFromPagesDir);\n const routePattern = toRoutePattern(relativeFromPagesDir, pageExtensions);\n\n return {\n id: entryPath,\n entryPath,\n absolutePath: entryPath,\n relativePath,\n routePattern,\n routePath: routePattern,\n fileName: '',\n dynamic,\n paramNames: getParamNames(relativeFromPagesDir),\n params: {},\n } satisfies HtPageInfo;\n });\n}","import path from 'node:path';\n\nexport function toPosix(value: string): string {\n return value.replace(/\\\\/g, '/');\n}\n\nexport function normalizeFsPath(value: string): string {\n return path.normalize(value);\n}\n\nexport function normalizeRoutePath(value: string): string {\n const normalized = toPosix(value).replace(/\\/+/g, '/');\n if (!normalized || normalized === '/') return '/';\n return normalized.startsWith('/') ? normalized : `/${normalized}`;\n}\n\nexport function stripPageSuffix(\n filePath: string,\n extensions: string[],\n): string {\n const normalized = toPosix(filePath);\n\n const match = [...extensions]\n .sort((a, b) => b.length - a.length)\n .find((ext) => normalized.endsWith(ext));\n\n if (!match) return normalized;\n\n return normalized.slice(0, -match.length);\n}","import { normalizeRoutePath, stripPageSuffix, toPosix } from './path-utils';\nimport type { HtPageInfo, StaticParamRecord } from './types';\n\nconst DYNAMIC_SEGMENT_RE = /\\[([A-Za-z0-9_]+)\\]/g;\nconst CATCH_ALL_SEGMENT_RE = /\\[\\.\\.\\.([A-Za-z0-9_]+)\\]/g;\nconst OPTIONAL_CATCH_ALL_SEGMENT_RE = /\\[\\.\\.\\.([A-Za-z0-9_]+)\\]\\?/g;\nconst ANY_PARAM_RE = /\\[(?:\\.\\.\\.)?([A-Za-z0-9_]+)\\]\\??/g;\nconst ROUTE_GROUP_RE = /(^|\\/)\\(([^)]+)\\)(?=\\/|$)/g;\n\nexport function getParamNames(relativeFromPagesDir: string): string[] {\n return [...relativeFromPagesDir.matchAll(ANY_PARAM_RE)].map((m) => m[1]);\n}\n\nexport function isDynamicPage(relativeFromPagesDir: string): boolean {\n return /\\[(?:\\.\\.\\.)?[A-Za-z0-9_]+\\]\\??/.test(relativeFromPagesDir);\n}\n\nexport function toRoutePattern(\n relativeFromPagesDir: string,\n extensions: string[],\n): string {\n const noExt = stripPageSuffix(toPosix(relativeFromPagesDir), extensions);\n\n const withoutGroups = noExt.replace(ROUTE_GROUP_RE, '$1');\n const withoutIndex = withoutGroups.replace(/\\/index$/i, '').replace(/^index$/i, '');\n\n const raw = withoutIndex\n .replace(OPTIONAL_CATCH_ALL_SEGMENT_RE, '*?:$1')\n .replace(CATCH_ALL_SEGMENT_RE, '*:$1')\n .replace(DYNAMIC_SEGMENT_RE, ':$1');\n\n return normalizeRoutePath(raw || '/');\n}\n\nexport function fillParams(\n pattern: string,\n params: Record<string, string>,\n): string {\n const result = pattern\n .replace(/\\*\\?:([A-Za-z0-9_]+)/g, (_, key) => {\n const value = params[key];\n if (value == null || value === '') {\n return '';\n }\n\n return String(value)\n .split('/')\n .map((part) => encodeURIComponent(part))\n .join('/');\n })\n .replace(/\\*:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) {\n throw new Error(`Missing catch-all route param \"${key}\"`);\n }\n\n return String(params[key])\n .split('/')\n .map((part) => encodeURIComponent(part))\n .join('/');\n })\n .replace(/:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) {\n throw new Error(`Missing route param \"${key}\"`);\n }\n\n return encodeURIComponent(params[key]);\n });\n\n return normalizeRoutePath(result || '/');\n}\n\nexport function fileNameFromRoute(\n routePath: string,\n cleanUrls: boolean,\n): string {\n const normalized = normalizeRoutePath(routePath);\n\n if (normalized === '/') return 'index.html';\n\n const base = normalized.slice(1);\n return cleanUrls ? `${base}/index.html` : `${base}.html`;\n}\n\nexport function expandStaticPaths(\n basePage: Omit<HtPageInfo, 'routePath' | 'fileName' | 'params'>,\n rows: StaticParamRecord[],\n cleanUrls: boolean,\n): HtPageInfo[] {\n return rows.map((row) => {\n const params = Object.fromEntries(\n Object.entries(row).map(([k, v]) => [k, String(v)]),\n );\n\n const routePath = fillParams(basePage.routePattern, params);\n\n return {\n ...basePage,\n routePath,\n fileName: fileNameFromRoute(routePath, cleanUrls),\n params,\n };\n });\n}\n\nexport function routeMatch(\n pattern: string,\n urlPath: string,\n): Record<string, string> | null {\n const a = normalizeRoutePath(pattern).split('/').filter(Boolean);\n const b = normalizeRoutePath(urlPath).split('/').filter(Boolean);\n const params: Record<string, string> = {};\n\n for (let i = 0; i < a.length; i++) {\n const patternSeg = a[i];\n const urlSeg = b[i];\n\n if (patternSeg.startsWith('*?:')) {\n params[patternSeg.slice(3)] =\n i < b.length ? b.slice(i).map(decodeURIComponent).join('/') : '';\n return params;\n }\n\n if (patternSeg.startsWith('*:')) {\n const rest = b.slice(i);\n if (rest.length === 0) return null;\n\n params[patternSeg.slice(2)] = rest.map(decodeURIComponent).join('/');\n return params;\n }\n\n if (!urlSeg) return null;\n\n if (patternSeg.startsWith(':')) {\n params[patternSeg.slice(1)] = decodeURIComponent(urlSeg);\n continue;\n }\n\n if (patternSeg !== urlSeg) return null;\n }\n\n return a.length === b.length ? params : null;\n}\n\nexport function compareRoutePriority(a: string, b: string): number {\n const aSegs = normalizeRoutePath(a).split('/').filter(Boolean);\n const bSegs = normalizeRoutePath(b).split('/').filter(Boolean);\n const len = Math.max(aSegs.length, bSegs.length);\n\n for (let i = 0; i < len; i++) {\n const aa = aSegs[i];\n const bb = bSegs[i];\n\n if (aa == null) return 1;\n if (bb == null) return -1;\n\n const aOptionalCatchAll = aa.startsWith('*?:');\n const bOptionalCatchAll = bb.startsWith('*?:');\n if (aOptionalCatchAll !== bOptionalCatchAll) {\n return aOptionalCatchAll ? 1 : -1;\n }\n\n const aCatchAll = aa.startsWith('*:');\n const bCatchAll = bb.startsWith('*:');\n if (aCatchAll !== bCatchAll) {\n return aCatchAll ? 1 : -1;\n }\n\n const aDynamic = aa.startsWith(':');\n const bDynamic = bb.startsWith(':');\n if (aDynamic !== bDynamic) {\n return aDynamic ? 1 : -1;\n }\n }\n\n return bSegs.length - aSegs.length;\n}","export const PLUGIN_NAME = 'vite-plugin-html-pages';\nexport const VIRTUAL_BUILD_ENTRY_ID = `\\0${PLUGIN_NAME}:build-entry`;\nexport const VIRTUAL_MANIFEST_ID = `\\0virtual:${PLUGIN_NAME}-manifest`;\nexport const CACHE_DIR_NAME = `node_modules/.cache/${PLUGIN_NAME}`;","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { ViteDevServer } from 'vite';\n\nimport { renderPage } from './render-runtime';\nimport type { HtPageInfo, HtPageModule } from './types';\nimport { PLUGIN_NAME } from './constants';\nimport { createPageModuleLoader } from './module-loader';\n\nfunction isStaticAssetRequest(url: string): boolean {\n return (\n url.endsWith('.css') ||\n url.endsWith('.js') ||\n url.endsWith('.mjs') ||\n url.endsWith('.ts') ||\n url.endsWith('.png') ||\n url.endsWith('.jpg') ||\n url.endsWith('.jpeg') ||\n url.endsWith('.gif') ||\n url.endsWith('.svg') ||\n url.endsWith('.webp') ||\n url.endsWith('.ico') ||\n url.endsWith('.woff') ||\n url.endsWith('.woff2') ||\n url.endsWith('.ttf') ||\n url.endsWith('.otf')\n );\n}\n\nfunction shouldSkipHtmlRouting(url: string): boolean {\n return (\n url.startsWith('/@vite') ||\n url.startsWith('/@fs/') ||\n url.startsWith('/node_modules/') ||\n url.startsWith('/src/') ||\n url === '/favicon.ico' ||\n isStaticAssetRequest(url)\n );\n}\n\nfunction tryRewriteRootAssetToSrc(server: ViteDevServer, url: string): string | null {\n if (!url.startsWith('/')) return null;\n if (!isStaticAssetRequest(url)) return null;\n if (url.startsWith('/src/')) return null;\n\n const root = server.config.root;\n const candidate = path.join(root, 'src', url.slice(1));\n\n if (fs.existsSync(candidate)) {\n return `/src/${url.slice(1)}`;\n }\n\n return null;\n}\n\nfunction shouldUseDynamicRendering(mod: HtPageModule): boolean {\n return mod.dynamic === true || mod.prerender === false;\n}\n\nexport function installDevServer(args: {\n server: ViteDevServer;\n getPages: () => Promise<HtPageInfo[]>;\n getEntries?: () => Promise<HtPageInfo[]>;\n}) {\n const { server, getPages } = args;\n\n server.middlewares.use(async (req, res, next) => {\n try {\n const originalUrl = req.url ?? '/';\n const url = originalUrl.split('?')[0];\n\n const rewrittenAssetUrl = tryRewriteRootAssetToSrc(server, url);\n if (rewrittenAssetUrl) {\n req.url = rewrittenAssetUrl + originalUrl.slice(url.length);\n return next();\n }\n\n if (shouldSkipHtmlRouting(url)) {\n return next();\n }\n\n const pages = await getPages();\n\n const page = pages.find((p) => p.routePath === url);\n\n if (!page) {\n return next();\n }\n\n const loadModule = await createPageModuleLoader({\n mode: 'dev',\n root: server.config.root,\n server,\n });\n\n const mod = await loadModule(page.entryPath, page.relativePath);\n\n if (!mod) {\n return next();\n }\n\n if (!shouldUseDynamicRendering(mod) && page.dynamic) {\n return next();\n }\n\n const html = await renderPage(page, mod, true);\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(html);\n } catch (error) {\n server.config.logger.error(\n `[${PLUGIN_NAME}] dev server render failed: ${\n error instanceof Error ? error.stack ?? error.message : String(error)\n }`,\n );\n\n next(error as Error);\n }\n });\n}","import type { HtPageInfo } from './types';\nimport { PLUGIN_NAME } from './constants';\nexport function invalidHtmlReturn(\n page: HtPageInfo,\n value: unknown,\n): Error {\n return new Error(\n `[${PLUGIN_NAME}] Page \"${page.relativePath}\" must resolve to an HTML string, got ${typeof value}`,\n );\n}\n\nexport function missingDefaultExport(page: HtPageInfo): Error {\n return new Error(\n `[${PLUGIN_NAME}] Page \"${page.relativePath}\" does not export a default renderer`,\n );\n}\n\nexport function pageError(page: HtPageInfo, cause: unknown): Error {\n const message = `[${PLUGIN_NAME}] Failed to render \"${page.relativePath}\" at route \"${page.routePath}\"`;\n\n if (cause instanceof Error) {\n const err = new Error(`${message}: ${cause.message}`);\n\n if (cause.stack) {\n err.stack = `${err.stack}\\nCaused by:\\n${cause.stack}`;\n }\n\n return err;\n }\n\n return new Error(`${message}: ${String(cause)}`);\n}","import { invalidHtmlReturn, pageError, missingDefaultExport } from './errors';\nimport type { HtPageInfo, HtPageModule, HtPageRenderContext } from './types';\n\nexport async function renderPage(\n page: HtPageInfo,\n mod: HtPageModule,\n dev = false,\n): Promise<string> {\n const ctx: HtPageRenderContext = {\n page,\n params: page.params,\n dev,\n };\n\n try {\n if (typeof mod.data === 'function') {\n ctx.data = await mod.data(ctx);\n }\n\n const entry = mod.default;\n\n if (entry == null) {\n throw missingDefaultExport(page);\n }\n\n const html = typeof entry === 'function' ? await entry(ctx) : entry;\n\n if (typeof html !== 'string') {\n throw invalidHtmlReturn(page, html);\n }\n\n return html;\n } catch (error) {\n throw pageError(page, error);\n }\n}","import path from 'node:path';\nimport { createServer, type InlineConfig, type ViteDevServer } from 'vite';\nimport type { HtPageModule } from './types';\n\nexport type PageModuleLoader = (\n entryPath: string,\n relativePath: string,\n) => Promise<HtPageModule>;\n\nlet buildServer: ViteDevServer | null = null;\n\nexport async function createPageModuleLoader(args: {\n mode: 'dev' | 'build';\n root: string;\n server?: ViteDevServer | null;\n}): Promise<PageModuleLoader> {\n const { mode, root, server } = args;\n\n if (mode === 'dev') {\n if (!server) {\n throw new Error('[vite-plugin-html-pages] dev server not available');\n }\n\n return async (_entryPath, relativePath) => {\n const mod = await server.ssrLoadModule(`/${relativePath}`);\n return mod as HtPageModule;\n };\n }\n\n if (!buildServer) {\n const config: InlineConfig = {\n root,\n configFile: false,\n logLevel: 'error',\n appType: 'custom',\n server: {\n middlewareMode: true,\n },\n };\n\n buildServer = await createServer(config);\n }\n\n return async (entryPath) => {\n const relativePath =\n '/' + path.relative(root, entryPath).replace(/\\\\/g, '/');\n\n const mod = await buildServer!.ssrLoadModule(relativePath);\n return mod as HtPageModule;\n };\n}\n\nexport async function closePageModuleLoader(): Promise<void> {\n if (buildServer) {\n await buildServer.close();\n buildServer = null;\n }\n}","import {\n compareRoutePriority,\n expandStaticPaths,\n fileNameFromRoute,\n} from './route-utils';\nimport type { HtPageInfo, HtPageModule, StaticParamRecord } from './types';\nimport { PLUGIN_NAME } from './constants';\nexport async function buildPageIndex(args: {\n entries: HtPageInfo[];\n modulesByEntry: Map<string, HtPageModule>;\n cleanUrls: boolean;\n}): Promise<HtPageInfo[]> {\n const { entries, modulesByEntry, cleanUrls } = args;\n const pages: HtPageInfo[] = [];\n\n for (const entry of entries) {\n const mod = modulesByEntry.get(entry.entryPath) ?? {};\n\n if (entry.dynamic) {\n const rows =\n (mod.generateStaticParams\n ? await mod.generateStaticParams()\n : []) ?? [];\n\n pages.push(\n ...expandStaticPaths(\n {\n id: entry.id,\n entryPath: entry.entryPath,\n absolutePath: entry.absolutePath,\n relativePath: entry.relativePath,\n routePattern: entry.routePattern,\n dynamic: entry.dynamic,\n paramNames: entry.paramNames,\n } as Omit<HtPageInfo, 'routePath' | 'fileName' | 'params'>,\n Array.isArray(rows) ? rows : [],\n cleanUrls,\n ),\n );\n } else {\n pages.push({\n ...entry,\n routePath: entry.routePattern,\n fileName: fileNameFromRoute(entry.routePattern, cleanUrls),\n params: {},\n });\n }\n }\n\n pages.sort((a, b) => compareRoutePriority(a.routePattern, b.routePattern));\n\n const seenRoutes = new Map<string, HtPageInfo>();\n\n for (const page of pages) {\n const existing = seenRoutes.get(page.routePath);\n\n if (existing) {\n throw new Error(\n `[${PLUGIN_NAME}] Duplicate route generated: \"${page.routePath}\" from \"${existing.relativePath}\" and \"${page.relativePath}\"`,\n );\n }\n\n seenRoutes.set(page.routePath, page);\n }\n\n return pages;\n}","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport fg from 'fast-glob';\nimport * as esbuild from 'esbuild';\nimport fsSync from 'node:fs';\n\nexport interface StaticAssetFile {\n absolutePath: string;\n relativePathFromSrc: string;\n outputFileName: string;\n kind: 'copy' | 'process';\n}\n\nexport interface CollectStaticAssetsArgs {\n root: string;\n pagesDir: string;\n pageExtensions: string[];\n}\n\nfunction normalizeSlashes(value: string): string {\n return value.replace(/\\\\/g, '/');\n}\n\nfunction hasAnySuffix(value: string, suffixes: string[]): boolean {\n return suffixes.some((suffix) => value.endsWith(suffix));\n}\n\nfunction shouldIgnoreFile(rel: string): boolean {\n return (\n rel.endsWith('.d.ts') ||\n rel.endsWith('.map') ||\n rel.endsWith('.tsbuildinfo') ||\n rel.startsWith('.') ||\n rel.includes('/.')\n );\n}\n\nfunction isProcessableAsset(rel: string): boolean {\n return (\n rel.endsWith('.js') ||\n rel.endsWith('.mjs') ||\n rel.endsWith('.ts') ||\n rel.endsWith('.css')\n );\n}\n\nfunction toOutputFileName(relativePathFromSrc: string): string {\n if (relativePathFromSrc.endsWith('.ts')) {\n return relativePathFromSrc.slice(0, -3) + '.js';\n }\n return relativePathFromSrc;\n}\n\nexport async function collectStaticAssets(\n args: CollectStaticAssetsArgs,\n): Promise<StaticAssetFile[]> {\n const { root, pagesDir, pageExtensions } = args;\n const srcDir = path.join(root, pagesDir);\n\n const entries = await fg('**/*', {\n cwd: srcDir,\n onlyFiles: true,\n dot: false,\n absolute: false,\n });\n\n const assets: StaticAssetFile[] = [];\n\n for (const entry of entries) {\n const rel = normalizeSlashes(entry);\n\n if (shouldIgnoreFile(rel)) continue;\n if (hasAnySuffix(rel, pageExtensions)) continue;\n\n const absolutePath = path.join(srcDir, rel);\n\n assets.push({\n absolutePath,\n relativePathFromSrc: rel,\n outputFileName: normalizeSlashes(toOutputFileName(rel)),\n kind: isProcessableAsset(rel) ? 'process' : 'copy',\n });\n }\n\n return assets;\n}\n\nexport async function copyStaticAssetSource(\n asset: StaticAssetFile,\n): Promise<Uint8Array> {\n return fs.readFile(asset.absolutePath);\n}\n\nexport async function buildProcessedStaticAssets(args: {\n root: string;\n pagesDir: string;\n assets: StaticAssetFile[];\n minify?: boolean;\n sourcemap?: boolean;\n }): Promise<Map<string, string | Uint8Array>> {\n const { root, pagesDir, assets, minify = true, sourcemap = false } = args;\n \n const processable = assets.filter((a) => a.kind === 'process');\n const out = new Map<string, string | Uint8Array>();\n \n if (processable.length === 0) {\n return out;\n }\n \n const srcDir = path.join(root, pagesDir);\n const distDir = path.join(root, 'dist');\n const warnedMissingAssets = new Set<string>();\n const result = await esbuild.build({\n entryPoints: processable.map((a) => a.absolutePath),\n absWorkingDir: root,\n outbase: srcDir,\n outdir: distDir,\n bundle: true,\n splitting: true,\n treeShaking: true,\n minify,\n sourcemap,\n format: 'esm',\n target: 'es2020',\n platform: 'browser',\n write: false,\n entryNames: '[dir]/[name]',\n assetNames: '[dir]/[name]',\n loader: {\n '.css': 'css',\n '.png': 'file',\n '.jpg': 'file',\n '.jpeg': 'file',\n '.gif': 'file',\n '.svg': 'file',\n '.webp': 'file',\n '.woff': 'file',\n '.woff2': 'file',\n '.ttf': 'file',\n '.otf': 'file',\n },\n plugins: [\n {\n name: 'html-pages-root-url-resolver',\n setup(build) {\n build.onResolve({ filter: /^\\// }, (resolveArgs) => {\n // Leave real filesystem absolute paths alone\n if (\n path.isAbsolute(resolveArgs.path) &&\n fsSync.existsSync(resolveArgs.path)\n ) {\n return { path: resolveArgs.path };\n }\n \n const cleanPath = resolveArgs.path.slice(1);\n \n const fromSrc = path.join(srcDir, cleanPath);\n if (fsSync.existsSync(fromSrc)) {\n return { path: fromSrc };\n }\n \n const fromPublic = path.join(root, 'public', cleanPath);\n if (fsSync.existsSync(fromPublic)) {\n return {\n path: resolveArgs.path,\n external: true,\n };\n }\n \n const isCssUrlToken = resolveArgs.kind === 'url-token';\n \n if (isCssUrlToken) {\n if (!warnedMissingAssets.has(resolveArgs.path)) {\n warnedMissingAssets.add(resolveArgs.path);\n console.warn(\n `[vite-plugin-html-pages] ⚠️ Missing CSS asset: ${resolveArgs.path}\\n` +\n ` Looked in:\\n` +\n ` - ${fromSrc}\\n` +\n ` - ${fromPublic}`\n );\n }\n \n // Keep the original root-relative URL in output CSS\n return {\n path: resolveArgs.path,\n external: true,\n };\n }\n \n // JS/CSS entry imports remain strict\n return {\n path: fromSrc,\n };\n });\n },\n },\n ],\n });\n \n for (const file of result.outputFiles) {\n const rel = normalizeSlashes(path.relative(distDir, file.path));\n out.set(rel, file.text ?? file.contents);\n }\n \n return out;\n }\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { CACHE_DIR_NAME } from './constants';\n\nexport type FetchCacheMode = 'auto' | 'memory' | 'fs' | 'none';\nexport interface FetchWithCacheOptions {\n maxAge?: number;\n cacheKey?: string;\n forceRefresh?: boolean;\n cache?: FetchCacheMode;\n}\n\ntype CachedResponseRecord = {\n timestamp: number;\n status: number;\n statusText: string;\n headers: [string, string][];\n body: string;\n};\n\nconst memoryCache = new Map<string, CachedResponseRecord>();\n\nfunction createDefaultCacheKey(\n input: RequestInfo | URL,\n init?: RequestInit,\n): string {\n const raw = JSON.stringify({\n url: String(input),\n method: init?.method ?? 'GET',\n headers: init?.headers ?? {},\n body: init?.body ?? null,\n });\n\n return createHash('sha256').update(raw).digest('hex');\n}\n\nfunction getCacheFilePath(cacheKey: string): string {\n return path.join(process.cwd(), CACHE_DIR_NAME, 'fetch', `${cacheKey}.json`);\n}\n\nfunction getEffectiveCacheMode(\n mode: FetchCacheMode | undefined,\n): Exclude<FetchCacheMode, 'auto'> {\n if (mode === 'memory' || mode === 'fs' || mode === 'none') {\n return mode;\n }\n\n return process.env.NODE_ENV === 'production' ? 'fs' : 'memory';\n}\n\nfunction toResponse(cached: CachedResponseRecord): Response {\n return new Response(cached.body, {\n status: cached.status,\n statusText: cached.statusText,\n headers: cached.headers,\n });\n}\n\nfunction isFresh(cached: CachedResponseRecord, maxAgeSeconds: number): boolean {\n const ageSeconds = (Date.now() - cached.timestamp) / 1000;\n return ageSeconds <= maxAgeSeconds;\n}\n\nexport function clearMemoryFetchCache(): void {\n memoryCache.clear();\n}\n\nexport function deleteMemoryFetchCache(cacheKey: string): void {\n memoryCache.delete(cacheKey);\n}\n\nexport async function fetchWithCache(\n input: RequestInfo | URL,\n init?: RequestInit,\n options: FetchWithCacheOptions = {},\n): Promise<Response> {\n const maxAge = options.maxAge ?? 60 * 60;\n const method = (init?.method ?? 'GET').toUpperCase();\n\n if (method !== 'GET' && !options.cacheKey) {\n return fetch(input, init);\n }\n\n const cacheMode = getEffectiveCacheMode(options.cache);\n const cacheKey = options.cacheKey ?? createDefaultCacheKey(input, init);\n\n if (cacheMode === 'none') {\n return fetch(input, init);\n }\n\n if (cacheMode === 'memory' && !options.forceRefresh) {\n const cached = memoryCache.get(cacheKey);\n\n if (cached && isFresh(cached, maxAge)) {\n return toResponse(cached);\n }\n }\n\n const filePath = getCacheFilePath(cacheKey);\n\n if (cacheMode === 'fs') {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n if (!options.forceRefresh) {\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n const cached = JSON.parse(raw) as CachedResponseRecord;\n\n if (isFresh(cached, maxAge)) {\n return toResponse(cached);\n }\n } catch {\n // cache miss or invalid cache; fetch fresh\n }\n }\n }\n\n const res = await fetch(input, init);\n const body = await res.text();\n\n const record: CachedResponseRecord = {\n timestamp: Date.now(),\n status: res.status,\n statusText: res.statusText,\n headers: [...res.headers.entries()],\n body,\n };\n\n if (cacheMode === 'memory') {\n memoryCache.set(cacheKey, record);\n } else if (cacheMode === 'fs') {\n await fs.writeFile(filePath, JSON.stringify(record), 'utf8');\n }\n\n return new Response(body, {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n}\n"],"mappings":"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","names":["path","fg","path","path","path","path","fs","path","build","fs","path","fs","path","path","fs","path"]}
1
+ {"version":3,"sources":["../src/plugin.ts","../src/discover.ts","../src/path-utils.ts","../src/route-utils.ts","../src/constants.ts","../src/dev-server.ts","../src/errors.ts","../src/render-runtime.ts","../src/module-loader.ts","../src/page-index.ts","../src/static-assets.ts","../src/html-asset-validator.ts","../src/fetch-cache.ts"],"sourcesContent":["import pLimit from 'p-limit';\nimport type { Plugin, ViteDevServer } from 'vite';\n\nimport { discoverEntryPages } from './discover';\nimport { installDevServer } from './dev-server';\nimport { createPageModuleLoader, closePageModuleLoader } from './module-loader';\nimport { buildPageIndex } from './page-index';\nimport { renderPage } from './render-runtime';\nimport {\n buildProcessedStaticAssets,\n collectStaticAssets,\n copyStaticAssetSource,\n} from './static-assets';\nimport { validateHtmlAssetReferences } from './html-asset-validator';\nimport type { HtPageInfo, HtPageModule, HtPagesPluginOptions } from './types';\nimport { PLUGIN_NAME, VIRTUAL_BUILD_ENTRY_ID } from './constants';\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nlet hasWarnedESM = false;\n\nfunction warnIfNotESM(root: string) {\n try {\n const pkgPath = path.join(root, 'package.json');\n\n if (!fs.existsSync(pkgPath)) return;\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n\n if (pkg.type !== 'module') {\n console.warn(\n `[${PLUGIN_NAME}] ⚠️ It is recommended to add \"type\": \"module\" to your package.json for optimal performance and to avoid Node ESM warnings.`,\n );\n }\n } catch {\n // silent — never break build\n }\n}\n\nfunction chunkArray<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) {\n out.push(items.slice(i, i + size));\n }\n return out;\n}\n\nexport function htPages(options: HtPagesPluginOptions = {}): Plugin {\n let root = process.cwd();\n let server: ViteDevServer | null = null;\n let devPages: HtPageInfo[] = [];\n\n const cleanUrls = options.cleanUrls ?? true;\n const pagesDir = options.pagesDir ?? 'src';\n const pageExtensions = options.pageExtensions?.length\n ? options.pageExtensions\n : ['.ht.js', '.html.js', '.ht.ts', '.html.ts'];\n\n function logDebug(enabled: boolean | undefined, ...args: unknown[]) {\n if (!enabled) return;\n console.log(`[${PLUGIN_NAME}]`, ...args);\n }\n\n async function loadDevPages(): Promise<HtPageInfo[]> {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n logDebug(\n options.debug,\n 'discovered entries',\n entries.map((e) => e.relativePath),\n );\n\n if (!server) return [];\n\n const loadModule = await createPageModuleLoader({\n mode: 'dev',\n root,\n server,\n });\n\n for (const entry of entries) {\n const mod = await loadModule(entry.entryPath, entry.relativePath);\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n devPages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n logDebug(\n options.debug,\n 'dev pages',\n devPages.map((p) => `${p.routePath} -> ${p.relativePath}`),\n );\n\n return devPages;\n }\n\n async function buildPagesPipeline() {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n const loadModule = await createPageModuleLoader({\n mode: 'build',\n root,\n });\n\n for (const entry of entries) {\n const mod = await loadModule(entry.entryPath, entry.relativePath);\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n const pages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n return { entries, modulesByEntry, pages };\n }\n\n return {\n name: PLUGIN_NAME,\n\n config(userConfig, env) {\n if (env.command !== 'build') return;\n\n const hasExplicitInput = userConfig.build?.rollupOptions?.input != null;\n if (hasExplicitInput) return;\n\n return {\n build: {\n rollupOptions: {\n input: VIRTUAL_BUILD_ENTRY_ID,\n },\n },\n };\n },\n\n resolveId(id) {\n if (id === VIRTUAL_BUILD_ENTRY_ID) return id;\n return null;\n },\n\n load(id) {\n if (id === VIRTUAL_BUILD_ENTRY_ID) {\n return 'export default {};';\n }\n return null;\n },\n\n configResolved(resolved) {\n root = resolved.root;\n\n if (!hasWarnedESM) {\n warnIfNotESM(root);\n hasWarnedESM = true;\n }\n },\n\n async buildStart() {\n const entries = await discoverEntryPages(root, options);\n\n for (const entry of entries) {\n this.addWatchFile(entry.entryPath);\n }\n\n const staticAssets = await collectStaticAssets({\n root,\n pagesDir,\n pageExtensions,\n });\n\n for (const asset of staticAssets) {\n this.addWatchFile(asset.absolutePath);\n }\n\n logDebug(\n options.debug,\n 'static assets',\n staticAssets.map((asset) => ({\n kind: asset.kind,\n input: asset.relativePathFromSrc,\n output: asset.outputFileName,\n })),\n );\n },\n\n configureServer(_server) {\n server = _server;\n\n installDevServer({\n server,\n getPages: async () => {\n if (devPages.length > 0) return devPages;\n return loadDevPages();\n },\n getEntries: async () => discoverEntryPages(root, options),\n });\n\n loadDevPages().catch((error) => {\n server?.config.logger.error(\n `[${PLUGIN_NAME}] loadDevPages failed: ${\n error instanceof Error ? error.stack ?? error.message : String(error)\n }`,\n );\n });\n },\n\n async handleHotUpdate(ctx) {\n if (!server) return;\n \n logDebug(options.debug, 'file changed', ctx.file);\n \n await loadDevPages();\n \n server.ws.send({\n type: 'full-reload',\n });\n \n return [];\n },\n\n async generateBundle(_, bundle) {\n try {\n const { modulesByEntry, pages } = await buildPagesPipeline();\n\n const staticAssets = await collectStaticAssets({\n root,\n pagesDir,\n pageExtensions,\n });\n\n logDebug(\n options.debug,\n 'emitting pages',\n pages.map((p) => p.fileName),\n );\n\n logDebug(\n options.debug,\n 'emitting static assets',\n staticAssets.map((asset) => ({\n kind: asset.kind,\n input: asset.relativePathFromSrc,\n output: asset.outputFileName,\n })),\n );\n\n const limit = pLimit(options.renderConcurrency ?? 8);\n const batchSize =\n options.renderBatchSize ??\n Math.max(options.renderConcurrency ?? 8, 32);\n\n const processedOutputs = await buildProcessedStaticAssets({\n root,\n pagesDir,\n assets: staticAssets,\n minify: true,\n sourcemap: false,\n });\n\n for (const [fileName, source] of processedOutputs) {\n this.emitFile({\n type: 'asset',\n fileName,\n source,\n });\n }\n\n for (const asset of staticAssets) {\n if (asset.kind !== 'copy') continue;\n\n const source = await copyStaticAssetSource(asset);\n\n this.emitFile({\n type: 'asset',\n fileName: asset.outputFileName,\n source,\n });\n }\n\n for (const batch of chunkArray(pages, batchSize)) {\n await Promise.all(\n batch.map((page) =>\n limit(async () => {\n const mod = modulesByEntry.get(page.entryPath);\n\n if (!mod) {\n throw new Error(\n `[${PLUGIN_NAME}] Missing module for page entry: ${page.entryPath}`,\n );\n }\n\n const html = await renderPage(page, mod, false);\n\n validateHtmlAssetReferences({\n root,\n pagesDir,\n html,\n pluginName: PLUGIN_NAME,\n pageLabel: page.relativePath,\n missingAssets: options.missingAssets ?? 'error',\n });\n \n this.emitFile({\n type: 'asset',\n fileName: options.mapOutputPath?.(page) ?? page.fileName,\n source: html,\n });\n }),\n ),\n );\n }\n\n const notFoundPage = pages.find((p) => p.routePath === '/404');\n\n if (notFoundPage) {\n const mod = modulesByEntry.get(notFoundPage.entryPath);\n\n if (!mod) {\n throw new Error(\n `[${PLUGIN_NAME}] Missing module for 404 page entry: ${notFoundPage.entryPath}`,\n );\n }\n\n const html = await renderPage(notFoundPage, mod, false);\n\n validateHtmlAssetReferences({\n root,\n pagesDir,\n html,\n pluginName: PLUGIN_NAME,\n pageLabel: notFoundPage.relativePath,\n missingAssets: options.missingAssets ?? 'error',\n });\n \n this.emitFile({\n type: 'asset',\n fileName: '404.html',\n source: html,\n });\n\n logDebug(options.debug, 'generated 404.html from user page');\n } else {\n const default404 = `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>404 - Page Not Found</title>\n <style>\n :root {\n color-scheme: light dark;\n }\n body {\n margin: 0;\n font-family: system-ui, sans-serif;\n min-height: 100vh;\n display: grid;\n place-items: center;\n padding: 2rem;\n }\n main {\n max-width: 40rem;\n text-align: center;\n }\n h1 {\n font-size: 3rem;\n margin: 0 0 1rem;\n }\n p {\n margin: 0.5rem 0;\n line-height: 1.5;\n }\n a {\n color: inherit;\n }\n </style>\n </head>\n <body>\n <main>\n <h1>404</h1>\n <p>Page not found.</p>\n <p><a href=\"/\">Go back home</a></p>\n </main>\n </body>\n</html>\n`;\n\n this.emitFile({\n type: 'asset',\n fileName: '404.html',\n source: default404,\n });\n\n logDebug(options.debug, 'generated default 404.html');\n }\n\n const sitemapBase = options.site ?? '';\n\n const sitemapRoutes = [...new Set(pages.map((p) => p.routePath))].filter(\n (route) => !route.includes(':') && !route.includes('*'),\n );\n\n if (sitemapBase && sitemapRoutes.length > 0) {\n const sitemap = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${sitemapRoutes\n .map((route) => ` <url><loc>${sitemapBase}${route}</loc></url>`)\n .join('\\n')}\\n</urlset>\\n`;\n\n this.emitFile({\n type: 'asset',\n fileName: 'sitemap.xml',\n source: sitemap,\n });\n\n logDebug(options.debug, 'generated sitemap.xml');\n }\n\n const rss = options.rss;\n\n if (rss?.site) {\n const routePrefix = rss.routePrefix ?? '/blog';\n \n const rssItems = pages\n .filter((page) => page.routePath.startsWith(routePrefix))\n .map((page) => {\n const url = `${rss.site}${page.routePath}`;\n \n return ` <item>\\n <title>${page.routePath}</title>\\n <link>${url}</link>\\n <guid>${url}</guid>\\n </item>`;\n })\n .join('\\n');\n \n const rssXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<rss version=\"2.0\">\\n<channel>\\n <title>${rss.title ?? PLUGIN_NAME}</title>\\n <link>${rss.site}</link>\\n <description>${rss.description ?? 'RSS feed'}</description>\\n${rssItems}\\n</channel>\\n</rss>\\n`;\n \n this.emitFile({\n type: 'asset',\n fileName: 'rss.xml',\n source: rssXml,\n });\n \n logDebug(options.debug, 'generated rss.xml');\n }\n\n for (const [fileName, output] of Object.entries(bundle)) {\n if (\n output.type === 'chunk' &&\n output.facadeModuleId === VIRTUAL_BUILD_ENTRY_ID\n ) {\n delete bundle[fileName];\n }\n }\n } finally {\n await closePageModuleLoader();\n }\n }\n };\n}\n\nexport default htPages;\n","import path from 'node:path';\nimport { normalizeFsPath, toPosix } from './path-utils';\nimport { getParamNames, isDynamicPage, toRoutePattern } from './route-utils';\nimport type { HtPageInfo, HtPagesPluginOptions } from './types';\nimport { PLUGIN_NAME } from './constants';\n\nfunction buildDefaultIncludeGlobs(\n pagesDir: string,\n pageExtensions: string[],\n): string[] {\n return pageExtensions.map((ext) => {\n const cleanExt = ext.startsWith('.') ? ext.slice(1) : ext;\n return `${pagesDir}/**/*.${cleanExt}`;\n });\n}\n\nexport async function discoverEntryPages(\n root: string,\n options: HtPagesPluginOptions,\n): Promise<HtPageInfo[]> {\n const fgModule = await import('fast-glob');\n const fg = (fgModule.default ?? fgModule) as typeof import('fast-glob');\n\n const pagesDir = options.pagesDir ?? 'src';\n const pageExtensions = options.pageExtensions?.length\n ? options.pageExtensions\n : ['.ht.js', '.html.js', '.ht.ts', '.html.ts'];\n\n const include = Array.isArray(options.include)\n ? options.include\n : options.include\n ? [options.include]\n : buildDefaultIncludeGlobs(pagesDir, pageExtensions);\n\n const exclude = Array.isArray(options.exclude)\n ? options.exclude\n : options.exclude\n ? [options.exclude]\n : [];\n\n const pagesRoot = normalizeFsPath(path.join(root, pagesDir));\n\n const files = await fg.glob(include, {\n cwd: root,\n ignore: exclude,\n absolute: true,\n });\n\n return files\n .sort()\n .map((absolutePath) => {\n const entryPath = normalizeFsPath(absolutePath);\n const relativePath = toPosix(path.relative(root, entryPath));\n const relativeFromPagesDir = toPosix(path.relative(pagesRoot, entryPath));\n\n if (\n relativeFromPagesDir.startsWith('../') ||\n relativeFromPagesDir === '..'\n ) {\n throw new Error(\n `[${PLUGIN_NAME}] Page is outside pagesDir: ${entryPath} (pagesDir: ${pagesDir})`,\n );\n }\n\n const dynamic = isDynamicPage(relativeFromPagesDir);\n const routePattern = toRoutePattern(relativeFromPagesDir, pageExtensions);\n\n return {\n id: entryPath,\n entryPath,\n absolutePath: entryPath,\n relativePath,\n routePattern,\n routePath: routePattern,\n fileName: '',\n dynamic,\n paramNames: getParamNames(relativeFromPagesDir),\n params: {},\n } satisfies HtPageInfo;\n });\n}","import path from 'node:path';\n\nexport function toPosix(value: string): string {\n return value.replace(/\\\\/g, '/');\n}\n\nexport function normalizeFsPath(value: string): string {\n return path.normalize(value);\n}\n\nexport function normalizeRoutePath(value: string): string {\n const normalized = toPosix(value).replace(/\\/+/g, '/');\n if (!normalized || normalized === '/') return '/';\n return normalized.startsWith('/') ? normalized : `/${normalized}`;\n}\n\nexport function stripPageSuffix(\n filePath: string,\n extensions: string[],\n): string {\n const normalized = toPosix(filePath);\n\n const match = [...extensions]\n .sort((a, b) => b.length - a.length)\n .find((ext) => normalized.endsWith(ext));\n\n if (!match) return normalized;\n\n return normalized.slice(0, -match.length);\n}","import { normalizeRoutePath, stripPageSuffix, toPosix } from './path-utils';\nimport type { HtPageInfo, StaticParamRecord } from './types';\n\nconst DYNAMIC_SEGMENT_RE = /\\[([A-Za-z0-9_]+)\\]/g;\nconst CATCH_ALL_SEGMENT_RE = /\\[\\.\\.\\.([A-Za-z0-9_]+)\\]/g;\nconst OPTIONAL_CATCH_ALL_SEGMENT_RE = /\\[\\.\\.\\.([A-Za-z0-9_]+)\\]\\?/g;\nconst ANY_PARAM_RE = /\\[(?:\\.\\.\\.)?([A-Za-z0-9_]+)\\]\\??/g;\nconst ROUTE_GROUP_RE = /(^|\\/)\\(([^)]+)\\)(?=\\/|$)/g;\n\nexport function getParamNames(relativeFromPagesDir: string): string[] {\n return [...relativeFromPagesDir.matchAll(ANY_PARAM_RE)].map((m) => m[1]);\n}\n\nexport function isDynamicPage(relativeFromPagesDir: string): boolean {\n return /\\[(?:\\.\\.\\.)?[A-Za-z0-9_]+\\]\\??/.test(relativeFromPagesDir);\n}\n\nexport function toRoutePattern(\n relativeFromPagesDir: string,\n extensions: string[],\n): string {\n const noExt = stripPageSuffix(toPosix(relativeFromPagesDir), extensions);\n\n const withoutGroups = noExt.replace(ROUTE_GROUP_RE, '$1');\n const withoutIndex = withoutGroups.replace(/\\/index$/i, '').replace(/^index$/i, '');\n\n const raw = withoutIndex\n .replace(OPTIONAL_CATCH_ALL_SEGMENT_RE, '*?:$1')\n .replace(CATCH_ALL_SEGMENT_RE, '*:$1')\n .replace(DYNAMIC_SEGMENT_RE, ':$1');\n\n return normalizeRoutePath(raw || '/');\n}\n\nexport function fillParams(\n pattern: string,\n params: Record<string, string>,\n): string {\n const result = pattern\n .replace(/\\*\\?:([A-Za-z0-9_]+)/g, (_, key) => {\n const value = params[key];\n if (value == null || value === '') {\n return '';\n }\n\n return String(value)\n .split('/')\n .map((part) => encodeURIComponent(part))\n .join('/');\n })\n .replace(/\\*:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) {\n throw new Error(`Missing catch-all route param \"${key}\"`);\n }\n\n return String(params[key])\n .split('/')\n .map((part) => encodeURIComponent(part))\n .join('/');\n })\n .replace(/:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) {\n throw new Error(`Missing route param \"${key}\"`);\n }\n\n return encodeURIComponent(params[key]);\n });\n\n return normalizeRoutePath(result || '/');\n}\n\nexport function fileNameFromRoute(\n routePath: string,\n cleanUrls: boolean,\n): string {\n const normalized = normalizeRoutePath(routePath);\n\n if (normalized === '/') return 'index.html';\n\n const base = normalized.slice(1);\n return cleanUrls ? `${base}/index.html` : `${base}.html`;\n}\n\nexport function expandStaticPaths(\n basePage: Omit<HtPageInfo, 'routePath' | 'fileName' | 'params'>,\n rows: StaticParamRecord[],\n cleanUrls: boolean,\n): HtPageInfo[] {\n return rows.map((row) => {\n const params = Object.fromEntries(\n Object.entries(row).map(([k, v]) => [k, String(v)]),\n );\n\n const routePath = fillParams(basePage.routePattern, params);\n\n return {\n ...basePage,\n routePath,\n fileName: fileNameFromRoute(routePath, cleanUrls),\n params,\n };\n });\n}\n\nexport function routeMatch(\n pattern: string,\n urlPath: string,\n): Record<string, string> | null {\n const a = normalizeRoutePath(pattern).split('/').filter(Boolean);\n const b = normalizeRoutePath(urlPath).split('/').filter(Boolean);\n const params: Record<string, string> = {};\n\n for (let i = 0; i < a.length; i++) {\n const patternSeg = a[i];\n const urlSeg = b[i];\n\n if (patternSeg.startsWith('*?:')) {\n params[patternSeg.slice(3)] =\n i < b.length ? b.slice(i).map(decodeURIComponent).join('/') : '';\n return params;\n }\n\n if (patternSeg.startsWith('*:')) {\n const rest = b.slice(i);\n if (rest.length === 0) return null;\n\n params[patternSeg.slice(2)] = rest.map(decodeURIComponent).join('/');\n return params;\n }\n\n if (!urlSeg) return null;\n\n if (patternSeg.startsWith(':')) {\n params[patternSeg.slice(1)] = decodeURIComponent(urlSeg);\n continue;\n }\n\n if (patternSeg !== urlSeg) return null;\n }\n\n return a.length === b.length ? params : null;\n}\n\nexport function compareRoutePriority(a: string, b: string): number {\n const aSegs = normalizeRoutePath(a).split('/').filter(Boolean);\n const bSegs = normalizeRoutePath(b).split('/').filter(Boolean);\n const len = Math.max(aSegs.length, bSegs.length);\n\n for (let i = 0; i < len; i++) {\n const aa = aSegs[i];\n const bb = bSegs[i];\n\n if (aa == null) return 1;\n if (bb == null) return -1;\n\n const aOptionalCatchAll = aa.startsWith('*?:');\n const bOptionalCatchAll = bb.startsWith('*?:');\n if (aOptionalCatchAll !== bOptionalCatchAll) {\n return aOptionalCatchAll ? 1 : -1;\n }\n\n const aCatchAll = aa.startsWith('*:');\n const bCatchAll = bb.startsWith('*:');\n if (aCatchAll !== bCatchAll) {\n return aCatchAll ? 1 : -1;\n }\n\n const aDynamic = aa.startsWith(':');\n const bDynamic = bb.startsWith(':');\n if (aDynamic !== bDynamic) {\n return aDynamic ? 1 : -1;\n }\n }\n\n return bSegs.length - aSegs.length;\n}","export const PLUGIN_NAME = 'vite-plugin-html-pages';\nexport const VIRTUAL_BUILD_ENTRY_ID = `\\0${PLUGIN_NAME}:build-entry`;\nexport const VIRTUAL_MANIFEST_ID = `\\0virtual:${PLUGIN_NAME}-manifest`;\nexport const CACHE_DIR_NAME = `node_modules/.cache/${PLUGIN_NAME}`;","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { ViteDevServer } from 'vite';\n\nimport { renderPage } from './render-runtime';\nimport type { HtPageInfo, HtPageModule } from './types';\nimport { PLUGIN_NAME } from './constants';\nimport { createPageModuleLoader } from './module-loader';\n\nfunction isStaticAssetRequest(url: string): boolean {\n return (\n url.endsWith('.css') ||\n url.endsWith('.js') ||\n url.endsWith('.mjs') ||\n url.endsWith('.ts') ||\n url.endsWith('.png') ||\n url.endsWith('.jpg') ||\n url.endsWith('.jpeg') ||\n url.endsWith('.gif') ||\n url.endsWith('.svg') ||\n url.endsWith('.webp') ||\n url.endsWith('.ico') ||\n url.endsWith('.woff') ||\n url.endsWith('.woff2') ||\n url.endsWith('.ttf') ||\n url.endsWith('.otf')\n );\n}\n\nfunction shouldSkipHtmlRouting(url: string): boolean {\n return (\n url.startsWith('/@vite') ||\n url.startsWith('/@fs/') ||\n url.startsWith('/node_modules/') ||\n url.startsWith('/src/') ||\n url === '/favicon.ico' ||\n isStaticAssetRequest(url)\n );\n}\n\nfunction tryRewriteRootAssetToSrc(server: ViteDevServer, url: string): string | null {\n if (!url.startsWith('/')) return null;\n if (!isStaticAssetRequest(url)) return null;\n if (url.startsWith('/src/')) return null;\n\n const root = server.config.root;\n const candidate = path.join(root, 'src', url.slice(1));\n\n if (fs.existsSync(candidate)) {\n return `/src/${url.slice(1)}`;\n }\n\n return null;\n}\n\nfunction shouldUseDynamicRendering(mod: HtPageModule): boolean {\n return mod.dynamic === true || mod.prerender === false;\n}\n\nexport function installDevServer(args: {\n server: ViteDevServer;\n getPages: () => Promise<HtPageInfo[]>;\n getEntries?: () => Promise<HtPageInfo[]>;\n}) {\n const { server, getPages } = args;\n\n server.middlewares.use(async (req, res, next) => {\n try {\n const originalUrl = req.url ?? '/';\n const url = originalUrl.split('?')[0];\n\n const rewrittenAssetUrl = tryRewriteRootAssetToSrc(server, url);\n if (rewrittenAssetUrl) {\n req.url = rewrittenAssetUrl + originalUrl.slice(url.length);\n return next();\n }\n\n if (shouldSkipHtmlRouting(url)) {\n return next();\n }\n\n const pages = await getPages();\n\n const page = pages.find((p) => p.routePath === url);\n\n if (!page) {\n return next();\n }\n\n const loadModule = await createPageModuleLoader({\n mode: 'dev',\n root: server.config.root,\n server,\n });\n\n const mod = await loadModule(page.entryPath, page.relativePath);\n\n if (!mod) {\n return next();\n }\n\n if (!shouldUseDynamicRendering(mod) && page.dynamic) {\n return next();\n }\n\n const html = await renderPage(page, mod, true);\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(html);\n } catch (error) {\n server.config.logger.error(\n `[${PLUGIN_NAME}] dev server render failed: ${\n error instanceof Error ? error.stack ?? error.message : String(error)\n }`,\n );\n\n next(error as Error);\n }\n });\n}","import type { HtPageInfo } from './types';\nimport { PLUGIN_NAME } from './constants';\nexport function invalidHtmlReturn(\n page: HtPageInfo,\n value: unknown,\n): Error {\n return new Error(\n `[${PLUGIN_NAME}] Page \"${page.relativePath}\" must resolve to an HTML string, got ${typeof value}`,\n );\n}\n\nexport function missingDefaultExport(page: HtPageInfo): Error {\n return new Error(\n `[${PLUGIN_NAME}] Page \"${page.relativePath}\" does not export a default renderer`,\n );\n}\n\nexport function pageError(page: HtPageInfo, cause: unknown): Error {\n const message = `[${PLUGIN_NAME}] Failed to render \"${page.relativePath}\" at route \"${page.routePath}\"`;\n\n if (cause instanceof Error) {\n const err = new Error(`${message}: ${cause.message}`);\n\n if (cause.stack) {\n err.stack = `${err.stack}\\nCaused by:\\n${cause.stack}`;\n }\n\n return err;\n }\n\n return new Error(`${message}: ${String(cause)}`);\n}","import { invalidHtmlReturn, pageError, missingDefaultExport } from './errors';\nimport type { HtPageInfo, HtPageModule, HtPageRenderContext } from './types';\n\nexport async function renderPage(\n page: HtPageInfo,\n mod: HtPageModule,\n dev = false,\n): Promise<string> {\n const ctx: HtPageRenderContext = {\n page,\n params: page.params,\n dev,\n };\n\n try {\n if (typeof mod.data === 'function') {\n ctx.data = await mod.data(ctx);\n }\n\n const entry = mod.default;\n\n if (entry == null) {\n throw missingDefaultExport(page);\n }\n\n const html = typeof entry === 'function' ? await entry(ctx) : entry;\n\n if (typeof html !== 'string') {\n throw invalidHtmlReturn(page, html);\n }\n\n return html;\n } catch (error) {\n throw pageError(page, error);\n }\n}","import path from 'node:path';\nimport { createServer, type InlineConfig, type ViteDevServer } from 'vite';\nimport type { HtPageModule } from './types';\n\nexport type PageModuleLoader = (\n entryPath: string,\n relativePath: string,\n) => Promise<HtPageModule>;\n\nlet buildServer: ViteDevServer | null = null;\n\nexport async function createPageModuleLoader(args: {\n mode: 'dev' | 'build';\n root: string;\n server?: ViteDevServer | null;\n}): Promise<PageModuleLoader> {\n const { mode, root, server } = args;\n\n if (mode === 'dev') {\n if (!server) {\n throw new Error('[vite-plugin-html-pages] dev server not available');\n }\n\n return async (_entryPath, relativePath) => {\n const mod = await server.ssrLoadModule(`/${relativePath}`);\n return mod as HtPageModule;\n };\n }\n\n if (!buildServer) {\n const config: InlineConfig = {\n root,\n configFile: false,\n logLevel: 'error',\n appType: 'custom',\n server: {\n middlewareMode: true,\n },\n };\n\n buildServer = await createServer(config);\n }\n\n return async (entryPath) => {\n const relativePath =\n '/' + path.relative(root, entryPath).replace(/\\\\/g, '/');\n\n const mod = await buildServer!.ssrLoadModule(relativePath);\n return mod as HtPageModule;\n };\n}\n\nexport async function closePageModuleLoader(): Promise<void> {\n if (buildServer) {\n await buildServer.close();\n buildServer = null;\n }\n}","import {\n compareRoutePriority,\n expandStaticPaths,\n fileNameFromRoute,\n} from './route-utils';\nimport type { HtPageInfo, HtPageModule, StaticParamRecord } from './types';\nimport { PLUGIN_NAME } from './constants';\nexport async function buildPageIndex(args: {\n entries: HtPageInfo[];\n modulesByEntry: Map<string, HtPageModule>;\n cleanUrls: boolean;\n}): Promise<HtPageInfo[]> {\n const { entries, modulesByEntry, cleanUrls } = args;\n const pages: HtPageInfo[] = [];\n\n for (const entry of entries) {\n const mod = modulesByEntry.get(entry.entryPath) ?? {};\n\n if (entry.dynamic) {\n const rows =\n (mod.generateStaticParams\n ? await mod.generateStaticParams()\n : []) ?? [];\n\n pages.push(\n ...expandStaticPaths(\n {\n id: entry.id,\n entryPath: entry.entryPath,\n absolutePath: entry.absolutePath,\n relativePath: entry.relativePath,\n routePattern: entry.routePattern,\n dynamic: entry.dynamic,\n paramNames: entry.paramNames,\n } as Omit<HtPageInfo, 'routePath' | 'fileName' | 'params'>,\n Array.isArray(rows) ? rows : [],\n cleanUrls,\n ),\n );\n } else {\n pages.push({\n ...entry,\n routePath: entry.routePattern,\n fileName: fileNameFromRoute(entry.routePattern, cleanUrls),\n params: {},\n });\n }\n }\n\n pages.sort((a, b) => compareRoutePriority(a.routePattern, b.routePattern));\n\n const seenRoutes = new Map<string, HtPageInfo>();\n\n for (const page of pages) {\n const existing = seenRoutes.get(page.routePath);\n\n if (existing) {\n throw new Error(\n `[${PLUGIN_NAME}] Duplicate route generated: \"${page.routePath}\" from \"${existing.relativePath}\" and \"${page.relativePath}\"`,\n );\n }\n\n seenRoutes.set(page.routePath, page);\n }\n\n return pages;\n}","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport fg from 'fast-glob';\nimport * as esbuild from 'esbuild';\nimport fsSync from 'node:fs';\n\nexport interface StaticAssetFile {\n absolutePath: string;\n relativePathFromSrc: string;\n outputFileName: string;\n kind: 'copy' | 'process';\n}\n\nexport interface CollectStaticAssetsArgs {\n root: string;\n pagesDir: string;\n pageExtensions: string[];\n}\n\nfunction normalizeSlashes(value: string): string {\n return value.replace(/\\\\/g, '/');\n}\n\nfunction hasAnySuffix(value: string, suffixes: string[]): boolean {\n return suffixes.some((suffix) => value.endsWith(suffix));\n}\n\nfunction shouldIgnoreFile(rel: string): boolean {\n return (\n rel.endsWith('.d.ts') ||\n rel.endsWith('.map') ||\n rel.endsWith('.tsbuildinfo') ||\n rel.startsWith('.') ||\n rel.includes('/.')\n );\n}\n\nfunction isProcessableAsset(rel: string): boolean {\n return (\n rel.endsWith('.js') ||\n rel.endsWith('.mjs') ||\n rel.endsWith('.ts') ||\n rel.endsWith('.css')\n );\n}\n\nfunction toOutputFileName(relativePathFromSrc: string): string {\n if (relativePathFromSrc.endsWith('.ts')) {\n return relativePathFromSrc.slice(0, -3) + '.js';\n }\n return relativePathFromSrc;\n}\n\nexport async function collectStaticAssets(\n args: CollectStaticAssetsArgs,\n): Promise<StaticAssetFile[]> {\n const { root, pagesDir, pageExtensions } = args;\n const srcDir = path.join(root, pagesDir);\n\n const entries = await fg('**/*', {\n cwd: srcDir,\n onlyFiles: true,\n dot: false,\n absolute: false,\n });\n\n const assets: StaticAssetFile[] = [];\n\n for (const entry of entries) {\n const rel = normalizeSlashes(entry);\n\n if (shouldIgnoreFile(rel)) continue;\n if (hasAnySuffix(rel, pageExtensions)) continue;\n\n const absolutePath = path.join(srcDir, rel);\n\n assets.push({\n absolutePath,\n relativePathFromSrc: rel,\n outputFileName: normalizeSlashes(toOutputFileName(rel)),\n kind: isProcessableAsset(rel) ? 'process' : 'copy',\n });\n }\n\n return assets;\n}\n\nexport async function copyStaticAssetSource(\n asset: StaticAssetFile,\n): Promise<Uint8Array> {\n return fs.readFile(asset.absolutePath);\n}\n\nexport async function buildProcessedStaticAssets(args: {\n root: string;\n pagesDir: string;\n assets: StaticAssetFile[];\n minify?: boolean;\n sourcemap?: boolean;\n }): Promise<Map<string, string | Uint8Array>> {\n const { root, pagesDir, assets, minify = true, sourcemap = false } = args;\n \n const processable = assets.filter((a) => a.kind === 'process');\n const out = new Map<string, string | Uint8Array>();\n \n if (processable.length === 0) {\n return out;\n }\n \n const srcDir = path.join(root, pagesDir);\n const distDir = path.join(root, 'dist');\n const warnedMissingAssets = new Set<string>();\n const result = await esbuild.build({\n entryPoints: processable.map((a) => a.absolutePath),\n absWorkingDir: root,\n outbase: srcDir,\n outdir: distDir,\n bundle: true,\n splitting: true,\n treeShaking: true,\n minify,\n sourcemap,\n format: 'esm',\n target: 'es2020',\n platform: 'browser',\n write: false,\n entryNames: '[dir]/[name]',\n assetNames: '[dir]/[name]',\n loader: {\n '.css': 'css',\n '.png': 'file',\n '.jpg': 'file',\n '.jpeg': 'file',\n '.gif': 'file',\n '.svg': 'file',\n '.webp': 'file',\n '.woff': 'file',\n '.woff2': 'file',\n '.ttf': 'file',\n '.otf': 'file',\n },\n plugins: [\n {\n name: 'html-pages-root-url-resolver',\n setup(build) {\n build.onResolve({ filter: /^\\// }, (resolveArgs) => {\n // Leave real filesystem absolute paths alone\n if (\n path.isAbsolute(resolveArgs.path) &&\n fsSync.existsSync(resolveArgs.path)\n ) {\n return { path: resolveArgs.path };\n }\n \n const cleanPath = resolveArgs.path.slice(1);\n \n const fromSrc = path.join(srcDir, cleanPath);\n if (fsSync.existsSync(fromSrc)) {\n return { path: fromSrc };\n }\n \n const fromPublic = path.join(root, 'public', cleanPath);\n if (fsSync.existsSync(fromPublic)) {\n return {\n path: resolveArgs.path,\n external: true,\n };\n }\n \n const isCssUrlToken = resolveArgs.kind === 'url-token';\n \n if (isCssUrlToken) {\n if (!warnedMissingAssets.has(resolveArgs.path)) {\n warnedMissingAssets.add(resolveArgs.path);\n console.warn(\n `[vite-plugin-html-pages] ⚠️ Missing CSS asset: ${resolveArgs.path}\\n` +\n ` Looked in:\\n` +\n ` - ${fromSrc}\\n` +\n ` - ${fromPublic}`\n );\n }\n \n // Keep the original root-relative URL in output CSS\n return {\n path: resolveArgs.path,\n external: true,\n };\n }\n \n // JS/CSS entry imports remain strict\n return {\n path: fromSrc,\n };\n });\n },\n },\n ],\n });\n \n for (const file of result.outputFiles) {\n const rel = normalizeSlashes(path.relative(distDir, file.path));\n out.set(rel, file.text ?? file.contents);\n }\n \n return out;\n }\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface HtmlAssetValidationOptions {\n root: string;\n pagesDir: string;\n html: string;\n pluginName: string;\n pageLabel?: string;\n missingAssets?: 'error' | 'warn';\n}\n\nfunction stripQueryAndHash(url: string): string {\n return url.split('#')[0].split('?')[0];\n}\n\nfunction isLocalRootUrl(url: string): boolean {\n return !!url && url.startsWith('/') && !url.startsWith('//');\n}\n\nfunction fileExistsForPublicUrl(root: string, pagesDir: string, url: string): boolean {\n const clean = stripQueryAndHash(url).slice(1);\n\n const fromSrc = path.join(root, pagesDir, clean);\n if (fs.existsSync(fromSrc)) return true;\n\n const fromPublic = path.join(root, 'public', clean);\n if (fs.existsSync(fromPublic)) return true;\n\n return false;\n}\n\nfunction collectScriptSrcs(html: string): string[] {\n const out: string[] = [];\n\n for (const match of html.matchAll(\n /<script\\b[^>]*\\bsrc=[\"']([^\"']+)[\"'][^>]*>/gi,\n )) {\n out.push(match[1]);\n }\n\n return out;\n}\n\nfunction collectStylesheetHrefs(html: string): string[] {\n const out: string[] = [];\n\n for (const match of html.matchAll(\n /<link\\b[^>]*\\brel=[\"']stylesheet[\"'][^>]*\\bhref=[\"']([^\"']+)[\"'][^>]*>/gi,\n )) {\n out.push(match[1]);\n }\n\n return out;\n}\n\nfunction collectLiteralDynamicImports(html: string): string[] {\n const out: string[] = [];\n\n for (const match of html.matchAll(\n /import\\s*\\(\\s*[\"']([^\"'`]+)[\"']\\s*\\)/gi,\n )) {\n out.push(match[1]);\n }\n\n return out;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction formatPageLabel(pageLabel?: string): string {\n return pageLabel ? ` (${pageLabel})` : '';\n}\n\nfunction missingAssetMessage(args: {\n pluginName: string;\n kind: string;\n url: string;\n root: string;\n pagesDir: string;\n pageLabel?: string;\n}): string {\n const { pluginName, kind, url, root, pagesDir, pageLabel } = args;\n const clean = stripQueryAndHash(url).slice(1);\n const pageSuffix = formatPageLabel(pageLabel);\n\n return (\n `[${pluginName}] Missing ${kind}${pageSuffix}: ${url}\\n` +\n `Expected one of:\\n` +\n `- ${path.join(root, pagesDir, clean)}\\n` +\n `- ${path.join(root, 'public', clean)}`\n );\n}\n\nfunction reportMissing(args: {\n mode: 'error' | 'warn';\n pluginName: string;\n kind: string;\n url: string;\n root: string;\n pagesDir: string;\n pageLabel?: string;\n}) {\n const message = missingAssetMessage(args);\n\n if (args.mode === 'warn') {\n console.warn(`⚠️ ${message}`);\n return;\n }\n\n throw new Error(message);\n}\n\nexport function validateHtmlAssetReferences(\n options: HtmlAssetValidationOptions,\n): void {\n const {\n root,\n pagesDir,\n html,\n pluginName,\n pageLabel,\n missingAssets = 'error',\n } = options;\n\n const scriptSrcs = unique(collectScriptSrcs(html)).filter(isLocalRootUrl);\n const stylesheetHrefs = unique(collectStylesheetHrefs(html)).filter(isLocalRootUrl);\n const literalDynamicImports = unique(collectLiteralDynamicImports(html)).filter(\n isLocalRootUrl,\n );\n\n for (const url of scriptSrcs) {\n if (!fileExistsForPublicUrl(root, pagesDir, url)) {\n reportMissing({\n mode: missingAssets,\n pluginName,\n kind: 'JavaScript asset',\n url,\n root,\n pagesDir,\n pageLabel,\n });\n }\n }\n\n for (const url of stylesheetHrefs) {\n if (!fileExistsForPublicUrl(root, pagesDir, url)) {\n reportMissing({\n mode: missingAssets,\n pluginName,\n kind: 'stylesheet asset',\n url,\n root,\n pagesDir,\n pageLabel,\n });\n }\n }\n\n for (const url of literalDynamicImports) {\n if (!fileExistsForPublicUrl(root, pagesDir, url)) {\n console.warn(\n `⚠️ ${missingAssetMessage({\n pluginName,\n kind: 'literal dynamic import',\n url,\n root,\n pagesDir,\n pageLabel,\n })}`,\n );\n }\n }\n}","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { CACHE_DIR_NAME } from './constants';\n\nexport type FetchCacheMode = 'auto' | 'memory' | 'fs' | 'none';\nexport interface FetchWithCacheOptions {\n maxAge?: number;\n cacheKey?: string;\n forceRefresh?: boolean;\n cache?: FetchCacheMode;\n}\n\ntype CachedResponseRecord = {\n timestamp: number;\n status: number;\n statusText: string;\n headers: [string, string][];\n body: string;\n};\n\nconst memoryCache = new Map<string, CachedResponseRecord>();\n\nfunction createDefaultCacheKey(\n input: RequestInfo | URL,\n init?: RequestInit,\n): string {\n const raw = JSON.stringify({\n url: String(input),\n method: init?.method ?? 'GET',\n headers: init?.headers ?? {},\n body: init?.body ?? null,\n });\n\n return createHash('sha256').update(raw).digest('hex');\n}\n\nfunction getCacheFilePath(cacheKey: string): string {\n return path.join(process.cwd(), CACHE_DIR_NAME, 'fetch', `${cacheKey}.json`);\n}\n\nfunction getEffectiveCacheMode(\n mode: FetchCacheMode | undefined,\n): Exclude<FetchCacheMode, 'auto'> {\n if (mode === 'memory' || mode === 'fs' || mode === 'none') {\n return mode;\n }\n\n return process.env.NODE_ENV === 'production' ? 'fs' : 'memory';\n}\n\nfunction toResponse(cached: CachedResponseRecord): Response {\n return new Response(cached.body, {\n status: cached.status,\n statusText: cached.statusText,\n headers: cached.headers,\n });\n}\n\nfunction isFresh(cached: CachedResponseRecord, maxAgeSeconds: number): boolean {\n const ageSeconds = (Date.now() - cached.timestamp) / 1000;\n return ageSeconds <= maxAgeSeconds;\n}\n\nexport function clearMemoryFetchCache(): void {\n memoryCache.clear();\n}\n\nexport function deleteMemoryFetchCache(cacheKey: string): void {\n memoryCache.delete(cacheKey);\n}\n\nexport async function fetchWithCache(\n input: RequestInfo | URL,\n init?: RequestInit,\n options: FetchWithCacheOptions = {},\n): Promise<Response> {\n const maxAge = options.maxAge ?? 60 * 60;\n const method = (init?.method ?? 'GET').toUpperCase();\n\n if (method !== 'GET' && !options.cacheKey) {\n return fetch(input, init);\n }\n\n const cacheMode = getEffectiveCacheMode(options.cache);\n const cacheKey = options.cacheKey ?? createDefaultCacheKey(input, init);\n\n if (cacheMode === 'none') {\n return fetch(input, init);\n }\n\n if (cacheMode === 'memory' && !options.forceRefresh) {\n const cached = memoryCache.get(cacheKey);\n\n if (cached && isFresh(cached, maxAge)) {\n return toResponse(cached);\n }\n }\n\n const filePath = getCacheFilePath(cacheKey);\n\n if (cacheMode === 'fs') {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n if (!options.forceRefresh) {\n try {\n const raw = await fs.readFile(filePath, 'utf8');\n const cached = JSON.parse(raw) as CachedResponseRecord;\n\n if (isFresh(cached, maxAge)) {\n return toResponse(cached);\n }\n } catch {\n // cache miss or invalid cache; fetch fresh\n }\n }\n }\n\n const res = await fetch(input, init);\n const body = await res.text();\n\n const record: CachedResponseRecord = {\n timestamp: Date.now(),\n status: res.status,\n statusText: res.statusText,\n headers: [...res.headers.entries()],\n body,\n };\n\n if (cacheMode === 'memory') {\n memoryCache.set(cacheKey, record);\n } else if (cacheMode === 'fs') {\n await fs.writeFile(filePath, JSON.stringify(record), 'utf8');\n }\n\n return new Response(body, {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n}\n"],"mappings":"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","names":["path","fg","path","path","path","path","fs","path","build","fs","path","fs","path","fs","path","path","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-html-pages",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "author": "Paul Browne",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,176 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export interface HtmlAssetValidationOptions {
5
+ root: string;
6
+ pagesDir: string;
7
+ html: string;
8
+ pluginName: string;
9
+ pageLabel?: string;
10
+ missingAssets?: 'error' | 'warn';
11
+ }
12
+
13
+ function stripQueryAndHash(url: string): string {
14
+ return url.split('#')[0].split('?')[0];
15
+ }
16
+
17
+ function isLocalRootUrl(url: string): boolean {
18
+ return !!url && url.startsWith('/') && !url.startsWith('//');
19
+ }
20
+
21
+ function fileExistsForPublicUrl(root: string, pagesDir: string, url: string): boolean {
22
+ const clean = stripQueryAndHash(url).slice(1);
23
+
24
+ const fromSrc = path.join(root, pagesDir, clean);
25
+ if (fs.existsSync(fromSrc)) return true;
26
+
27
+ const fromPublic = path.join(root, 'public', clean);
28
+ if (fs.existsSync(fromPublic)) return true;
29
+
30
+ return false;
31
+ }
32
+
33
+ function collectScriptSrcs(html: string): string[] {
34
+ const out: string[] = [];
35
+
36
+ for (const match of html.matchAll(
37
+ /<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/gi,
38
+ )) {
39
+ out.push(match[1]);
40
+ }
41
+
42
+ return out;
43
+ }
44
+
45
+ function collectStylesheetHrefs(html: string): string[] {
46
+ const out: string[] = [];
47
+
48
+ for (const match of html.matchAll(
49
+ /<link\b[^>]*\brel=["']stylesheet["'][^>]*\bhref=["']([^"']+)["'][^>]*>/gi,
50
+ )) {
51
+ out.push(match[1]);
52
+ }
53
+
54
+ return out;
55
+ }
56
+
57
+ function collectLiteralDynamicImports(html: string): string[] {
58
+ const out: string[] = [];
59
+
60
+ for (const match of html.matchAll(
61
+ /import\s*\(\s*["']([^"'`]+)["']\s*\)/gi,
62
+ )) {
63
+ out.push(match[1]);
64
+ }
65
+
66
+ return out;
67
+ }
68
+
69
+ function unique(values: string[]): string[] {
70
+ return [...new Set(values)];
71
+ }
72
+
73
+ function formatPageLabel(pageLabel?: string): string {
74
+ return pageLabel ? ` (${pageLabel})` : '';
75
+ }
76
+
77
+ function missingAssetMessage(args: {
78
+ pluginName: string;
79
+ kind: string;
80
+ url: string;
81
+ root: string;
82
+ pagesDir: string;
83
+ pageLabel?: string;
84
+ }): string {
85
+ const { pluginName, kind, url, root, pagesDir, pageLabel } = args;
86
+ const clean = stripQueryAndHash(url).slice(1);
87
+ const pageSuffix = formatPageLabel(pageLabel);
88
+
89
+ return (
90
+ `[${pluginName}] Missing ${kind}${pageSuffix}: ${url}\n` +
91
+ `Expected one of:\n` +
92
+ `- ${path.join(root, pagesDir, clean)}\n` +
93
+ `- ${path.join(root, 'public', clean)}`
94
+ );
95
+ }
96
+
97
+ function reportMissing(args: {
98
+ mode: 'error' | 'warn';
99
+ pluginName: string;
100
+ kind: string;
101
+ url: string;
102
+ root: string;
103
+ pagesDir: string;
104
+ pageLabel?: string;
105
+ }) {
106
+ const message = missingAssetMessage(args);
107
+
108
+ if (args.mode === 'warn') {
109
+ console.warn(`⚠️ ${message}`);
110
+ return;
111
+ }
112
+
113
+ throw new Error(message);
114
+ }
115
+
116
+ export function validateHtmlAssetReferences(
117
+ options: HtmlAssetValidationOptions,
118
+ ): void {
119
+ const {
120
+ root,
121
+ pagesDir,
122
+ html,
123
+ pluginName,
124
+ pageLabel,
125
+ missingAssets = 'error',
126
+ } = options;
127
+
128
+ const scriptSrcs = unique(collectScriptSrcs(html)).filter(isLocalRootUrl);
129
+ const stylesheetHrefs = unique(collectStylesheetHrefs(html)).filter(isLocalRootUrl);
130
+ const literalDynamicImports = unique(collectLiteralDynamicImports(html)).filter(
131
+ isLocalRootUrl,
132
+ );
133
+
134
+ for (const url of scriptSrcs) {
135
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
136
+ reportMissing({
137
+ mode: missingAssets,
138
+ pluginName,
139
+ kind: 'JavaScript asset',
140
+ url,
141
+ root,
142
+ pagesDir,
143
+ pageLabel,
144
+ });
145
+ }
146
+ }
147
+
148
+ for (const url of stylesheetHrefs) {
149
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
150
+ reportMissing({
151
+ mode: missingAssets,
152
+ pluginName,
153
+ kind: 'stylesheet asset',
154
+ url,
155
+ root,
156
+ pagesDir,
157
+ pageLabel,
158
+ });
159
+ }
160
+ }
161
+
162
+ for (const url of literalDynamicImports) {
163
+ if (!fileExistsForPublicUrl(root, pagesDir, url)) {
164
+ console.warn(
165
+ `⚠️ ${missingAssetMessage({
166
+ pluginName,
167
+ kind: 'literal dynamic import',
168
+ url,
169
+ root,
170
+ pagesDir,
171
+ pageLabel,
172
+ })}`,
173
+ );
174
+ }
175
+ }
176
+ }
package/src/plugin.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  collectStaticAssets,
12
12
  copyStaticAssetSource,
13
13
  } from './static-assets';
14
-
14
+ import { validateHtmlAssetReferences } from './html-asset-validator';
15
15
  import type { HtPageInfo, HtPageModule, HtPagesPluginOptions } from './types';
16
16
  import { PLUGIN_NAME, VIRTUAL_BUILD_ENTRY_ID } from './constants';
17
17
 
@@ -213,11 +213,16 @@ export function htPages(options: HtPagesPluginOptions = {}): Plugin {
213
213
 
214
214
  async handleHotUpdate(ctx) {
215
215
  if (!server) return;
216
-
216
+
217
217
  logDebug(options.debug, 'file changed', ctx.file);
218
-
218
+
219
219
  await loadDevPages();
220
- return undefined;
220
+
221
+ server.ws.send({
222
+ type: 'full-reload',
223
+ });
224
+
225
+ return [];
221
226
  },
222
227
 
223
228
  async generateBundle(_, bundle) {
@@ -293,6 +298,15 @@ export function htPages(options: HtPagesPluginOptions = {}): Plugin {
293
298
 
294
299
  const html = await renderPage(page, mod, false);
295
300
 
301
+ validateHtmlAssetReferences({
302
+ root,
303
+ pagesDir,
304
+ html,
305
+ pluginName: PLUGIN_NAME,
306
+ pageLabel: page.relativePath,
307
+ missingAssets: options.missingAssets ?? 'error',
308
+ });
309
+
296
310
  this.emitFile({
297
311
  type: 'asset',
298
312
  fileName: options.mapOutputPath?.(page) ?? page.fileName,
@@ -316,6 +330,15 @@ export function htPages(options: HtPagesPluginOptions = {}): Plugin {
316
330
 
317
331
  const html = await renderPage(notFoundPage, mod, false);
318
332
 
333
+ validateHtmlAssetReferences({
334
+ root,
335
+ pagesDir,
336
+ html,
337
+ pluginName: PLUGIN_NAME,
338
+ pageLabel: notFoundPage.relativePath,
339
+ missingAssets: options.missingAssets ?? 'error',
340
+ });
341
+
319
342
  this.emitFile({
320
343
  type: 'asset',
321
344
  fileName: '404.html',
package/src/types.ts CHANGED
@@ -49,6 +49,7 @@ export interface HtPagesPluginOptions {
49
49
  mapOutputPath?: (page: HtPageInfo) => string;
50
50
  debug?: boolean;
51
51
  site?: string;
52
+ missingAssets?: 'error' | 'warn';
52
53
  rss?: {
53
54
  site: string;
54
55
  title?: string;