vite-plugin-htjs-pages 0.5.2 → 0.5.4

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.js CHANGED
@@ -185,7 +185,7 @@ function installDevServer(args) {
185
185
  server.middlewares.use(async (req, res, next) => {
186
186
  if (!req.url || req.method !== "GET") return next();
187
187
  const pathname = req.url.split("?")[0];
188
- const pages = getPages();
188
+ const pages = await getPages();
189
189
  for (const page of pages) {
190
190
  const params = routeMatch(page.routePattern, pathname);
191
191
  if (!params) continue;
@@ -262,6 +262,7 @@ ${records}
262
262
  }
263
263
 
264
264
  // src/render-bundle.ts
265
+ import { nodeResolve } from "@rollup/plugin-node-resolve";
265
266
  var VIRTUAL_MANIFEST_ID = "\0virtual:htjs-pages-manifest";
266
267
  async function buildRenderBundle(args) {
267
268
  const { entries, cacheDir, ssrPlugins = [] } = args;
@@ -281,6 +282,9 @@ async function buildRenderBundle(args) {
281
282
  return id === VIRTUAL_MANIFEST_ID ? source : null;
282
283
  }
283
284
  },
285
+ nodeResolve({
286
+ preferBuiltins: true
287
+ }),
284
288
  ...ssrPlugins
285
289
  ],
286
290
  treeshake: true
@@ -334,11 +338,11 @@ function htPages(options = {}) {
334
338
  }
335
339
  return {
336
340
  name: "vite-plugin-htjs-pages",
337
- config(userConfig) {
341
+ config(userConfig, env) {
342
+ if (env.command !== "build") return;
338
343
  const hasExplicitInput = userConfig.build?.rollupOptions?.input != null;
339
344
  if (hasExplicitInput) return;
340
345
  return {
341
- appType: "custom",
342
346
  build: {
343
347
  rollupOptions: {
344
348
  input: VIRTUAL_BUILD_ENTRY_ID
@@ -369,7 +373,10 @@ function htPages(options = {}) {
369
373
  server = _server;
370
374
  installDevServer({
371
375
  server,
372
- getPages: () => devPages
376
+ getPages: async () => {
377
+ if (devPages.length > 0) return devPages;
378
+ return await loadDevPages();
379
+ }
373
380
  });
374
381
  loadDevPages().catch((error) => {
375
382
  server?.config.logger.error(String(error));
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/errors.ts","../src/render-runtime.ts","../src/dev-server.ts","../src/page-index.ts","../src/render-bundle.ts","../src/manifest.ts"],"sourcesContent":["import path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { createHash } from 'node:crypto';\nimport pLimit from 'p-limit';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport { discoverEntryPages } from './discover';\nimport { installDevServer } from './dev-server';\nimport { buildPageIndex } from './page-index';\nimport { buildRenderBundle } from './render-bundle';\nimport { renderPage } from './render-runtime';\nimport type { HtPageInfo, HtPageModule, HtPagesPluginOptions } from './types';\n\nconst VIRTUAL_BUILD_ENTRY_ID = '\\0vite-plugin-htjs-pages:build-entry';\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\nfunction createEntriesKey(entries: HtPageInfo[]): string {\n const raw = entries\n .map((e) => `${e.entryPath}|${e.routePattern}|${e.dynamic}`)\n .join('\\n');\n\n return createHash('sha256').update(raw).digest('hex');\n}\n\nasync function importManifest(bundlePath: string): Promise<Array<{ page: HtPageInfo; mod: HtPageModule }>> {\n const mod = await import(pathToFileURL(bundlePath).href + `?t=${Date.now()}`);\n return mod.manifest as Array<{ page: HtPageInfo; mod: HtPageModule }>;\n}\n\nexport function htPages(options: HtPagesPluginOptions = {}): Plugin {\n let root = process.cwd();\n let server: ViteDevServer | null = null;\n let devPages: HtPageInfo[] = [];\n const cleanUrls = options.cleanUrls ?? true;\n\n async function loadDevPages(): Promise<HtPageInfo[]> {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n if (!server) return [];\n\n for (const entry of entries) {\n const mod = (await server.ssrLoadModule(entry.entryPath)) as HtPageModule;\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n devPages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n return devPages;\n }\n\n return {\n name: 'vite-plugin-htjs-pages',\n\n config(userConfig) {\n const hasExplicitInput =\n userConfig.build?.rollupOptions?.input != null;\n\n if (hasExplicitInput) return;\n\n return {\n appType: 'custom',\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\n async buildStart() {\n const entries = await discoverEntryPages(root, options);\n for (const entry of entries) {\n this.addWatchFile(entry.entryPath);\n }\n },\n\n configureServer(_server) {\n server = _server;\n\n installDevServer({\n server,\n getPages: () => devPages,\n });\n\n loadDevPages().catch((error) => {\n server?.config.logger.error(String(error));\n });\n\n return () => {\n server = null;\n };\n },\n\n async handleHotUpdate() {\n if (server) {\n await loadDevPages();\n }\n return undefined;\n },\n\n async generateBundle() {\n const entries = await discoverEntryPages(root, options);\n const cacheDir = path.join(root, 'node_modules/.cache/vite-plugin-htjs-pages');\n const bundlePath = await buildRenderBundle({\n entries,\n cacheDir,\n ssrPlugins: options.ssrPlugins,\n });\n\n const manifest = await importManifest(bundlePath);\n const modulesByEntry = new Map<string, HtPageModule>();\n for (const rec of manifest) {\n modulesByEntry.set(rec.page.entryPath, rec.mod);\n }\n\n const pages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n const limit = pLimit(options.renderConcurrency ?? 8);\n const batchSize = options.renderBatchSize ?? Math.max(options.renderConcurrency ?? 8, 32);\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 if (!mod) throw new Error(`Missing module for page entry: ${page.entryPath}`);\n const html = await renderPage(page, mod, false);\n this.emitFile({\n type: 'asset',\n fileName: options.mapOutputPath?.(page) ?? page.fileName,\n source: html,\n });\n }),\n ),\n );\n }\n },\n };\n}","import path from 'node:path';\nimport fg from 'fast-glob';\nimport { normalizeFsPath, toPosix } from './path-utils';\nimport { getParamNames, isDynamicPage, toRoutePattern } from './route-utils';\nimport type { HtPageInfo, HtPagesPluginOptions } from './types';\n\nexport async function discoverEntryPages(root: string, options: HtPagesPluginOptions): Promise<HtPageInfo[]> {\n const include = Array.isArray(options.include) ? options.include : [options.include ?? 'src/**/*.ht.js'];\n const exclude = Array.isArray(options.exclude) ? options.exclude : options.exclude ? [options.exclude] : [];\n const pagesDir = options.pagesDir ?? 'src';\n\n const files = await fg(include, {\n cwd: root,\n ignore: exclude,\n absolute: true,\n });\n\n return files.sort().map((absolutePath) => {\n const entryPath = normalizeFsPath(absolutePath);\n const relativePath = toPosix(path.relative(root, entryPath));\n const relativeFromPagesDir = toPosix(path.relative(path.join(root, pagesDir), entryPath));\n const dynamic = isDynamicPage(relativeFromPagesDir);\n const routePattern = toRoutePattern(relativeFromPagesDir);\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 };\n });\n}","import path from 'node:path';\n\nexport function toPosix(p: string): string {\n return p.split(path.sep).join('/');\n}\n\nexport function stripHtSuffix(file: string): string {\n return file.replace(/\\.ht\\.js$/i, '');\n}\n\nexport function normalizeRoutePath(p: string): string {\n let out = p.startsWith('/') ? p : `/${p}`;\n out = out.replace(/\\/+/g, '/');\n if (out !== '/' && out.endsWith('/')) out = out.slice(0, -1);\n return out;\n}\n\nexport function normalizeFsPath(p: string): string {\n return toPosix(path.resolve(p));\n}","import { normalizeRoutePath, stripHtSuffix, 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 ANY_PARAM_RE = /\\[(?:\\.\\.\\.)?([A-Za-z0-9_]+)\\]/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 ANY_PARAM_RE.test(relativeFromPagesDir);\n}\n\nexport function toRoutePattern(relativeFromPagesDir: string): string {\n const noExt = stripHtSuffix(toPosix(relativeFromPagesDir));\n const raw = noExt\n .replace(/(^|\\/)index$/i, '$1')\n .replace(CATCH_ALL_SEGMENT_RE, '*:$1')\n .replace(DYNAMIC_SEGMENT_RE, ':$1');\n return normalizeRoutePath(raw || '/');\n}\n\nexport function fillParams(pattern: string, params: Record<string, string>): string {\n return pattern\n .replace(/\\*:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) throw new Error(`Missing catch-all route param \"${key}\"`);\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)) throw new Error(`Missing route param \"${key}\"`);\n return encodeURIComponent(params[key]);\n });\n}\n\nexport function fileNameFromRoute(routePath: string, cleanUrls: boolean): string {\n const normalized = normalizeRoutePath(routePath);\n if (normalized === '/') return 'index.html';\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 const routePath = fillParams(basePage.routePattern, params);\n return {\n ...basePage,\n routePath,\n fileName: fileNameFromRoute(routePath, cleanUrls),\n params,\n };\n });\n}\n\nexport function routeMatch(pattern: string, urlPath: string): 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, j = 0; i < a.length; i++, j++) {\n const seg = a[i];\n\n if (seg.startsWith('*:')) {\n params[seg.slice(2)] = b.slice(j).map(decodeURIComponent).join('/');\n return params;\n }\n\n if (j >= b.length) return null;\n\n if (seg.startsWith(':')) {\n params[seg.slice(1)] = decodeURIComponent(b[j]);\n continue;\n }\n\n if (seg !== b[j]) 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 aCatchAll = aa.startsWith('*:');\n const bCatchAll = bb.startsWith('*:');\n if (aCatchAll !== bCatchAll) return aCatchAll ? 1 : -1;\n\n const aDynamic = aa.startsWith(':');\n const bDynamic = bb.startsWith(':');\n if (aDynamic !== bDynamic) return aDynamic ? 1 : -1;\n }\n\n return aSegs.length - bSegs.length;\n}","import type { HtPageInfo } from './types';\n\nexport function invalidHtmlReturn(page: HtPageInfo, value: unknown): Error {\n return new Error(\n `[vite-plugin-htjs-pages] Page \"${page.relativePath}\" must resolve to an HTML string, got ${typeof value}`,\n );\n}\n\nexport function pageError(page: HtPageInfo, cause: unknown): Error {\n const message = `[vite-plugin-htjs-pages] Failed to render ${page.relativePath} (${page.routePath})`;\n if (cause instanceof Error && cause.stack) {\n const err = new Error(message);\n err.stack = `${err.stack}\nCaused by:\n${cause.stack}`;\n return err;\n }\n return new Error(message);\n}","import { invalidHtmlReturn, pageError } from './errors';\nimport type { HtPageInfo, HtPageModule, HtPageRenderContext } from './types';\n\nexport async function renderPage(page: HtPageInfo, mod: HtPageModule, dev = false): 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 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 type { ViteDevServer } from 'vite';\nimport { renderPage } from './render-runtime';\nimport { routeMatch } from './route-utils';\nimport type { HtPageInfo, HtPageModule } from './types';\n\nexport function installDevServer(args: {\n server: ViteDevServer;\n getPages: () => HtPageInfo[];\n}): void {\n const { server, getPages } = args;\n\n server.middlewares.use(async (req, res, next) => {\n if (!req.url || req.method !== 'GET') return next();\n\n const pathname = req.url.split('?')[0];\n const pages = getPages();\n\n for (const page of pages) {\n const params = routeMatch(page.routePattern, pathname);\n if (!params) continue;\n\n const mod = (await server.ssrLoadModule(page.entryPath)) as HtPageModule;\n const resolvedPage = { ...page, routePath: pathname || '/', params };\n const html = await renderPage(resolvedPage, mod, true);\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(html);\n return;\n }\n\n next();\n });\n}","import { compareRoutePriority, expandStaticPaths, fileNameFromRoute } from './route-utils';\nimport type { HtPageInfo, HtPageModule, StaticParamRecord } from './types';\n\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 = mod.generateStaticParams ? await mod.generateStaticParams() : [];\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 rows as StaticParamRecord[],\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 return pages;\n}","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { rollup, type Plugin as RollupPlugin } from 'rollup';\nimport { createManifestModule } from './manifest';\nimport type { HtPageInfo } from './types';\n\nconst VIRTUAL_MANIFEST_ID = '\\0virtual:htjs-pages-manifest';\n\nexport async function buildRenderBundle(args: {\n entries: HtPageInfo[];\n cacheDir: string;\n ssrPlugins?: RollupPlugin[];\n}): Promise<string> {\n const { entries, cacheDir, ssrPlugins = [] } = args;\n const source = createManifestModule(entries);\n const hash = createHash('sha256').update(source).digest('hex').slice(0, 12);\n const bundlePath = path.join(cacheDir, `render-${hash}.mjs`);\n\n await fs.mkdir(cacheDir, { recursive: true });\n\n const bundle = await rollup({\n input: VIRTUAL_MANIFEST_ID,\n plugins: [\n {\n name: 'htjs-pages:virtual-manifest',\n resolveId(id) {\n return id === VIRTUAL_MANIFEST_ID ? id : null;\n },\n load(id) {\n return id === VIRTUAL_MANIFEST_ID ? source : null;\n },\n },\n ...ssrPlugins,\n ],\n treeshake: true,\n });\n\n const { output } = await bundle.generate({\n format: 'esm',\n exports: 'named',\n inlineDynamicImports: true,\n });\n\n const chunk = output.find((item) => item.type === 'chunk');\n if (!chunk || chunk.type !== 'chunk') {\n throw new Error('Failed to generate HT pages render bundle.');\n }\n\n await fs.writeFile(bundlePath, chunk.code, 'utf8');\n await bundle.close();\n return bundlePath;\n}","import type { HtPageInfo } from './types';\n\nfunction js(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport function createManifestModule(entries: HtPageInfo[]): string {\n const imports = entries\n .map((page, i) => `import * as page${i} from ${js(page.entryPath)};`)\n .join('');\n\n const records = entries\n .map((page, i) => `{\n page: ${js(page)},\n mod: page${i}\n}`)\n .join(',');\n\n return `${imports}\n\nexport const manifest = [\n${records}\n];\n`;\n}"],"mappings":";AAAA,OAAOA,WAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,cAAAC,mBAAkB;AAC3B,OAAO,YAAY;;;ACHnB,OAAOC,WAAU;AACjB,OAAO,QAAQ;;;ACDf,OAAO,UAAU;AAEV,SAAS,QAAQ,GAAmB;AACzC,SAAO,EAAE,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACnC;AAEO,SAAS,cAAc,MAAsB;AAClD,SAAO,KAAK,QAAQ,cAAc,EAAE;AACtC;AAEO,SAAS,mBAAmB,GAAmB;AACpD,MAAI,MAAM,EAAE,WAAW,GAAG,IAAI,IAAI,IAAI,CAAC;AACvC,QAAM,IAAI,QAAQ,QAAQ,GAAG;AAC7B,MAAI,QAAQ,OAAO,IAAI,SAAS,GAAG,EAAG,OAAM,IAAI,MAAM,GAAG,EAAE;AAC3D,SAAO;AACT;AAEO,SAAS,gBAAgB,GAAmB;AACjD,SAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAChC;;;AChBA,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAC7B,IAAM,eAAe;AAEd,SAAS,cAAc,sBAAwC;AACpE,SAAO,CAAC,GAAG,qBAAqB,SAAS,YAAY,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACzE;AAEO,SAAS,cAAc,sBAAuC;AACnE,SAAO,aAAa,KAAK,oBAAoB;AAC/C;AAEO,SAAS,eAAe,sBAAsC;AACnE,QAAM,QAAQ,cAAc,QAAQ,oBAAoB,CAAC;AACzD,QAAM,MAAM,MACT,QAAQ,iBAAiB,IAAI,EAC7B,QAAQ,sBAAsB,MAAM,EACpC,QAAQ,oBAAoB,KAAK;AACpC,SAAO,mBAAmB,OAAO,GAAG;AACtC;AAEO,SAAS,WAAW,SAAiB,QAAwC;AAClF,SAAO,QACJ,QAAQ,uBAAuB,CAAC,GAAG,QAAQ;AAC1C,QAAI,EAAE,OAAO,QAAS,OAAM,IAAI,MAAM,kCAAkC,GAAG,GAAG;AAC9E,WAAO,OAAO,OAAO,GAAG,CAAC,EACtB,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,mBAAmB,IAAI,CAAC,EACtC,KAAK,GAAG;AAAA,EACb,CAAC,EACA,QAAQ,qBAAqB,CAAC,GAAG,QAAQ;AACxC,QAAI,EAAE,OAAO,QAAS,OAAM,IAAI,MAAM,wBAAwB,GAAG,GAAG;AACpE,WAAO,mBAAmB,OAAO,GAAG,CAAC;AAAA,EACvC,CAAC;AACL;AAEO,SAAS,kBAAkB,WAAmB,WAA4B;AAC/E,QAAM,aAAa,mBAAmB,SAAS;AAC/C,MAAI,eAAe,IAAK,QAAO;AAC/B,QAAM,OAAO,WAAW,MAAM,CAAC;AAC/B,SAAO,YAAY,GAAG,IAAI,gBAAgB,GAAG,IAAI;AACnD;AAEO,SAAS,kBACd,UACA,MACA,WACc;AACd,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAM,SAAS,OAAO;AAAA,MACpB,OAAO,QAAQ,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;AAAA,IACpD;AACA,UAAM,YAAY,WAAW,SAAS,cAAc,MAAM;AAC1D,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,UAAU,kBAAkB,WAAW,SAAS;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,WAAW,SAAiB,SAAgD;AAC1F,QAAM,IAAI,mBAAmB,OAAO,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/D,QAAM,IAAI,mBAAmB,OAAO,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/D,QAAM,SAAiC,CAAC;AAExC,WAAS,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,KAAK;AAC7C,UAAM,MAAM,EAAE,CAAC;AAEf,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,aAAO,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG;AAClE,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,EAAE,OAAQ,QAAO;AAE1B,QAAI,IAAI,WAAW,GAAG,GAAG;AACvB,aAAO,IAAI,MAAM,CAAC,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;AAC9C;AAAA,IACF;AAEA,QAAI,QAAQ,EAAE,CAAC,EAAG,QAAO;AAAA,EAC3B;AAEA,SAAO,EAAE,WAAW,EAAE,SAAS,SAAS;AAC1C;AAEO,SAAS,qBAAqB,GAAW,GAAmB;AACjE,QAAM,QAAQ,mBAAmB,CAAC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC7D,QAAM,QAAQ,mBAAmB,CAAC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AAC7D,QAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,MAAM;AAE/C,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAM,KAAK,MAAM,CAAC;AAClB,UAAM,KAAK,MAAM,CAAC;AAElB,QAAI,MAAM,KAAM,QAAO;AACvB,QAAI,MAAM,KAAM,QAAO;AAEvB,UAAM,YAAY,GAAG,WAAW,IAAI;AACpC,UAAM,YAAY,GAAG,WAAW,IAAI;AACpC,QAAI,cAAc,UAAW,QAAO,YAAY,IAAI;AAEpD,UAAM,WAAW,GAAG,WAAW,GAAG;AAClC,UAAM,WAAW,GAAG,WAAW,GAAG;AAClC,QAAI,aAAa,SAAU,QAAO,WAAW,IAAI;AAAA,EACnD;AAEA,SAAO,MAAM,SAAS,MAAM;AAC9B;;;AF3GA,eAAsB,mBAAmB,MAAc,SAAsD;AAC3G,QAAM,UAAU,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,CAAC,QAAQ,WAAW,gBAAgB;AACvG,QAAM,UAAU,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,QAAQ,UAAU,CAAC,QAAQ,OAAO,IAAI,CAAC;AAC1G,QAAM,WAAW,QAAQ,YAAY;AAErC,QAAM,QAAQ,MAAM,GAAG,SAAS;AAAA,IAC9B,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,CAAC;AAED,SAAO,MAAM,KAAK,EAAE,IAAI,CAAC,iBAAiB;AACxC,UAAM,YAAY,gBAAgB,YAAY;AAC9C,UAAM,eAAe,QAAQC,MAAK,SAAS,MAAM,SAAS,CAAC;AAC3D,UAAM,uBAAuB,QAAQA,MAAK,SAASA,MAAK,KAAK,MAAM,QAAQ,GAAG,SAAS,CAAC;AACxF,UAAM,UAAU,cAAc,oBAAoB;AAClD,UAAM,eAAe,eAAe,oBAAoB;AAExD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,UAAU;AAAA,MACV;AAAA,MACA,YAAY,cAAc,oBAAoB;AAAA,MAC9C,QAAQ,CAAC;AAAA,IACX;AAAA,EACF,CAAC;AACH;;;AGnCO,SAAS,kBAAkB,MAAkB,OAAuB;AACzE,SAAO,IAAI;AAAA,IACT,kCAAkC,KAAK,YAAY,yCAAyC,OAAO,KAAK;AAAA,EAC1G;AACF;AAEO,SAAS,UAAU,MAAkB,OAAuB;AACjE,QAAM,UAAU,6CAA6C,KAAK,YAAY,KAAK,KAAK,SAAS;AACjG,MAAI,iBAAiB,SAAS,MAAM,OAAO;AACzC,UAAM,MAAM,IAAI,MAAM,OAAO;AAC7B,QAAI,QAAQ,GAAG,IAAI,KAAK;AAAA;AAAA,EAE1B,MAAM,KAAK;AACT,WAAO;AAAA,EACT;AACA,SAAO,IAAI,MAAM,OAAO;AAC1B;;;ACfA,eAAsB,WAAW,MAAkB,KAAmB,MAAM,OAAwB;AAClG,QAAM,MAA2B;AAAA,IAC/B;AAAA,IACA,QAAQ,KAAK;AAAA,IACb;AAAA,EACF;AAEA,MAAI;AACF,QAAI,OAAO,IAAI,SAAS,YAAY;AAClC,UAAI,OAAO,MAAM,IAAI,KAAK,GAAG;AAAA,IAC/B;AAEA,UAAM,QAAQ,IAAI;AAClB,UAAM,OAAO,OAAO,UAAU,aAAa,MAAM,MAAM,GAAG,IAAI;AAE9D,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,kBAAkB,MAAM,IAAI;AAAA,IACpC;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,MAAM,KAAK;AAAA,EAC7B;AACF;;;ACrBO,SAAS,iBAAiB,MAGxB;AACP,QAAM,EAAE,QAAQ,SAAS,IAAI;AAE7B,SAAO,YAAY,IAAI,OAAO,KAAK,KAAK,SAAS;AAC/C,QAAI,CAAC,IAAI,OAAO,IAAI,WAAW,MAAO,QAAO,KAAK;AAElD,UAAM,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC;AACrC,UAAM,QAAQ,SAAS;AAEvB,eAAW,QAAQ,OAAO;AACxB,YAAM,SAAS,WAAW,KAAK,cAAc,QAAQ;AACrD,UAAI,CAAC,OAAQ;AAEb,YAAM,MAAO,MAAM,OAAO,cAAc,KAAK,SAAS;AACtD,YAAM,eAAe,EAAE,GAAG,MAAM,WAAW,YAAY,KAAK,OAAO;AACnE,YAAM,OAAO,MAAM,WAAW,cAAc,KAAK,IAAI;AAErD,UAAI,aAAa;AACjB,UAAI,UAAU,gBAAgB,0BAA0B;AACxD,UAAI,IAAI,IAAI;AACZ;AAAA,IACF;AAEA,SAAK;AAAA,EACP,CAAC;AACH;;;AC9BA,eAAsB,eAAe,MAIX;AACxB,QAAM,EAAE,SAAS,gBAAgB,UAAU,IAAI;AAC/C,QAAM,QAAsB,CAAC;AAE7B,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAM,eAAe,IAAI,MAAM,SAAS,KAAK,CAAC;AAEpD,QAAI,MAAM,SAAS;AACjB,YAAM,OAAO,IAAI,uBAAuB,MAAM,IAAI,qBAAqB,IAAI,CAAC;AAC5E,YAAM;AAAA,QACJ,GAAG;AAAA,UACD;AAAA,YACE,IAAI,MAAM;AAAA,YACV,WAAW,MAAM;AAAA,YACjB,cAAc,MAAM;AAAA,YACpB,cAAc,MAAM;AAAA,YACpB,cAAc,MAAM;AAAA,YACpB,SAAS,MAAM;AAAA,YACf,YAAY,MAAM;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,KAAK;AAAA,QACT,GAAG;AAAA,QACH,WAAW,MAAM;AAAA,QACjB,UAAU,kBAAkB,MAAM,cAAc,SAAS;AAAA,QACzD,QAAQ,CAAC;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM,qBAAqB,EAAE,cAAc,EAAE,YAAY,CAAC;AACzE,SAAO;AACT;;;AC3CA,OAAOC,WAAU;AACjB,OAAO,QAAQ;AACf,SAAS,kBAAkB;AAC3B,SAAS,cAA2C;;;ACDpD,SAAS,GAAG,OAAwB;AAClC,SAAO,KAAK,UAAU,KAAK;AAC7B;AAEO,SAAS,qBAAqB,SAA+B;AAClE,QAAM,UAAU,QACb,IAAI,CAAC,MAAM,MAAM,mBAAmB,CAAC,SAAS,GAAG,KAAK,SAAS,CAAC,GAAG,EACnE,KAAK,EAAE;AAEV,QAAM,UAAU,QACb,IAAI,CAAC,MAAM,MAAM;AAAA,UACZ,GAAG,IAAI,CAAC;AAAA,aACL,CAAC;AAAA,EACZ,EACG,KAAK,GAAG;AAEX,SAAO,GAAG,OAAO;AAAA;AAAA;AAAA,EAGjB,OAAO;AAAA;AAAA;AAGT;;;ADjBA,IAAM,sBAAsB;AAE5B,eAAsB,kBAAkB,MAIpB;AAClB,QAAM,EAAE,SAAS,UAAU,aAAa,CAAC,EAAE,IAAI;AAC/C,QAAM,SAAS,qBAAqB,OAAO;AAC3C,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC1E,QAAM,aAAaC,MAAK,KAAK,UAAU,UAAU,IAAI,MAAM;AAE3D,QAAM,GAAG,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAE5C,QAAM,SAAS,MAAM,OAAO;AAAA,IAC1B,OAAO;AAAA,IACP,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,UAAU,IAAI;AACZ,iBAAO,OAAO,sBAAsB,KAAK;AAAA,QAC3C;AAAA,QACA,KAAK,IAAI;AACP,iBAAO,OAAO,sBAAsB,SAAS;AAAA,QAC/C;AAAA,MACF;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,WAAW;AAAA,EACb,CAAC;AAED,QAAM,EAAE,OAAO,IAAI,MAAM,OAAO,SAAS;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,sBAAsB;AAAA,EACxB,CAAC;AAED,QAAM,QAAQ,OAAO,KAAK,CAAC,SAAS,KAAK,SAAS,OAAO;AACzD,MAAI,CAAC,SAAS,MAAM,SAAS,SAAS;AACpC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAEA,QAAM,GAAG,UAAU,YAAY,MAAM,MAAM,MAAM;AACjD,QAAM,OAAO,MAAM;AACnB,SAAO;AACT;;;ARxCA,IAAM,yBAAyB;AAE/B,SAAS,WAAc,OAAY,MAAqB;AACtD,QAAM,MAAa,CAAC;AACpB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM;AAC3C,QAAI,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACnC;AACA,SAAO;AACT;AAUA,eAAe,eAAe,YAA6E;AACzG,QAAM,MAAM,MAAM,OAAO,cAAc,UAAU,EAAE,OAAO,MAAM,KAAK,IAAI,CAAC;AAC1E,SAAO,IAAI;AACb;AAEO,SAAS,QAAQ,UAAgC,CAAC,GAAW;AAClE,MAAI,OAAO,QAAQ,IAAI;AACvB,MAAI,SAA+B;AACnC,MAAI,WAAyB,CAAC;AAC9B,QAAM,YAAY,QAAQ,aAAa;AAEvC,iBAAe,eAAsC;AACnD,UAAM,UAAU,MAAM,mBAAmB,MAAM,OAAO;AACtD,UAAM,iBAAiB,oBAAI,IAA0B;AAErD,QAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,eAAW,SAAS,SAAS;AAC3B,YAAM,MAAO,MAAM,OAAO,cAAc,MAAM,SAAS;AACvD,qBAAe,IAAI,MAAM,WAAW,GAAG;AAAA,IACzC;AAEA,eAAW,MAAM,eAAe;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,OAAO,YAAY;AACjB,YAAM,mBACJ,WAAW,OAAO,eAAe,SAAS;AAE5C,UAAI,iBAAkB;AAEtB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,UACL,eAAe;AAAA,YACb,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,UAAU,IAAI;AACZ,UAAI,OAAO,uBAAwB,QAAO;AAC1C,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,IAAI;AACP,UAAI,OAAO,wBAAwB;AACjC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,UAAU;AACvB,aAAO,SAAS;AAAA,IAClB;AAAA,IAEA,MAAM,aAAa;AACjB,YAAM,UAAU,MAAM,mBAAmB,MAAM,OAAO;AACtD,iBAAW,SAAS,SAAS;AAC3B,aAAK,aAAa,MAAM,SAAS;AAAA,MACnC;AAAA,IACF;AAAA,IAEA,gBAAgB,SAAS;AACvB,eAAS;AAET,uBAAiB;AAAA,QACf;AAAA,QACA,UAAU,MAAM;AAAA,MAClB,CAAC;AAED,mBAAa,EAAE,MAAM,CAAC,UAAU;AAC9B,gBAAQ,OAAO,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,MAC3C,CAAC;AAED,aAAO,MAAM;AACX,iBAAS;AAAA,MACX;AAAA,IACF;AAAA,IAEA,MAAM,kBAAkB;AACtB,UAAI,QAAQ;AACV,cAAM,aAAa;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,iBAAiB;AACrB,YAAM,UAAU,MAAM,mBAAmB,MAAM,OAAO;AACtD,YAAM,WAAWC,MAAK,KAAK,MAAM,4CAA4C;AAC7E,YAAM,aAAa,MAAM,kBAAkB;AAAA,QACzC;AAAA,QACA;AAAA,QACA,YAAY,QAAQ;AAAA,MACtB,CAAC;AAED,YAAM,WAAW,MAAM,eAAe,UAAU;AAChD,YAAM,iBAAiB,oBAAI,IAA0B;AACrD,iBAAW,OAAO,UAAU;AAC1B,uBAAe,IAAI,IAAI,KAAK,WAAW,IAAI,GAAG;AAAA,MAChD;AAEA,YAAM,QAAQ,MAAM,eAAe;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,QAAQ,OAAO,QAAQ,qBAAqB,CAAC;AACnD,YAAM,YAAY,QAAQ,mBAAmB,KAAK,IAAI,QAAQ,qBAAqB,GAAG,EAAE;AAExF,iBAAW,SAAS,WAAW,OAAO,SAAS,GAAG;AAChD,cAAM,QAAQ;AAAA,UACZ,MAAM;AAAA,YAAI,CAAC,SACT,MAAM,YAAY;AAChB,oBAAM,MAAM,eAAe,IAAI,KAAK,SAAS;AAC7C,kBAAI,CAAC,IAAK,OAAM,IAAI,MAAM,kCAAkC,KAAK,SAAS,EAAE;AAC5E,oBAAM,OAAO,MAAM,WAAW,MAAM,KAAK,KAAK;AAC9C,mBAAK,SAAS;AAAA,gBACZ,MAAM;AAAA,gBACN,UAAU,QAAQ,gBAAgB,IAAI,KAAK,KAAK;AAAA,gBAChD,QAAQ;AAAA,cACV,CAAC;AAAA,YACH,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["path","createHash","path","path","path","path","path"]}
1
+ {"version":3,"sources":["../src/plugin.ts","../src/discover.ts","../src/path-utils.ts","../src/route-utils.ts","../src/errors.ts","../src/render-runtime.ts","../src/dev-server.ts","../src/page-index.ts","../src/render-bundle.ts","../src/manifest.ts"],"sourcesContent":["import path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { createHash } from 'node:crypto';\nimport pLimit from 'p-limit';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport { discoverEntryPages } from './discover';\nimport { installDevServer } from './dev-server';\nimport { buildPageIndex } from './page-index';\nimport { buildRenderBundle } from './render-bundle';\nimport { renderPage } from './render-runtime';\nimport type { HtPageInfo, HtPageModule, HtPagesPluginOptions } from './types';\n\nconst VIRTUAL_BUILD_ENTRY_ID = '\\0vite-plugin-htjs-pages:build-entry';\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\nfunction createEntriesKey(entries: HtPageInfo[]): string {\n const raw = entries\n .map((e) => `${e.entryPath}|${e.routePattern}|${e.dynamic}`)\n .join('\\n');\n\n return createHash('sha256').update(raw).digest('hex');\n}\n\nasync function importManifest(bundlePath: string): Promise<Array<{ page: HtPageInfo; mod: HtPageModule }>> {\n const mod = await import(pathToFileURL(bundlePath).href + `?t=${Date.now()}`);\n return mod.manifest as Array<{ page: HtPageInfo; mod: HtPageModule }>;\n}\n\nexport function htPages(options: HtPagesPluginOptions = {}): Plugin {\n let root = process.cwd();\n let server: ViteDevServer | null = null;\n let devPages: HtPageInfo[] = [];\n const cleanUrls = options.cleanUrls ?? true;\n\n async function loadDevPages(): Promise<HtPageInfo[]> {\n const entries = await discoverEntryPages(root, options);\n const modulesByEntry = new Map<string, HtPageModule>();\n\n if (!server) return [];\n\n for (const entry of entries) {\n const mod = (await server.ssrLoadModule(entry.entryPath)) as HtPageModule;\n modulesByEntry.set(entry.entryPath, mod);\n }\n\n devPages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n return devPages;\n }\n\n return {\n name: 'vite-plugin-htjs-pages',\n\n config(userConfig, env) {\n if (env.command !== 'build') return;\n \n const hasExplicitInput =\n userConfig.build?.rollupOptions?.input != null;\n \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\n async buildStart() {\n const entries = await discoverEntryPages(root, options);\n for (const entry of entries) {\n this.addWatchFile(entry.entryPath);\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 await loadDevPages();\n },\n });\n\n loadDevPages().catch((error) => {\n server?.config.logger.error(String(error));\n });\n\n return () => {\n server = null;\n };\n },\n\n async handleHotUpdate() {\n if (server) {\n await loadDevPages();\n }\n return undefined;\n },\n\n async generateBundle() {\n const entries = await discoverEntryPages(root, options);\n const cacheDir = path.join(root, 'node_modules/.cache/vite-plugin-htjs-pages');\n const bundlePath = await buildRenderBundle({\n entries,\n cacheDir,\n ssrPlugins: options.ssrPlugins,\n });\n\n const manifest = await importManifest(bundlePath);\n const modulesByEntry = new Map<string, HtPageModule>();\n for (const rec of manifest) {\n modulesByEntry.set(rec.page.entryPath, rec.mod);\n }\n\n const pages = await buildPageIndex({\n entries,\n modulesByEntry,\n cleanUrls,\n });\n\n const limit = pLimit(options.renderConcurrency ?? 8);\n const batchSize = options.renderBatchSize ?? Math.max(options.renderConcurrency ?? 8, 32);\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 if (!mod) throw new Error(`Missing module for page entry: ${page.entryPath}`);\n const html = await renderPage(page, mod, false);\n this.emitFile({\n type: 'asset',\n fileName: options.mapOutputPath?.(page) ?? page.fileName,\n source: html,\n });\n }),\n ),\n );\n }\n },\n };\n}","import path from 'node:path';\nimport fg from 'fast-glob';\nimport { normalizeFsPath, toPosix } from './path-utils';\nimport { getParamNames, isDynamicPage, toRoutePattern } from './route-utils';\nimport type { HtPageInfo, HtPagesPluginOptions } from './types';\n\nexport async function discoverEntryPages(root: string, options: HtPagesPluginOptions): Promise<HtPageInfo[]> {\n const include = Array.isArray(options.include) ? options.include : [options.include ?? 'src/**/*.ht.js'];\n const exclude = Array.isArray(options.exclude) ? options.exclude : options.exclude ? [options.exclude] : [];\n const pagesDir = options.pagesDir ?? 'src';\n\n const files = await fg(include, {\n cwd: root,\n ignore: exclude,\n absolute: true,\n });\n\n return files.sort().map((absolutePath) => {\n const entryPath = normalizeFsPath(absolutePath);\n const relativePath = toPosix(path.relative(root, entryPath));\n const relativeFromPagesDir = toPosix(path.relative(path.join(root, pagesDir), entryPath));\n const dynamic = isDynamicPage(relativeFromPagesDir);\n const routePattern = toRoutePattern(relativeFromPagesDir);\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 };\n });\n}","import path from 'node:path';\n\nexport function toPosix(p: string): string {\n return p.split(path.sep).join('/');\n}\n\nexport function stripHtSuffix(file: string): string {\n return file.replace(/\\.ht\\.js$/i, '');\n}\n\nexport function normalizeRoutePath(p: string): string {\n let out = p.startsWith('/') ? p : `/${p}`;\n out = out.replace(/\\/+/g, '/');\n if (out !== '/' && out.endsWith('/')) out = out.slice(0, -1);\n return out;\n}\n\nexport function normalizeFsPath(p: string): string {\n return toPosix(path.resolve(p));\n}","import { normalizeRoutePath, stripHtSuffix, 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 ANY_PARAM_RE = /\\[(?:\\.\\.\\.)?([A-Za-z0-9_]+)\\]/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 ANY_PARAM_RE.test(relativeFromPagesDir);\n}\n\nexport function toRoutePattern(relativeFromPagesDir: string): string {\n const noExt = stripHtSuffix(toPosix(relativeFromPagesDir));\n const raw = noExt\n .replace(/(^|\\/)index$/i, '$1')\n .replace(CATCH_ALL_SEGMENT_RE, '*:$1')\n .replace(DYNAMIC_SEGMENT_RE, ':$1');\n return normalizeRoutePath(raw || '/');\n}\n\nexport function fillParams(pattern: string, params: Record<string, string>): string {\n return pattern\n .replace(/\\*:([A-Za-z0-9_]+)/g, (_, key) => {\n if (!(key in params)) throw new Error(`Missing catch-all route param \"${key}\"`);\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)) throw new Error(`Missing route param \"${key}\"`);\n return encodeURIComponent(params[key]);\n });\n}\n\nexport function fileNameFromRoute(routePath: string, cleanUrls: boolean): string {\n const normalized = normalizeRoutePath(routePath);\n if (normalized === '/') return 'index.html';\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 const routePath = fillParams(basePage.routePattern, params);\n return {\n ...basePage,\n routePath,\n fileName: fileNameFromRoute(routePath, cleanUrls),\n params,\n };\n });\n}\n\nexport function routeMatch(pattern: string, urlPath: string): 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, j = 0; i < a.length; i++, j++) {\n const seg = a[i];\n\n if (seg.startsWith('*:')) {\n params[seg.slice(2)] = b.slice(j).map(decodeURIComponent).join('/');\n return params;\n }\n\n if (j >= b.length) return null;\n\n if (seg.startsWith(':')) {\n params[seg.slice(1)] = decodeURIComponent(b[j]);\n continue;\n }\n\n if (seg !== b[j]) 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 aCatchAll = aa.startsWith('*:');\n const bCatchAll = bb.startsWith('*:');\n if (aCatchAll !== bCatchAll) return aCatchAll ? 1 : -1;\n\n const aDynamic = aa.startsWith(':');\n const bDynamic = bb.startsWith(':');\n if (aDynamic !== bDynamic) return aDynamic ? 1 : -1;\n }\n\n return aSegs.length - bSegs.length;\n}","import type { HtPageInfo } from './types';\n\nexport function invalidHtmlReturn(page: HtPageInfo, value: unknown): Error {\n return new Error(\n `[vite-plugin-htjs-pages] Page \"${page.relativePath}\" must resolve to an HTML string, got ${typeof value}`,\n );\n}\n\nexport function pageError(page: HtPageInfo, cause: unknown): Error {\n const message = `[vite-plugin-htjs-pages] Failed to render ${page.relativePath} (${page.routePath})`;\n if (cause instanceof Error && cause.stack) {\n const err = new Error(message);\n err.stack = `${err.stack}\nCaused by:\n${cause.stack}`;\n return err;\n }\n return new Error(message);\n}","import { invalidHtmlReturn, pageError } from './errors';\nimport type { HtPageInfo, HtPageModule, HtPageRenderContext } from './types';\n\nexport async function renderPage(page: HtPageInfo, mod: HtPageModule, dev = false): 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 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 type { ViteDevServer } from 'vite';\nimport { renderPage } from './render-runtime';\nimport { routeMatch } from './route-utils';\nimport type { HtPageInfo, HtPageModule } from './types';\n\nexport function installDevServer(args: {\n server: ViteDevServer;\n getPages: () => Promise<HtPageInfo[]>;\n}): void {\n const { server, getPages } = args;\n\n server.middlewares.use(async (req, res, next) => {\n if (!req.url || req.method !== 'GET') return next();\n\n const pathname = req.url.split('?')[0];\n const pages = await getPages();\n\n for (const page of pages) {\n const params = routeMatch(page.routePattern, pathname);\n if (!params) continue;\n\n const mod = (await server.ssrLoadModule(page.entryPath)) as HtPageModule;\n const resolvedPage = { ...page, routePath: pathname || '/', params };\n const html = await renderPage(resolvedPage, mod, true);\n\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(html);\n return;\n }\n\n next();\n });\n}","import { compareRoutePriority, expandStaticPaths, fileNameFromRoute } from './route-utils';\nimport type { HtPageInfo, HtPageModule, StaticParamRecord } from './types';\n\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 = mod.generateStaticParams ? await mod.generateStaticParams() : [];\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 rows as StaticParamRecord[],\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 return pages;\n}","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { rollup, type Plugin as RollupPlugin } from 'rollup';\nimport { createManifestModule } from './manifest';\nimport type { HtPageInfo } from './types';\nimport { nodeResolve } from '@rollup/plugin-node-resolve';\n\nconst VIRTUAL_MANIFEST_ID = '\\0virtual:htjs-pages-manifest';\n\nexport async function buildRenderBundle(args: {\n entries: HtPageInfo[];\n cacheDir: string;\n ssrPlugins?: RollupPlugin[];\n}): Promise<string> {\n const { entries, cacheDir, ssrPlugins = [] } = args;\n const source = createManifestModule(entries);\n const hash = createHash('sha256').update(source).digest('hex').slice(0, 12);\n const bundlePath = path.join(cacheDir, `render-${hash}.mjs`);\n\n await fs.mkdir(cacheDir, { recursive: true });\n\n const bundle = await rollup({\n input: VIRTUAL_MANIFEST_ID,\n plugins: [\n {\n name: 'htjs-pages:virtual-manifest',\n resolveId(id) {\n return id === VIRTUAL_MANIFEST_ID ? id : null;\n },\n load(id) {\n return id === VIRTUAL_MANIFEST_ID ? source : null;\n },\n },\n nodeResolve({\n preferBuiltins: true,\n }),\n ...ssrPlugins,\n ],\n treeshake: true,\n });\n\n const { output } = await bundle.generate({\n format: 'esm',\n exports: 'named',\n inlineDynamicImports: true,\n });\n\n const chunk = output.find((item) => item.type === 'chunk');\n if (!chunk || chunk.type !== 'chunk') {\n throw new Error('Failed to generate HT pages render bundle.');\n }\n\n await fs.writeFile(bundlePath, chunk.code, 'utf8');\n await bundle.close();\n return bundlePath;\n}","import type { HtPageInfo } from './types';\n\nfunction js(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport function createManifestModule(entries: HtPageInfo[]): string {\n const imports = entries\n .map((page, i) => `import * as page${i} from ${js(page.entryPath)};`)\n .join('');\n\n const records = entries\n .map((page, i) => `{\n page: ${js(page)},\n mod: page${i}\n}`)\n .join(',');\n\n return `${imports}\n\nexport const manifest = [\n${records}\n];\n`;\n}"],"mappings":"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","names":["path","createHash","path","path","path","path","path"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-plugin-htjs-pages",
3
3
  "author": "Paul Browne",
4
- "version": "0.5.2",
4
+ "version": "0.5.4",
5
5
  "type": "module",
6
6
  "description": "Small HT.js pages plugin for Vite with dynamic routes, catch-all routes, and static params",
7
7
  "main": "./dist/index.js",
@@ -15,12 +15,16 @@
15
15
  },
16
16
  "scripts": {
17
17
  "build": "tsup",
18
- "typecheck": "tsc --noEmit"
18
+ "typecheck": "tsc --noEmit",
19
+ "test:dev": "vite",
20
+ "test:build": "vite build",
21
+ "test:preview": "vite preview"
19
22
  },
20
23
  "peerDependencies": {
21
24
  "vite": ">=5"
22
25
  },
23
26
  "dependencies": {
27
+ "@rollup/plugin-node-resolve": "^16.0.3",
24
28
  "fast-glob": "^3.3.3",
25
29
  "p-limit": "^4.0.0",
26
30
  "rollup": "^4.34.6"
@@ -30,8 +34,9 @@
30
34
  },
31
35
  "devDependencies": {
32
36
  "@types/node": "^20.17.0",
37
+ "javascript-to-html": "^1.1.1",
33
38
  "tsup": "^8.3.6",
34
39
  "typescript": "^5.7.3",
35
- "vite": "^6.0.0"
40
+ "vite": "^6.4.1"
36
41
  }
37
- }
42
+ }
@@ -4,6 +4,7 @@ import { createHash } from 'node:crypto';
4
4
  import { rollup, type Plugin as RollupPlugin } from 'rollup';
5
5
  import { createManifestModule } from './manifest';
6
6
  import type { HtPageInfo } from './types';
7
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
7
8
 
8
9
  const VIRTUAL_MANIFEST_ID = '\0virtual:htjs-pages-manifest';
9
10
 
@@ -31,6 +32,9 @@ export async function buildRenderBundle(args: {
31
32
  return id === VIRTUAL_MANIFEST_ID ? source : null;
32
33
  },
33
34
  },
35
+ nodeResolve({
36
+ preferBuiltins: true,
37
+ }),
34
38
  ...ssrPlugins,
35
39
  ],
36
40
  treeshake: true,