@pagesmith/core 0.1.0

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 (85) hide show
  1. package/README.md +481 -0
  2. package/assets/fonts/OFL.txt +7 -0
  3. package/assets/fonts/jetbrains-mono-variable.woff2 +0 -0
  4. package/assets/fonts/open-sans-variable.woff2 +0 -0
  5. package/assets/fonts.css +17 -0
  6. package/dist/ai/index.d.mts +41 -0
  7. package/dist/ai/index.d.mts.map +1 -0
  8. package/dist/ai/index.mjs +414 -0
  9. package/dist/ai/index.mjs.map +1 -0
  10. package/dist/assets/index.d.mts +31 -0
  11. package/dist/assets/index.d.mts.map +1 -0
  12. package/dist/assets/index.mjs +2 -0
  13. package/dist/assets-bX08zEJm.mjs +155 -0
  14. package/dist/assets-bX08zEJm.mjs.map +1 -0
  15. package/dist/content-config-fHPaFZ7i.d.mts +1128 -0
  16. package/dist/content-config-fHPaFZ7i.d.mts.map +1 -0
  17. package/dist/content-layer-B7fQ3im4.mjs +590 -0
  18. package/dist/content-layer-B7fQ3im4.mjs.map +1 -0
  19. package/dist/convert-DnuB6SVV.mjs +52 -0
  20. package/dist/convert-DnuB6SVV.mjs.map +1 -0
  21. package/dist/create/index.d.mts +20 -0
  22. package/dist/create/index.d.mts.map +1 -0
  23. package/dist/create/index.mjs +215 -0
  24. package/dist/create/index.mjs.map +1 -0
  25. package/dist/css/index.d.mts +2 -0
  26. package/dist/css/index.mjs +2 -0
  27. package/dist/css-ekIt2Fdb.mjs +19 -0
  28. package/dist/css-ekIt2Fdb.mjs.map +1 -0
  29. package/dist/heading-Dhvzlay-.d.mts +27 -0
  30. package/dist/heading-Dhvzlay-.d.mts.map +1 -0
  31. package/dist/index-BQ6B1-qG.d.mts +41 -0
  32. package/dist/index-BQ6B1-qG.d.mts.map +1 -0
  33. package/dist/index-CeNDTM-y.d.mts +7 -0
  34. package/dist/index-CeNDTM-y.d.mts.map +1 -0
  35. package/dist/index-DpRBzO8Q.d.mts +15 -0
  36. package/dist/index-DpRBzO8Q.d.mts.map +1 -0
  37. package/dist/index-sFCx17CD.d.mts +59 -0
  38. package/dist/index-sFCx17CD.d.mts.map +1 -0
  39. package/dist/index.d.mts +131 -0
  40. package/dist/index.d.mts.map +1 -0
  41. package/dist/index.mjs +56 -0
  42. package/dist/index.mjs.map +1 -0
  43. package/dist/jsx-runtime/index.d.mts +24 -0
  44. package/dist/jsx-runtime/index.d.mts.map +1 -0
  45. package/dist/jsx-runtime/index.mjs +88 -0
  46. package/dist/jsx-runtime/index.mjs.map +1 -0
  47. package/dist/loaders/index.d.mts +3 -0
  48. package/dist/loaders/index.mjs +2 -0
  49. package/dist/loaders-DyABmDrE.mjs +179 -0
  50. package/dist/loaders-DyABmDrE.mjs.map +1 -0
  51. package/dist/markdown/index.d.mts +3 -0
  52. package/dist/markdown/index.mjs +2 -0
  53. package/dist/markdown-Cj5X26FL.mjs +95 -0
  54. package/dist/markdown-Cj5X26FL.mjs.map +1 -0
  55. package/dist/runtime/index.d.mts +28 -0
  56. package/dist/runtime/index.d.mts.map +1 -0
  57. package/dist/runtime/index.mjs +90 -0
  58. package/dist/runtime/index.mjs.map +1 -0
  59. package/dist/schemas/index.d.mts +4 -0
  60. package/dist/schemas/index.mjs +2 -0
  61. package/dist/schemas-DJS7wOzd.mjs +47 -0
  62. package/dist/schemas-DJS7wOzd.mjs.map +1 -0
  63. package/dist/types-DUsjRE7Y.d.mts +28 -0
  64. package/dist/types-DUsjRE7Y.d.mts.map +1 -0
  65. package/dist/vite/index.d.mts +9878 -0
  66. package/dist/vite/index.d.mts.map +1 -0
  67. package/dist/vite/index.mjs +549 -0
  68. package/dist/vite/index.mjs.map +1 -0
  69. package/package.json +136 -0
  70. package/src/styles/code/inline.css +26 -0
  71. package/src/styles/content/alerts.css +87 -0
  72. package/src/styles/content/prose.css +225 -0
  73. package/src/styles/content/toc.css +87 -0
  74. package/src/styles/content.css +22 -0
  75. package/src/styles/foundations/reset.css +49 -0
  76. package/src/styles/foundations/tokens.css +66 -0
  77. package/src/styles/layout/grid.css +179 -0
  78. package/src/styles/layout/sidebar.css +18 -0
  79. package/src/styles/standalone.css +18 -0
  80. package/src/styles/viewport.css +20 -0
  81. package/templates/docs/content/README.md +18 -0
  82. package/templates/docs/content/guide/README.md +11 -0
  83. package/templates/docs/content/guide/getting-started/README.md +9 -0
  84. package/templates/docs/content/reference/README.md +11 -0
  85. package/templates/docs/pagesmith.config.json5 +15 -0
