@pagesmith/core 0.4.0 → 0.4.1

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.
Files changed (71) hide show
  1. package/README.md +19 -0
  2. package/REFERENCE.md +160 -94
  3. package/dist/{content-config-DJXUOcNG.d.mts → content-config-Bu2HH0Yx.d.mts} +2 -2
  4. package/dist/{content-config-DJXUOcNG.d.mts.map → content-config-Bu2HH0Yx.d.mts.map} +1 -1
  5. package/dist/{content-layer-B5enqWeJ.mjs → content-layer-CJRrNpZ_.mjs} +71 -10
  6. package/dist/content-layer-CJRrNpZ_.mjs.map +1 -0
  7. package/dist/{content-layer-CpHYUYNN.d.mts → content-layer-Ckt08g2i.d.mts} +4 -3
  8. package/dist/content-layer-Ckt08g2i.d.mts.map +1 -0
  9. package/dist/create/index.d.mts.map +1 -1
  10. package/dist/create/index.mjs +5 -2
  11. package/dist/create/index.mjs.map +1 -1
  12. package/dist/css/index.mjs +1 -1
  13. package/dist/css-CO3CBqxx.mjs +24 -0
  14. package/dist/css-CO3CBqxx.mjs.map +1 -0
  15. package/dist/heading-D4X2L4vd.d.mts +12 -0
  16. package/dist/heading-D4X2L4vd.d.mts.map +1 -0
  17. package/dist/{index-C0QFHYwb.d.mts → index-B4YZRIzb.d.mts} +1 -1
  18. package/dist/{index-C0QFHYwb.d.mts.map → index-B4YZRIzb.d.mts.map} +1 -1
  19. package/dist/{index-DCznbvaV.d.mts → index-CryArLlX.d.mts} +1 -1
  20. package/dist/{index-DCznbvaV.d.mts.map → index-CryArLlX.d.mts.map} +1 -1
  21. package/dist/{index-CJkBs8YQ.d.mts → index-D44syBt-.d.mts} +3 -2
  22. package/dist/index-D44syBt-.d.mts.map +1 -0
  23. package/dist/index.d.mts +7 -6
  24. package/dist/index.d.mts.map +1 -1
  25. package/dist/index.mjs +4 -4
  26. package/dist/loaders/index.d.mts +1 -1
  27. package/dist/loaders/index.mjs +1 -1
  28. package/dist/{loaders-Cf-BXf2L.mjs → loaders-DnyWfANR.mjs} +3 -3
  29. package/dist/loaders-DnyWfANR.mjs.map +1 -0
  30. package/dist/markdown/index.d.mts +2 -2
  31. package/dist/markdown/index.mjs +1 -1
  32. package/dist/{markdown-BmDJgYeB.mjs → markdown-DMHd400a.mjs} +7 -2
  33. package/dist/{markdown-BmDJgYeB.mjs.map → markdown-DMHd400a.mjs.map} +1 -1
  34. package/dist/{heading-Dhvzlay-.d.mts → markdown-config-CDvh5aJ-.d.mts} +2 -10
  35. package/dist/markdown-config-CDvh5aJ-.d.mts.map +1 -0
  36. package/dist/mcp/index.d.mts.map +1 -1
  37. package/dist/mcp/index.mjs +1 -1
  38. package/dist/mcp/server.d.mts +1 -1
  39. package/dist/mcp/server.d.mts.map +1 -1
  40. package/dist/mcp/server.mjs +1 -1
  41. package/dist/runtime/index.d.mts.map +1 -1
  42. package/dist/runtime/index.mjs +4 -9
  43. package/dist/runtime/index.mjs.map +1 -1
  44. package/dist/schemas/index.d.mts +4 -3
  45. package/dist/{server-D3DHoh5f.mjs → server-BZA_iSen.mjs} +2 -1
  46. package/dist/server-BZA_iSen.mjs.map +1 -0
  47. package/dist/ssg-utils/index.d.mts +3 -13
  48. package/dist/ssg-utils/index.d.mts.map +1 -1
  49. package/dist/ssg-utils/index.mjs +2 -1
  50. package/dist/ssg-utils/index.mjs.map +1 -1
  51. package/dist/vite/index.d.mts +2 -2
  52. package/dist/vite/index.d.mts.map +1 -1
  53. package/dist/vite/index.mjs +5 -5
  54. package/dist/vite/index.mjs.map +1 -1
  55. package/docs/agents/AGENTS.md.template +24 -4
  56. package/docs/agents/changelog-notes.md +1 -1
  57. package/docs/agents/errors.md +61 -7
  58. package/docs/agents/migration.md +7 -7
  59. package/docs/agents/recipes.md +26 -2
  60. package/docs/agents/usage.md +66 -5
  61. package/docs/llms-full.txt +73 -15
  62. package/docs/llms.txt +46 -7
  63. package/package.json +2 -1
  64. package/dist/content-layer-B5enqWeJ.mjs.map +0 -1
  65. package/dist/content-layer-CpHYUYNN.d.mts.map +0 -1
  66. package/dist/css-BneO430t.mjs +0 -20
  67. package/dist/css-BneO430t.mjs.map +0 -1
  68. package/dist/heading-Dhvzlay-.d.mts.map +0 -1
  69. package/dist/index-CJkBs8YQ.d.mts.map +0 -1
  70. package/dist/loaders-Cf-BXf2L.mjs.map +0 -1
  71. package/dist/server-D3DHoh5f.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import "../markdown-BmDJgYeB.mjs";
2
- import { l as toSlug, t as createContentLayer } from "../content-layer-B5enqWeJ.mjs";
3
- import { r as resolveLoader } from "../loaders-Cf-BXf2L.mjs";
1
+ import "../markdown-DMHd400a.mjs";
2
+ import { l as toSlug, t as createContentLayer } from "../content-layer-CJRrNpZ_.mjs";
3
+ import { r as resolveLoader } from "../loaders-DnyWfANR.mjs";
4
4
  import { i as copyPublicFiles, n as collectContentAssets, t as CONTENT_ASSET_EXTS } from "../assets-CAPOqQ_P.mjs";
5
5
  import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
6
6
  import { basename, dirname, extname, join, relative, resolve } from "path";
@@ -87,7 +87,7 @@ function sharedAssetsPlugin() {
87
87
  }
