@sigx/ssg 0.1.6

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +358 -0
  3. package/dist/build.d.ts +17 -0
  4. package/dist/build.d.ts.map +1 -0
  5. package/dist/build.js +309 -0
  6. package/dist/build.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +62 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/client.d.ts +28 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +38 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/config.d.ts +33 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/dev.d.ts +43 -0
  18. package/dist/dev.d.ts.map +1 -0
  19. package/dist/dev.js +71 -0
  20. package/dist/dev.js.map +1 -0
  21. package/dist/errors.d.ts +58 -0
  22. package/dist/errors.d.ts.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +58 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/layouts/index.d.ts +7 -0
  28. package/dist/layouts/index.d.ts.map +1 -0
  29. package/dist/layouts/resolver.d.ts +49 -0
  30. package/dist/layouts/resolver.d.ts.map +1 -0
  31. package/dist/layouts/virtual.d.ts +34 -0
  32. package/dist/layouts/virtual.d.ts.map +1 -0
  33. package/dist/mdx/frontmatter.d.ts +42 -0
  34. package/dist/mdx/frontmatter.d.ts.map +1 -0
  35. package/dist/mdx/index.d.ts +9 -0
  36. package/dist/mdx/index.d.ts.map +1 -0
  37. package/dist/mdx/plugin.d.ts +32 -0
  38. package/dist/mdx/plugin.d.ts.map +1 -0
  39. package/dist/mdx/rehype-headings.d.ts +39 -0
  40. package/dist/mdx/rehype-headings.d.ts.map +1 -0
  41. package/dist/mdx/shiki.d.ts +32 -0
  42. package/dist/mdx/shiki.d.ts.map +1 -0
  43. package/dist/plugin-DxH1VUGC.js +547 -0
  44. package/dist/plugin-DxH1VUGC.js.map +1 -0
  45. package/dist/routing/index.d.ts +12 -0
  46. package/dist/routing/index.d.ts.map +1 -0
  47. package/dist/routing/navigation.d.ts +44 -0
  48. package/dist/routing/navigation.d.ts.map +1 -0
  49. package/dist/routing/resolver.d.ts +66 -0
  50. package/dist/routing/resolver.d.ts.map +1 -0
  51. package/dist/routing/scanner.d.ts +60 -0
  52. package/dist/routing/scanner.d.ts.map +1 -0
  53. package/dist/routing/virtual-navigation.d.ts +39 -0
  54. package/dist/routing/virtual-navigation.d.ts.map +1 -0
  55. package/dist/routing/virtual.d.ts +28 -0
  56. package/dist/routing/virtual.d.ts.map +1 -0
  57. package/dist/sitemap.d.ts +55 -0
  58. package/dist/sitemap.d.ts.map +1 -0
  59. package/dist/types.d.ts +562 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/virtual-entries-Bz97SKQ0.js +1053 -0
  62. package/dist/virtual-entries-Bz97SKQ0.js.map +1 -0
  63. package/dist/vite/index.d.ts +6 -0
  64. package/dist/vite/index.d.ts.map +1 -0
  65. package/dist/vite/plugin.d.ts +35 -0
  66. package/dist/vite/plugin.d.ts.map +1 -0
  67. package/dist/vite/plugin.js +3 -0
  68. package/dist/vite/virtual-entries.d.ts +59 -0
  69. package/dist/vite/virtual-entries.d.ts.map +1 -0
  70. package/package.json +92 -0