@@ -0,0 +1,549 @@
1
+ import "../markdown-Cj5X26FL.mjs";
2
+ import { s as toSlug, t as createContentLayer } from "../content-layer-B7fQ3im4.mjs";
3
+ import { n as resolveLoader } from "../loaders-DyABmDrE.mjs";
4
+ import { n as copyPublicFiles } from "../assets-bX08zEJm.mjs";
5
+ import { dirname, extname, join, relative, resolve } from "path";
6
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
7
+ import { fileURLToPath, pathToFileURL } from "url";
8
+ import { uneval } from "devalue";
9
+ //#region src/vite/ssg.ts
10
+ /**
11
+ * Pre-rendering utility for Vite-based SSG sites.
12
+ *
13
+ * Call after running both the client and SSR Vite builds.
14
+ * Loads the SSR module, renders each route, injects into the
15
+ * client HTML template, and writes static files.
16
+ */
17
+ /**
18
+ * Pre-render routes to static HTML files.
19
+ *
20
+ * Expects the SSR entry to export a `render(url: string): string` function.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { build } from 'vite'
25
+ * import { prerenderRoutes } from '@pagesmith/core/vite'
26
+ *
27
+ * // 1. Client build
28
+ * await build({ build: { outDir: 'dist' } })
29
+ *
30
+ * // 2. SSR build
31
+ * await build({ build: { ssr: 'src/entry-server.tsx', outDir: 'dist/.server' } })
32
+ *
33
+ * // 3. Pre-render
34
+ * await prerenderRoutes({
35
+ * outDir: resolve('dist'),
36
+ * serverEntry: resolve('dist/.server/entry-server.js'),
37
+ * routes: ['/', '/about', '/posts/hello-world'],
38
+ * })
39
+ * ```
40
+ */
41
+ async function prerenderRoutes(options) {
42
+ const placeholder = options.placeholder ?? "<!--ssr-outlet-->";
43
+ const cleanup = options.cleanup ?? true;
44
+ if (!existsSync(options.serverEntry)) throw new Error(`SSR entry not found: ${options.serverEntry}`);
45
+ const mod = await import(pathToFileURL(options.serverEntry).href);
46
+ const render = mod.render ?? mod.default?.render;
47
+ if (typeof render !== "function") throw new Error(`SSR entry must export a 'render(url: string)' function. Found exports: ${Object.keys(mod).join(", ")}`);
48
+ const template = readFileSync(resolve(options.outDir, "index.html"), "utf-8");
49
+ if (!template.includes(placeholder)) throw new Error(`HTML template does not contain placeholder "${placeholder}". Add it to your index.html where SSR content should be injected.`);
50
+ for (const route of options.routes) {
51
+ const rendered = await render(route);
52
+ const html = template.replace(placeholder, rendered);
53
+ const routePath = route === "/" ? "" : route.replace(/^\//, "");
54
+ const outPath = resolve(options.outDir, routePath, "index.html");
55
+ mkdirSync(dirname(outPath), { recursive: true });
56
+ writeFileSync(outPath, html);
57
+ }
58
+ if (cleanup) rmSync(dirname(options.serverEntry), {
59
+ recursive: true,
60
+ force: true
61
+ });
62
+ return { pages: options.routes.length };
63
+ }
64
+ //#endregion
65
+ //#region src/vite/shared-assets.ts
66
+ /**
67
+ * Vite plugin that serves shared font assets during development.
68
+ * In production, fonts are copied to the output directory by the build script.
69
+ */
70
+ function sharedAssetsPlugin() {
71
+ const assetsDir = join(join(dirname(fileURLToPath(import.meta.url)), "..", ".."), "assets");
72
+ return {
73
+ name: "pagesmith:shared-assets",
74
+ configureServer(server) {
75
+ server.middlewares.use((req, res, next) => {
76
+ const url = req.url ?? "";
77
+ if (url === "/assets/fonts.css" || url.endsWith("/assets/fonts.css")) {
78
+ const filePath = join(assetsDir, "fonts.css");
79
+ if (existsSync(filePath)) {
80
+ res.writeHead(200, {
81
+ "Content-Type": "text/css",
82
+ "Cache-Control": "no-cache"
83
+ });
84
+ res.end(readFileSync(filePath, "utf-8"));
85
+ return;
86
+ }
87
+ }
88
+ if (url.includes("/assets/fonts/") && url.endsWith(".woff2")) {
89
+ const fileName = url.split("/assets/fonts/").pop();
90
+ if (fileName) {
91
+ const filePath = join(assetsDir, "fonts", fileName);
92
+ if (existsSync(filePath)) {
93
+ res.writeHead(200, {
94
+ "Content-Type": "font/woff2",
95
+ "Cache-Control": "public, max-age=31536000"
96
+ });
97
+ res.end(readFileSync(filePath));
98
+ return;
99
+ }
100
+ }
101
+ }
102
+ next();
103
+ });
104
+ }
105
+ };
106
+ }
107
+ //#endregion
108
+ //#region src/vite/ssg-plugin.ts
109
+ /**
110
+ * Vite plugin for static site generation with @pagesmith/core.
111
+ *
112
+ * Handles both development (on-the-fly SSR via middleware) and
113
+ * production (post-build SSG + pagefind indexing).
114
+ *
115
+ * The SSR entry module must export:
116
+ * - `getRoutes(config)` — returns route paths to pre-render
117
+ * - `render(url, config)` — renders a route to an HTML string
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * // vite.config.ts
122
+ * import { pagesmithSsg } from '@pagesmith/core/vite'
123
+ *
124
+ * export default defineConfig({
125
+ * base: '/my-site/',
126
+ * plugins: [pagesmithSsg({ entry: './src/entry-server.tsx' })],
127
+ * })
128
+ * ```
129
+ */
130
+ const MIME = {
131
+ ".html": "text/html; charset=utf-8",
132
+ ".css": "text/css; charset=utf-8",
133
+ ".js": "application/javascript; charset=utf-8",
134
+ ".json": "application/json; charset=utf-8",
135
+ ".svg": "image/svg+xml",
136
+ ".png": "image/png",
137
+ ".jpg": "image/jpeg",
138
+ ".jpeg": "image/jpeg",
139
+ ".gif": "image/gif",
140
+ ".webp": "image/webp",
141
+ ".avif": "image/avif",
142
+ ".ico": "image/x-icon",
143
+ ".woff2": "font/woff2",
144
+ ".woff": "font/woff",
145
+ ".ttf": "font/ttf",
146
+ ".txt": "text/plain; charset=utf-8",
147
+ ".xml": "application/xml; charset=utf-8"
148
+ };
149
+ const CONTENT_ASSET_EXTS = new Set([
150
+ ".svg",
151
+ ".png",
152
+ ".jpg",
153
+ ".jpeg",
154
+ ".gif",
155
+ ".webp",
156
+ ".avif",
157
+ ".ico"
158
+ ]);
159
+ function resolveContentDirs(projectRoot, contentDirs = []) {
160
+ return contentDirs.map((dir) => resolve(projectRoot, dir));
161
+ }
162
+ function isAssetReference(ref) {
163
+ if (!ref.startsWith("./")) return false;
164
+ const path = ref.split(/[?#]/u, 1)[0] ?? ref;
165
+ return CONTENT_ASSET_EXTS.has(extname(path).toLowerCase());
166
+ }
167
+ function rewriteContentAssetRefs(html, base) {
168
+ const basePrefix = base.replace(/\/+$/u, "");
169
+ return html.replace(/(src|href|srcset)="([^"]+)"/g, (match, attr, ref) => {
170
+ if (!isAssetReference(ref)) return match;
171
+ const pathname = ref.split(/[?#]/u, 1)[0] ?? ref;
172
+ const suffix = ref.slice(pathname.length);
173
+ return `${attr}="${basePrefix}/assets/${pathname.split("/").pop() ?? pathname}${suffix}"`;
174
+ });
175
+ }
176
+ function collectContentAssets(contentDirs) {
177
+ const assets = /* @__PURE__ */ new Map();
178
+ function walk(dir) {
179
+ if (!existsSync(dir)) return;
180
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
181
+ if (entry.name.startsWith(".")) continue;
182
+ const fullPath = join(dir, entry.name);
183
+ if (entry.isDirectory()) {
184
+ walk(fullPath);
185
+ continue;
186
+ }
187
+ const ext = extname(entry.name).toLowerCase();
188
+ if (!CONTENT_ASSET_EXTS.has(ext)) continue;
189
+ if (assets.has(entry.name) && assets.get(entry.name) !== fullPath) console.warn(`pagesmith:ssg duplicate companion asset basename "${entry.name}" detected; using ${fullPath}`);
190
+ assets.set(entry.name, fullPath);
191
+ }
192
+ }
193
+ for (const dir of contentDirs) walk(dir);
194
+ return assets;
195
+ }
196
+ function copyContentAssetsToOutDir(outDir, assets) {
197
+ if (assets.size === 0) return;
198
+ const assetsDir = join(outDir, "assets");
199
+ mkdirSync(assetsDir, { recursive: true });
200
+ for (const [fileName, sourcePath] of assets) copyFileSync(sourcePath, join(assetsDir, fileName));
201
+ }
202
+ function pagesmithSsg(options) {
203
+ const enablePagefind = options.pagefind !== false;
204
+ let config;
205
+ let projectRoot;
206
+ let base;
207
+ let outDir;
208
+ let contentDirs = [];
209
+ let contentAssets = /* @__PURE__ */ new Map();
210
+ return [{
211
+ name: "pagesmith:ssg-dev",
212
+ apply: "serve",
213
+ config() {
214
+ return { appType: "custom" };
215
+ },
216
+ configResolved(resolved) {
217
+ config = resolved;
218
+ projectRoot = resolved.root;
219
+ base = resolved.base.replace(/\/+$/, "");
220
+ outDir = resolve(projectRoot, resolved.build.outDir);
221
+ contentDirs = resolveContentDirs(projectRoot, options.contentDirs);
222
+ },
223
+ configureServer(server) {
224
+ async function refreshContentArtifacts() {
225
+ contentAssets = collectContentAssets(contentDirs);
226
+ }
227
+ refreshContentArtifacts().catch((error) => {
228
+ console.warn(`pagesmith:ssg failed to prepare companion assets: ${error instanceof Error ? error.message : String(error)}`);
229
+ });
230
+ if (contentDirs.length > 0) {
231
+ server.watcher.add(contentDirs);
232
+ const refresh = () => {
233
+ refreshContentArtifacts().catch((error) => {
234
+ console.warn(`pagesmith:ssg failed to refresh companion assets: ${error instanceof Error ? error.message : String(error)}`);
235
+ });
236
+ };
237
+ server.watcher.on("add", refresh);
238
+ server.watcher.on("change", refresh);
239
+ server.watcher.on("unlink", refresh);
240
+ }
241
+ server.middlewares.use(async (req, res, next) => {
242
+ const url = req.url ?? "/";
243
+ const pathname = url.split(/[?#]/u, 1)[0] ?? url;
244
+ if (pathname.includes("/assets/")) {
245
+ const assetName = pathname.split("/assets/").pop();
246
+ const assetPath = assetName ? contentAssets.get(assetName) : void 0;
247
+ if (assetPath) {
248
+ const ext = extname(assetPath).toLowerCase();
249
+ res.writeHead(200, {
250
+ "Content-Type": MIME[ext] ?? "application/octet-stream",
251
+ "Cache-Control": "no-cache"
252
+ });
253
+ res.end(readFileSync(assetPath));
254
+ return;
255
+ }
256
+ }
257
+ if (!(req.headers.accept ?? "").includes("text/html")) return next();
258
+ if (base && (url === "/" || url === "")) {
259
+ res.writeHead(302, { Location: `${base}/` });
260
+ res.end();
261
+ return;
262
+ }
263
+ if (base && !url.startsWith(base)) return next();
264
+ try {
265
+ const renderFn = (await server.ssrLoadModule(resolve(projectRoot, options.entry))).render;
266
+ if (typeof renderFn !== "function") return next();
267
+ let html = await renderFn(url, {
268
+ base,
269
+ root: projectRoot,
270
+ cssPath: `${base}/src/theme.css`,
271
+ jsPath: void 0,
272
+ searchEnabled: false,
273
+ isDev: true
274
+ });
275
+ html = rewriteContentAssetRefs(html, base);
276
+ html = html.replace("</head>", `<script type="module" src="/@vite/client"><\/script>\n<link rel="stylesheet" href="${base}/src/theme.css">\n</head>`);
277
+ html = await server.transformIndexHtml(url, html);
278
+ const status = html.includes("doc-not-found") ? 404 : 200;
279
+ res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
280
+ res.end(html);
281
+ } catch (err) {
282
+ server.ssrFixStacktrace(err);
283
+ console.error(`SSR error for ${url}:`, err.message);
284
+ next(err);
285
+ }
286
+ });
287
+ }
288
+ }, {
289
+ name: "pagesmith:ssg-build",
290
+ apply: "build",
291
+ configResolved(resolved) {
292
+ config = resolved;
293
+ projectRoot = resolved.root;
294
+ base = resolved.base.replace(/\/+$/, "");
295
+ outDir = resolve(projectRoot, resolved.build.outDir);
296
+ contentDirs = resolveContentDirs(projectRoot, options.contentDirs);
297
+ },
298
+ async closeBundle() {
299
+ if (config.build.ssr) return;
300
+ console.log("\nSSG: Starting static site generation...");
301
+ contentAssets = collectContentAssets(contentDirs);
302
+ const corePkgDir = dirname(fileURLToPath(import.meta.resolve("@pagesmith/core/package.json")));
303
+ const coreFontsDir = join(corePkgDir, "assets", "fonts");
304
+ const outFontsDir = join(outDir, "assets", "fonts");
305
+ mkdirSync(outFontsDir, { recursive: true });
306
+ for (const file of readdirSync(coreFontsDir)) if (file.endsWith(".woff2")) copyFileSync(join(coreFontsDir, file), join(outFontsDir, file));
307
+ copyFileSync(join(corePkgDir, "assets", "fonts.css"), join(outDir, "assets", "fonts.css"));
308
+ copyPublicFiles(join(projectRoot, "public"), outDir);
309
+ const builtIndex = join(outDir, "index.html");
310
+ let cssPath = `${base}/assets/style.css`;
311
+ let jsPath;
312
+ if (existsSync(builtIndex)) {
313
+ const html = readFileSync(builtIndex, "utf-8");
314
+ const cssMatch = html.match(/href="([^"]*\.css)"/);
315
+ const jsMatch = html.match(/src="([^"]*\.js)"/);
316
+ if (cssMatch) cssPath = cssMatch[1];
317
+ if (jsMatch) jsPath = jsMatch[1];
318
+ }
319
+ console.log("SSG: Building SSR bundle...");
320
+ const { execFileSync } = await import("child_process");
321
+ const serverDir = join(outDir, ".server");
322
+ const ssrEntry = resolve(projectRoot, options.entry);
323
+ const buildScript = `
324
+ import { build } from 'vite-plus';
325
+ await build({
326
+ root: ${JSON.stringify(projectRoot)},
327
+ logLevel: 'warn',
328
+ mode: ${JSON.stringify(config.mode)},
329
+ build: {
330
+ ssr: ${JSON.stringify(ssrEntry)},
331
+ outDir: ${JSON.stringify(serverDir)},
332
+ emptyOutDir: true,
333
+ },
334
+ });
335
+ `;
336
+ execFileSync(process.execPath, [
337
+ "--input-type=module",
338
+ "-e",
339
+ buildScript
340
+ ], {
341
+ stdio: "inherit",
342
+ cwd: projectRoot
343
+ });
344
+ const ssrMod = await import(pathToFileURL(join(serverDir, "entry-server.js")).href);
345
+ const renderConfig = {
346
+ base,
347
+ root: projectRoot,
348
+ cssPath,
349
+ jsPath,
350
+ searchEnabled: true,
351
+ isDev: false
352
+ };
353
+ const routes = await ssrMod.getRoutes(renderConfig);
354
+ console.log(`SSG: Rendering ${routes.length} pages...`);
355
+ for (const route of routes) {
356
+ const html = rewriteContentAssetRefs(await ssrMod.render(route, renderConfig), base);
357
+ const routePath = route === "/" ? "" : route.replace(/^\//, "");
358
+ const outputPath = join(outDir, routePath, "index.html");
359
+ mkdirSync(dirname(outputPath), { recursive: true });
360
+ writeFileSync(outputPath, `<!DOCTYPE html>\n${html}`);
361
+ if (route === "/404") writeFileSync(join(outDir, "404.html"), `<!DOCTYPE html>\n${html}`);
362
+ }
363
+ copyContentAssetsToOutDir(outDir, contentAssets);
364
+ rmSync(serverDir, {
365
+ recursive: true,
366
+ force: true
367
+ });
368
+ if (enablePagefind) {
369
+ console.log("SSG: Indexing with Pagefind...");
370
+ try {
371
+ const pagefindBin = join(dirname(fileURLToPath(import.meta.resolve("pagefind"))), "..", "lib", "runner", "bin.cjs");
372
+ const { execFileSync } = await import("child_process");
373
+ execFileSync(process.execPath, [
374
+ pagefindBin,
375
+ "--site",
376
+ outDir
377
+ ], { stdio: "inherit" });
378
+ } catch {
379
+ console.warn("SSG: Pagefind not found, skipping search indexing");
380
+ }
381
+ }
382
+ console.log(`SSG: Done — ${routes.length} pages generated`);
383
+ }
384
+ }];
385
+ }
386
+ //#endregion
387
+ //#region src/vite/index.ts
388
+ const DEFAULT_MODULE_ID = "virtual:content";
389
+ function stripExtension(filePath) {
390
+ return filePath.replace(/\.(c|m)?[jt]sx?$/u, "");
391
+ }
392
+ function normalizePath(value) {
393
+ return value.replace(/\\/g, "/");
394
+ }
395
+ function isPathWithin(parent, candidate) {
396
+ const rel = normalizePath(relative(parent, candidate));
397
+ return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
398
+ }
399
+ function commonDirectory(paths) {
400
+ const normalized = paths.map((path) => normalizePath(resolve(path)));
401
+ if (normalized.length === 0) return process.cwd();
402
+ if (normalized.length === 1) return normalized[0];
403
+ const segments = normalized.map((path) => path.split("/").filter(Boolean));
404
+ const shared = [];
405
+ const first = segments[0];
406
+ for (let index = 0; index < first.length; index += 1) {
407
+ const segment = first[index];
408
+ if (segments.every((parts) => parts[index] === segment)) {
409
+ shared.push(segment);
410
+ continue;
411
+ }
412
+ break;
413
+ }
414
+ if (shared.length === 0) return resolve("/");
415
+ return resolve(`/${shared.join("/")}`);
416
+ }
417
+ function resolveDtsPath(projectRoot, dts) {
418
+ if (dts === false) return "";
419
+ if (typeof dts === "string") return resolve(projectRoot, dts);
420
+ if (typeof dts === "object" && dts?.path) return resolve(projectRoot, dts.path);
421
+ const srcPath = resolve(projectRoot, "src");
422
+ if (existsSync(srcPath)) return resolve(srcPath, "pagesmith-content.d.ts");
423
+ return resolve(projectRoot, "pagesmith-content.d.ts");
424
+ }
425
+ function createDtsSource(moduleId, collectionNames, dtsPath, configPath) {
426
+ return `// Generated by @pagesmith/core/vite. Do not edit manually.
427
+ type __PagesmithCollections = typeof import('${normalizePath(stripExtension(relative(dirname(dtsPath), configPath)).replace(/^[^.]/u, "./$&"))}').default
428
+
429
+ declare module '${moduleId}' {
430
+ const content: import('@pagesmith/core/vite').ContentModuleMap<__PagesmithCollections>
431
+ export default content
432
+ }
433
+
434
+ ${collectionNames.map((name) => `declare module '${moduleId}/${name}' {
435
+ const collection: import('@pagesmith/core/vite').ContentCollectionModule<
436
+ __PagesmithCollections['${name.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}']
437
+ >
438
+ export default collection
439
+ }`).join("\n\n")}
440
+ `;
441
+ }
442
+ async function serializeCollection(layer, collectionName, collectionDef, contentRoot) {
443
+ const entries = await layer.getCollection(collectionName);
444
+ const loader = resolveLoader(collectionDef.loader);
445
+ const sortedEntries = [...entries].sort((left, right) => left.filePath.localeCompare(right.filePath));
446
+ return `const collection = ${uneval(await Promise.all(sortedEntries.map(async (entry) => {
447
+ const contentSlug = toSlug(entry.filePath, contentRoot);
448
+ const base = {
449
+ id: contentSlug,
450
+ contentSlug
451
+ };
452
+ if (loader.kind === "markdown") {
453
+ const rendered = await entry.render();
454
+ return {
455
+ ...base,
456
+ html: rendered.html,
457
+ headings: rendered.headings,
458
+ frontmatter: entry.data
459
+ };
460
+ }
461
+ return {
462
+ ...base,
463
+ data: entry.data
464
+ };
465
+ })))};\nexport default collection;\n`;
466
+ }
467
+ function createRootModuleSource(moduleId, collectionNames) {
468
+ return `${collectionNames.map((name, index) => `import collection${index} from '${moduleId}/${name}'`).join("\n")}\n\nexport default { ${collectionNames.map((name, index) => `${JSON.stringify(name)}: collection${index}`).join(", ")} };\n`;
469
+ }
470
+ function resolvePluginOptions(collectionsOrOptions, maybeOptions = {}) {
471
+ if ("collections" in collectionsOrOptions) return collectionsOrOptions;
472
+ return {
473
+ ...maybeOptions,
474
+ collections: collectionsOrOptions
475
+ };
476
+ }
477
+ function pagesmithContent(collectionsOrOptions, maybeOptions = {}) {
478
+ const options = resolvePluginOptions(collectionsOrOptions, maybeOptions);
479
+ const collectionNames = Object.keys(options.collections);
480
+ const moduleId = options.moduleId ?? DEFAULT_MODULE_ID;
481
+ const resolvedPrefix = `\0${moduleId}/`;
482
+ const resolvedRootId = `\0${moduleId}`;
483
+ let projectRoot = process.cwd();
484
+ let layerRoot = projectRoot;
485
+ let contentRoot = projectRoot;
486
+ let configPath = resolve(projectRoot, options.configPath ?? "content.config.ts");
487
+ let dtsPath = resolveDtsPath(projectRoot, options.dts);
488
+ let layer = createContentLayer({
489
+ ...options,
490
+ root: layerRoot
491
+ });
492
+ const ensureDeclarations = () => {
493
+ if (options.dts === false) return;
494
+ const source = createDtsSource(moduleId, collectionNames, dtsPath, configPath);
495
+ mkdirSync(dirname(dtsPath), { recursive: true });
496
+ writeFileSync(dtsPath, source);
497
+ };
498
+ return {
499
+ name: "pagesmith-content",
500
+ enforce: "pre",
501
+ configResolved(config) {
502
+ projectRoot = resolve(config.root);
503
+ layerRoot = resolve(projectRoot, options.root ?? ".");
504
+ configPath = resolve(projectRoot, options.configPath ?? "content.config.ts");
505
+ dtsPath = resolveDtsPath(projectRoot, options.dts);
506
+ const collectionDirectories = collectionNames.map((name) => resolve(layerRoot, options.collections[name].directory));
507
+ contentRoot = options.contentRoot ? resolve(layerRoot, options.contentRoot) : commonDirectory(collectionDirectories);
508
+ layer = createContentLayer({
509
+ ...options,
510
+ root: layerRoot
511
+ });
512
+ ensureDeclarations();
513
+ },
514
+ buildStart() {
515
+ ensureDeclarations();
516
+ },
517
+ resolveId(id) {
518
+ if (id === moduleId) return resolvedRootId;
519
+ for (const name of collectionNames) if (id === `${moduleId}/${name}`) return `${resolvedPrefix}${name}`;
520
+ },
521
+ async load(id) {
522
+ if (id === resolvedRootId) return createRootModuleSource(moduleId, collectionNames);
523
+ if (!id.startsWith(resolvedPrefix)) return;
524
+ const collectionName = id.slice(resolvedPrefix.length);
525
+ const collectionDef = options.collections[collectionName];
526
+ if (!collectionDef) return;
527
+ return serializeCollection(layer, collectionName, collectionDef, contentRoot);
528
+ },
529
+ handleHotUpdate({ file, server }) {
530
+ const resolvedFile = resolve(file);
531
+ const touchesConfig = resolvedFile === configPath;
532
+ const touchesContent = collectionNames.some((name) => isPathWithin(resolve(layerRoot, options.collections[name].directory), resolvedFile));
533
+ if (!touchesConfig && !touchesContent) return;
534
+ if (touchesConfig) ensureDeclarations();
535
+ const rootModule = server.moduleGraph.getModuleById(resolvedRootId);
536
+ if (rootModule) server.moduleGraph.invalidateModule(rootModule);
537
+ for (const name of collectionNames) {
538
+ const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`);
539
+ if (moduleNode) server.moduleGraph.invalidateModule(moduleNode);
540
+ }
541
+ layer.invalidateAll();
542
+ server.ws.send({ type: "full-reload" });
543
+ }
544
+ };
545
+ }
546
+ //#endregion
547
+ export { pagesmithContent, pagesmithSsg, prerenderRoutes, sharedAssetsPlugin };
548
+
549
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/vite/ssg.ts","../../src/vite/shared-assets.ts","../../src/vite/ssg-plugin.ts","../../src/vite/index.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 * 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 {\n copyFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'fs'\nimport { dirname, extname, join, resolve } from 'path'\nimport { fileURLToPath, pathToFileURL } from 'url'\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'\nimport { copyPublicFiles } from '../assets'\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\nconst 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\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\nconst CONTENT_ASSET_EXTS = new Set([\n '.svg',\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.webp',\n '.avif',\n '.ico',\n])\n\nfunction 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\nfunction rewriteContentAssetRefs(html: string, base: string): string {\n const basePrefix = base.replace(/\\/+$/u, '')\n\n return html.replace(/(src|href|srcset)=\"([^\"]+)\"/g, (match, attr: string, ref: string) => {\n if (!isAssetReference(ref)) return match\n const pathname = ref.split(/[?#]/u, 1)[0] ?? ref\n const suffix = ref.slice(pathname.length)\n return `${attr}=\"${basePrefix}/assets/${pathname.split('/').pop() ?? pathname}${suffix}\"`\n })\n}\n\nfunction collectContentAssets(contentDirs: string[]): Map<string, string> {\n const assets = new Map<string, string>()\n\n function walk(dir: string): void {\n if (!existsSync(dir)) return\n\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.name.startsWith('.')) continue\n\n const fullPath = join(dir, entry.name)\n\n if (entry.isDirectory()) {\n walk(fullPath)\n continue\n }\n\n const ext = extname(entry.name).toLowerCase()\n if (!CONTENT_ASSET_EXTS.has(ext)) continue\n\n if (assets.has(entry.name) && assets.get(entry.name) !== fullPath) {\n console.warn(\n `pagesmith:ssg duplicate companion asset basename \"${entry.name}\" detected; using ${fullPath}`,\n )\n }\n\n assets.set(entry.name, fullPath)\n }\n }\n\n for (const dir of contentDirs) {\n walk(dir)\n }\n\n return assets\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\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 let contentAssets = new Map<string, 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: ViteDevServer) {\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)\n const accept = req.headers.accept ?? ''\n if (!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, options.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: any) {\n server.ssrFixStacktrace(err)\n console.error(`SSR error for ${url}:`, err.message)\n next(err)\n }\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 console.log('\\nSSG: Starting static site generation...')\n\n contentAssets = collectContentAssets(contentDirs)\n\n // Copy font assets from @pagesmith/core\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 // 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 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\n // SSR build — use child process to avoid nested Vite resolution issues\n console.log('SSG: Building SSR bundle...')\n const { execFileSync } = await import('child_process')\n const serverDir = join(outDir, '.server')\n const ssrEntry = resolve(projectRoot, options.entry)\n // Write a temp build script that externalizes node_modules and skips the SSG plugin\n const buildScript = `\n import { build } from 'vite-plus';\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 // Load SSR module\n const serverEntry = join(serverDir, 'entry-server.js')\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\n const routes: string[] = await ssrMod.getRoutes(renderConfig)\n console.log(`SSG: Rendering ${routes.length} pages...`)\n\n for (const route of routes) {\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 copyContentAssetsToOutDir(outDir, contentAssets)\n\n // Cleanup SSR build\n rmSync(serverDir, { recursive: true, force: true })\n\n // Run pagefind\n if (enablePagefind) {\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 console.log(`SSG: Done — ${routes.length} pages generated`)\n },\n }\n\n return [devPlugin, buildPlugin]\n}\n","export { prerenderRoutes } from './ssg'\nexport type { PrerenderOptions } from './ssg'\nexport { sharedAssetsPlugin } from './shared-assets.js'\nexport { pagesmithSsg } from './ssg-plugin.js'\nexport type { SsgPluginOptions, SsgRenderConfig } from './ssg-plugin.js'\n\nimport { existsSync, 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'\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 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\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\nfunction 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\nfunction 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\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 = createContentLayer({\n ...options,\n root: layerRoot,\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(layer, collectionName, collectionDef, contentRoot)\n },\n\n handleHotUpdate({ file, server }) {\n const resolvedFile = resolve(file)\n const touchesConfig = resolvedFile === configPath\n const touchesContent = collectionNames.some((name) =>\n isPathWithin(resolve(layerRoot, options.collections[name]!.directory), resolvedFile),\n )\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 for (const name of collectionNames) {\n const moduleNode = server.moduleGraph.getModuleById(`${resolvedPrefix}${name}`)\n if (moduleNode) {\n server.moduleGraph.invalidateModule(moduleNode)\n }\n }\n\n layer.invalidateAll()\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,UAAU;MACZ,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;;;;;;;;;;;;;;;;;;;;;;;;;ACYH,MAAM,OAA+B;CACnC,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;AASD,MAAM,qBAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,mBAAmB,aAAqB,cAAwB,EAAE,EAAY;AACrF,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,SAAS,wBAAwB,MAAc,MAAsB;CACnE,MAAM,aAAa,KAAK,QAAQ,SAAS,GAAG;AAE5C,QAAO,KAAK,QAAQ,iCAAiC,OAAO,MAAc,QAAgB;AACxF,MAAI,CAAC,iBAAiB,IAAI,CAAE,QAAO;EACnC,MAAM,WAAW,IAAI,MAAM,SAAS,EAAE,CAAC,MAAM;EAC7C,MAAM,SAAS,IAAI,MAAM,SAAS,OAAO;AACzC,SAAO,GAAG,KAAK,IAAI,WAAW,UAAU,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI,WAAW,OAAO;GACvF;;AAGJ,SAAS,qBAAqB,aAA4C;CACxE,MAAM,yBAAS,IAAI,KAAqB;CAExC,SAAS,KAAK,KAAmB;AAC/B,MAAI,CAAC,WAAW,IAAI,CAAE;AAEtB,OAAK,MAAM,SAAS,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC,EAAE;AAC7D,OAAI,MAAM,KAAK,WAAW,IAAI,CAAE;GAEhC,MAAM,WAAW,KAAK,KAAK,MAAM,KAAK;AAEtC,OAAI,MAAM,aAAa,EAAE;AACvB,SAAK,SAAS;AACd;;GAGF,MAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,aAAa;AAC7C,OAAI,CAAC,mBAAmB,IAAI,IAAI,CAAE;AAElC,OAAI,OAAO,IAAI,MAAM,KAAK,IAAI,OAAO,IAAI,MAAM,KAAK,KAAK,SACvD,SAAQ,KACN,qDAAqD,MAAM,KAAK,oBAAoB,WACrF;AAGH,UAAO,IAAI,MAAM,MAAM,SAAS;;;AAIpC,MAAK,MAAM,OAAO,YAChB,MAAK,IAAI;AAGX,QAAO;;AAGT,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;;AAIvD,SAAgB,aAAa,SAAqC;CAChE,MAAM,iBAAiB,QAAQ,aAAa;CAC5C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,cAAwB,EAAE;CAC9B,IAAI,gCAAgB,IAAI,KAAqB;AA4P7C,QAAO,CAzPmB;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,QAAuB;GACrC,eAAe,0BAAyC;AACtD,oBAAgB,qBAAqB,YAAY;;AAG9C,4BAAyB,CAAC,OAAO,UAAU;AAC9C,YAAQ,KACN,qDAAqD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5G;KACD;AAEF,OAAI,YAAY,SAAS,GAAG;AAC1B,WAAO,QAAQ,IAAI,YAAY;IAE/B,MAAM,gBAAgB;AACf,8BAAyB,CAAC,OAAO,UAAU;AAC9C,cAAQ,KACN,qDAAqD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5G;OACD;;AAGJ,WAAO,QAAQ,GAAG,OAAO,QAAQ;AACjC,WAAO,QAAQ,GAAG,UAAU,QAAQ;AACpC,WAAO,QAAQ,GAAG,UAAU,QAAQ;;AAKtC,UAAO,YAAY,IAAI,OAAO,KAAK,KAAK,SAAS;IAC/C,MAAM,MAAM,IAAI,OAAO;IACvB,MAAM,WAAW,IAAI,MAAM,SAAS,EAAE,CAAC,MAAM;AAE7C,QAAI,SAAS,SAAS,WAAW,EAAE;KACjC,MAAM,YAAY,SAAS,MAAM,WAAW,CAAC,KAAK;KAClD,MAAM,YAAY,YAAY,cAAc,IAAI,UAAU,GAAG,KAAA;AAE7D,SAAI,WAAW;MACb,MAAM,MAAM,QAAQ,UAAU,CAAC,aAAa;AAC5C,UAAI,UAAU,KAAK;OACjB,gBAAgB,KAAK,QAAQ;OAC7B,iBAAiB;OAClB,CAAC;AACF,UAAI,IAAI,aAAa,UAAU,CAAC;AAChC;;;AAMJ,QAAI,EADW,IAAI,QAAQ,UAAU,IACzB,SAAS,YAAY,CAAE,QAAO,MAAM;AAGhD,QAAI,SAAS,QAAQ,OAAO,QAAQ,KAAK;AACvC,SAAI,UAAU,KAAK,EAAE,UAAU,GAAG,KAAK,IAAI,CAAC;AAC5C,SAAI,KAAK;AACT;;AAIF,QAAI,QAAQ,CAAC,IAAI,WAAW,KAAK,CAAE,QAAO,MAAM;AAEhD,QAAI;KAGF,MAAM,YADS,MAAM,OAAO,cAAc,QAAQ,aAAa,QAAQ,MAAM,CAAC,EAErE;AAET,SAAI,OAAO,aAAa,WACtB,QAAO,MAAM;KAYf,IAAI,OAAO,MAAM,SAAS,KATY;MACpC;MACA,MAAM;MACN,SAAS,GAAG,KAAK;MACjB,QAAQ,KAAA;MACR,eAAe;MACf,OAAO;MACR,CAE2C;AAC5C,YAAO,wBAAwB,MAAM,KAAK;AAG1C,YAAO,KAAK,QACV,WACA,sFACkC,KAAK,2BAExC;AAGD,YAAO,MAAM,OAAO,mBAAmB,KAAK,KAAK;KAEjD,MAAM,SAAS,KAAK,SAAS,gBAAgB,GAAG,MAAM;AACtD,SAAI,UAAU,QAAQ,EAAE,gBAAgB,4BAA4B,CAAC;AACrE,SAAI,IAAI,KAAK;aACN,KAAU;AACjB,YAAO,iBAAiB,IAAI;AAC5B,aAAQ,MAAM,iBAAiB,IAAI,IAAI,IAAI,QAAQ;AACnD,UAAK,IAAI;;KAEX;;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;AAEtB,WAAQ,IAAI,4CAA4C;AAExD,mBAAgB,qBAAqB,YAAY;GAGjD,MAAM,aAAa,QAAQ,cAAc,OAAO,KAAK,QAAQ,+BAA+B,CAAC,CAAC;GAC9F,MAAM,eAAe,KAAK,YAAY,UAAU,QAAQ;GACxD,MAAM,cAAc,KAAK,QAAQ,UAAU,QAAQ;AACnD,aAAU,aAAa,EAAE,WAAW,MAAM,CAAC;AAC3C,QAAK,MAAM,QAAQ,YAAY,aAAa,CAC1C,KAAI,KAAK,SAAS,SAAS,CACzB,cAAa,KAAK,cAAc,KAAK,EAAE,KAAK,aAAa,KAAK,CAAC;AAGnE,gBAAa,KAAK,YAAY,UAAU,YAAY,EAAE,KAAK,QAAQ,UAAU,YAAY,CAAC;AAI1F,mBADkB,KAAK,aAAa,SAAS,EAClB,OAAO;GAGlC,MAAM,aAAa,KAAK,QAAQ,aAAa;GAC7C,IAAI,UAAU,GAAG,KAAK;GACtB,IAAI;AACJ,OAAI,WAAW,WAAW,EAAE;IAC1B,MAAM,OAAO,aAAa,YAAY,QAAQ;IAC9C,MAAM,WAAW,KAAK,MAAM,sBAAsB;IAClD,MAAM,UAAU,KAAK,MAAM,oBAAoB;AAC/C,QAAI,SAAU,WAAU,SAAS;AACjC,QAAI,QAAS,UAAS,QAAQ;;AAIhC,WAAQ,IAAI,8BAA8B;GAC1C,MAAM,EAAE,iBAAiB,MAAM,OAAO;GACtC,MAAM,YAAY,KAAK,QAAQ,UAAU;GACzC,MAAM,WAAW,QAAQ,aAAa,QAAQ,MAAM;GAEpD,MAAM,cAAc;;;kBAGR,KAAK,UAAU,YAAY,CAAC;;kBAE5B,KAAK,UAAU,OAAO,KAAK,CAAC;;mBAE3B,KAAK,UAAU,SAAS,CAAC;sBACtB,KAAK,UAAU,UAAU,CAAC;;;;;AAK1C,gBAAa,QAAQ,UAAU;IAAC;IAAuB;IAAM;IAAY,EAAE;IACzE,OAAO;IACP,KAAK;IACN,CAAC;GAIF,MAAM,SAAS,MAAM,OAAO,cADR,KAAK,WAAW,kBAAkB,CACA,CAAC;GAEvD,MAAM,eAAgC;IACpC;IACA,MAAM;IACN;IACA;IACA,eAAe;IACf,OAAO;IACR;GAGD,MAAM,SAAmB,MAAM,OAAO,UAAU,aAAa;AAC7D,WAAQ,IAAI,kBAAkB,OAAO,OAAO,WAAW;AAEvD,QAAK,MAAM,SAAS,QAAQ;IAC1B,MAAM,OAAO,wBAAwB,MAAM,OAAO,OAAO,OAAO,aAAa,EAAE,KAAK;IACpF,MAAM,YAAY,UAAU,MAAM,KAAK,MAAM,QAAQ,OAAO,GAAG;IAC/D,MAAM,aAAa,KAAK,QAAQ,WAAW,aAAa;AACxD,cAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AACnD,kBAAc,YAAY,oBAAoB,OAAO;AAErD,QAAI,UAAU,OACZ,eAAc,KAAK,QAAQ,WAAW,EAAE,oBAAoB,OAAO;;AAIvE,6BAA0B,QAAQ,cAAc;AAGhD,UAAO,WAAW;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;AAGnD,OAAI,gBAAgB;AAClB,YAAQ,IAAI,iCAAiC;AAC7C,QAAI;KAEF,MAAM,cAAc,KAAK,QADJ,cAAc,OAAO,KAAK,QAAQ,WAAW,CAAC,CACrB,EAAE,MAAM,OAAO,UAAU,UAAU;KACjF,MAAM,EAAE,iBAAiB,MAAM,OAAO;AACtC,kBAAa,QAAQ,UAAU;MAAC;MAAa;MAAU;MAAO,EAAE,EAAE,OAAO,WAAW,CAAC;YAC/E;AACN,aAAQ,KAAK,oDAAoD;;;AAIrE,WAAQ,IAAI,eAAe,OAAO,OAAO,kBAAkB;;EAE9D,CAE8B;;;;AC/TjC,MAAM,oBAAoB;AAE1B,SAAS,eAAe,UAA0B;AAChD,QAAO,SAAS,QAAQ,qBAAqB,GAAG;;AAGlD,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,SAAS,eACP,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,SAAS,gBACP,UACA,iBACA,SACA,YACQ;AAgBR,QAAO;+CAfkB,cACvB,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;;;AAId,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,QAAQ,mBAAmB;EAC7B,GAAG;EACH,MAAM;EACP,CAAC;CAEF,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,OAAO,gBAAgB,eAAe,YAAY;;EAG/E,gBAAgB,EAAE,MAAM,UAAU;GAChC,MAAM,eAAe,QAAQ,KAAK;GAClC,MAAM,gBAAgB,iBAAiB;GACvC,MAAM,iBAAiB,gBAAgB,MAAM,SAC3C,aAAa,QAAQ,WAAW,QAAQ,YAAY,MAAO,UAAU,EAAE,aAAa,CACrF;AAED,OAAI,CAAC,iBAAiB,CAAC,eAAgB;AAEvC,OAAI,cACF,qBAAoB;GAGtB,MAAM,aAAa,OAAO,YAAY,cAAc,eAAe;AACnE,OAAI,WACF,QAAO,YAAY,iBAAiB,WAAW;AAGjD,QAAK,MAAM,QAAQ,iBAAiB;IAClC,MAAM,aAAa,OAAO,YAAY,cAAc,GAAG,iBAAiB,OAAO;AAC/E,QAAI,WACF,QAAO,YAAY,iBAAiB,WAAW;;AAInD,SAAM,eAAe;AACrB,UAAO,GAAG,KAAK,EAAE,MAAM,eAAe,CAAC;;EAE1C"}