88
88
  if (url.includes("/assets/fonts/") && url.endsWith(".woff2")) {
89
89
  const fileName = url.split("/assets/fonts/").pop();
90
- if (fileName) {
90
+ if (fileName && !fileName.includes("..") && !fileName.includes("/")) {
91
91
  const filePath = join(assetsDir, "fonts", fileName);
92
92
  if (existsSync(filePath)) {
93
93
  res.writeHead(200, {
@@ -340,7 +340,7 @@ function configureSsgDevServer(server, context) {
340
340
  res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
341
341
  res.end(html);
342
342
  } catch (err) {
343
- server.ssrFixStacktrace(err);
343
+ if (err instanceof Error) server.ssrFixStacktrace(err);
344
344
  console.error(`SSR error for ${url}:`, err instanceof Error ? err.message : String(err));
345
345
  next(err);
346
346
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["normalizePath"],"sources":["../../src/vite/ssg.ts","../../src/vite/shared-assets.ts","../../src/vite/ssg-render.ts","../../src/vite/ssg-hmr.ts","../../src/vite/ssg-pagefind.ts","../../src/vite/ssg-plugin.ts","../../src/vite/dts.ts","../../src/vite/content-plugin.ts"],"sourcesContent":["/**\n * Pre-rendering utility for Vite-based SSG sites.\n *\n * Call after running both the client and SSR Vite builds.\n * Loads the SSR module, renders each route, injects into the\n * client HTML template, and writes static files.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'\nimport { dirname, resolve } from 'path'\nimport { pathToFileURL } from 'url'\n\nexport type PrerenderOptions = {\n /** Absolute path to the client build output directory (e.g., `dist/`) */\n outDir: string\n /** Absolute path to the built SSR entry module (e.g., `dist/.server/entry-server.js`) */\n serverEntry: string\n /** Routes to pre-render (e.g., `['/', '/about', '/posts/hello-world']`) */\n routes: string[]\n /** HTML placeholder to replace with rendered content (default: `'<!--ssr-outlet-->'`) */\n placeholder?: string\n /** Remove the server build directory after pre-rendering (default: true) */\n cleanup?: boolean\n}\n\n/**\n * Pre-render routes to static HTML files.\n *\n * Expects the SSR entry to export a `render(url: string): string` function.\n *\n * @example\n * ```ts\n * import { build } from 'vite'\n * import { prerenderRoutes } from '@pagesmith/core/vite'\n *\n * // 1. Client build\n * await build({ build: { outDir: 'dist' } })\n *\n * // 2. SSR build\n * await build({ build: { ssr: 'src/entry-server.tsx', outDir: 'dist/.server' } })\n *\n * // 3. Pre-render\n * await prerenderRoutes({\n * outDir: resolve('dist'),\n * serverEntry: resolve('dist/.server/entry-server.js'),\n * routes: ['/', '/about', '/posts/hello-world'],\n * })\n * ```\n */\nexport async function prerenderRoutes(options: PrerenderOptions): Promise<{ pages: number }> {\n const placeholder = options.placeholder ?? '<!--ssr-outlet-->'\n const cleanup = options.cleanup ?? true\n\n // Load SSR module\n if (!existsSync(options.serverEntry)) {\n throw new Error(`SSR entry not found: ${options.serverEntry}`)\n }\n\n const mod = await import(pathToFileURL(options.serverEntry).href)\n const render: (url: string) => string | Promise<string> = mod.render ?? mod.default?.render\n\n if (typeof render !== 'function') {\n throw new Error(\n `SSR entry must export a 'render(url: string)' function. ` +\n `Found exports: ${Object.keys(mod).join(', ')}`,\n )\n }\n\n // Read client HTML template\n const templatePath = resolve(options.outDir, 'index.html')\n const template = readFileSync(templatePath, 'utf-8')\n\n if (!template.includes(placeholder)) {\n throw new Error(\n `HTML template does not contain placeholder \"${placeholder}\". ` +\n `Add it to your index.html where SSR content should be injected.`,\n )\n }\n\n // Pre-render each route\n for (const route of options.routes) {\n const rendered = await render(route)\n const html = template.replace(placeholder, rendered)\n\n const routePath = route === '/' ? '' : route.replace(/^\\//, '')\n const outPath = resolve(options.outDir, routePath, 'index.html')\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, html)\n }\n\n // Clean up server build\n if (cleanup) {\n const serverDir = dirname(options.serverEntry)\n rmSync(serverDir, { recursive: true, force: true })\n }\n\n return { pages: options.routes.length }\n}\n","import { existsSync, readFileSync } from 'fs'\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\nimport type { Plugin } from 'vite'\n\n/**\n * Vite plugin that serves shared font assets during development.\n * In production, fonts are copied to the output directory by the build script.\n */\nexport function sharedAssetsPlugin(): Plugin {\n const pkgDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..')\n const assetsDir = join(pkgDir, 'assets')\n\n return {\n name: 'pagesmith:shared-assets',\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? ''\n\n // Serve fonts.css\n if (url === '/assets/fonts.css' || url.endsWith('/assets/fonts.css')) {\n const filePath = join(assetsDir, 'fonts.css')\n if (existsSync(filePath)) {\n res.writeHead(200, { 'Content-Type': 'text/css', 'Cache-Control': 'no-cache' })\n res.end(readFileSync(filePath, 'utf-8'))\n return\n }\n }\n\n // Serve font files\n if (url.includes('/assets/fonts/') && url.endsWith('.woff2')) {\n const fileName = url.split('/assets/fonts/').pop()\n if (fileName) {\n const filePath = join(assetsDir, 'fonts', fileName)\n if (existsSync(filePath)) {\n res.writeHead(200, {\n 'Content-Type': 'font/woff2',\n 'Cache-Control': 'public, max-age=31536000',\n })\n res.end(readFileSync(filePath))\n return\n }\n }\n }\n\n next()\n })\n },\n }\n}\n","/**\n * Route collection, pre-rendering, and content asset handling for the SSG plugin.\n *\n * Provides:\n * - Content companion asset discovery and copying\n * - HTML asset reference rewriting\n * - SSR bundle building via child process\n * - Route pre-rendering to static HTML files\n * - Font and public file copying\n */\n\nimport {\n copyFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'fs'\nimport { basename, dirname, extname, join, resolve } from 'path'\nimport { fileURLToPath, pathToFileURL } from 'url'\nimport type { ResolvedConfig } from 'vite'\nimport { collectContentAssets, CONTENT_ASSET_EXTS, copyPublicFiles } from '../assets'\nimport type { SsgRenderConfig } from './ssg-plugin'\n\nexport const MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.ico': 'image/x-icon',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.txt': 'text/plain; charset=utf-8',\n '.xml': 'application/xml; charset=utf-8',\n}\n\n// ── Content directory helpers ──\n\nexport function resolveContentDirs(projectRoot: string, contentDirs: string[] = []): string[] {\n return contentDirs.map((dir) => resolve(projectRoot, dir))\n}\n\nfunction isAssetReference(ref: string): boolean {\n if (!ref.startsWith('./')) return false\n const path = ref.split(/[?#]/u, 1)[0] ?? ref\n return CONTENT_ASSET_EXTS.has(extname(path).toLowerCase())\n}\n\nexport function rewriteContentAssetRefs(html: string, base: string): string {\n const basePrefix = base.replace(/\\/+$/u, '')\n\n return html.replace(\n /(src|href|srcset)=(?:\"([^\"]+)\"|'([^']+)')/g,\n (match, attr: string, doubleRef: string | undefined, singleRef: string | undefined) => {\n const ref = doubleRef ?? singleRef ?? ''\n if (!isAssetReference(ref)) return match\n const pathname = ref.split(/[?#]/u, 1)[0] ?? ref\n const suffix = ref.slice(pathname.length)\n const quote = doubleRef !== undefined ? '\"' : \"'\"\n return `${attr}=${quote}${basePrefix}/assets/${pathname.split('/').pop() ?? pathname}${suffix}${quote}`\n },\n )\n}\n\nfunction copyContentAssetsToOutDir(outDir: string, assets: Map<string, string>): void {\n if (assets.size === 0) return\n\n const assetsDir = join(outDir, 'assets')\n mkdirSync(assetsDir, { recursive: true })\n\n for (const [fileName, sourcePath] of assets) {\n copyFileSync(sourcePath, join(assetsDir, fileName))\n }\n}\n\n// ── Build-time rendering ──\n\nexport type SsgBuildContext = {\n /** Vite resolved config */\n config: ResolvedConfig\n /** Absolute path to the project root */\n projectRoot: string\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Absolute path to the build output directory */\n outDir: string\n /** Resolved content directories (absolute paths) */\n contentDirs: string[]\n /** Path to the SSR entry module */\n entry: string\n}\n\n/**\n * Run the full SSG build: SSR bundle, route pre-rendering, asset copying.\n *\n * Returns the number of pages rendered.\n */\nexport async function renderStaticSite(context: SsgBuildContext): Promise<number> {\n const { config, projectRoot, base, outDir, contentDirs, entry } = context\n\n console.log('\\nSSG: Starting static site generation...')\n\n const contentAssets = collectContentAssets(contentDirs)\n\n // Copy font assets from @pagesmith/core\n copyFontAssets(outDir)\n\n // Copy public/ files (favicon etc.)\n const publicDir = join(projectRoot, 'public')\n copyPublicFiles(publicDir, outDir)\n\n // Discover built asset paths from the client build output\n const { cssPath, jsPath } = discoverBuiltAssets(outDir, base)\n\n // SSR build — use child process to avoid nested Vite resolution issues\n console.log('SSG: Building SSR bundle...')\n await buildSsrBundle(config, projectRoot, outDir, entry)\n\n // Load SSR module — derive output filename from the configured entry path\n const entryBaseName = basename(entry).replace(/\\.(c|m)?[jt]sx?$/u, '.js')\n const serverDir = join(outDir, '.server')\n const serverEntry = join(serverDir, entryBaseName)\n const ssrMod = await import(pathToFileURL(serverEntry).href)\n\n const renderConfig: SsgRenderConfig = {\n base,\n root: projectRoot,\n cssPath,\n jsPath,\n searchEnabled: true,\n isDev: false,\n }\n\n // Get routes and render with bounded concurrency\n const routes: string[] = await ssrMod.getRoutes(renderConfig)\n console.log(`SSG: Rendering ${routes.length} pages...`)\n\n const concurrency = Math.min(routes.length, 8)\n let routeIndex = 0\n\n async function renderWorker(): Promise<void> {\n while (routeIndex < routes.length) {\n const i = routeIndex++\n const route = routes[i]\n const html = rewriteContentAssetRefs(await ssrMod.render(route, renderConfig), base)\n const routePath = route === '/' ? '' : route.replace(/^\\//, '')\n const outputPath = join(outDir, routePath, 'index.html')\n mkdirSync(dirname(outputPath), { recursive: true })\n writeFileSync(outputPath, `<!DOCTYPE html>\\n${html}`)\n\n if (route === '/404') {\n writeFileSync(join(outDir, '404.html'), `<!DOCTYPE html>\\n${html}`)\n }\n }\n }\n\n const workers = Array.from({ length: concurrency }, () => renderWorker())\n await Promise.all(workers)\n\n copyContentAssetsToOutDir(outDir, contentAssets)\n\n // Cleanup SSR build\n rmSync(serverDir, { recursive: true, force: true })\n\n return routes.length\n}\n\nfunction copyFontAssets(outDir: string): void {\n const corePkgDir = dirname(fileURLToPath(import.meta.resolve('@pagesmith/core/package.json')))\n const coreFontsDir = join(corePkgDir, 'assets', 'fonts')\n const outFontsDir = join(outDir, 'assets', 'fonts')\n mkdirSync(outFontsDir, { recursive: true })\n for (const file of readdirSync(coreFontsDir)) {\n if (file.endsWith('.woff2')) {\n copyFileSync(join(coreFontsDir, file), join(outFontsDir, file))\n }\n }\n copyFileSync(join(corePkgDir, 'assets', 'fonts.css'), join(outDir, 'assets', 'fonts.css'))\n}\n\nfunction discoverBuiltAssets(\n outDir: string,\n base: string,\n): { cssPath: string; jsPath: string | undefined } {\n const builtIndex = join(outDir, 'index.html')\n let cssPath = `${base}/assets/style.css`\n let jsPath: string | undefined\n if (existsSync(builtIndex)) {\n const html = readFileSync(builtIndex, 'utf-8')\n const cssMatch = html.match(/href=\"([^\"]*\\.css)\"/)\n const jsMatch = html.match(/src=\"([^\"]*\\.js)\"/)\n if (cssMatch) cssPath = cssMatch[1]\n if (jsMatch) jsPath = jsMatch[1]\n }\n return { cssPath, jsPath }\n}\n\nasync function buildSsrBundle(\n config: ResolvedConfig,\n projectRoot: string,\n outDir: string,\n entry: string,\n): Promise<void> {\n const { execFileSync } = await import('child_process')\n const serverDir = join(outDir, '.server')\n const ssrEntry = resolve(projectRoot, entry)\n // Write a temp build script that externalizes node_modules and skips the SSG plugin\n const buildScript = `\n import { build } from 'vite';\n await build({\n root: ${JSON.stringify(projectRoot)},\n logLevel: 'warn',\n mode: ${JSON.stringify(config.mode)},\n build: {\n ssr: ${JSON.stringify(ssrEntry)},\n outDir: ${JSON.stringify(serverDir)},\n emptyOutDir: true,\n },\n });\n `\n execFileSync(process.execPath, ['--input-type=module', '-e', buildScript], {\n stdio: 'inherit',\n cwd: projectRoot,\n })\n}\n","/**\n * Dev-server middleware for the SSG plugin.\n *\n * Handles on-the-fly SSR rendering during development, including:\n * - Content companion asset serving from content directories\n * - HTML navigation request handling via server-side rendering\n * - Vite HMR client injection for live reload\n */\n\nimport { extname, resolve } from 'path'\nimport { readFileSync } from 'fs'\nimport type { ViteDevServer } from 'vite'\nimport type { SsgRenderConfig } from './ssg-plugin'\nimport { collectContentAssets } from '../assets'\nimport { MIME, rewriteContentAssetRefs } from './ssg-render'\n\nconst WS_RELOAD_SCRIPT = `<script type=\"module\">\nimport 'vite/modulepreload-polyfill'\nif (import.meta.hot) {\n import.meta.hot.on('full-reload', () => location.reload())\n}\n</script>`\n\nexport type SsgDevContext = {\n /** Absolute path to the project root */\n projectRoot: string\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Resolved content directories (absolute paths) */\n contentDirs: string[]\n /** Path to the SSR entry module */\n entry: string\n}\n\n/**\n * Configure the Vite dev server with SSR middleware for on-the-fly rendering.\n *\n * Sets up:\n * - File watcher for content companion assets\n * - Middleware for serving companion assets from `/assets/` paths\n * - Middleware for SSR-rendering HTML navigation requests\n */\nexport function configureSsgDevServer(server: ViteDevServer, context: SsgDevContext): void {\n const { projectRoot, base, contentDirs, entry } = context\n let contentAssets = new Map<string, string>()\n\n async function refreshContentArtifacts(): Promise<void> {\n contentAssets = collectContentAssets(contentDirs)\n }\n\n void refreshContentArtifacts().catch((error) => {\n console.warn(\n `pagesmith:ssg failed to prepare companion assets: ${error instanceof Error ? error.message : String(error)}`,\n )\n })\n\n if (contentDirs.length > 0) {\n server.watcher.add(contentDirs)\n\n const refresh = () => {\n void refreshContentArtifacts().catch((error) => {\n console.warn(\n `pagesmith:ssg failed to refresh companion assets: ${error instanceof Error ? error.message : String(error)}`,\n )\n })\n }\n\n server.watcher.on('add', refresh)\n server.watcher.on('change', refresh)\n server.watcher.on('unlink', refresh)\n }\n\n // Register middleware directly — appType: 'custom' disables Vite's\n // built-in HTML serving, so we handle all HTML requests via SSR.\n server.middlewares.use(async (req, res, next) => {\n const url = req.url ?? '/'\n const pathname = url.split(/[?#]/u, 1)[0] ?? url\n\n if (pathname.includes('/assets/')) {\n const assetName = pathname.split('/assets/').pop()\n const assetPath = assetName ? contentAssets.get(assetName) : undefined\n\n if (assetPath) {\n const ext = extname(assetPath).toLowerCase()\n res.writeHead(200, {\n 'Content-Type': MIME[ext] ?? 'application/octet-stream',\n 'Cache-Control': 'no-cache',\n })\n res.end(readFileSync(assetPath))\n return\n }\n }\n\n // Only handle HTML navigation requests (not assets, not files with extensions)\n const accept = req.headers.accept ?? ''\n const pathExt = extname(pathname)\n if (pathExt && pathExt !== '.html') return next()\n if (!pathExt && !accept.includes('text/html')) return next()\n\n // Redirect root to base\n if (base && (url === '/' || url === '')) {\n res.writeHead(302, { Location: `${base}/` })\n res.end()\n return\n }\n\n // Must start with base path\n if (base && !url.startsWith(base)) return next()\n\n try {\n // Load SSR module on-the-fly (Vite transforms TSX etc.)\n const ssrMod = await server.ssrLoadModule(resolve(projectRoot, entry))\n const renderFn: (url: string, cfg: SsgRenderConfig) => Promise<string> | string =\n ssrMod.render\n\n if (typeof renderFn !== 'function') {\n return next()\n }\n\n const renderConfig: SsgRenderConfig = {\n base,\n root: projectRoot,\n cssPath: `${base}/src/theme.css`, // Vite transforms this in dev\n jsPath: undefined,\n searchEnabled: false,\n isDev: true,\n }\n\n let html = await renderFn(url, renderConfig)\n html = rewriteContentAssetRefs(html, base)\n\n // Inject Vite's client + HMR script for live reload\n html = html.replace(\n '</head>',\n `<script type=\"module\" src=\"/@vite/client\"></script>\\n` +\n `<link rel=\"stylesheet\" href=\"${base}/src/theme.css\">\\n` +\n `</head>`,\n )\n\n // Let Vite transform the HTML (resolves module URLs, etc.)\n html = await server.transformIndexHtml(url, html)\n\n const status = html.includes('doc-not-found') ? 404 : 200\n res.writeHead(status, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(html)\n } catch (err: unknown) {\n server.ssrFixStacktrace(err as Error)\n console.error(`SSR error for ${url}:`, err instanceof Error ? err.message : String(err))\n next(err)\n }\n })\n}\n","/**\n * Pagefind search indexing for the SSG plugin.\n *\n * Runs the Pagefind CLI to index the generated static site output,\n * producing the search index used by the docs theme.\n */\n\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\n\n/**\n * Run Pagefind indexing on the built site output directory.\n *\n * Resolves the Pagefind binary from the installed package and invokes it\n * via a child process. Logs a warning and continues if Pagefind is not\n * installed.\n */\nexport async function runPagefindIndexing(outDir: string): Promise<void> {\n console.log('SSG: Indexing with Pagefind...')\n try {\n const pagefindMain = fileURLToPath(import.meta.resolve('pagefind'))\n const pagefindBin = join(dirname(pagefindMain), '..', 'lib', 'runner', 'bin.cjs')\n const { execFileSync } = await import('child_process')\n execFileSync(process.execPath, [pagefindBin, '--site', outDir], { stdio: 'inherit' })\n } catch {\n console.warn('SSG: Pagefind not found, skipping search indexing')\n }\n}\n","/**\n * Vite plugin for static site generation with @pagesmith/core.\n *\n * Handles both development (on-the-fly SSR via middleware) and\n * production (post-build SSG + pagefind indexing).\n *\n * The SSR entry module must export:\n * - `getRoutes(config)` — returns route paths to pre-render\n * - `render(url, config)` — renders a route to an HTML string\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { pagesmithSsg } from '@pagesmith/core/vite'\n *\n * export default defineConfig({\n * base: '/my-site/',\n * plugins: [pagesmithSsg({ entry: './src/entry-server.tsx' })],\n * })\n * ```\n */\n\nimport { resolve } from 'path'\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport { configureSsgDevServer } from './ssg-hmr'\nimport { resolveContentDirs, renderStaticSite } from './ssg-render'\nimport { runPagefindIndexing } from './ssg-pagefind'\n\nexport type SsgPluginOptions = {\n /** Path to the SSR entry module (e.g., './src/entry-server.tsx') */\n entry: string\n /** Run pagefind after build (default: true) */\n pagefind?: boolean\n /** Content roots used for copying companion assets. */\n contentDirs?: string[]\n}\n\nexport type SsgRenderConfig = {\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Absolute path to the project root */\n root: string\n /** Path to the built CSS asset */\n cssPath: string\n /** Path to the built JS asset (undefined in dev for inline-script examples) */\n jsPath?: string\n /** Whether search is enabled (false in dev) */\n searchEnabled: boolean\n /** Whether running in dev mode */\n isDev: boolean\n}\n\nexport function pagesmithSsg(options: SsgPluginOptions): Plugin[] {\n const enablePagefind = options.pagefind !== false\n let config: ResolvedConfig\n let projectRoot: string\n let base: string // e.g., '/my-site'\n let outDir: string\n let contentDirs: string[] = []\n\n // ── Dev plugin: SSR middleware ──\n const devPlugin: Plugin = {\n name: 'pagesmith:ssg-dev',\n apply: 'serve',\n\n config() {\n // Disable Vite's built-in SPA HTML serving so the SSG middleware\n // can handle all HTML requests via server-side rendering.\n return { appType: 'custom' }\n },\n\n configResolved(resolved) {\n config = resolved\n projectRoot = resolved.root\n base = resolved.base.replace(/\\/+$/, '')\n outDir = resolve(projectRoot, resolved.build.outDir)\n contentDirs = resolveContentDirs(projectRoot, options.contentDirs)\n },\n\n configureServer(server) {\n configureSsgDevServer(server, {\n projectRoot,\n base,\n contentDirs,\n entry: options.entry,\n })\n },\n }\n\n // ── Build plugin: SSG post-build ──\n const buildPlugin: Plugin = {\n name: 'pagesmith:ssg-build',\n apply: 'build',\n\n configResolved(resolved) {\n config = resolved\n projectRoot = resolved.root\n base = resolved.base.replace(/\\/+$/, '')\n outDir = resolve(projectRoot, resolved.build.outDir)\n contentDirs = resolveContentDirs(projectRoot, options.contentDirs)\n },\n\n async closeBundle() {\n // Skip SSG during the SSR build itself (detected by ssr option)\n if (config.build.ssr) return\n\n const pageCount = await renderStaticSite({\n config,\n projectRoot,\n base,\n outDir,\n contentDirs,\n entry: options.entry,\n })\n\n if (enablePagefind) {\n await runPagefindIndexing(outDir)\n }\n\n console.log(`SSG: Done — ${pageCount} pages generated`)\n },\n }\n\n return [devPlugin, buildPlugin]\n}\n","import { existsSync } from 'fs'\nimport { dirname, relative, resolve } from 'path'\nimport type { PagesmithContentPluginOptions } from './content-plugin'\n\nfunction stripExtension(filePath: string): string {\n return filePath.replace(/\\.(c|m)?[jt]sx?$/u, '')\n}\n\nfunction normalizePath(value: string): string {\n return value.replace(/\\\\/g, '/')\n}\n\nexport function resolveDtsPath(\n projectRoot: string,\n dts: PagesmithContentPluginOptions<any>['dts'],\n): string {\n if (dts === false) {\n return ''\n }\n\n if (typeof dts === 'string') {\n return resolve(projectRoot, dts)\n }\n\n if (typeof dts === 'object' && dts?.path) {\n return resolve(projectRoot, dts.path)\n }\n\n const srcPath = resolve(projectRoot, 'src')\n if (existsSync(srcPath)) {\n return resolve(srcPath, 'pagesmith-content.d.ts')\n }\n\n return resolve(projectRoot, 'pagesmith-content.d.ts')\n}\n\nexport function createDtsSource(\n moduleId: string,\n collectionNames: string[],\n dtsPath: string,\n configPath: string,\n): string {\n const configImportPath = normalizePath(\n stripExtension(relative(dirname(dtsPath), configPath)).replace(/^[^.]/u, './$&'),\n )\n\n const moduleLines = collectionNames\n .map(\n (name) => `declare module '${moduleId}/${name}' {\n const collection: import('@pagesmith/core/vite').ContentCollectionModule<\n __PagesmithCollections['${name.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\")}']\n >\n export default collection\n}`,\n )\n .join('\\n\\n')\n\n return `// Generated by @pagesmith/core/vite. Do not edit manually.\ntype __PagesmithCollections = typeof import('${configImportPath}').default\n\ndeclare module '${moduleId}' {\n const content: import('@pagesmith/core/vite').ContentModuleMap<__PagesmithCollections>\n export default content\n}\n\n${moduleLines}\n`\n}\n","import { mkdirSync, writeFileSync } from 'fs'\nimport { dirname, relative, resolve } from 'path'\nimport { uneval } from 'devalue'\nimport { createContentLayer } from '../content-layer'\nimport { resolveLoader } from '../loaders'\nimport type { Heading } from '../schemas/heading'\nimport type { CollectionDef, CollectionMap, InferCollectionData } from '../schemas/collection'\nimport type { ContentLayerConfig } from '../schemas/content-config'\nimport { toSlug } from '../utils/slug'\nimport { createDtsSource, resolveDtsPath } from './dts'\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {}\n\ntype PagesmithResolvedConfig = {\n root: string\n}\n\ntype PagesmithModuleGraph = {\n getModuleById(id: string): unknown\n invalidateModule(module: unknown): void\n}\n\ntype PagesmithDevServer = {\n moduleGraph: PagesmithModuleGraph\n ws: {\n send(payload: { type: string }): void\n }\n}\n\nexport type PagesmithVitePlugin = {\n name: string\n enforce?: 'pre' | 'post'\n configResolved?: (config: PagesmithResolvedConfig) => void\n buildStart?: () => void\n resolveId?: (id: string) => string | void\n load?: (id: string) => Promise<string | void> | string | void\n handleHotUpdate?: (context: { file: string; server: PagesmithDevServer }) => void\n}\n\nexport type BaseContentModuleEntry = {\n id: string\n contentSlug: string\n}\n\nexport type MarkdownContentModuleEntry<TCollection extends CollectionDef<any, any, any>> = Simplify<\n BaseContentModuleEntry & {\n html: string\n headings: Heading[]\n frontmatter: InferCollectionData<TCollection>\n }\n>\n\nexport type DataContentModuleEntry<TCollection extends CollectionDef<any, any, any>> = Simplify<\n BaseContentModuleEntry & {\n data: InferCollectionData<TCollection>\n }\n>\n\ntype LoaderKindFromCollection<TCollection extends CollectionDef<any, any, any>> =\n TCollection['loader'] extends 'markdown'\n ? 'markdown'\n : TCollection['loader'] extends { kind: infer TKind }\n ? TKind\n : 'data'\n\nexport type ContentCollectionModule<TCollection extends CollectionDef<any, any, any>> =\n LoaderKindFromCollection<TCollection> extends 'markdown'\n ? MarkdownContentModuleEntry<TCollection>[]\n : DataContentModuleEntry<TCollection>[]\n\nexport type ContentModuleMap<TCollections extends CollectionMap> = {\n [TName in keyof TCollections]: ContentCollectionModule<TCollections[TName]>\n}\n\nexport type PagesmithContentPluginOptions<TCollections extends CollectionMap> = Omit<\n ContentLayerConfig,\n 'collections'\n> & {\n collections: TCollections\n /**\n * Shared content root used to compute `id` and `contentSlug`.\n * Defaults to the deepest common parent directory across all collection directories.\n */\n contentRoot?: string\n /**\n * Root virtual module id.\n * Per-collection modules are exposed as `${moduleId}/<collection-name>`.\n */\n moduleId?: string\n /**\n * Path to the content config module used for generated typings.\n * Defaults to `./content.config.ts`.\n */\n configPath?: string\n /**\n * Generate module declarations for the virtual modules.\n * Defaults to `src/pagesmith-content.d.ts` when `src/` exists, otherwise `pagesmith-content.d.ts`.\n */\n dts?: boolean | string | { path?: string }\n}\n\nconst DEFAULT_MODULE_ID = 'virtual:content'\n\nfunction normalizePath(value: string): string {\n return value.replace(/\\\\/g, '/')\n}\n\nfunction isPathWithin(parent: string, candidate: string): boolean {\n const rel = normalizePath(relative(parent, candidate))\n return rel === '' || (!rel.startsWith('..') && !rel.startsWith('/'))\n}\n\nfunction commonDirectory(paths: string[]): string {\n const normalized = paths.map((path) => normalizePath(resolve(path)))\n if (normalized.length === 0) return process.cwd()\n if (normalized.length === 1) return normalized[0]\n\n const segments = normalized.map((path) => path.split('/').filter(Boolean))\n const shared: string[] = []\n const first = segments[0]!\n\n for (let index = 0; index < first.length; index += 1) {\n const segment = first[index]\n if (segments.every((parts) => parts[index] === segment)) {\n shared.push(segment)\n continue\n }\n break\n }\n\n if (shared.length === 0) {\n return resolve('/')\n }\n\n return resolve(`/${shared.join('/')}`)\n}\n\nasync function serializeCollection(\n layer: ReturnType<typeof createContentLayer>,\n collectionName: string,\n collectionDef: CollectionDef<any, any, any>,\n contentRoot: string,\n): Promise<string> {\n const entries = await layer.getCollection(collectionName)\n const loader = resolveLoader(collectionDef.loader)\n const sortedEntries = [...entries].sort((left, right) =>\n left.filePath.localeCompare(right.filePath),\n )\n\n const payload = await Promise.all(\n sortedEntries.map(async (entry) => {\n const contentSlug = toSlug(entry.filePath, contentRoot)\n const base = {\n id: contentSlug,\n contentSlug,\n }\n\n if (loader.kind === 'markdown') {\n const rendered = await entry.render()\n return {\n ...base,\n html: rendered.html,\n headings: rendered.headings,\n frontmatter: entry.data,\n }\n }\n\n return {\n ...base,\n data: entry.data,\n }\n }),\n )\n\n return `const collection = ${uneval(payload)};\\nexport default collection;\\n`\n}\n\nfunction createRootModuleSource(moduleId: string, collectionNames: string[]): string {\n const imports = collectionNames\n .map((name, index) => `import collection${index} from '${moduleId}/${name}'`)\n .join('\\n')\n const contentMap = collectionNames\n .map((name, index) => `${JSON.stringify(name)}: collection${index}`)\n .join(', ')\n\n return `${imports}\\n\\nexport default { ${contentMap} };\\n`\n}\n\nfunction resolvePluginOptions<TCollections extends CollectionMap>(\n collectionsOrOptions: TCollections | PagesmithContentPluginOptions<TCollections>,\n maybeOptions: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'> = {},\n): PagesmithContentPluginOptions<TCollections> {\n if ('collections' in collectionsOrOptions) {\n return collectionsOrOptions as PagesmithContentPluginOptions<TCollections>\n }\n\n return {\n ...maybeOptions,\n collections: collectionsOrOptions,\n }\n}\n\nexport function pagesmithContent<TCollections extends CollectionMap>(\n collections: TCollections,\n options?: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'>,\n): PagesmithVitePlugin\nexport function pagesmithContent<TCollections extends CollectionMap>(\n options: PagesmithContentPluginOptions<TCollections>,\n): PagesmithVitePlugin\nexport function pagesmithContent<TCollections extends CollectionMap>(\n collectionsOrOptions: TCollections | PagesmithContentPluginOptions<TCollections>,\n maybeOptions: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'> = {},\n): PagesmithVitePlugin {\n const options = resolvePluginOptions(collectionsOrOptions, maybeOptions)\n const collectionNames = Object.keys(options.collections)\n const moduleId = options.moduleId ?? DEFAULT_MODULE_ID\n const resolvedPrefix = `\\0${moduleId}/`\n const resolvedRootId = `\\0${moduleId}`\n\n let projectRoot = process.cwd()\n let layerRoot = projectRoot\n let contentRoot = projectRoot\n let configPath = resolve(projectRoot, options.configPath ?? 'content.config.ts')\n let dtsPath = resolveDtsPath(projectRoot, options.dts)\n let layer: ReturnType<typeof createContentLayer> | null = null\n\n function getLayer(): ReturnType<typeof createContentLayer> {\n if (!layer) {\n throw new Error(\n 'pagesmith-content: ContentLayer not initialized. configResolved has not run yet.',\n )\n }\n return layer\n }\n\n const ensureDeclarations = (): void => {\n if (options.dts === false) return\n\n const source = createDtsSource(moduleId, collectionNames, dtsPath, configPath)\n mkdirSync(dirname(dtsPath), { recursive: true })\n writeFileSync(dtsPath, source)\n }\n\n return {\n name: 'pagesmith-content',\n enforce: 'pre',\n\n configResolved(config) {\n projectRoot = resolve(config.root)\n layerRoot = resolve(projectRoot, options.root ?? '.')\n configPath = resolve(projectRoot, options.configPath ?? 'content.config.ts')\n dtsPath = resolveDtsPath(projectRoot, options.dts)\n\n const collectionDirectories = collectionNames.map((name) =>\n resolve(layerRoot, options.collections[name]!.directory),\n )\n contentRoot = options.contentRoot\n ? resolve(layerRoot, options.contentRoot)\n : commonDirectory(collectionDirectories)\n\n layer = createContentLayer({\n ...options,\n root: layerRoot,\n })\n\n ensureDeclarations()\n },\n\n buildStart() {\n ensureDeclarations()\n },\n\n resolveId(id) {\n if (id === moduleId) {\n return resolvedRootId\n }\n\n for (const name of collectionNames) {\n if (id === `${moduleId}/${name}`) {\n return `${resolvedPrefix}${name}`\n }\n }\n },\n\n async load(id) {\n if (id === resolvedRootId) {\n return createRootModuleSource(moduleId, collectionNames)\n }\n\n if (!id.startsWith(resolvedPrefix)) return\n\n const collectionName = id.slice(resolvedPrefix.length)\n const collectionDef = options.collections[collectionName]\n if (!collectionDef) return\n\n return serializeCollection(getLayer(), collectionName, collectionDef, contentRoot)\n },\n\n handleHotUpdate({ file, server }) {\n const resolvedFile = resolve(file)\n const touchesConfig = resolvedFile === configPath\n\n const affectedCollections = collectionNames.filter((name) =>\n isPathWithin(resolve(layerRoot, options.collections[name]!.directory), resolvedFile),\n )\n\n const touchesContent = affectedCollections.length > 0\n\n if (!touchesConfig && !touchesContent) return\n\n if (touchesConfig) {\n ensureDeclarations()\n }\n\n const rootModule = server.moduleGraph.getModuleById(resolvedRootId)\n if (rootModule) {\n server.moduleGraph.invalidateModule(rootModule)\n }\n\n if (touchesContent) {\n for (const name of affectedCollections) {\n const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`)\n if (moduleNode) {\n server.moduleGraph.invalidateModule(moduleNode)\n }\n getLayer()\n .invalidateCollection(name)\n .catch((err) => {\n console.warn(`[pagesmith] Failed to invalidate collection \"${name}\":`, err)\n })\n }\n } else {\n for (const name of collectionNames) {\n const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`)\n if (moduleNode) {\n server.moduleGraph.invalidateModule(moduleNode)\n }\n }\n getLayer().invalidateAll()\n }\n\n server.ws.send({ type: 'full-reload' })\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["normalizePath"],"sources":["../../src/vite/ssg.ts","../../src/vite/shared-assets.ts","../../src/vite/ssg-render.ts","../../src/vite/ssg-hmr.ts","../../src/vite/ssg-pagefind.ts","../../src/vite/ssg-plugin.ts","../../src/vite/dts.ts","../../src/vite/content-plugin.ts"],"sourcesContent":["/**\n * Pre-rendering utility for Vite-based SSG sites.\n *\n * Call after running both the client and SSR Vite builds.\n * Loads the SSR module, renders each route, injects into the\n * client HTML template, and writes static files.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'\nimport { dirname, resolve } from 'path'\nimport { pathToFileURL } from 'url'\n\nexport type PrerenderOptions = {\n /** Absolute path to the client build output directory (e.g., `dist/`) */\n outDir: string\n /** Absolute path to the built SSR entry module (e.g., `dist/.server/entry-server.js`) */\n serverEntry: string\n /** Routes to pre-render (e.g., `['/', '/about', '/posts/hello-world']`) */\n routes: string[]\n /** HTML placeholder to replace with rendered content (default: `'<!--ssr-outlet-->'`) */\n placeholder?: string\n /** Remove the server build directory after pre-rendering (default: true) */\n cleanup?: boolean\n}\n\n/**\n * Pre-render routes to static HTML files.\n *\n * Expects the SSR entry to export a `render(url: string): string` function.\n *\n * @example\n * ```ts\n * import { build } from 'vite'\n * import { prerenderRoutes } from '@pagesmith/core/vite'\n *\n * // 1. Client build\n * await build({ build: { outDir: 'dist' } })\n *\n * // 2. SSR build\n * await build({ build: { ssr: 'src/entry-server.tsx', outDir: 'dist/.server' } })\n *\n * // 3. Pre-render\n * await prerenderRoutes({\n * outDir: resolve('dist'),\n * serverEntry: resolve('dist/.server/entry-server.js'),\n * routes: ['/', '/about', '/posts/hello-world'],\n * })\n * ```\n */\nexport async function prerenderRoutes(options: PrerenderOptions): Promise<{ pages: number }> {\n const placeholder = options.placeholder ?? '<!--ssr-outlet-->'\n const cleanup = options.cleanup ?? true\n\n // Load SSR module\n if (!existsSync(options.serverEntry)) {\n throw new Error(`SSR entry not found: ${options.serverEntry}`)\n }\n\n const mod = await import(pathToFileURL(options.serverEntry).href)\n const render: (url: string) => string | Promise<string> = mod.render ?? mod.default?.render\n\n if (typeof render !== 'function') {\n throw new Error(\n `SSR entry must export a 'render(url: string)' function. ` +\n `Found exports: ${Object.keys(mod).join(', ')}`,\n )\n }\n\n // Read client HTML template\n const templatePath = resolve(options.outDir, 'index.html')\n const template = readFileSync(templatePath, 'utf-8')\n\n if (!template.includes(placeholder)) {\n throw new Error(\n `HTML template does not contain placeholder \"${placeholder}\". ` +\n `Add it to your index.html where SSR content should be injected.`,\n )\n }\n\n // Pre-render each route\n for (const route of options.routes) {\n const rendered = await render(route)\n const html = template.replace(placeholder, rendered)\n\n const routePath = route === '/' ? '' : route.replace(/^\\//, '')\n const outPath = resolve(options.outDir, routePath, 'index.html')\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, html)\n }\n\n // Clean up server build\n if (cleanup) {\n const serverDir = dirname(options.serverEntry)\n rmSync(serverDir, { recursive: true, force: true })\n }\n\n return { pages: options.routes.length }\n}\n","import { existsSync, readFileSync } from 'fs'\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\nimport type { Plugin } from 'vite'\n\n/**\n * Vite plugin that serves shared font assets during development.\n * In production, fonts are copied to the output directory by the build script.\n */\nexport function sharedAssetsPlugin(): Plugin {\n const pkgDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..')\n const assetsDir = join(pkgDir, 'assets')\n\n return {\n name: 'pagesmith:shared-assets',\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? ''\n\n // Serve fonts.css\n if (url === '/assets/fonts.css' || url.endsWith('/assets/fonts.css')) {\n const filePath = join(assetsDir, 'fonts.css')\n if (existsSync(filePath)) {\n res.writeHead(200, { 'Content-Type': 'text/css', 'Cache-Control': 'no-cache' })\n res.end(readFileSync(filePath, 'utf-8'))\n return\n }\n }\n\n // Serve font files\n if (url.includes('/assets/fonts/') && url.endsWith('.woff2')) {\n const fileName = url.split('/assets/fonts/').pop()\n if (fileName && !fileName.includes('..') && !fileName.includes('/')) {\n const filePath = join(assetsDir, 'fonts', fileName)\n if (existsSync(filePath)) {\n res.writeHead(200, {\n 'Content-Type': 'font/woff2',\n 'Cache-Control': 'public, max-age=31536000',\n })\n res.end(readFileSync(filePath))\n return\n }\n }\n }\n\n next()\n })\n },\n }\n}\n","/**\n * Route collection, pre-rendering, and content asset handling for the SSG plugin.\n *\n * Provides:\n * - Content companion asset discovery and copying\n * - HTML asset reference rewriting\n * - SSR bundle building via child process\n * - Route pre-rendering to static HTML files\n * - Font and public file copying\n */\n\nimport {\n copyFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'fs'\nimport { basename, dirname, extname, join, resolve } from 'path'\nimport { fileURLToPath, pathToFileURL } from 'url'\nimport type { ResolvedConfig } from 'vite'\nimport { collectContentAssets, CONTENT_ASSET_EXTS, copyPublicFiles } from '../assets'\nimport type { SsgRenderConfig } from './ssg-plugin'\n\nexport const MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.ico': 'image/x-icon',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.txt': 'text/plain; charset=utf-8',\n '.xml': 'application/xml; charset=utf-8',\n}\n\n// ── Content directory helpers ──\n\nexport function resolveContentDirs(projectRoot: string, contentDirs: string[] = []): string[] {\n return contentDirs.map((dir) => resolve(projectRoot, dir))\n}\n\nfunction isAssetReference(ref: string): boolean {\n if (!ref.startsWith('./')) return false\n const path = ref.split(/[?#]/u, 1)[0] ?? ref\n return CONTENT_ASSET_EXTS.has(extname(path).toLowerCase())\n}\n\nexport function rewriteContentAssetRefs(html: string, base: string): string {\n const basePrefix = base.replace(/\\/+$/u, '')\n\n return html.replace(\n /(src|href|srcset)=(?:\"([^\"]+)\"|'([^']+)')/g,\n (match, attr: string, doubleRef: string | undefined, singleRef: string | undefined) => {\n const ref = doubleRef ?? singleRef ?? ''\n if (!isAssetReference(ref)) return match\n const pathname = ref.split(/[?#]/u, 1)[0] ?? ref\n const suffix = ref.slice(pathname.length)\n const quote = doubleRef !== undefined ? '\"' : \"'\"\n return `${attr}=${quote}${basePrefix}/assets/${pathname.split('/').pop() ?? pathname}${suffix}${quote}`\n },\n )\n}\n\nfunction copyContentAssetsToOutDir(outDir: string, assets: Map<string, string>): void {\n if (assets.size === 0) return\n\n const assetsDir = join(outDir, 'assets')\n mkdirSync(assetsDir, { recursive: true })\n\n for (const [fileName, sourcePath] of assets) {\n copyFileSync(sourcePath, join(assetsDir, fileName))\n }\n}\n\n// ── Build-time rendering ──\n\nexport type SsgBuildContext = {\n /** Vite resolved config */\n config: ResolvedConfig\n /** Absolute path to the project root */\n projectRoot: string\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Absolute path to the build output directory */\n outDir: string\n /** Resolved content directories (absolute paths) */\n contentDirs: string[]\n /** Path to the SSR entry module */\n entry: string\n}\n\n/**\n * Run the full SSG build: SSR bundle, route pre-rendering, asset copying.\n *\n * Returns the number of pages rendered.\n */\nexport async function renderStaticSite(context: SsgBuildContext): Promise<number> {\n const { config, projectRoot, base, outDir, contentDirs, entry } = context\n\n console.log('\\nSSG: Starting static site generation...')\n\n const contentAssets = collectContentAssets(contentDirs)\n\n // Copy font assets from @pagesmith/core\n copyFontAssets(outDir)\n\n // Copy public/ files (favicon etc.)\n const publicDir = join(projectRoot, 'public')\n copyPublicFiles(publicDir, outDir)\n\n // Discover built asset paths from the client build output\n const { cssPath, jsPath } = discoverBuiltAssets(outDir, base)\n\n // SSR build — use child process to avoid nested Vite resolution issues\n console.log('SSG: Building SSR bundle...')\n await buildSsrBundle(config, projectRoot, outDir, entry)\n\n // Load SSR module — derive output filename from the configured entry path\n const entryBaseName = basename(entry).replace(/\\.(c|m)?[jt]sx?$/u, '.js')\n const serverDir = join(outDir, '.server')\n const serverEntry = join(serverDir, entryBaseName)\n const ssrMod = await import(pathToFileURL(serverEntry).href)\n\n const renderConfig: SsgRenderConfig = {\n base,\n root: projectRoot,\n cssPath,\n jsPath,\n searchEnabled: true,\n isDev: false,\n }\n\n // Get routes and render with bounded concurrency\n const routes: string[] = await ssrMod.getRoutes(renderConfig)\n console.log(`SSG: Rendering ${routes.length} pages...`)\n\n const concurrency = Math.min(routes.length, 8)\n let routeIndex = 0\n\n async function renderWorker(): Promise<void> {\n while (routeIndex < routes.length) {\n const i = routeIndex++\n const route = routes[i]\n const html = rewriteContentAssetRefs(await ssrMod.render(route, renderConfig), base)\n const routePath = route === '/' ? '' : route.replace(/^\\//, '')\n const outputPath = join(outDir, routePath, 'index.html')\n mkdirSync(dirname(outputPath), { recursive: true })\n writeFileSync(outputPath, `<!DOCTYPE html>\\n${html}`)\n\n if (route === '/404') {\n writeFileSync(join(outDir, '404.html'), `<!DOCTYPE html>\\n${html}`)\n }\n }\n }\n\n const workers = Array.from({ length: concurrency }, () => renderWorker())\n await Promise.all(workers)\n\n copyContentAssetsToOutDir(outDir, contentAssets)\n\n // Cleanup SSR build\n rmSync(serverDir, { recursive: true, force: true })\n\n return routes.length\n}\n\nfunction copyFontAssets(outDir: string): void {\n const corePkgDir = dirname(fileURLToPath(import.meta.resolve('@pagesmith/core/package.json')))\n const coreFontsDir = join(corePkgDir, 'assets', 'fonts')\n const outFontsDir = join(outDir, 'assets', 'fonts')\n mkdirSync(outFontsDir, { recursive: true })\n for (const file of readdirSync(coreFontsDir)) {\n if (file.endsWith('.woff2')) {\n copyFileSync(join(coreFontsDir, file), join(outFontsDir, file))\n }\n }\n copyFileSync(join(corePkgDir, 'assets', 'fonts.css'), join(outDir, 'assets', 'fonts.css'))\n}\n\nfunction discoverBuiltAssets(\n outDir: string,\n base: string,\n): { cssPath: string; jsPath: string | undefined } {\n const builtIndex = join(outDir, 'index.html')\n let cssPath = `${base}/assets/style.css`\n let jsPath: string | undefined\n if (existsSync(builtIndex)) {\n const html = readFileSync(builtIndex, 'utf-8')\n const cssMatch = html.match(/href=\"([^\"]*\\.css)\"/)\n const jsMatch = html.match(/src=\"([^\"]*\\.js)\"/)\n if (cssMatch) cssPath = cssMatch[1]\n if (jsMatch) jsPath = jsMatch[1]\n }\n return { cssPath, jsPath }\n}\n\nasync function buildSsrBundle(\n config: ResolvedConfig,\n projectRoot: string,\n outDir: string,\n entry: string,\n): Promise<void> {\n const { execFileSync } = await import('child_process')\n const serverDir = join(outDir, '.server')\n const ssrEntry = resolve(projectRoot, entry)\n // Write a temp build script that externalizes node_modules and skips the SSG plugin\n const buildScript = `\n import { build } from 'vite';\n await build({\n root: ${JSON.stringify(projectRoot)},\n logLevel: 'warn',\n mode: ${JSON.stringify(config.mode)},\n build: {\n ssr: ${JSON.stringify(ssrEntry)},\n outDir: ${JSON.stringify(serverDir)},\n emptyOutDir: true,\n },\n });\n `\n execFileSync(process.execPath, ['--input-type=module', '-e', buildScript], {\n stdio: 'inherit',\n cwd: projectRoot,\n })\n}\n","/**\n * Dev-server middleware for the SSG plugin.\n *\n * Handles on-the-fly SSR rendering during development, including:\n * - Content companion asset serving from content directories\n * - HTML navigation request handling via server-side rendering\n * - Vite HMR client injection for live reload\n */\n\nimport { extname, resolve } from 'path'\nimport { readFileSync } from 'fs'\nimport type { ViteDevServer } from 'vite'\nimport type { SsgRenderConfig } from './ssg-plugin'\nimport { collectContentAssets } from '../assets'\nimport { MIME, rewriteContentAssetRefs } from './ssg-render'\n\nexport type SsgDevContext = {\n /** Absolute path to the project root */\n projectRoot: string\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Resolved content directories (absolute paths) */\n contentDirs: string[]\n /** Path to the SSR entry module */\n entry: string\n}\n\n/**\n * Configure the Vite dev server with SSR middleware for on-the-fly rendering.\n *\n * Sets up:\n * - File watcher for content companion assets\n * - Middleware for serving companion assets from `/assets/` paths\n * - Middleware for SSR-rendering HTML navigation requests\n */\nexport function configureSsgDevServer(server: ViteDevServer, context: SsgDevContext): void {\n const { projectRoot, base, contentDirs, entry } = context\n let contentAssets = new Map<string, string>()\n\n async function refreshContentArtifacts(): Promise<void> {\n contentAssets = collectContentAssets(contentDirs)\n }\n\n void refreshContentArtifacts().catch((error) => {\n console.warn(\n `pagesmith:ssg failed to prepare companion assets: ${error instanceof Error ? error.message : String(error)}`,\n )\n })\n\n if (contentDirs.length > 0) {\n server.watcher.add(contentDirs)\n\n const refresh = () => {\n void refreshContentArtifacts().catch((error) => {\n console.warn(\n `pagesmith:ssg failed to refresh companion assets: ${error instanceof Error ? error.message : String(error)}`,\n )\n })\n }\n\n server.watcher.on('add', refresh)\n server.watcher.on('change', refresh)\n server.watcher.on('unlink', refresh)\n }\n\n // Register middleware directly — appType: 'custom' disables Vite's\n // built-in HTML serving, so we handle all HTML requests via SSR.\n server.middlewares.use(async (req, res, next) => {\n const url = req.url ?? '/'\n const pathname = url.split(/[?#]/u, 1)[0] ?? url\n\n if (pathname.includes('/assets/')) {\n const assetName = pathname.split('/assets/').pop()\n const assetPath = assetName ? contentAssets.get(assetName) : undefined\n\n if (assetPath) {\n const ext = extname(assetPath).toLowerCase()\n res.writeHead(200, {\n 'Content-Type': MIME[ext] ?? 'application/octet-stream',\n 'Cache-Control': 'no-cache',\n })\n res.end(readFileSync(assetPath))\n return\n }\n }\n\n // Only handle HTML navigation requests (not assets, not files with extensions)\n const accept = req.headers.accept ?? ''\n const pathExt = extname(pathname)\n if (pathExt && pathExt !== '.html') return next()\n if (!pathExt && !accept.includes('text/html')) return next()\n\n // Redirect root to base\n if (base && (url === '/' || url === '')) {\n res.writeHead(302, { Location: `${base}/` })\n res.end()\n return\n }\n\n // Must start with base path\n if (base && !url.startsWith(base)) return next()\n\n try {\n // Load SSR module on-the-fly (Vite transforms TSX etc.)\n const ssrMod = await server.ssrLoadModule(resolve(projectRoot, entry))\n const renderFn: (url: string, cfg: SsgRenderConfig) => Promise<string> | string =\n ssrMod.render\n\n if (typeof renderFn !== 'function') {\n return next()\n }\n\n const renderConfig: SsgRenderConfig = {\n base,\n root: projectRoot,\n cssPath: `${base}/src/theme.css`, // Vite transforms this in dev\n jsPath: undefined,\n searchEnabled: false,\n isDev: true,\n }\n\n let html = await renderFn(url, renderConfig)\n html = rewriteContentAssetRefs(html, base)\n\n // Inject Vite's client + HMR script for live reload\n html = html.replace(\n '</head>',\n `<script type=\"module\" src=\"/@vite/client\"></script>\\n` +\n `<link rel=\"stylesheet\" href=\"${base}/src/theme.css\">\\n` +\n `</head>`,\n )\n\n // Let Vite transform the HTML (resolves module URLs, etc.)\n html = await server.transformIndexHtml(url, html)\n\n const status = html.includes('doc-not-found') ? 404 : 200\n res.writeHead(status, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(html)\n } catch (err: unknown) {\n if (err instanceof Error) {\n server.ssrFixStacktrace(err)\n }\n console.error(`SSR error for ${url}:`, err instanceof Error ? err.message : String(err))\n next(err)\n }\n })\n}\n","/**\n * Pagefind search indexing for the SSG plugin.\n *\n * Runs the Pagefind CLI to index the generated static site output,\n * producing the search index used by the docs theme.\n */\n\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\n\n/**\n * Run Pagefind indexing on the built site output directory.\n *\n * Resolves the Pagefind binary from the installed package and invokes it\n * via a child process. Logs a warning and continues if Pagefind is not\n * installed.\n */\nexport async function runPagefindIndexing(outDir: string): Promise<void> {\n console.log('SSG: Indexing with Pagefind...')\n try {\n const pagefindMain = fileURLToPath(import.meta.resolve('pagefind'))\n const pagefindBin = join(dirname(pagefindMain), '..', 'lib', 'runner', 'bin.cjs')\n const { execFileSync } = await import('child_process')\n execFileSync(process.execPath, [pagefindBin, '--site', outDir], { stdio: 'inherit' })\n } catch {\n console.warn('SSG: Pagefind not found, skipping search indexing')\n }\n}\n","/**\n * Vite plugin for static site generation with @pagesmith/core.\n *\n * Handles both development (on-the-fly SSR via middleware) and\n * production (post-build SSG + pagefind indexing).\n *\n * The SSR entry module must export:\n * - `getRoutes(config)` — returns route paths to pre-render\n * - `render(url, config)` — renders a route to an HTML string\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { pagesmithSsg } from '@pagesmith/core/vite'\n *\n * export default defineConfig({\n * base: '/my-site/',\n * plugins: [pagesmithSsg({ entry: './src/entry-server.tsx' })],\n * })\n * ```\n */\n\nimport { resolve } from 'path'\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport { configureSsgDevServer } from './ssg-hmr'\nimport { resolveContentDirs, renderStaticSite } from './ssg-render'\nimport { runPagefindIndexing } from './ssg-pagefind'\n\nexport type SsgPluginOptions = {\n /** Path to the SSR entry module (e.g., './src/entry-server.tsx') */\n entry: string\n /** Run pagefind after build (default: true) */\n pagefind?: boolean\n /** Content roots used for copying companion assets. */\n contentDirs?: string[]\n}\n\nexport type SsgRenderConfig = {\n /** Base path without trailing slash (e.g., '/my-site') */\n base: string\n /** Absolute path to the project root */\n root: string\n /** Path to the built CSS asset */\n cssPath: string\n /** Path to the built JS asset (undefined in dev for inline-script examples) */\n jsPath?: string\n /** Whether search is enabled (false in dev) */\n searchEnabled: boolean\n /** Whether running in dev mode */\n isDev: boolean\n}\n\nexport function pagesmithSsg(options: SsgPluginOptions): Plugin[] {\n const enablePagefind = options.pagefind !== false\n let config: ResolvedConfig\n let projectRoot: string\n let base: string // e.g., '/my-site'\n let outDir: string\n let contentDirs: string[] = []\n\n // ── Dev plugin: SSR middleware ──\n const devPlugin: Plugin = {\n name: 'pagesmith:ssg-dev',\n apply: 'serve',\n\n config() {\n // Disable Vite's built-in SPA HTML serving so the SSG middleware\n // can handle all HTML requests via server-side rendering.\n return { appType: 'custom' }\n },\n\n configResolved(resolved) {\n config = resolved\n projectRoot = resolved.root\n base = resolved.base.replace(/\\/+$/, '')\n outDir = resolve(projectRoot, resolved.build.outDir)\n contentDirs = resolveContentDirs(projectRoot, options.contentDirs)\n },\n\n configureServer(server) {\n configureSsgDevServer(server, {\n projectRoot,\n base,\n contentDirs,\n entry: options.entry,\n })\n },\n }\n\n // ── Build plugin: SSG post-build ──\n const buildPlugin: Plugin = {\n name: 'pagesmith:ssg-build',\n apply: 'build',\n\n configResolved(resolved) {\n config = resolved\n projectRoot = resolved.root\n base = resolved.base.replace(/\\/+$/, '')\n outDir = resolve(projectRoot, resolved.build.outDir)\n contentDirs = resolveContentDirs(projectRoot, options.contentDirs)\n },\n\n async closeBundle() {\n // Skip SSG during the SSR build itself (detected by ssr option)\n if (config.build.ssr) return\n\n const pageCount = await renderStaticSite({\n config,\n projectRoot,\n base,\n outDir,\n contentDirs,\n entry: options.entry,\n })\n\n if (enablePagefind) {\n await runPagefindIndexing(outDir)\n }\n\n console.log(`SSG: Done — ${pageCount} pages generated`)\n },\n }\n\n return [devPlugin, buildPlugin]\n}\n","import { existsSync } from 'fs'\nimport { dirname, relative, resolve } from 'path'\nimport type { PagesmithContentPluginOptions } from './content-plugin'\n\nfunction stripExtension(filePath: string): string {\n return filePath.replace(/\\.(c|m)?[jt]sx?$/u, '')\n}\n\nfunction normalizePath(value: string): string {\n return value.replace(/\\\\/g, '/')\n}\n\nexport function resolveDtsPath(\n projectRoot: string,\n dts: PagesmithContentPluginOptions<any>['dts'],\n): string {\n if (dts === false) {\n return ''\n }\n\n if (typeof dts === 'string') {\n return resolve(projectRoot, dts)\n }\n\n if (typeof dts === 'object' && dts?.path) {\n return resolve(projectRoot, dts.path)\n }\n\n const srcPath = resolve(projectRoot, 'src')\n if (existsSync(srcPath)) {\n return resolve(srcPath, 'pagesmith-content.d.ts')\n }\n\n return resolve(projectRoot, 'pagesmith-content.d.ts')\n}\n\nexport function createDtsSource(\n moduleId: string,\n collectionNames: string[],\n dtsPath: string,\n configPath: string,\n): string {\n const configImportPath = normalizePath(\n stripExtension(relative(dirname(dtsPath), configPath)).replace(/^[^.]/u, './$&'),\n )\n\n const moduleLines = collectionNames\n .map(\n (name) => `declare module '${moduleId}/${name}' {\n const collection: import('@pagesmith/core/vite').ContentCollectionModule<\n __PagesmithCollections['${name.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\")}']\n >\n export default collection\n}`,\n )\n .join('\\n\\n')\n\n return `// Generated by @pagesmith/core/vite. Do not edit manually.\ntype __PagesmithCollections = typeof import('${configImportPath}').default\n\ndeclare module '${moduleId}' {\n const content: import('@pagesmith/core/vite').ContentModuleMap<__PagesmithCollections>\n export default content\n}\n\n${moduleLines}\n`\n}\n","import { mkdirSync, writeFileSync } from 'fs'\nimport { dirname, relative, resolve } from 'path'\nimport { uneval } from 'devalue'\nimport { createContentLayer } from '../content-layer'\nimport { resolveLoader } from '../loaders'\nimport type { Heading } from '../schemas/heading'\nimport type { CollectionDef, CollectionMap, InferCollectionData } from '../schemas/collection'\nimport type { ContentLayerConfig } from '../schemas/content-config'\nimport { toSlug } from '../utils/slug'\nimport { createDtsSource, resolveDtsPath } from './dts'\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {}\n\ntype PagesmithResolvedConfig = {\n root: string\n}\n\ntype PagesmithModuleGraph = {\n getModuleById(id: string): unknown\n invalidateModule(module: unknown): void\n}\n\ntype PagesmithDevServer = {\n moduleGraph: PagesmithModuleGraph\n ws: {\n send(payload: { type: string }): void\n }\n}\n\nexport type PagesmithVitePlugin = {\n name: string\n enforce?: 'pre' | 'post'\n configResolved?: (config: PagesmithResolvedConfig) => void\n buildStart?: () => void\n resolveId?: (id: string) => string | void\n load?: (id: string) => Promise<string | void> | string | void\n handleHotUpdate?: (context: { file: string; server: PagesmithDevServer }) => void\n}\n\nexport type BaseContentModuleEntry = {\n id: string\n contentSlug: string\n}\n\nexport type MarkdownContentModuleEntry<TCollection extends CollectionDef<any, any, any>> = Simplify<\n BaseContentModuleEntry & {\n html: string\n headings: Heading[]\n frontmatter: InferCollectionData<TCollection>\n }\n>\n\nexport type DataContentModuleEntry<TCollection extends CollectionDef<any, any, any>> = Simplify<\n BaseContentModuleEntry & {\n data: InferCollectionData<TCollection>\n }\n>\n\ntype LoaderKindFromCollection<TCollection extends CollectionDef<any, any, any>> =\n TCollection['loader'] extends 'markdown'\n ? 'markdown'\n : TCollection['loader'] extends { kind: infer TKind }\n ? TKind\n : 'data'\n\nexport type ContentCollectionModule<TCollection extends CollectionDef<any, any, any>> =\n LoaderKindFromCollection<TCollection> extends 'markdown'\n ? MarkdownContentModuleEntry<TCollection>[]\n : DataContentModuleEntry<TCollection>[]\n\nexport type ContentModuleMap<TCollections extends CollectionMap> = {\n [TName in keyof TCollections]: ContentCollectionModule<TCollections[TName]>\n}\n\nexport type PagesmithContentPluginOptions<TCollections extends CollectionMap> = Omit<\n ContentLayerConfig,\n 'collections'\n> & {\n collections: TCollections\n /**\n * Shared content root used to compute `id` and `contentSlug`.\n * Defaults to the deepest common parent directory across all collection directories.\n */\n contentRoot?: string\n /**\n * Root virtual module id.\n * Per-collection modules are exposed as `${moduleId}/<collection-name>`.\n */\n moduleId?: string\n /**\n * Path to the content config module used for generated typings.\n * Defaults to `./content.config.ts`.\n */\n configPath?: string\n /**\n * Generate module declarations for the virtual modules.\n * Defaults to `src/pagesmith-content.d.ts` when `src/` exists, otherwise `pagesmith-content.d.ts`.\n */\n dts?: boolean | string | { path?: string }\n}\n\nconst DEFAULT_MODULE_ID = 'virtual:content'\n\nfunction normalizePath(value: string): string {\n return value.replace(/\\\\/g, '/')\n}\n\nfunction isPathWithin(parent: string, candidate: string): boolean {\n const rel = normalizePath(relative(parent, candidate))\n return rel === '' || (!rel.startsWith('..') && !rel.startsWith('/'))\n}\n\nfunction commonDirectory(paths: string[]): string {\n const normalized = paths.map((path) => normalizePath(resolve(path)))\n if (normalized.length === 0) return process.cwd()\n if (normalized.length === 1) return normalized[0]\n\n const segments = normalized.map((path) => path.split('/').filter(Boolean))\n const shared: string[] = []\n const first = segments[0]!\n\n for (let index = 0; index < first.length; index += 1) {\n const segment = first[index]\n if (segments.every((parts) => parts[index] === segment)) {\n shared.push(segment)\n continue\n }\n break\n }\n\n if (shared.length === 0) {\n return resolve('/')\n }\n\n return resolve(`/${shared.join('/')}`)\n}\n\nasync function serializeCollection(\n layer: ReturnType<typeof createContentLayer>,\n collectionName: string,\n collectionDef: CollectionDef<any, any, any>,\n contentRoot: string,\n): Promise<string> {\n const entries = await layer.getCollection(collectionName)\n const loader = resolveLoader(collectionDef.loader)\n const sortedEntries = [...entries].sort((left, right) =>\n left.filePath.localeCompare(right.filePath),\n )\n\n const payload = await Promise.all(\n sortedEntries.map(async (entry) => {\n const contentSlug = toSlug(entry.filePath, contentRoot)\n const base = {\n id: contentSlug,\n contentSlug,\n }\n\n if (loader.kind === 'markdown') {\n const rendered = await entry.render()\n return {\n ...base,\n html: rendered.html,\n headings: rendered.headings,\n frontmatter: entry.data,\n }\n }\n\n return {\n ...base,\n data: entry.data,\n }\n }),\n )\n\n return `const collection = ${uneval(payload)};\\nexport default collection;\\n`\n}\n\nfunction createRootModuleSource(moduleId: string, collectionNames: string[]): string {\n const imports = collectionNames\n .map((name, index) => `import collection${index} from '${moduleId}/${name}'`)\n .join('\\n')\n const contentMap = collectionNames\n .map((name, index) => `${JSON.stringify(name)}: collection${index}`)\n .join(', ')\n\n return `${imports}\\n\\nexport default { ${contentMap} };\\n`\n}\n\nfunction resolvePluginOptions<TCollections extends CollectionMap>(\n collectionsOrOptions: TCollections | PagesmithContentPluginOptions<TCollections>,\n maybeOptions: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'> = {},\n): PagesmithContentPluginOptions<TCollections> {\n if ('collections' in collectionsOrOptions) {\n return collectionsOrOptions as PagesmithContentPluginOptions<TCollections>\n }\n\n return {\n ...maybeOptions,\n collections: collectionsOrOptions,\n }\n}\n\nexport function pagesmithContent<TCollections extends CollectionMap>(\n collections: TCollections,\n options?: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'>,\n): PagesmithVitePlugin\nexport function pagesmithContent<TCollections extends CollectionMap>(\n options: PagesmithContentPluginOptions<TCollections>,\n): PagesmithVitePlugin\nexport function pagesmithContent<TCollections extends CollectionMap>(\n collectionsOrOptions: TCollections | PagesmithContentPluginOptions<TCollections>,\n maybeOptions: Omit<PagesmithContentPluginOptions<TCollections>, 'collections'> = {},\n): PagesmithVitePlugin {\n const options = resolvePluginOptions(collectionsOrOptions, maybeOptions)\n const collectionNames = Object.keys(options.collections)\n const moduleId = options.moduleId ?? DEFAULT_MODULE_ID\n const resolvedPrefix = `\\0${moduleId}/`\n const resolvedRootId = `\\0${moduleId}`\n\n let projectRoot = process.cwd()\n let layerRoot = projectRoot\n let contentRoot = projectRoot\n let configPath = resolve(projectRoot, options.configPath ?? 'content.config.ts')\n let dtsPath = resolveDtsPath(projectRoot, options.dts)\n let layer: ReturnType<typeof createContentLayer> | null = null\n\n function getLayer(): ReturnType<typeof createContentLayer> {\n if (!layer) {\n throw new Error(\n 'pagesmith-content: ContentLayer not initialized. configResolved has not run yet.',\n )\n }\n return layer\n }\n\n const ensureDeclarations = (): void => {\n if (options.dts === false) return\n\n const source = createDtsSource(moduleId, collectionNames, dtsPath, configPath)\n mkdirSync(dirname(dtsPath), { recursive: true })\n writeFileSync(dtsPath, source)\n }\n\n return {\n name: 'pagesmith-content',\n enforce: 'pre',\n\n configResolved(config) {\n projectRoot = resolve(config.root)\n layerRoot = resolve(projectRoot, options.root ?? '.')\n configPath = resolve(projectRoot, options.configPath ?? 'content.config.ts')\n dtsPath = resolveDtsPath(projectRoot, options.dts)\n\n const collectionDirectories = collectionNames.map((name) =>\n resolve(layerRoot, options.collections[name]!.directory),\n )\n contentRoot = options.contentRoot\n ? resolve(layerRoot, options.contentRoot)\n : commonDirectory(collectionDirectories)\n\n layer = createContentLayer({\n ...options,\n root: layerRoot,\n })\n\n ensureDeclarations()\n },\n\n buildStart() {\n ensureDeclarations()\n },\n\n resolveId(id) {\n if (id === moduleId) {\n return resolvedRootId\n }\n\n for (const name of collectionNames) {\n if (id === `${moduleId}/${name}`) {\n return `${resolvedPrefix}${name}`\n }\n }\n },\n\n async load(id) {\n if (id === resolvedRootId) {\n return createRootModuleSource(moduleId, collectionNames)\n }\n\n if (!id.startsWith(resolvedPrefix)) return\n\n const collectionName = id.slice(resolvedPrefix.length)\n const collectionDef = options.collections[collectionName]\n if (!collectionDef) return\n\n return serializeCollection(getLayer(), collectionName, collectionDef, contentRoot)\n },\n\n handleHotUpdate({ file, server }) {\n const resolvedFile = resolve(file)\n const touchesConfig = resolvedFile === configPath\n\n const affectedCollections = collectionNames.filter((name) =>\n isPathWithin(resolve(layerRoot, options.collections[name]!.directory), resolvedFile),\n )\n\n const touchesContent = affectedCollections.length > 0\n\n if (!touchesConfig && !touchesContent) return\n\n if (touchesConfig) {\n ensureDeclarations()\n }\n\n const rootModule = server.moduleGraph.getModuleById(resolvedRootId)\n if (rootModule) {\n server.moduleGraph.invalidateModule(rootModule)\n }\n\n if (touchesContent) {\n for (const name of affectedCollections) {\n const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`)\n if (moduleNode) {\n server.moduleGraph.invalidateModule(moduleNode)\n }\n getLayer()\n .invalidateCollection(name)\n .catch((err) => {\n console.warn(`[pagesmith] Failed to invalidate collection \"${name}\":`, err)\n })\n }\n } else {\n for (const name of collectionNames) {\n const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`)\n if (moduleNode) {\n server.moduleGraph.invalidateModule(moduleNode)\n }\n }\n getLayer().invalidateAll()\n }\n\n server.ws.send({ type: 'full-reload' })\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,eAAsB,gBAAgB,SAAuD;CAC3F,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,UAAU,QAAQ,WAAW;AAGnC,KAAI,CAAC,WAAW,QAAQ,YAAY,CAClC,OAAM,IAAI,MAAM,wBAAwB,QAAQ,cAAc;CAGhE,MAAM,MAAM,MAAM,OAAO,cAAc,QAAQ,YAAY,CAAC;CAC5D,MAAM,SAAoD,IAAI,UAAU,IAAI,SAAS;AAErF,KAAI,OAAO,WAAW,WACpB,OAAM,IAAI,MACR,0EACoB,OAAO,KAAK,IAAI,CAAC,KAAK,KAAK,GAChD;CAKH,MAAM,WAAW,aADI,QAAQ,QAAQ,QAAQ,aAAa,EACd,QAAQ;AAEpD,KAAI,CAAC,SAAS,SAAS,YAAY,CACjC,OAAM,IAAI,MACR,+CAA+C,YAAY,oEAE5D;AAIH,MAAK,MAAM,SAAS,QAAQ,QAAQ;EAClC,MAAM,WAAW,MAAM,OAAO,MAAM;EACpC,MAAM,OAAO,SAAS,QAAQ,aAAa,SAAS;EAEpD,MAAM,YAAY,UAAU,MAAM,KAAK,MAAM,QAAQ,OAAO,GAAG;EAC/D,MAAM,UAAU,QAAQ,QAAQ,QAAQ,WAAW,aAAa;AAChE,YAAU,QAAQ,QAAQ,EAAE,EAAE,WAAW,MAAM,CAAC;AAChD,gBAAc,SAAS,KAAK;;AAI9B,KAAI,QAEF,QADkB,QAAQ,QAAQ,YAAY,EAC5B;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAGrD,QAAO,EAAE,OAAO,QAAQ,OAAO,QAAQ;;;;;;;;ACvFzC,SAAgB,qBAA6B;CAE3C,MAAM,YAAY,KADH,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EAAE,MAAM,KAAK,EACzC,SAAS;AAExC,QAAO;EACL,MAAM;EACN,gBAAgB,QAAQ;AACtB,UAAO,YAAY,KAAK,KAAK,KAAK,SAAS;IACzC,MAAM,MAAM,IAAI,OAAO;AAGvB,QAAI,QAAQ,uBAAuB,IAAI,SAAS,oBAAoB,EAAE;KACpE,MAAM,WAAW,KAAK,WAAW,YAAY;AAC7C,SAAI,WAAW,SAAS,EAAE;AACxB,UAAI,UAAU,KAAK;OAAE,gBAAgB;OAAY,iBAAiB;OAAY,CAAC;AAC/E,UAAI,IAAI,aAAa,UAAU,QAAQ,CAAC;AACxC;;;AAKJ,QAAI,IAAI,SAAS,iBAAiB,IAAI,IAAI,SAAS,SAAS,EAAE;KAC5D,MAAM,WAAW,IAAI,MAAM,iBAAiB,CAAC,KAAK;AAClD,SAAI,YAAY,CAAC,SAAS,SAAS,KAAK,IAAI,CAAC,SAAS,SAAS,IAAI,EAAE;MACnE,MAAM,WAAW,KAAK,WAAW,SAAS,SAAS;AACnD,UAAI,WAAW,SAAS,EAAE;AACxB,WAAI,UAAU,KAAK;QACjB,gBAAgB;QAChB,iBAAiB;QAClB,CAAC;AACF,WAAI,IAAI,aAAa,SAAS,CAAC;AAC/B;;;;AAKN,UAAM;KACN;;EAEL;;;;;;;;;;;;;;ACtBH,MAAa,OAA+B;CAC1C,SAAS;CACT,QAAQ;CACR,OAAO;CACP,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;CACR,UAAU;CACV,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;CACT;AAID,SAAgB,mBAAmB,aAAqB,cAAwB,EAAE,EAAY;AAC5F,QAAO,YAAY,KAAK,QAAQ,QAAQ,aAAa,IAAI,CAAC;;AAG5D,SAAS,iBAAiB,KAAsB;AAC9C,KAAI,CAAC,IAAI,WAAW,KAAK,CAAE,QAAO;CAClC,MAAM,OAAO,IAAI,MAAM,SAAS,EAAE,CAAC,MAAM;AACzC,QAAO,mBAAmB,IAAI,QAAQ,KAAK,CAAC,aAAa,CAAC;;AAG5D,SAAgB,wBAAwB,MAAc,MAAsB;CAC1E,MAAM,aAAa,KAAK,QAAQ,SAAS,GAAG;AAE5C,QAAO,KAAK,QACV,+CACC,OAAO,MAAc,WAA+B,cAAkC;EACrF,MAAM,MAAM,aAAa,aAAa;AACtC,MAAI,CAAC,iBAAiB,IAAI,CAAE,QAAO;EACnC,MAAM,WAAW,IAAI,MAAM,SAAS,EAAE,CAAC,MAAM;EAC7C,MAAM,SAAS,IAAI,MAAM,SAAS,OAAO;EACzC,MAAM,QAAQ,cAAc,KAAA,IAAY,OAAM;AAC9C,SAAO,GAAG,KAAK,GAAG,QAAQ,WAAW,UAAU,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI,WAAW,SAAS;GAEnG;;AAGH,SAAS,0BAA0B,QAAgB,QAAmC;AACpF,KAAI,OAAO,SAAS,EAAG;CAEvB,MAAM,YAAY,KAAK,QAAQ,SAAS;AACxC,WAAU,WAAW,EAAE,WAAW,MAAM,CAAC;AAEzC,MAAK,MAAM,CAAC,UAAU,eAAe,OACnC,cAAa,YAAY,KAAK,WAAW,SAAS,CAAC;;;;;;;AA0BvD,eAAsB,iBAAiB,SAA2C;CAChF,MAAM,EAAE,QAAQ,aAAa,MAAM,QAAQ,aAAa,UAAU;AAElE,SAAQ,IAAI,4CAA4C;CAExD,MAAM,gBAAgB,qBAAqB,YAAY;AAGvD,gBAAe,OAAO;AAItB,iBADkB,KAAK,aAAa,SAAS,EAClB,OAAO;CAGlC,MAAM,EAAE,SAAS,WAAW,oBAAoB,QAAQ,KAAK;AAG7D,SAAQ,IAAI,8BAA8B;AAC1C,OAAM,eAAe,QAAQ,aAAa,QAAQ,MAAM;CAGxD,MAAM,gBAAgB,SAAS,MAAM,CAAC,QAAQ,qBAAqB,MAAM;CACzE,MAAM,YAAY,KAAK,QAAQ,UAAU;CAEzC,MAAM,SAAS,MAAM,OAAO,cADR,KAAK,WAAW,cAAc,CACI,CAAC;CAEvD,MAAM,eAAgC;EACpC;EACA,MAAM;EACN;EACA;EACA,eAAe;EACf,OAAO;EACR;CAGD,MAAM,SAAmB,MAAM,OAAO,UAAU,aAAa;AAC7D,SAAQ,IAAI,kBAAkB,OAAO,OAAO,WAAW;CAEvD,MAAM,cAAc,KAAK,IAAI,OAAO,QAAQ,EAAE;CAC9C,IAAI,aAAa;CAEjB,eAAe,eAA8B;AAC3C,SAAO,aAAa,OAAO,QAAQ;GAEjC,MAAM,QAAQ,OADJ;GAEV,MAAM,OAAO,wBAAwB,MAAM,OAAO,OAAO,OAAO,aAAa,EAAE,KAAK;GAEpF,MAAM,aAAa,KAAK,QADN,UAAU,MAAM,KAAK,MAAM,QAAQ,OAAO,GAAG,EACpB,aAAa;AACxD,aAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AACnD,iBAAc,YAAY,oBAAoB,OAAO;AAErD,OAAI,UAAU,OACZ,eAAc,KAAK,QAAQ,WAAW,EAAE,oBAAoB,OAAO;;;CAKzE,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,aAAa,QAAQ,cAAc,CAAC;AACzE,OAAM,QAAQ,IAAI,QAAQ;AAE1B,2BAA0B,QAAQ,cAAc;AAGhD,QAAO,WAAW;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEnD,QAAO,OAAO;;AAGhB,SAAS,eAAe,QAAsB;CAC5C,MAAM,aAAa,QAAQ,cAAc,OAAO,KAAK,QAAQ,+BAA+B,CAAC,CAAC;CAC9F,MAAM,eAAe,KAAK,YAAY,UAAU,QAAQ;CACxD,MAAM,cAAc,KAAK,QAAQ,UAAU,QAAQ;AACnD,WAAU,aAAa,EAAE,WAAW,MAAM,CAAC;AAC3C,MAAK,MAAM,QAAQ,YAAY,aAAa,CAC1C,KAAI,KAAK,SAAS,SAAS,CACzB,cAAa,KAAK,cAAc,KAAK,EAAE,KAAK,aAAa,KAAK,CAAC;AAGnE,cAAa,KAAK,YAAY,UAAU,YAAY,EAAE,KAAK,QAAQ,UAAU,YAAY,CAAC;;AAG5F,SAAS,oBACP,QACA,MACiD;CACjD,MAAM,aAAa,KAAK,QAAQ,aAAa;CAC7C,IAAI,UAAU,GAAG,KAAK;CACtB,IAAI;AACJ,KAAI,WAAW,WAAW,EAAE;EAC1B,MAAM,OAAO,aAAa,YAAY,QAAQ;EAC9C,MAAM,WAAW,KAAK,MAAM,sBAAsB;EAClD,MAAM,UAAU,KAAK,MAAM,oBAAoB;AAC/C,MAAI,SAAU,WAAU,SAAS;AACjC,MAAI,QAAS,UAAS,QAAQ;;AAEhC,QAAO;EAAE;EAAS;EAAQ;;AAG5B,eAAe,eACb,QACA,aACA,QACA,OACe;CACf,MAAM,EAAE,iBAAiB,MAAM,OAAO;CACtC,MAAM,YAAY,KAAK,QAAQ,UAAU;CACzC,MAAM,WAAW,QAAQ,aAAa,MAAM;CAE5C,MAAM,cAAc;;;cAGR,KAAK,UAAU,YAAY,CAAC;;cAE5B,KAAK,UAAU,OAAO,KAAK,CAAC;;eAE3B,KAAK,UAAU,SAAS,CAAC;kBACtB,KAAK,UAAU,UAAU,CAAC;;;;;AAK1C,cAAa,QAAQ,UAAU;EAAC;EAAuB;EAAM;EAAY,EAAE;EACzE,OAAO;EACP,KAAK;EACN,CAAC;;;;;;;;;;;;;;;;;;;;ACtMJ,SAAgB,sBAAsB,QAAuB,SAA8B;CACzF,MAAM,EAAE,aAAa,MAAM,aAAa,UAAU;CAClD,IAAI,gCAAgB,IAAI,KAAqB;CAE7C,eAAe,0BAAyC;AACtD,kBAAgB,qBAAqB,YAAY;;AAG9C,0BAAyB,CAAC,OAAO,UAAU;AAC9C,UAAQ,KACN,qDAAqD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5G;GACD;AAEF,KAAI,YAAY,SAAS,GAAG;AAC1B,SAAO,QAAQ,IAAI,YAAY;EAE/B,MAAM,gBAAgB;AACf,4BAAyB,CAAC,OAAO,UAAU;AAC9C,YAAQ,KACN,qDAAqD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5G;KACD;;AAGJ,SAAO,QAAQ,GAAG,OAAO,QAAQ;AACjC,SAAO,QAAQ,GAAG,UAAU,QAAQ;AACpC,SAAO,QAAQ,GAAG,UAAU,QAAQ;;AAKtC,QAAO,YAAY,IAAI,OAAO,KAAK,KAAK,SAAS;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,WAAW,IAAI,MAAM,SAAS,EAAE,CAAC,MAAM;AAE7C,MAAI,SAAS,SAAS,WAAW,EAAE;GACjC,MAAM,YAAY,SAAS,MAAM,WAAW,CAAC,KAAK;GAClD,MAAM,YAAY,YAAY,cAAc,IAAI,UAAU,GAAG,KAAA;AAE7D,OAAI,WAAW;IACb,MAAM,MAAM,QAAQ,UAAU,CAAC,aAAa;AAC5C,QAAI,UAAU,KAAK;KACjB,gBAAgB,KAAK,QAAQ;KAC7B,iBAAiB;KAClB,CAAC;AACF,QAAI,IAAI,aAAa,UAAU,CAAC;AAChC;;;EAKJ,MAAM,SAAS,IAAI,QAAQ,UAAU;EACrC,MAAM,UAAU,QAAQ,SAAS;AACjC,MAAI,WAAW,YAAY,QAAS,QAAO,MAAM;AACjD,MAAI,CAAC,WAAW,CAAC,OAAO,SAAS,YAAY,CAAE,QAAO,MAAM;AAG5D,MAAI,SAAS,QAAQ,OAAO,QAAQ,KAAK;AACvC,OAAI,UAAU,KAAK,EAAE,UAAU,GAAG,KAAK,IAAI,CAAC;AAC5C,OAAI,KAAK;AACT;;AAIF,MAAI,QAAQ,CAAC,IAAI,WAAW,KAAK,CAAE,QAAO,MAAM;AAEhD,MAAI;GAGF,MAAM,YADS,MAAM,OAAO,cAAc,QAAQ,aAAa,MAAM,CAAC,EAE7D;AAET,OAAI,OAAO,aAAa,WACtB,QAAO,MAAM;GAYf,IAAI,OAAO,MAAM,SAAS,KATY;IACpC;IACA,MAAM;IACN,SAAS,GAAG,KAAK;IACjB,QAAQ,KAAA;IACR,eAAe;IACf,OAAO;IACR,CAE2C;AAC5C,UAAO,wBAAwB,MAAM,KAAK;AAG1C,UAAO,KAAK,QACV,WACA,sFACkC,KAAK,2BAExC;AAGD,UAAO,MAAM,OAAO,mBAAmB,KAAK,KAAK;GAEjD,MAAM,SAAS,KAAK,SAAS,gBAAgB,GAAG,MAAM;AACtD,OAAI,UAAU,QAAQ,EAAE,gBAAgB,4BAA4B,CAAC;AACrE,OAAI,IAAI,KAAK;WACN,KAAc;AACrB,OAAI,eAAe,MACjB,QAAO,iBAAiB,IAAI;AAE9B,WAAQ,MAAM,iBAAiB,IAAI,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACxF,QAAK,IAAI;;GAEX;;;;;;;;;;;;;;;;;AChIJ,eAAsB,oBAAoB,QAA+B;AACvE,SAAQ,IAAI,iCAAiC;AAC7C,KAAI;EAEF,MAAM,cAAc,KAAK,QADJ,cAAc,OAAO,KAAK,QAAQ,WAAW,CAAC,CACrB,EAAE,MAAM,OAAO,UAAU,UAAU;EACjF,MAAM,EAAE,iBAAiB,MAAM,OAAO;AACtC,eAAa,QAAQ,UAAU;GAAC;GAAa;GAAU;GAAO,EAAE,EAAE,OAAO,WAAW,CAAC;SAC/E;AACN,UAAQ,KAAK,oDAAoD;;;;;;;;;;;;;;;;;;;;;;;;;;AC2BrE,SAAgB,aAAa,SAAqC;CAChE,MAAM,iBAAiB,QAAQ,aAAa;CAC5C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,cAAwB,EAAE;AAiE9B,QAAO,CA9DmB;EACxB,MAAM;EACN,OAAO;EAEP,SAAS;AAGP,UAAO,EAAE,SAAS,UAAU;;EAG9B,eAAe,UAAU;AACvB,YAAS;AACT,iBAAc,SAAS;AACvB,UAAO,SAAS,KAAK,QAAQ,QAAQ,GAAG;AACxC,YAAS,QAAQ,aAAa,SAAS,MAAM,OAAO;AACpD,iBAAc,mBAAmB,aAAa,QAAQ,YAAY;;EAGpE,gBAAgB,QAAQ;AACtB,yBAAsB,QAAQ;IAC5B;IACA;IACA;IACA,OAAO,QAAQ;IAChB,CAAC;;EAEL,EAG2B;EAC1B,MAAM;EACN,OAAO;EAEP,eAAe,UAAU;AACvB,YAAS;AACT,iBAAc,SAAS;AACvB,UAAO,SAAS,KAAK,QAAQ,QAAQ,GAAG;AACxC,YAAS,QAAQ,aAAa,SAAS,MAAM,OAAO;AACpD,iBAAc,mBAAmB,aAAa,QAAQ,YAAY;;EAGpE,MAAM,cAAc;AAElB,OAAI,OAAO,MAAM,IAAK;GAEtB,MAAM,YAAY,MAAM,iBAAiB;IACvC;IACA;IACA;IACA;IACA;IACA,OAAO,QAAQ;IAChB,CAAC;AAEF,OAAI,eACF,OAAM,oBAAoB,OAAO;AAGnC,WAAQ,IAAI,eAAe,UAAU,kBAAkB;;EAE1D,CAE8B;;;;ACvHjC,SAAS,eAAe,UAA0B;AAChD,QAAO,SAAS,QAAQ,qBAAqB,GAAG;;AAGlD,SAASA,gBAAc,OAAuB;AAC5C,QAAO,MAAM,QAAQ,OAAO,IAAI;;AAGlC,SAAgB,eACd,aACA,KACQ;AACR,KAAI,QAAQ,MACV,QAAO;AAGT,KAAI,OAAO,QAAQ,SACjB,QAAO,QAAQ,aAAa,IAAI;AAGlC,KAAI,OAAO,QAAQ,YAAY,KAAK,KAClC,QAAO,QAAQ,aAAa,IAAI,KAAK;CAGvC,MAAM,UAAU,QAAQ,aAAa,MAAM;AAC3C,KAAI,WAAW,QAAQ,CACrB,QAAO,QAAQ,SAAS,yBAAyB;AAGnD,QAAO,QAAQ,aAAa,yBAAyB;;AAGvD,SAAgB,gBACd,UACA,iBACA,SACA,YACQ;AAgBR,QAAO;+CAfkBA,gBACvB,eAAe,SAAS,QAAQ,QAAQ,EAAE,WAAW,CAAC,CAAC,QAAQ,UAAU,OAAO,CACjF,CAc6D;;kBAE9C,SAAS;;;;;EAdL,gBACjB,KACE,SAAS,mBAAmB,SAAS,GAAG,KAAK;;8BAEtB,KAAK,WAAW,MAAM,OAAO,CAAC,WAAW,KAAK,MAAM,CAAC;;;GAI9E,CACA,KAAK,OAAO,CAUH;;;;;ACoCd,MAAM,oBAAoB;AAE1B,SAAS,cAAc,OAAuB;AAC5C,QAAO,MAAM,QAAQ,OAAO,IAAI;;AAGlC,SAAS,aAAa,QAAgB,WAA4B;CAChE,MAAM,MAAM,cAAc,SAAS,QAAQ,UAAU,CAAC;AACtD,QAAO,QAAQ,MAAO,CAAC,IAAI,WAAW,KAAK,IAAI,CAAC,IAAI,WAAW,IAAI;;AAGrE,SAAS,gBAAgB,OAAyB;CAChD,MAAM,aAAa,MAAM,KAAK,SAAS,cAAc,QAAQ,KAAK,CAAC,CAAC;AACpE,KAAI,WAAW,WAAW,EAAG,QAAO,QAAQ,KAAK;AACjD,KAAI,WAAW,WAAW,EAAG,QAAO,WAAW;CAE/C,MAAM,WAAW,WAAW,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAAC;CAC1E,MAAM,SAAmB,EAAE;CAC3B,MAAM,QAAQ,SAAS;AAEvB,MAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;EACpD,MAAM,UAAU,MAAM;AACtB,MAAI,SAAS,OAAO,UAAU,MAAM,WAAW,QAAQ,EAAE;AACvD,UAAO,KAAK,QAAQ;AACpB;;AAEF;;AAGF,KAAI,OAAO,WAAW,EACpB,QAAO,QAAQ,IAAI;AAGrB,QAAO,QAAQ,IAAI,OAAO,KAAK,IAAI,GAAG;;AAGxC,eAAe,oBACb,OACA,gBACA,eACA,aACiB;CACjB,MAAM,UAAU,MAAM,MAAM,cAAc,eAAe;CACzD,MAAM,SAAS,cAAc,cAAc,OAAO;CAClD,MAAM,gBAAgB,CAAC,GAAG,QAAQ,CAAC,MAAM,MAAM,UAC7C,KAAK,SAAS,cAAc,MAAM,SAAS,CAC5C;AA2BD,QAAO,sBAAsB,OAzBb,MAAM,QAAQ,IAC5B,cAAc,IAAI,OAAO,UAAU;EACjC,MAAM,cAAc,OAAO,MAAM,UAAU,YAAY;EACvD,MAAM,OAAO;GACX,IAAI;GACJ;GACD;AAED,MAAI,OAAO,SAAS,YAAY;GAC9B,MAAM,WAAW,MAAM,MAAM,QAAQ;AACrC,UAAO;IACL,GAAG;IACH,MAAM,SAAS;IACf,UAAU,SAAS;IACnB,aAAa,MAAM;IACpB;;AAGH,SAAO;GACL,GAAG;GACH,MAAM,MAAM;GACb;GACD,CACH,CAE2C,CAAC;;AAG/C,SAAS,uBAAuB,UAAkB,iBAAmC;AAQnF,QAAO,GAPS,gBACb,KAAK,MAAM,UAAU,oBAAoB,MAAM,SAAS,SAAS,GAAG,KAAK,GAAG,CAC5E,KAAK,KAAK,CAKK,uBAJC,gBAChB,KAAK,MAAM,UAAU,GAAG,KAAK,UAAU,KAAK,CAAC,cAAc,QAAQ,CACnE,KAAK,KAAK,CAEuC;;AAGtD,SAAS,qBACP,sBACA,eAAiF,EAAE,EACtC;AAC7C,KAAI,iBAAiB,qBACnB,QAAO;AAGT,QAAO;EACL,GAAG;EACH,aAAa;EACd;;AAUH,SAAgB,iBACd,sBACA,eAAiF,EAAE,EAC9D;CACrB,MAAM,UAAU,qBAAqB,sBAAsB,aAAa;CACxE,MAAM,kBAAkB,OAAO,KAAK,QAAQ,YAAY;CACxD,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,iBAAiB,KAAK,SAAS;CACrC,MAAM,iBAAiB,KAAK;CAE5B,IAAI,cAAc,QAAQ,KAAK;CAC/B,IAAI,YAAY;CAChB,IAAI,cAAc;CAClB,IAAI,aAAa,QAAQ,aAAa,QAAQ,cAAc,oBAAoB;CAChF,IAAI,UAAU,eAAe,aAAa,QAAQ,IAAI;CACtD,IAAI,QAAsD;CAE1D,SAAS,WAAkD;AACzD,MAAI,CAAC,MACH,OAAM,IAAI,MACR,mFACD;AAEH,SAAO;;CAGT,MAAM,2BAAiC;AACrC,MAAI,QAAQ,QAAQ,MAAO;EAE3B,MAAM,SAAS,gBAAgB,UAAU,iBAAiB,SAAS,WAAW;AAC9E,YAAU,QAAQ,QAAQ,EAAE,EAAE,WAAW,MAAM,CAAC;AAChD,gBAAc,SAAS,OAAO;;AAGhC,QAAO;EACL,MAAM;EACN,SAAS;EAET,eAAe,QAAQ;AACrB,iBAAc,QAAQ,OAAO,KAAK;AAClC,eAAY,QAAQ,aAAa,QAAQ,QAAQ,IAAI;AACrD,gBAAa,QAAQ,aAAa,QAAQ,cAAc,oBAAoB;AAC5E,aAAU,eAAe,aAAa,QAAQ,IAAI;GAElD,MAAM,wBAAwB,gBAAgB,KAAK,SACjD,QAAQ,WAAW,QAAQ,YAAY,MAAO,UAAU,CACzD;AACD,iBAAc,QAAQ,cAClB,QAAQ,WAAW,QAAQ,YAAY,GACvC,gBAAgB,sBAAsB;AAE1C,WAAQ,mBAAmB;IACzB,GAAG;IACH,MAAM;IACP,CAAC;AAEF,uBAAoB;;EAGtB,aAAa;AACX,uBAAoB;;EAGtB,UAAU,IAAI;AACZ,OAAI,OAAO,SACT,QAAO;AAGT,QAAK,MAAM,QAAQ,gBACjB,KAAI,OAAO,GAAG,SAAS,GAAG,OACxB,QAAO,GAAG,iBAAiB;;EAKjC,MAAM,KAAK,IAAI;AACb,OAAI,OAAO,eACT,QAAO,uBAAuB,UAAU,gBAAgB;AAG1D,OAAI,CAAC,GAAG,WAAW,eAAe,CAAE;GAEpC,MAAM,iBAAiB,GAAG,MAAM,eAAe,OAAO;GACtD,MAAM,gBAAgB,QAAQ,YAAY;AAC1C,OAAI,CAAC,cAAe;AAEpB,UAAO,oBAAoB,UAAU,EAAE,gBAAgB,eAAe,YAAY;;EAGpF,gBAAgB,EAAE,MAAM,UAAU;GAChC,MAAM,eAAe,QAAQ,KAAK;GAClC,MAAM,gBAAgB,iBAAiB;GAEvC,MAAM,sBAAsB,gBAAgB,QAAQ,SAClD,aAAa,QAAQ,WAAW,QAAQ,YAAY,MAAO,UAAU,EAAE,aAAa,CACrF;GAED,MAAM,iBAAiB,oBAAoB,SAAS;AAEpD,OAAI,CAAC,iBAAiB,CAAC,eAAgB;AAEvC,OAAI,cACF,qBAAoB;GAGtB,MAAM,aAAa,OAAO,YAAY,cAAc,eAAe;AACnE,OAAI,WACF,QAAO,YAAY,iBAAiB,WAAW;AAGjD,OAAI,eACF,MAAK,MAAM,QAAQ,qBAAqB;IACtC,MAAM,aAAa,OAAO,YAAY,cAAc,GAAG,iBAAiB,OAAO;AAC/E,QAAI,WACF,QAAO,YAAY,iBAAiB,WAAW;AAEjD,cAAU,CACP,qBAAqB,KAAK,CAC1B,OAAO,QAAQ;AACd,aAAQ,KAAK,gDAAgD,KAAK,KAAK,IAAI;MAC3E;;QAED;AACL,SAAK,MAAM,QAAQ,iBAAiB;KAClC,MAAM,aAAa,OAAO,YAAY,cAAc,GAAG,iBAAiB,OAAO;AAC/E,SAAI,WACF,QAAO,YAAY,iBAAiB,WAAW;;AAGnD,cAAU,CAAC,eAAe;;AAG5B,UAAO,GAAG,KAAK,EAAE,MAAM,eAAe,CAAC;;EAE1C"}
@@ -2,8 +2,28 @@
2
2
 
3
3
  ## @pagesmith/core
4
4
 
5
- Use the installed package guidance, not copied snippets:
5
+ Install: `npm add @pagesmith/core`
6
6
 
7
- - `node_modules/@pagesmith/core/docs/agents/usage.md`
8
- - `node_modules/@pagesmith/core/docs/agents/recipes.md`
9
- - `node_modules/@pagesmith/core/REFERENCE.md`
7
+ Use the installed package guidance — these files are version-matched to what you have installed:
8
+
9
+ ### Primary references
10
+
11
+ - `node_modules/@pagesmith/core/REFERENCE.md` — complete API reference: content layer, collections, loaders, markdown, JSX, CSS, Vite plugins
12
+ - `node_modules/@pagesmith/core/docs/agents/usage.md` — agent rules, integration shape, and copy-paste prompts for common workflows
13
+ - `node_modules/@pagesmith/core/docs/agents/errors.md` — error catalog with patterns and fixes
14
+
15
+ ### Task-specific files
16
+
17
+ | Task | Read |
18
+ |---|---|
19
+ | Initial Vite setup | `node_modules/@pagesmith/core/REFERENCE.md`, `node_modules/@pagesmith/core/docs/agents/recipes.md` |
20
+ | Defining collections and schemas | `node_modules/@pagesmith/core/REFERENCE.md` |
21
+ | Writing markdown content (code blocks, mermaid, frontmatter) | `node_modules/@pagesmith/core/REFERENCE.md` |
22
+ | Customizing the markdown pipeline | `node_modules/@pagesmith/core/REFERENCE.md`, `node_modules/@pagesmith/core/docs/agents/recipes.md` |
23
+ | Troubleshooting validation errors | `node_modules/@pagesmith/core/docs/agents/errors.md` |
24
+ | Migration and upgrades | `node_modules/@pagesmith/core/docs/agents/migration.md`, `node_modules/@pagesmith/core/docs/agents/changelog-notes.md` |
25
+
26
+ ### Docs package (if also using @pagesmith/docs)
27
+
28
+ - `node_modules/@pagesmith/docs/REFERENCE.md`
29
+ - `node_modules/@pagesmith/docs/docs/agents/usage.md`
@@ -12,4 +12,4 @@
12
12
  - Added `docs/agents/migration.md` with pre-1.0 upgrade guidance
13
13
  - AI installer split into focused modules for maintainability
14
14
  - AI exports removed from main barrel — use `@pagesmith/core/ai` subpath or CLI `npx pagesmith init --ai`
15
- - Scripts converted from JavaScript to TypeScript (using `node --strip-types`)
15
+ - Scripts converted from JavaScript to TypeScript (using `node --strip-types`)
@@ -5,9 +5,11 @@ Machine-readable error solutions for AI agents. Each section maps a common error
5
5
  ## Schema Validation Errors
6
6
 
7
7
  ### Required field missing
8
+
8
9
  **Pattern:** `Required at "<field>"`
9
10
  **Fix:** Add the missing field to your frontmatter. Check the collection schema for required fields.
10
11
  **Example:**
12
+
11
13
  ```yaml
12
14
  ---
13
15
  title: My Page # ← required by BaseFrontmatterSchema
@@ -16,17 +18,21 @@ description: A summary # ← required by BaseFrontmatterSchema
16
18
  ```
17
19
 
18
20
  ### Invalid date format
21
+
19
22
  **Pattern:** `Expected date, received string` or `Invalid date`
20
23
  **Fix:** Use ISO 8601 format: `YYYY-MM-DD` or `YYYY-MM-DDTHH:mm:ss`.
21
24
  **Example:** `publishedDate: 2024-01-15`
22
25
 
23
26
  ### Unknown field
27
+
24
28
  **Pattern:** `Unrecognized key(s) in object: "<field>"`
25
29
  **Fix:** The schema uses `.strict()`. Remove the unrecognized field or update the schema to include it.
26
30
 
27
31
  ### Type mismatch
32
+
28
33
  **Pattern:** `Expected <type>, received <type>`
29
34
  **Fix:** Ensure the frontmatter value matches the schema type. Common mismatches:
35
+
30
36
  - `tags` must be an array: `tags: [a, b]` not `tags: a, b`
31
37
  - `draft` must be boolean: `draft: true` not `draft: "true"`
32
38
  - `order` must be number: `order: 1` not `order: "1"`
@@ -34,63 +40,111 @@ description: A summary # ← required by BaseFrontmatterSchema
34
40
  ## Content Validation Errors
35
41
 
36
42
  ### Missing heading
37
- **Pattern:** `No h1 heading found`
43
+
44
+ **Pattern:** `Document has content but no headings`
38
45
  **Fix:** Add a top-level `# Heading` to your markdown content, or set `title` in frontmatter (some setups auto-generate h1 from title).
39
46
 
40
47
  ### Heading level skip
41
- **Pattern:** `Heading level skipped from h<n> to h<m>`
48
+
49
+ **Pattern:** `Heading level skip: h<n> -> h<m> ("<text>")`
42
50
  **Fix:** Don't skip heading levels. After `## Section`, use `### Subsection`, not `#### Deep`.
43
51
 
44
52
  ### Bare URL
53
+
45
54
  **Pattern:** `Bare URL found`
46
55
  **Fix:** Wrap URLs in markdown links: `[Link text](https://example.com)` instead of bare `https://example.com`.
47
56
 
48
57
  ### Missing code language
49
- **Pattern:** `Code block without language specifier`
50
- **Fix:** Add a language to fenced code blocks: ` ```js ` instead of ` ``` `.
58
+
59
+ **Pattern:** `Code block has meta properties but no language identifier`
60
+ **Fix:** Add a language identifier to code blocks that use meta properties like `title`, `mark`, etc.
61
+
62
+ ### Unknown meta property
63
+
64
+ **Pattern:** `Unknown code block meta property: "<prop>"`
65
+ **Fix:** Use only supported Expressive Code meta properties: `title`, `showLineNumbers`, `startLineNumber`, `wrap`, `frame`, `collapse`, `mark`, `ins`, `del`.
51
66
 
52
67
  ### Unknown code language
68
+
53
69
  **Pattern:** `Unknown language "<lang>"`
54
70
  **Fix:** Use a supported language identifier. Common mappings: `ts` for TypeScript, `js` for JavaScript, `sh`/`bash` for Shell. See Expressive Code language list.
55
71
 
56
72
  ## Plugin Validation Errors
57
73
 
58
74
  ### Plugin threw
59
- **Pattern:** `Validator "<name>" threw: <message>`
75
+
76
+ **Pattern:** `[<name>] Validator threw: <message>`
60
77
  **Fix:** A custom or plugin validator encountered an unexpected error. Check the plugin's documentation for the specific error message. The validator name identifies which plugin failed.
61
78
 
62
79
  ## Load Errors
63
80
 
64
81
  ### File not found
82
+
65
83
  **Pattern:** `Failed to load <path>: ENOENT`
66
84
  **Fix:** The file was deleted or moved. Update your content directory or remove the reference.
67
85
 
68
86
  ### Invalid YAML frontmatter
87
+
69
88
  **Pattern:** `Failed to load <path>: YAMLException`
70
89
  **Fix:** Check frontmatter YAML syntax. Common issues:
90
+
71
91
  - Missing `---` delimiters
72
92
  - Unquoted special characters (`:`, `#`, `[`, `{`)
73
93
  - Incorrect indentation
74
94
 
75
95
  ### Invalid JSON
96
+
76
97
  **Pattern:** `Failed to load <path>: JSON` or `Unexpected token`
77
98
  **Fix:** Validate your JSON/JSON5 file syntax. Use a JSON linter.
78
99
 
79
100
  ## MCP Server Errors
80
101
 
81
102
  ### Config not found
82
- **Pattern:** `No pagesmith.config.json5 file found`
103
+
104
+ **Pattern:** `No pagesmith.config.json5 file found at <path>`
83
105
  **Fix:** Run `npx pagesmith init` to create a config file, or pass `--config <path>` to specify the location.
84
106
 
85
107
  ### Entry not found
108
+
86
109
  **Pattern:** `Entry not found: <collection>/<slug>`
87
110
  **Fix:** Verify the collection name and slug. Use `core_list_entries` to see available entries.
88
111
 
112
+ ## Content Layer Errors
113
+
114
+ ### Collection not found
115
+
116
+ **Pattern:** `Collection "<name>" not found. Available: <list>`
117
+ **Fix:** Check the collection name passed to `getCollection()` or `getEntry()`. The error lists all configured collection names — use one of those.
118
+
119
+ ### Markdown processing failed
120
+
121
+ **Pattern:** `Markdown processing failed: <message>`
122
+ **Fix:** The unified markdown pipeline threw an error. Common causes:
123
+
124
+ - Invalid remark/rehype plugin configuration
125
+ - Malformed markdown that breaks a parser plugin
126
+ - Shiki theme or language loading failure
127
+
128
+ Check the inner error message for details. If caused by a custom plugin, verify the plugin implementation.
129
+
130
+ ### Unknown loader type
131
+
132
+ **Pattern:** `Unknown loader type: <type>`
133
+ **Fix:** The `loader` field in your collection definition uses an unrecognized type string. Supported built-in types: `markdown`, `json`, `json5`, `jsonc`, `yaml`, `toml`. For custom loaders, pass a `Loader` object instead of a string.
134
+
135
+ ## Vite Plugin Errors
136
+
137
+ ### ContentLayer not initialized
138
+
139
+ **Pattern:** `pagesmith-content: ContentLayer not initialized. configResolved has not run yet.`
140
+ **Fix:** The `pagesmithContent` Vite plugin tried to load content before Vite called `configResolved`. This usually means the plugin was misconfigured or a module tried to import content at config time. Ensure the plugin is registered in `vite.config.ts` and content is only imported from application code (not config files).
141
+
89
142
  ## Quick Diagnostic Workflow
90
143
 
91
144
  When encountering an error:
92
145
 
93
- 1. **Identify the source** — check the `source` field: `schema`, `content`, `plugin`, or `custom`
146
+ 1. **Identify the source** — each `ValidationIssue` has a `source` field indicating where it originated: `schema` (Zod safeParse), `content` (MDAST-based validators), `plugin` (plugin validators), or `custom` (collection `validate` function)
94
147
  2. **Match the pattern** — find the error pattern above
95
148
  3. **Apply the fix** — follow the specific fix instructions
96
149
  4. **Re-validate** — use `core_validate` MCP tool or rebuild to confirm the fix
150
+
@@ -5,13 +5,13 @@
5
5
  ## Upgrade checklist
6
6
 
7
7
  1. Prefer subpath imports from the package export map:
8
- - `@pagesmith/core/vite`
9
- - `@pagesmith/core/mcp`
10
- - `@pagesmith/core/ssg-utils`
8
+ - `@pagesmith/core/vite`
9
+ - `@pagesmith/core/mcp`
10
+ - `@pagesmith/core/ssg-utils`
11
11
  2. Keep Vite integration scripts aligned with current examples (`vite dev`, `vite build`) in downstream projects.
12
12
  3. Re-run validation and tests after upgrade:
13
- - `vp check`
14
- - `vp test`
13
+ - `vp check`
14
+ - `vp test`
15
15
 
16
16
  ## Behavior updates to note
17
17
 
@@ -21,5 +21,5 @@
21
21
 
22
22
  ## Related docs
23
23
 
24
- - `docs/agents/changelog-notes.md`
25
- - `REFERENCE.md`
24
+ - `node_modules/@pagesmith/core/docs/agents/changelog-notes.md`
25
+ - `node_modules/@pagesmith/core/REFERENCE.md`
@@ -1,5 +1,7 @@
1
1
  # @pagesmith/core Agent Recipes
2
2
 
3
+ Short procedural recipes for common content layer workflows. For the full reference, see `node_modules/@pagesmith/core/REFERENCE.md`.
4
+
3
5
  ## Create a collection
4
6
 
5
7
  1. Add a directory under `content/`.
@@ -7,20 +9,42 @@
7
9
  3. Register with `defineCollection`.
8
10
  4. Expose via `defineCollections` or `defineConfig`.
9
11
 
12
+ **Read:** `node_modules/@pagesmith/core/REFERENCE.md` (Content Layer API, Collections)
13
+
10
14
  ## Add Vite integration
11
15
 
12
16
  1. Import `pagesmithContent` and `pagesmithSsg` from `@pagesmith/core/vite`.
13
17
  2. Register content plugin before SSG output steps.
14
18
  3. Ensure SSR entry exports `getRoutes` and `render`.
15
19
 
20
+ **Read:** `node_modules/@pagesmith/core/REFERENCE.md` (Vite Plugins)
21
+
22
+ ## Write markdown content
23
+
24
+ 1. Create markdown files with frontmatter (`title`, `description`, etc.).
25
+ 2. Use fenced code blocks with language identifiers.
26
+ 3. Use Expressive Code meta for titles, line numbers, and line highlighting.
27
+ 4. Use mermaid code blocks for diagrams (` ```mermaid `).
28
+ 5. Use GitHub Alerts for callouts (`> [!NOTE]`, `> [!TIP]`, `> [!WARNING]`).
29
+ 6. Validate with built-in content validators.
30
+
31
+ **Read:** `node_modules/@pagesmith/core/REFERENCE.md` (Markdown Pipeline, Expressive Code, Validators)
32
+
16
33
  ## Update markdown behavior
17
34
 
18
35
  1. Update config through markdown options (`remarkPlugins`, `rehypePlugins`, `shiki`).
19
36
  2. Keep plugin order consistent with pipeline expectations.
20
37
  3. Validate with rendered output and built-in validators.
21
38
 
39
+ **Read:** `node_modules/@pagesmith/core/REFERENCE.md` (Markdown Pipeline, Custom Plugins)
40
+
22
41
  ## Update AI pointers in consuming project
23
42
 
24
- Add one pointer line to root `CLAUDE.md` or `AGENTS.md`:
43
+ Add pointer lines to root `CLAUDE.md` or `AGENTS.md`:
44
+
45
+ ```
46
+ For @pagesmith/core usage and prompts, read node_modules/@pagesmith/core/docs/agents/usage.md
47
+ For the full @pagesmith/core API reference, see node_modules/@pagesmith/core/REFERENCE.md
48
+ ```
25
49
 
26
- `Use node_modules/@pagesmith/core/docs/agents/usage.md as the canonical @pagesmith/core guide.`
50
+ Or copy `node_modules/@pagesmith/core/docs/agents/AGENTS.md.template` as a starting point.