@@ -0,0 +1,547 @@
1
+ import { D as parseFrontmatter, E as extractTitleFromContent, O as defineSSGConfig, T as scanPages, _ as generateNavigationModule, a as VIRTUAL_SERVER_ID, b as generateLazyRoutesModule, c as generateHtmlTemplate, d as RESOLVED_VIRTUAL_LAYOUTS_ID, f as VIRTUAL_LAYOUTS_ID, g as VIRTUAL_NAVIGATION_ID, h as RESOLVED_VIRTUAL_NAVIGATION_ID, i as VIRTUAL_CLIENT_ID, k as loadConfig, m as discoverLayouts, n as RESOLVED_VIRTUAL_SERVER_ID, o as detectCustomEntries, p as generateLayoutsModule, r as SSG_CLIENT_ENTRY_PATH, s as generateClientEntry, t as RESOLVED_VIRTUAL_CLIENT_ID, u as generateServerEntry, v as RESOLVED_VIRTUAL_ROUTES_ID, x as generateRoutesModule, y as VIRTUAL_ROUTES_ID } from "./virtual-entries-Bz97SKQ0.js";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import { createHighlighter } from "shiki";
5
+ import { visit } from "unist-util-visit";
6
+ import { toString } from "hast-util-to-string";
7
+ var highlighterPromise = null;
8
+ var DEFAULT_CONFIG = {
9
+ light: "github-light",
10
+ dark: "github-dark",
11
+ langs: [
12
+ "javascript",
13
+ "typescript",
14
+ "jsx",
15
+ "tsx",
16
+ "json",
17
+ "css",
18
+ "html",
19
+ "markdown",
20
+ "bash",
21
+ "shell"
22
+ ]
23
+ };
24
+ async function getHighlighter(config) {
25
+ if (!highlighterPromise) {
26
+ const mergedConfig = {
27
+ ...DEFAULT_CONFIG,
28
+ ...config
29
+ };
30
+ highlighterPromise = createHighlighter({
31
+ themes: [mergedConfig.light, mergedConfig.dark],
32
+ langs: mergedConfig.langs
33
+ });
34
+ }
35
+ return highlighterPromise;
36
+ }
37
+ async function highlightCode(code, lang, config, meta) {
38
+ const highlighter = await getHighlighter(config);
39
+ const mergedConfig = {
40
+ ...DEFAULT_CONFIG,
41
+ ...config
42
+ };
43
+ const effectiveLang = highlighter.getLoadedLanguages().includes(lang) ? lang : "text";
44
+ const codeHtml = highlighter.codeToHtml(code, {
45
+ lang: effectiveLang,
46
+ themes: {
47
+ light: mergedConfig.light,
48
+ dark: mergedConfig.dark
49
+ }
50
+ });
51
+ const filename = meta?.filename ?? "";
52
+ const isLive = meta?.live ?? false;
53
+ const tabs = meta?.tabs;
54
+ const hasTabs = tabs && tabs.length > 0;
55
+ const filenameHtml = filename ? `<span class="code-window-filename">${escapeHtml(filename)}</span>` : `<span class="code-window-lang">${getLanguageLabel(effectiveLang)}</span>`;
56
+ if (hasTabs) {
57
+ const base64Code = encodeBase64(code);
58
+ const firstTab = tabs[0];
59
+ const tabButtonsHtml = tabs.map((tab, i) => {
60
+ const label = tab.charAt(0).toUpperCase() + tab.slice(1);
61
+ return `<button class="code-window-tab${i === 0 ? " code-window-tab-active" : ""}">${label}</button>`;
62
+ }).join("\n ");
63
+ return `<div
64
+ class="live-preview-island"
65
+ data-island="LivePreview"
66
+ data-island-strategy="visible"
67
+ data-island-props="${escapeHtml(JSON.stringify({
68
+ code: base64Code,
69
+ highlightedCode: codeHtml,
70
+ language: effectiveLang,
71
+ filename,
72
+ tabs,
73
+ live: isLive
74
+ }))}"
75
+ >
76
+ <div class="code-window code-window-live code-window-preview">
77
+ <div class="code-window-header">
78
+ <div class="code-window-header-left">
79
+ <div class="code-window-dots">
80
+ <span class="code-window-dot dot-red"></span>
81
+ <span class="code-window-dot dot-yellow"></span>
82
+ <span class="code-window-dot dot-green"></span>
83
+ </div>
84
+ ${filenameHtml}
85
+ </div>
86
+ <div class="code-window-tabs">
87
+ ${tabButtonsHtml}
88
+ </div>
89
+ <button class="code-window-try-live" disabled>⚡ Try Live</button>
90
+ </div>
91
+ <div class="code-window-preview-pane"${firstTab !== "preview" ? " style=\"display:none;\"" : ""}>
92
+ <div class="code-window-preview-loading">
93
+ <span class="code-window-spinner"></span>
94
+ Loading preview...
95
+ </div>
96
+ </div>
97
+ <div class="code-window-console-pane"${firstTab !== "console" ? " style=\"display:none;\"" : ""}>
98
+ <div class="code-window-console-empty">No console output</div>
99
+ </div>
100
+ <div class="code-window-content"${firstTab !== "code" ? " style=\"display:none;\"" : ""}>
101
+ ${codeHtml}
102
+ </div>
103
+ </div>
104
+ </div>`;
105
+ }
106
+ const tryLiveButton = isLive ? `<button class="code-window-try-live" data-live-code="${escapeHtml(encodeBase64(code))}" data-lang="${effectiveLang}" data-filename="${escapeHtml(filename)}" title="Open in Live Playground">⚡ Try Live</button>` : "";
107
+ return `<div class="code-window${isLive ? " code-window-live" : ""}">
108
+ <div class="code-window-header">
109
+ <div class="code-window-header-left">
110
+ <div class="code-window-dots">
111
+ <span class="code-window-dot dot-red"></span>
112
+ <span class="code-window-dot dot-yellow"></span>
113
+ <span class="code-window-dot dot-green"></span>
114
+ </div>
115
+ ${filenameHtml}
116
+ </div>
117
+ ${tryLiveButton}
118
+ </div>
119
+ <div class="code-window-content">
120
+ ${codeHtml}
121
+ </div>
122
+ </div>`;
123
+ }
124
+ function encodeBase64(str) {
125
+ if (typeof Buffer !== "undefined") return Buffer.from(str, "utf-8").toString("base64");
126
+ return btoa(unescape(encodeURIComponent(str)));
127
+ }
128
+ function getLanguageLabel(lang) {
129
+ return {
130
+ "tsx": "TSX",
131
+ "jsx": "JSX",
132
+ "ts": "TypeScript",
133
+ "typescript": "TypeScript",
134
+ "js": "JavaScript",
135
+ "javascript": "JavaScript",
136
+ "css": "CSS",
137
+ "html": "HTML",
138
+ "json": "JSON",
139
+ "bash": "Terminal",
140
+ "shell": "Terminal",
141
+ "sh": "Terminal",
142
+ "md": "Markdown",
143
+ "markdown": "Markdown",
144
+ "python": "Python",
145
+ "py": "Python",
146
+ "rust": "Rust",
147
+ "go": "Go",
148
+ "text": ""
149
+ }[lang.toLowerCase()] ?? lang.toUpperCase();
150
+ }
151
+ function escapeHtml(str) {
152
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
153
+ }
154
+ function rehypeShiki(config) {
155
+ return async (tree) => {
156
+ const { visit } = await import("unist-util-visit");
157
+ const { fromHtml } = await import("hast-util-from-html");
158
+ const nodesToProcess = [];
159
+ visit(tree, "element", (node, index, parent) => {
160
+ if (node.tagName === "pre" && node.children?.[0]?.tagName === "code") nodesToProcess.push({
161
+ node,
162
+ parent,
163
+ index: index ?? 0
164
+ });
165
+ });
166
+ await Promise.all(nodesToProcess.map(async ({ node, parent, index }) => {
167
+ const codeNode = node.children[0];
168
+ const lang = (codeNode.properties?.className?.[0] || "").replace(/^language-/, "") || "text";
169
+ const metaString = codeNode.data?.meta || codeNode.properties?.metastring || "";
170
+ const filename = extractMeta(metaString, "filename") || extractMeta(metaString, "title") || "";
171
+ const isLive = /\blive\b/i.test(metaString);
172
+ const tabKeywords = [
173
+ "preview",
174
+ "code",
175
+ "console"
176
+ ];
177
+ const tabs = [];
178
+ const tabPositions = [];
179
+ for (const keyword of tabKeywords) {
180
+ const regex = new RegExp(`\\b${keyword}\\b`, "i");
181
+ const match = metaString.match(regex);
182
+ if (match && match.index !== void 0) tabPositions.push({
183
+ tab: keyword,
184
+ index: match.index
185
+ });
186
+ }
187
+ tabPositions.sort((a, b) => a.index - b.index);
188
+ for (const { tab } of tabPositions) tabs.push(tab);
189
+ const fragment = fromHtml(await highlightCode(getTextContent(codeNode).trim(), lang, config, {
190
+ filename,
191
+ live: isLive,
192
+ tabs: tabs.length > 0 ? tabs : void 0
193
+ }), { fragment: true });
194
+ if (parent && typeof index === "number" && fragment.children.length > 0) parent.children[index] = fragment.children[0];
195
+ }));
196
+ };
197
+ }
198
+ function extractMeta(metaString, key) {
199
+ if (!metaString) return null;
200
+ const regex = new RegExp(`${key}=["']?([^"'\\s]+)["']?`, "i");
201
+ const match = metaString.match(regex);
202
+ return match ? match[1] : null;
203
+ }
204
+ function getTextContent(node) {
205
+ if (node.type === "text") return node.value;
206
+ if (node.children) return node.children.map(getTextContent).join("");
207
+ return "";
208
+ }
209
+ function rehypeExtractHeadings(options = {}) {
210
+ const { minLevel = 2, maxLevel = 3 } = options;
211
+ return (tree, file) => {
212
+ const headings = [];
213
+ visit(tree, "element", (node) => {
214
+ const match = /^h([1-6])$/.exec(node.tagName);
215
+ if (!match) return;
216
+ const level = parseInt(match[1], 10);
217
+ if (level < minLevel || level > maxLevel) return;
218
+ const id = node.properties?.id;
219
+ if (!id) return;
220
+ const text = toString(node).trim();
221
+ if (!text) return;
222
+ headings.push({
223
+ id,
224
+ text,
225
+ level
226
+ });
227
+ });
228
+ file.data = file.data || {};
229
+ file.data.headings = headings;
230
+ };
231
+ }
232
+ function mdxPlugin(options = {}) {
233
+ const { markdown = {} } = options;
234
+ let mdxRollup;
235
+ let viteConfig;
236
+ return {
237
+ name: "sigx-ssg-mdx",
238
+ enforce: "pre",
239
+ async configResolved(config) {
240
+ viteConfig = config;
241
+ const mdxModule = await import("@mdx-js/rollup");
242
+ const remarkFrontmatter = (await import("remark-frontmatter")).default;
243
+ const remarkMdxFrontmatter = (await import("remark-mdx-frontmatter")).default;
244
+ const remarkGfm = (await import("remark-gfm")).default;
245
+ const rehypeSlug = (await import("rehype-slug")).default;
246
+ const rehypeAutolinkHeadings = (await import("rehype-autolink-headings")).default;
247
+ const tocConfig = options.ssgConfig?.toc || {
248
+ minLevel: 2,
249
+ maxLevel: 3
250
+ };
251
+ const rehypePlugins = [];
252
+ rehypePlugins.push(rehypeSlug);
253
+ rehypePlugins.push([rehypeAutolinkHeadings, {
254
+ behavior: "append",
255
+ properties: {
256
+ class: "heading-anchor",
257
+ ariaHidden: true,
258
+ tabIndex: -1
259
+ },
260
+ content: {
261
+ type: "element",
262
+ tagName: "span",
263
+ properties: { class: "heading-anchor-icon" },
264
+ children: [{
265
+ type: "text",
266
+ value: "#"
267
+ }]
268
+ }
269
+ }]);
270
+ rehypePlugins.push([rehypeExtractHeadings, tocConfig]);
271
+ if (markdown.shiki !== false) {
272
+ const shikiConfig = typeof markdown.shiki === "object" ? markdown.shiki : void 0;
273
+ rehypePlugins.push([rehypeShiki, shikiConfig]);
274
+ }
275
+ if (markdown.rehypePlugins) rehypePlugins.push(...markdown.rehypePlugins);
276
+ const remarkPlugins = [
277
+ remarkFrontmatter,
278
+ [remarkMdxFrontmatter, { name: "frontmatter" }],
279
+ remarkGfm
280
+ ];
281
+ if (markdown.remarkPlugins) remarkPlugins.push(...markdown.remarkPlugins);
282
+ mdxRollup = mdxModule.default({
283
+ jsx: false,
284
+ jsxImportSource: "sigx",
285
+ remarkPlugins,
286
+ rehypePlugins,
287
+ providerImportSource: void 0
288
+ });
289
+ },
290
+ async transform(code, id) {
291
+ if (!/\.mdx?$/.test(id)) return null;
292
+ const { data: frontmatter, content } = parseFrontmatter(code);
293
+ if (!frontmatter.title) {
294
+ const extractedTitle = extractTitleFromContent(content);
295
+ if (extractedTitle) frontmatter.title = extractedTitle;
296
+ }
297
+ if (!mdxRollup?.transform) throw new Error("MDX plugin not initialized");
298
+ const result = await mdxRollup.transform(code, id);
299
+ if (!result) return null;
300
+ const headings = await extractHeadingsFromContent(content, options);
301
+ const moduleId = id.replace(/\\/g, "/");
302
+ return {
303
+ code: wrapMDXComponent(result.code, frontmatter, headings, moduleId, viteConfig.command === "serve"),
304
+ map: result.map
305
+ };
306
+ }
307
+ };
308
+ }
309
+ function wrapMDXComponent(code, frontmatter, headings, moduleId, isDev) {
310
+ if (isDev) {
311
+ const fileName = moduleId.split("/").pop()?.replace(/\.mdx?$/, "") || "MDXPage";
312
+ const componentName = fileName.charAt(0).toUpperCase() + fileName.slice(1).replace(/[^a-zA-Z0-9]/g, "") + "Page";
313
+ return `
314
+ import { registerHMRModule } from '@sigx/vite/hmr';
315
+ import { component as __component } from 'sigx';
316
+ registerHMRModule('${moduleId}');
317
+
318
+ ${code.replace(/export\s+default\s+function\s+MDXContent/g, "function _MDXContent").replace(/export\s+{\s*MDXContent\s+as\s+default\s*}/g, "")}
319
+
320
+ // Export layout from frontmatter for SSG routing
321
+ export const layout = ${frontmatter.layout ? JSON.stringify(frontmatter.layout) : "undefined"};
322
+
323
+ // Export headings for table of contents
324
+ export const headings = ${JSON.stringify(headings)};
325
+
326
+ // Wrap MDXContent in a sigx component for HMR support
327
+ const MDXPage = __component(() => {
328
+ return () => _MDXContent({});
329
+ }, { name: '${componentName}' });
330
+
331
+ export default MDXPage;
332
+
333
+ if (import.meta.hot) {
334
+ // Accept HMR updates with a callback to trigger re-render after module is updated
335
+ import.meta.hot.accept((newModule) => {
336
+ if (newModule) {
337
+ // Notify LayoutRouter to clear its cache and re-render with new module
338
+ window.dispatchEvent(new CustomEvent('sigx:mdx-hmr', {
339
+ detail: { moduleId: '${moduleId}', newModule }
340
+ }));
341
+ }
342
+ });
343
+ }
344
+ `;
345
+ }
346
+ return `
347
+ ${code}
348
+
349
+ // Export layout from frontmatter for SSG routing
350
+ export const layout = ${frontmatter.layout ? JSON.stringify(frontmatter.layout) : "undefined"};
351
+
352
+ // Export headings for table of contents
353
+ export const headings = ${JSON.stringify(headings)};
354
+ `;
355
+ }
356
+ async function extractHeadingsFromContent(content, options) {
357
+ const { unified } = await import("unified");
358
+ const remarkParse = (await import("remark-parse")).default;
359
+ const remarkRehype = (await import("remark-rehype")).default;
360
+ const rehypeSlug = (await import("rehype-slug")).default;
361
+ const rehypeStringify = (await import("rehype-stringify")).default;
362
+ const tocConfig = options.ssgConfig?.toc || {
363
+ minLevel: 2,
364
+ maxLevel: 3
365
+ };
366
+ return (await unified().use(remarkParse).use(remarkRehype).use(rehypeSlug).use(rehypeExtractHeadings, tocConfig).use(rehypeStringify).process(content)).data.headings || [];
367
+ }
368
+ var VIRTUAL_CONFIG_ID = "virtual:ssg-config";
369
+ var RESOLVED_VIRTUAL_CONFIG_ID = "\0" + VIRTUAL_CONFIG_ID;
370
+ function ssgPlugin(options = {}) {
371
+ let config;
372
+ let ssgConfig;
373
+ let root;
374
+ let entryDetection;
375
+ let routesCache = null;
376
+ let layoutsCache = null;
377
+ let navigationCache = null;
378
+ const frontmatterHashCache = /* @__PURE__ */ new Map();
379
+ const mainPlugin = {
380
+ name: "sigx-ssg",
381
+ enforce: "pre",
382
+ async configResolved(resolvedConfig) {
383
+ config = resolvedConfig;
384
+ root = resolvedConfig.root;
385
+ ssgConfig = defineSSGConfig({
386
+ ...await loadConfig(options.configPath),
387
+ ...options
388
+ });
389
+ entryDetection = detectCustomEntries(root, ssgConfig);
390
+ if (entryDetection.useVirtualClient || entryDetection.useVirtualServer) {
391
+ console.log("📦 @sigx/ssg: Using zero-config mode");
392
+ if (entryDetection.useVirtualClient) console.log(" → Virtual client entry");
393
+ if (entryDetection.useVirtualServer) console.log(" → Virtual server entry");
394
+ if (entryDetection.globalCssPath) console.log(` → Auto-importing ${entryDetection.globalCssPath}`);
395
+ }
396
+ },
397
+ configureServer(devServer) {
398
+ const pagesDir = path.resolve(root, ssgConfig.pages || "src/pages");
399
+ const layoutsDir = path.resolve(root, ssgConfig.layouts || "src/layouts");
400
+ path.resolve(root, ssgConfig.content || "src/content");
401
+ devServer.watcher.on("add", (file) => {
402
+ if (file.startsWith(pagesDir)) {
403
+ routesCache = null;
404
+ navigationCache = null;
405
+ invalidateModule(RESOLVED_VIRTUAL_ROUTES_ID);
406
+ invalidateModule(RESOLVED_VIRTUAL_NAVIGATION_ID);
407
+ } else if (file.startsWith(layoutsDir)) {
408
+ layoutsCache = null;
409
+ invalidateModule(RESOLVED_VIRTUAL_LAYOUTS_ID);
410
+ }
411
+ });
412
+ devServer.watcher.on("unlink", (file) => {
413
+ if (file.startsWith(pagesDir)) {
414
+ routesCache = null;
415
+ navigationCache = null;
416
+ frontmatterHashCache.delete(file);
417
+ invalidateModule(RESOLVED_VIRTUAL_ROUTES_ID);
418
+ invalidateModule(RESOLVED_VIRTUAL_NAVIGATION_ID);
419
+ } else if (file.startsWith(layoutsDir)) {
420
+ layoutsCache = null;
421
+ invalidateModule(RESOLVED_VIRTUAL_LAYOUTS_ID);
422
+ }
423
+ });
424
+ devServer.watcher.on("change", async (file) => {
425
+ if (!file.startsWith(pagesDir)) return;
426
+ if (!/\.mdx?$/.test(file)) return;
427
+ try {
428
+ const { data: newFrontmatter } = parseFrontmatter(await fs.promises.readFile(file, "utf-8"));
429
+ const newHash = JSON.stringify(newFrontmatter);
430
+ const oldHash = frontmatterHashCache.get(file);
431
+ frontmatterHashCache.set(file, newHash);
432
+ if (oldHash !== void 0 && oldHash !== newHash) {
433
+ navigationCache = null;
434
+ routesCache = null;
435
+ const navMod = devServer.moduleGraph.getModuleById(RESOLVED_VIRTUAL_NAVIGATION_ID);
436
+ if (navMod) devServer.moduleGraph.invalidateModule(navMod);
437
+ const routesMod = devServer.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ROUTES_ID);
438
+ if (routesMod) devServer.moduleGraph.invalidateModule(routesMod);
439
+ devServer.ws.send({ type: "full-reload" });
440
+ }
441
+ } catch (err) {}
442
+ });
443
+ function invalidateModule(id) {
444
+ const mod = devServer.moduleGraph.getModuleById(id);
445
+ if (mod) {
446
+ devServer.moduleGraph.invalidateModule(mod);
447
+ devServer.ws.send({ type: "full-reload" });
448
+ }
449
+ }
450
+ if (entryDetection.useVirtualHtml) devServer.middlewares.use((req, res, next) => {
451
+ if (req.url?.startsWith("/@") || req.url?.startsWith("/__") || req.url?.includes("virtual:") || req.url?.includes("node_modules") || req.url?.startsWith("/@vite") || req.url?.startsWith("/@fs")) return next();
452
+ if (req.url && (req.url === "/" || !req.url.includes("."))) {
453
+ const html = generateHtmlTemplate(ssgConfig);
454
+ devServer.transformIndexHtml(req.url, html).then((transformedHtml) => {
455
+ res.setHeader("Content-Type", "text/html");
456
+ res.end(transformedHtml);
457
+ }).catch(next);
458
+ return;
459
+ }
460
+ next();
461
+ });
462
+ },
463
+ resolveId(id) {
464
+ if (id === "virtual:ssg-routes") return RESOLVED_VIRTUAL_ROUTES_ID;
465
+ if (id === "virtual:generated-layouts") return RESOLVED_VIRTUAL_LAYOUTS_ID;
466
+ if (id === VIRTUAL_CONFIG_ID) return RESOLVED_VIRTUAL_CONFIG_ID;
467
+ if (id === "virtual:ssg-navigation") return RESOLVED_VIRTUAL_NAVIGATION_ID;
468
+ if (id === "virtual:ssg-client" || id === "/@ssg/client.tsx") return RESOLVED_VIRTUAL_CLIENT_ID;
469
+ if (id === "virtual:ssg-server") return RESOLVED_VIRTUAL_SERVER_ID;
470
+ return null;
471
+ },
472
+ async load(id) {
473
+ if (id === "\0virtual:ssg-routes") {
474
+ if (!routesCache) {
475
+ const routes = await scanPages(ssgConfig, root);
476
+ routesCache = {
477
+ routes,
478
+ code: config.command === "serve" ? generateLazyRoutesModule(routes, ssgConfig) : generateRoutesModule(routes, ssgConfig)
479
+ };
480
+ }
481
+ return routesCache.code;
482
+ }
483
+ if (id === "\0virtual:generated-layouts") {
484
+ if (!layoutsCache) {
485
+ const layouts = await discoverLayouts(ssgConfig, root);
486
+ layoutsCache = {
487
+ layouts,
488
+ code: generateLayoutsModule(layouts, ssgConfig)
489
+ };
490
+ }
491
+ return layoutsCache.code;
492
+ }
493
+ if (id === "\0virtual:ssg-navigation") {
494
+ if (!navigationCache) {
495
+ if (!routesCache) {
496
+ const routes = await scanPages(ssgConfig, root);
497
+ routesCache = {
498
+ routes,
499
+ code: config.command === "serve" ? generateLazyRoutesModule(routes, ssgConfig) : generateRoutesModule(routes, ssgConfig)
500
+ };
501
+ }
502
+ const isDev = config.command === "serve";
503
+ navigationCache = { code: generateNavigationModule(routesCache.routes, ssgConfig, isDev) };
504
+ }
505
+ return navigationCache.code;
506
+ }
507
+ if (id === RESOLVED_VIRTUAL_CONFIG_ID) return `export default ${JSON.stringify(ssgConfig)};`;
508
+ if (id === "\0virtual:ssg-client.tsx") {
509
+ const code = generateClientEntry(ssgConfig, entryDetection);
510
+ return (await (await import("esbuild")).transform(code, {
511
+ loader: "tsx",
512
+ jsx: "automatic",
513
+ jsxImportSource: "sigx"
514
+ })).code;
515
+ }
516
+ if (id === "\0virtual:ssg-server.tsx") {
517
+ const code = generateServerEntry(ssgConfig);
518
+ return (await (await import("esbuild")).transform(code, {
519
+ loader: "tsx",
520
+ jsx: "automatic",
521
+ jsxImportSource: "sigx"
522
+ })).code;
523
+ }
524
+ return null;
525
+ },
526
+ async handleHotUpdate({ file, server }) {
527
+ const layoutsDir = path.resolve(root, ssgConfig.layouts || "src/layouts");
528
+ const pagesDir = path.resolve(root, ssgConfig.pages || "src/pages");
529
+ if (file.startsWith(layoutsDir)) {
530
+ layoutsCache = null;
531
+ const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_LAYOUTS_ID);
532
+ if (mod) server.moduleGraph.invalidateModule(mod);
533
+ return [];
534
+ }
535
+ if (file.startsWith(pagesDir) && /\.mdx?$/.test(file)) return;
536
+ }
537
+ };
538
+ if (options.enableMdx !== false) return [mainPlugin, mdxPlugin({
539
+ markdown: options.markdown,
540
+ ssgConfig: void 0
541
+ })];
542
+ return [mainPlugin];
543
+ }
544
+ var plugin_default = ssgPlugin;
545
+ export { ssgPlugin as n, plugin_default as t };
546
+
547
+ //# sourceMappingURL=plugin-DxH1VUGC.js.map