semajsx 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{computed-BpjqvQu1.mjs → computed-BidG06Lt.mjs} +2 -2
- package/dist/{computed-BpjqvQu1.mjs.map → computed-BidG06Lt.mjs.map} +1 -1
- package/dist/{document-OGuk9jhK.mjs → document-BOJDaiBc.mjs} +19 -4
- package/dist/document-BOJDaiBc.mjs.map +1 -0
- package/dist/{document-DFsOtfef.mjs → document-CwHVG_PJ.mjs} +2 -2
- package/dist/dom/index.d.mts +68 -3
- package/dist/dom/index.d.mts.map +1 -1
- package/dist/dom/index.mjs +4 -4
- package/dist/dom/jsx-dev-runtime.d.mts +4 -4
- package/dist/dom/jsx-dev-runtime.mjs +1 -1
- package/dist/dom/jsx-runtime.d.mts +4 -4
- package/dist/dom/jsx-runtime.mjs +2 -2
- package/dist/{helpers-DrifjCXb.d.mts → helpers-CfRDJgcP.d.mts} +3 -3
- package/dist/{helpers-DrifjCXb.d.mts.map → helpers-CfRDJgcP.d.mts.map} +1 -1
- package/dist/{index-DS5X3Pvb.d.mts → index-B1pjI-Su.d.mts} +2 -2
- package/dist/{index-DS5X3Pvb.d.mts.map → index-B1pjI-Su.d.mts.map} +1 -1
- package/dist/index-DC3tthWf.d.mts +81 -0
- package/dist/index-DC3tthWf.d.mts.map +1 -0
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +5 -5
- package/dist/{island-marker-hZdmHMvx.d.mts → island-marker-BJIO07Vj.d.mts} +1 -1
- package/dist/island-marker-BJIO07Vj.d.mts.map +1 -0
- package/dist/{jsx-CGW4OyqA.d.mts → jsx-fNlLjLou.d.mts} +2 -2
- package/dist/{jsx-CGW4OyqA.d.mts.map → jsx-fNlLjLou.d.mts.map} +1 -1
- package/dist/{jsx-runtime-DU8DRISG.d.mts → jsx-runtime-BFuFPDzn.d.mts} +3 -3
- package/dist/{jsx-runtime-DU8DRISG.d.mts.map → jsx-runtime-BFuFPDzn.d.mts.map} +1 -1
- package/dist/jsx-runtime-D9ZNjMJ2.mjs.map +1 -1
- package/dist/{jsx-runtime-mBpL8czJ.d.mts → jsx-runtime-DZx2Yv-t.d.mts} +28 -6
- package/dist/{jsx-runtime-mBpL8czJ.d.mts.map → jsx-runtime-DZx2Yv-t.d.mts.map} +1 -1
- package/dist/lucide-CVtHepGM.mjs +126 -0
- package/dist/lucide-CVtHepGM.mjs.map +1 -0
- package/dist/{resource-B1IudM8_.d.mts → resource-BQI6AeJ0.d.mts} +23 -3
- package/dist/resource-BQI6AeJ0.d.mts.map +1 -0
- package/dist/{resource-BjsDAkbG.mjs → resource-DSlXDZZi.mjs} +2 -2
- package/dist/{resource-BjsDAkbG.mjs.map → resource-DSlXDZZi.mjs.map} +1 -1
- package/dist/signal/index.d.mts +2 -2
- package/dist/signal/index.mjs +3 -3
- package/dist/{signal-4PgGfydw.mjs → signal-BN8vHXDb.mjs} +1 -1
- package/dist/{signal-4PgGfydw.mjs.map → signal-BN8vHXDb.mjs.map} +1 -1
- package/dist/{signal-CLsaPA7c.d.mts → signal-BwxUlXKs.d.mts} +1 -1
- package/dist/{signal-CLsaPA7c.d.mts.map → signal-BwxUlXKs.d.mts.map} +1 -1
- package/dist/{src-CRi0xsNK.mjs → src-BqX3sryB.mjs} +68 -5
- package/dist/src-BqX3sryB.mjs.map +1 -0
- package/dist/src-DR-EWgVP.mjs +868 -0
- package/dist/src-DR-EWgVP.mjs.map +1 -0
- package/dist/{src-DEoBG1zB.mjs → src-DUpFNNM_.mjs} +4 -4
- package/dist/{src-DEoBG1zB.mjs.map → src-DUpFNNM_.mjs.map} +1 -1
- package/dist/{src-BlS3Hc-L.mjs → src-DW3tIczg.mjs} +75 -5
- package/dist/src-DW3tIczg.mjs.map +1 -0
- package/dist/{src-Jbt_w0hc.mjs → src-Ds9vl42d.mjs} +37 -35
- package/dist/src-Ds9vl42d.mjs.map +1 -0
- package/dist/{src-iC-NFwTy.mjs → src-DuSN6go_.mjs} +79 -22
- package/dist/src-DuSN6go_.mjs.map +1 -0
- package/dist/ssg/index.d.mts +4 -182
- package/dist/ssg/index.d.mts.map +1 -1
- package/dist/ssg/index.mjs +7 -756
- package/dist/ssg/index.mjs.map +1 -1
- package/dist/ssg/plugins/docs-theme.d.mts +180 -0
- package/dist/ssg/plugins/docs-theme.d.mts.map +1 -0
- package/dist/ssg/plugins/docs-theme.mjs +2042 -0
- package/dist/ssg/plugins/docs-theme.mjs.map +1 -0
- package/dist/ssg/plugins/lucide.d.mts +3 -0
- package/dist/ssg/plugins/lucide.mjs +7 -0
- package/dist/ssr/client.d.mts +3 -3
- package/dist/ssr/client.mjs +5 -5
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.mts.map +1 -1
- package/dist/ssr/index.mjs +6 -5
- package/dist/style/index.d.mts +2 -2
- package/dist/style/index.d.mts.map +1 -1
- package/dist/style/index.mjs +1 -1
- package/dist/style/react.d.mts +2 -2
- package/dist/style/react.mjs +2 -2
- package/dist/style/vue.d.mts +2 -2
- package/dist/style/vue.mjs +2 -2
- package/dist/terminal/index.d.mts +4 -4
- package/dist/terminal/index.mjs +2 -2
- package/dist/terminal/jsx-dev-runtime.d.mts +4 -4
- package/dist/terminal/jsx-dev-runtime.mjs +1 -1
- package/dist/terminal/jsx-runtime.d.mts +4 -4
- package/dist/terminal/jsx-runtime.mjs +1 -1
- package/dist/{types-DlNR9ZaJ.d.mts → types-BlaUrkq0.d.mts} +2 -2
- package/dist/{types-DlNR9ZaJ.d.mts.map → types-BlaUrkq0.d.mts.map} +1 -1
- package/dist/types-CGkRxnQB.d.mts +220 -0
- package/dist/types-CGkRxnQB.d.mts.map +1 -0
- package/dist/{types-Dgj6n-EE.d.mts → types-CZMcXQTW.d.mts} +9 -4
- package/dist/types-CZMcXQTW.d.mts.map +1 -0
- package/dist/{types-Bjx1Pp14.d.mts → types-D0jRO840.d.mts} +1 -1
- package/dist/{types-Bjx1Pp14.d.mts.map → types-D0jRO840.d.mts.map} +1 -1
- package/dist/{types-DEi0apQO.d.mts → types-DucvOZQ2.d.mts} +2 -2
- package/dist/{types-DEi0apQO.d.mts.map → types-DucvOZQ2.d.mts.map} +1 -1
- package/dist/{utils-BrGmTgfG.mjs → utils-DbTAs943.mjs} +1 -1
- package/dist/{utils-BrGmTgfG.mjs.map → utils-DbTAs943.mjs.map} +1 -1
- package/package.json +30 -2
- package/dist/document-OGuk9jhK.mjs.map +0 -1
- package/dist/island-marker-hZdmHMvx.d.mts.map +0 -1
- package/dist/jsx-runtime-D2B2BK8X.mjs +0 -4
- package/dist/resource-B1IudM8_.d.mts.map +0 -1
- package/dist/src-BlS3Hc-L.mjs.map +0 -1
- package/dist/src-CRi0xsNK.mjs.map +0 -1
- package/dist/src-Jbt_w0hc.mjs.map +0 -1
- package/dist/src-iC-NFwTy.mjs.map +0 -1
- package/dist/types-Dgj6n-EE.d.mts.map +0 -1
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
import { a as jsxs, i as jsx } from "./src-DW3tIczg.mjs";
|
|
2
|
+
import { s as createApp } from "./src-DuSN6go_.mjs";
|
|
3
|
+
import { n as renderDocument } from "./document-BOJDaiBc.mjs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join, relative, resolve } from "path";
|
|
6
|
+
import { mkdir, readFile, rm, watch, writeFile } from "fs/promises";
|
|
7
|
+
import { compile } from "@mdx-js/mdx";
|
|
8
|
+
import { glob } from "glob";
|
|
9
|
+
import matter from "gray-matter";
|
|
10
|
+
import { exec } from "child_process";
|
|
11
|
+
import { promisify } from "util";
|
|
12
|
+
import { z as z$1 } from "zod";
|
|
13
|
+
|
|
14
|
+
//#region rolldown:runtime
|
|
15
|
+
var __defProp = Object.defineProperty;
|
|
16
|
+
var __exportAll = (all, symbols) => {
|
|
17
|
+
let target = {};
|
|
18
|
+
for (var name in all) {
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (symbols) {
|
|
25
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
};
|
|
29
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region ../ssg/src/document.tsx
|
|
33
|
+
/**
|
|
34
|
+
* Default HTML document template for SSG
|
|
35
|
+
*/
|
|
36
|
+
const DefaultDocument = ({ children, title = "SSG Page", scripts, css }) => /* @__PURE__ */ jsxs("html", {
|
|
37
|
+
lang: "en",
|
|
38
|
+
children: [/* @__PURE__ */ jsxs("head", { children: [
|
|
39
|
+
/* @__PURE__ */ jsx("meta", { charSet: "UTF-8" }),
|
|
40
|
+
/* @__PURE__ */ jsx("meta", {
|
|
41
|
+
name: "viewport",
|
|
42
|
+
content: "width=device-width, initial-scale=1.0"
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ jsx("title", { children: title }),
|
|
45
|
+
css?.map((href) => /* @__PURE__ */ jsx("link", {
|
|
46
|
+
rel: "stylesheet",
|
|
47
|
+
href
|
|
48
|
+
}))
|
|
49
|
+
] }), /* @__PURE__ */ jsxs("body", { children: [children, scripts] })]
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region ../ssg/src/types.ts
|
|
54
|
+
/**
|
|
55
|
+
* Raw HTML VNode that can be used directly in JSX or converted to string
|
|
56
|
+
*/
|
|
57
|
+
var RawHTML = class {
|
|
58
|
+
constructor(html) {
|
|
59
|
+
this.html = html;
|
|
60
|
+
this.type = "div";
|
|
61
|
+
this.children = [];
|
|
62
|
+
this.props = { dangerouslySetInnerHTML: { __html: html } };
|
|
63
|
+
}
|
|
64
|
+
toString() {
|
|
65
|
+
return this.html;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region ../ssg/src/mdx/processor.ts
|
|
71
|
+
/**
|
|
72
|
+
* MDX Processor for compiling MDX content to JSX components
|
|
73
|
+
*/
|
|
74
|
+
var MDXProcessor = class {
|
|
75
|
+
constructor(config = {}) {
|
|
76
|
+
this.config = config;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Compile MDX content to a JSX component
|
|
80
|
+
*/
|
|
81
|
+
async compile(content, frontmatter = {}) {
|
|
82
|
+
const headings = this.extractHeadings(content);
|
|
83
|
+
const compiled = await compile(content, {
|
|
84
|
+
outputFormat: "function-body",
|
|
85
|
+
development: false,
|
|
86
|
+
remarkPlugins: this.config.remarkPlugins ?? [],
|
|
87
|
+
rehypePlugins: this.config.rehypePlugins ?? [],
|
|
88
|
+
jsxImportSource: "semajsx/dom"
|
|
89
|
+
});
|
|
90
|
+
const jsxRuntime = await import("semajsx/dom/jsx-runtime");
|
|
91
|
+
return {
|
|
92
|
+
Content: this.createComponent(String(compiled), this.config.components ?? {}, jsxRuntime),
|
|
93
|
+
frontmatter,
|
|
94
|
+
headings
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create a component from compiled MDX code
|
|
99
|
+
*/
|
|
100
|
+
createComponent(code, components, jsxRuntime) {
|
|
101
|
+
return (props = {}) => {
|
|
102
|
+
try {
|
|
103
|
+
return new Function(code + "\nreturn MDXContent;").call(null, jsxRuntime).default({
|
|
104
|
+
...props,
|
|
105
|
+
components
|
|
106
|
+
});
|
|
107
|
+
} catch (e) {
|
|
108
|
+
throw new Error(`MDX rendering failed: ${e.message}`);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Extract headings from markdown content
|
|
114
|
+
*/
|
|
115
|
+
extractHeadings(content) {
|
|
116
|
+
const headings = [];
|
|
117
|
+
const headingRegex = /^(#{1,6})\s+(.+)$/gm;
|
|
118
|
+
let match;
|
|
119
|
+
while ((match = headingRegex.exec(content)) !== null) {
|
|
120
|
+
const hashes = match[1];
|
|
121
|
+
const rawText = match[2];
|
|
122
|
+
if (!hashes || !rawText) continue;
|
|
123
|
+
const depth = hashes.length;
|
|
124
|
+
const text = rawText.trim();
|
|
125
|
+
const slug = this.slugify(text);
|
|
126
|
+
headings.push({
|
|
127
|
+
depth,
|
|
128
|
+
text,
|
|
129
|
+
slug
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return headings;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Convert text to URL-friendly slug
|
|
136
|
+
*/
|
|
137
|
+
slugify(text) {
|
|
138
|
+
return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Create an MDX processor instance
|
|
143
|
+
*/
|
|
144
|
+
function createMDXProcessor(config) {
|
|
145
|
+
return new MDXProcessor(config);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region ../ssg/src/mdx/vite-plugin.ts
|
|
150
|
+
/**
|
|
151
|
+
* Vite plugin for MDX support
|
|
152
|
+
* Transforms .mdx files to JSX modules
|
|
153
|
+
*/
|
|
154
|
+
function viteMDXPlugin(options = {}) {
|
|
155
|
+
return {
|
|
156
|
+
name: "semajsx-mdx",
|
|
157
|
+
async transform(code, id) {
|
|
158
|
+
if (!id.endsWith(".mdx")) return null;
|
|
159
|
+
try {
|
|
160
|
+
const compiled = await compile(code, {
|
|
161
|
+
jsxImportSource: "semajsx/dom",
|
|
162
|
+
outputFormat: "program",
|
|
163
|
+
development: false,
|
|
164
|
+
remarkPlugins: options.remarkPlugins ?? [],
|
|
165
|
+
rehypePlugins: options.rehypePlugins ?? []
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
code: String(compiled),
|
|
169
|
+
map: null
|
|
170
|
+
};
|
|
171
|
+
} catch (error) {
|
|
172
|
+
const err = error;
|
|
173
|
+
throw new Error(`MDX compilation failed for ${id}: ${err.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region ../ssg/src/ssg.ts
|
|
181
|
+
/**
|
|
182
|
+
* Sort plugins by enforce order: 'pre' → normal → 'post'
|
|
183
|
+
*/
|
|
184
|
+
function sortPlugins(plugins) {
|
|
185
|
+
const pre = [];
|
|
186
|
+
const normal = [];
|
|
187
|
+
const post = [];
|
|
188
|
+
for (const plugin of plugins) if (plugin.enforce === "pre") pre.push(plugin);
|
|
189
|
+
else if (plugin.enforce === "post") post.push(plugin);
|
|
190
|
+
else normal.push(plugin);
|
|
191
|
+
return [
|
|
192
|
+
...pre,
|
|
193
|
+
...normal,
|
|
194
|
+
...post
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Merge a partial MDX config into an existing one.
|
|
199
|
+
*/
|
|
200
|
+
function mergeMdxConfig(base, partial) {
|
|
201
|
+
return {
|
|
202
|
+
remarkPlugins: [...base.remarkPlugins ?? [], ...partial.remarkPlugins ?? []],
|
|
203
|
+
rehypePlugins: [...base.rehypePlugins ?? [], ...partial.rehypePlugins ?? []],
|
|
204
|
+
components: {
|
|
205
|
+
...base.components,
|
|
206
|
+
...partial.components
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Run config hooks on all plugins, then merge with user config.
|
|
212
|
+
*
|
|
213
|
+
* Plugin arrays are flattened Vite-style: plugin factories may return
|
|
214
|
+
* `SSGPlugin | SSGPlugin[]`, and the top-level array is `.flat()`-ed
|
|
215
|
+
* before sorting and processing.
|
|
216
|
+
*
|
|
217
|
+
* Merge strategies:
|
|
218
|
+
* - mdx: merge (concat arrays, merge component objects)
|
|
219
|
+
* - document: override (last writer wins, user config last)
|
|
220
|
+
* - routes: concat (plugin routes first, then user routes)
|
|
221
|
+
* - collections: concat (plugin collections first, then user collections)
|
|
222
|
+
*/
|
|
223
|
+
function resolvePlugins(plugins, config) {
|
|
224
|
+
const sorted = sortPlugins(plugins.flat());
|
|
225
|
+
let mdx = {
|
|
226
|
+
remarkPlugins: [],
|
|
227
|
+
rehypePlugins: [],
|
|
228
|
+
components: {}
|
|
229
|
+
};
|
|
230
|
+
let document;
|
|
231
|
+
const routes = [];
|
|
232
|
+
const collections = [];
|
|
233
|
+
for (const plugin of sorted) {
|
|
234
|
+
if (!plugin.config) continue;
|
|
235
|
+
const partial = plugin.config(config);
|
|
236
|
+
if (!partial) continue;
|
|
237
|
+
if (partial.mdx) mdx = mergeMdxConfig(mdx, partial.mdx);
|
|
238
|
+
if (partial.document) document = partial.document;
|
|
239
|
+
if (partial.routes) routes.push(...partial.routes);
|
|
240
|
+
if (partial.collections) collections.push(...partial.collections);
|
|
241
|
+
}
|
|
242
|
+
if (config.mdx) mdx = mergeMdxConfig(mdx, config.mdx);
|
|
243
|
+
if (config.document) document = config.document;
|
|
244
|
+
if (config.routes) routes.push(...config.routes);
|
|
245
|
+
if (config.collections) collections.push(...config.collections);
|
|
246
|
+
return {
|
|
247
|
+
config: {
|
|
248
|
+
mdx,
|
|
249
|
+
document,
|
|
250
|
+
routes,
|
|
251
|
+
collections
|
|
252
|
+
},
|
|
253
|
+
allPlugins: sorted
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* SSG (Static Site Generator) core class
|
|
258
|
+
* Built on top of server's createApp
|
|
259
|
+
*/
|
|
260
|
+
var SSG = class {
|
|
261
|
+
constructor(config) {
|
|
262
|
+
this.mdxModules = /* @__PURE__ */ new Map();
|
|
263
|
+
this.rootDir = config.rootDir ?? process.cwd();
|
|
264
|
+
const { config: resolved, allPlugins } = resolvePlugins(config.plugins ?? [], config);
|
|
265
|
+
this.plugins = allPlugins;
|
|
266
|
+
this.config = {
|
|
267
|
+
base: "/",
|
|
268
|
+
...config,
|
|
269
|
+
mdx: resolved.mdx,
|
|
270
|
+
document: resolved.document,
|
|
271
|
+
routes: resolved.routes,
|
|
272
|
+
collections: resolved.collections,
|
|
273
|
+
outDir: resolve(this.rootDir, config.outDir)
|
|
274
|
+
};
|
|
275
|
+
for (const plugin of this.plugins) plugin.configResolved?.(this.config);
|
|
276
|
+
this.collections = /* @__PURE__ */ new Map();
|
|
277
|
+
this.entriesCache = /* @__PURE__ */ new Map();
|
|
278
|
+
this.app = createApp({
|
|
279
|
+
root: this.rootDir,
|
|
280
|
+
vite: { plugins: [{
|
|
281
|
+
name: "ssg-virtual-mdx",
|
|
282
|
+
resolveId: (id) => {
|
|
283
|
+
if (id.startsWith("virtual:mdx:")) return "\0" + id;
|
|
284
|
+
},
|
|
285
|
+
load: (id) => {
|
|
286
|
+
if (id.startsWith("\0virtual:mdx:")) {
|
|
287
|
+
const mdxId = id.replace("\0virtual:mdx:", "");
|
|
288
|
+
return this.mdxModules.get(mdxId);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}, viteMDXPlugin(resolved.mdx)] }
|
|
292
|
+
});
|
|
293
|
+
for (const collection of this.config.collections ?? []) this.collections.set(collection.name, collection);
|
|
294
|
+
}
|
|
295
|
+
getRootDir() {
|
|
296
|
+
return this.rootDir;
|
|
297
|
+
}
|
|
298
|
+
async getCollection(name) {
|
|
299
|
+
const collection = this.collections.get(name);
|
|
300
|
+
if (!collection) throw new Error(`Collection "${name}" not found`);
|
|
301
|
+
if (this.entriesCache.has(name)) return this.entriesCache.get(name);
|
|
302
|
+
const validatedEntries = (await collection.source.getEntries()).map((entry) => {
|
|
303
|
+
const result = collection.schema.safeParse(entry.data);
|
|
304
|
+
if (!result.success) throw new Error(`Validation error in ${name}/${entry.id}: ${result.error.message}`);
|
|
305
|
+
return {
|
|
306
|
+
...entry,
|
|
307
|
+
data: result.data,
|
|
308
|
+
render: async () => {
|
|
309
|
+
const vite = this.app.getViteServer();
|
|
310
|
+
if (!vite) throw new Error("Vite server not initialized");
|
|
311
|
+
const mdxId = `${name}/${entry.id}.mdx`;
|
|
312
|
+
this.mdxModules.set(mdxId, entry.body);
|
|
313
|
+
try {
|
|
314
|
+
const moduleExports = await vite.ssrLoadModule(`virtual:mdx:${mdxId}`);
|
|
315
|
+
const Content = (props = {}) => moduleExports.default({
|
|
316
|
+
...props,
|
|
317
|
+
components: this.config.mdx?.components ?? {}
|
|
318
|
+
});
|
|
319
|
+
return {
|
|
320
|
+
Content,
|
|
321
|
+
headings: this.extractHeadings(entry.body)
|
|
322
|
+
};
|
|
323
|
+
} finally {
|
|
324
|
+
this.mdxModules.delete(mdxId);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
});
|
|
329
|
+
this.entriesCache.set(name, validatedEntries);
|
|
330
|
+
return validatedEntries;
|
|
331
|
+
}
|
|
332
|
+
async getEntry(name, id) {
|
|
333
|
+
return (await this.getCollection(name)).find((e) => e.id === id || e.slug === id) ?? null;
|
|
334
|
+
}
|
|
335
|
+
async build(options = {}) {
|
|
336
|
+
const { incremental = false, state: prevState } = options;
|
|
337
|
+
const outDir = this.config.outDir;
|
|
338
|
+
for (const plugin of this.plugins) await plugin.buildStart?.();
|
|
339
|
+
await this.app.prepare();
|
|
340
|
+
try {
|
|
341
|
+
await this.registerRoutes();
|
|
342
|
+
const result = await this.buildPages(incremental, prevState, outDir);
|
|
343
|
+
const documentTemplate = this.config.document ?? DefaultDocument;
|
|
344
|
+
await this.app.build({
|
|
345
|
+
outDir,
|
|
346
|
+
mode: "full",
|
|
347
|
+
minify: true,
|
|
348
|
+
renderHtml: ({ html, css, scripts, title, path: routePath }) => {
|
|
349
|
+
const scriptsHtml = scripts.map((s) => `<script type="module" src="${s.src}"><\/script>`).join("\n");
|
|
350
|
+
return renderDocument(documentTemplate({
|
|
351
|
+
children: new RawHTML(html),
|
|
352
|
+
title,
|
|
353
|
+
base: this.config.base ?? "/",
|
|
354
|
+
path: routePath,
|
|
355
|
+
props: {},
|
|
356
|
+
scripts: scriptsHtml ? new RawHTML(scriptsHtml) : void 0,
|
|
357
|
+
css: css ?? []
|
|
358
|
+
}));
|
|
359
|
+
},
|
|
360
|
+
vite: { build: { rollupOptions: { external: [] } } }
|
|
361
|
+
});
|
|
362
|
+
for (const plugin of this.plugins) await plugin.buildEnd?.(result);
|
|
363
|
+
return result;
|
|
364
|
+
} finally {
|
|
365
|
+
await this.app.close();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async registerRoutes() {
|
|
369
|
+
const routes = this.config.routes ?? [];
|
|
370
|
+
for (const route of routes) if (route.getStaticPaths) {
|
|
371
|
+
const staticPaths = await route.getStaticPaths(this);
|
|
372
|
+
for (const sp of staticPaths) {
|
|
373
|
+
const path = this.applyParams(route.path, sp.params);
|
|
374
|
+
const props = {
|
|
375
|
+
...sp.props,
|
|
376
|
+
params: sp.params
|
|
377
|
+
};
|
|
378
|
+
this.app.route(path, (_context) => {
|
|
379
|
+
return route.component(props);
|
|
380
|
+
}, { title: props.title });
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
let props = {};
|
|
384
|
+
if (typeof route.props === "function") props = await route.props(this);
|
|
385
|
+
else if (route.props) props = route.props;
|
|
386
|
+
this.app.route(route.path, (_context) => {
|
|
387
|
+
return route.component(props);
|
|
388
|
+
}, { title: props.title });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
async buildPages(incremental, prevState, outDir) {
|
|
392
|
+
const state = {
|
|
393
|
+
cursors: {},
|
|
394
|
+
pageHashes: {},
|
|
395
|
+
timestamp: Date.now()
|
|
396
|
+
};
|
|
397
|
+
const stats = {
|
|
398
|
+
added: 0,
|
|
399
|
+
updated: 0,
|
|
400
|
+
deleted: 0,
|
|
401
|
+
unchanged: 0
|
|
402
|
+
};
|
|
403
|
+
const builtPaths = [];
|
|
404
|
+
if (!incremental) await rm(outDir, {
|
|
405
|
+
recursive: true,
|
|
406
|
+
force: true
|
|
407
|
+
});
|
|
408
|
+
await mkdir(outDir, { recursive: true });
|
|
409
|
+
this.entriesCache.clear();
|
|
410
|
+
const allPaths = await this.generateAllPaths();
|
|
411
|
+
const currentPaths = new Set(allPaths.map((p) => p.path));
|
|
412
|
+
if (incremental && prevState) {
|
|
413
|
+
for (const oldPath of Object.keys(prevState.pageHashes)) if (!currentPaths.has(oldPath)) {
|
|
414
|
+
const filePath = this.pathToFilePath(oldPath);
|
|
415
|
+
try {
|
|
416
|
+
await rm(join(outDir, filePath));
|
|
417
|
+
stats.deleted++;
|
|
418
|
+
} catch {}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
for (const { path, props } of allPaths) {
|
|
422
|
+
const html = await this.renderPage(path, props);
|
|
423
|
+
const hash = this.hashContent(html);
|
|
424
|
+
const prevHash = prevState?.pageHashes[path];
|
|
425
|
+
if (!incremental || !prevHash || prevHash !== hash) {
|
|
426
|
+
const fullPath = join(outDir, this.pathToFilePath(path));
|
|
427
|
+
await mkdir(dirname(fullPath), { recursive: true });
|
|
428
|
+
await writeFile(fullPath, html);
|
|
429
|
+
builtPaths.push(path);
|
|
430
|
+
if (!prevHash) stats.added++;
|
|
431
|
+
else stats.updated++;
|
|
432
|
+
} else stats.unchanged++;
|
|
433
|
+
state.pageHashes[path] = hash;
|
|
434
|
+
}
|
|
435
|
+
for (const [name, collection] of this.collections) if (collection.source.getChanges) state.cursors[name] = Date.now().toString();
|
|
436
|
+
return {
|
|
437
|
+
state,
|
|
438
|
+
paths: builtPaths,
|
|
439
|
+
stats
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
async renderPage(path, props) {
|
|
443
|
+
const result = await this.app.render(path);
|
|
444
|
+
const documentProps = {
|
|
445
|
+
children: new RawHTML(result.html),
|
|
446
|
+
title: props.title,
|
|
447
|
+
base: this.config.base ?? "/",
|
|
448
|
+
path,
|
|
449
|
+
props,
|
|
450
|
+
scripts: result.scripts ? new RawHTML(result.scripts) : void 0,
|
|
451
|
+
css: result.css ?? []
|
|
452
|
+
};
|
|
453
|
+
return renderDocument((this.config.document ?? DefaultDocument)(documentProps));
|
|
454
|
+
}
|
|
455
|
+
async generateAllPaths() {
|
|
456
|
+
const paths = [];
|
|
457
|
+
const routes = this.config.routes ?? [];
|
|
458
|
+
for (const route of routes) if (route.getStaticPaths) {
|
|
459
|
+
const staticPaths = await route.getStaticPaths(this);
|
|
460
|
+
for (const sp of staticPaths) {
|
|
461
|
+
const path = this.applyParams(route.path, sp.params);
|
|
462
|
+
paths.push({
|
|
463
|
+
path,
|
|
464
|
+
props: {
|
|
465
|
+
...sp.props,
|
|
466
|
+
params: sp.params
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
let props = {};
|
|
472
|
+
if (typeof route.props === "function") props = await route.props(this);
|
|
473
|
+
else if (route.props) props = route.props;
|
|
474
|
+
paths.push({
|
|
475
|
+
path: route.path,
|
|
476
|
+
props
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
return paths;
|
|
480
|
+
}
|
|
481
|
+
watch(options = {}) {
|
|
482
|
+
const unsubscribers = [];
|
|
483
|
+
for (const [name, collection] of this.collections) if (collection.source.watch) {
|
|
484
|
+
const unsubscribe = collection.source.watch(async () => {
|
|
485
|
+
try {
|
|
486
|
+
this.entriesCache.delete(name);
|
|
487
|
+
const result = await this.build({ incremental: true });
|
|
488
|
+
options.onRebuild?.(result);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
options.onError?.(error);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
unsubscribers.push(unsubscribe);
|
|
494
|
+
}
|
|
495
|
+
return { close: () => unsubscribers.forEach((fn) => fn()) };
|
|
496
|
+
}
|
|
497
|
+
pathToFilePath(urlPath) {
|
|
498
|
+
if (urlPath === "/") return "index.html";
|
|
499
|
+
return `${urlPath.slice(1)}/index.html`;
|
|
500
|
+
}
|
|
501
|
+
applyParams(pattern, params) {
|
|
502
|
+
let path = pattern;
|
|
503
|
+
for (const [key, value] of Object.entries(params)) path = path.replace(`:${key}`, value);
|
|
504
|
+
return path;
|
|
505
|
+
}
|
|
506
|
+
hashContent(content) {
|
|
507
|
+
let hash = 0;
|
|
508
|
+
for (let i = 0; i < content.length; i++) {
|
|
509
|
+
const char = content.charCodeAt(i);
|
|
510
|
+
hash = (hash << 5) - hash + char;
|
|
511
|
+
hash = hash & hash;
|
|
512
|
+
}
|
|
513
|
+
return hash.toString(16);
|
|
514
|
+
}
|
|
515
|
+
extractHeadings(content) {
|
|
516
|
+
const headings = [];
|
|
517
|
+
const regex = /^(#{1,6})\s+(.+)$/gm;
|
|
518
|
+
let match;
|
|
519
|
+
while ((match = regex.exec(content)) !== null) {
|
|
520
|
+
if (!match[1] || !match[2]) continue;
|
|
521
|
+
const depth = match[1].length;
|
|
522
|
+
const text = match[2].trim();
|
|
523
|
+
const slug = text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-");
|
|
524
|
+
headings.push({
|
|
525
|
+
depth,
|
|
526
|
+
text,
|
|
527
|
+
slug
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
return headings;
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
function createSSG(config) {
|
|
534
|
+
return new SSG(config);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region ../ssg/src/collection/index.ts
|
|
539
|
+
/**
|
|
540
|
+
* Define a collection with schema validation
|
|
541
|
+
*/
|
|
542
|
+
function defineCollection(config) {
|
|
543
|
+
return {
|
|
544
|
+
name: config.name,
|
|
545
|
+
source: config.source,
|
|
546
|
+
schema: config.schema
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region ../ssg/src/sources/base.ts
|
|
552
|
+
/**
|
|
553
|
+
* Base class for collection sources
|
|
554
|
+
*/
|
|
555
|
+
var BaseSource = class {
|
|
556
|
+
async getEntry(id) {
|
|
557
|
+
return (await this.getEntries()).find((e) => e.id === id) ?? null;
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region ../ssg/src/sources/file.ts
|
|
563
|
+
/**
|
|
564
|
+
* File system source for collections
|
|
565
|
+
*/
|
|
566
|
+
var FileSource = class extends BaseSource {
|
|
567
|
+
constructor(options, contentRoot = process.cwd()) {
|
|
568
|
+
super();
|
|
569
|
+
this.directory = options.directory;
|
|
570
|
+
this.include = options.include ?? "**/*.{md,mdx}";
|
|
571
|
+
this.shouldWatch = options.watch ?? false;
|
|
572
|
+
this.contentRoot = contentRoot;
|
|
573
|
+
this.id = `file:${this.directory}`;
|
|
574
|
+
}
|
|
575
|
+
async getEntries() {
|
|
576
|
+
const dir = join(this.contentRoot, this.directory);
|
|
577
|
+
const files = await glob(join(dir, this.include));
|
|
578
|
+
return await Promise.all(files.map(async (filePath) => {
|
|
579
|
+
const { data, content: body } = matter(await readFile(filePath, "utf-8"));
|
|
580
|
+
const id = relative(dir, filePath).replace(/\.(md|mdx)$/, "");
|
|
581
|
+
return {
|
|
582
|
+
id,
|
|
583
|
+
slug: id.replace(/\\/g, "/"),
|
|
584
|
+
data,
|
|
585
|
+
body,
|
|
586
|
+
render: async () => {
|
|
587
|
+
return { Content: () => {
|
|
588
|
+
throw new Error("MDX rendering not yet implemented");
|
|
589
|
+
} };
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
}));
|
|
593
|
+
}
|
|
594
|
+
watch(callback) {
|
|
595
|
+
if (!this.shouldWatch) return () => {};
|
|
596
|
+
const dir = join(this.contentRoot, this.directory);
|
|
597
|
+
const abortController = new AbortController();
|
|
598
|
+
const startWatching = async () => {
|
|
599
|
+
try {
|
|
600
|
+
const watcher = watch(dir, {
|
|
601
|
+
recursive: true,
|
|
602
|
+
signal: abortController.signal
|
|
603
|
+
});
|
|
604
|
+
for await (const _event of watcher) {
|
|
605
|
+
const entries = await this.getEntries();
|
|
606
|
+
callback({
|
|
607
|
+
cursor: Date.now().toString(),
|
|
608
|
+
added: [],
|
|
609
|
+
updated: entries,
|
|
610
|
+
deleted: []
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
} catch (err) {
|
|
614
|
+
if (err.name !== "AbortError") throw err;
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
startWatching();
|
|
618
|
+
return () => {
|
|
619
|
+
abortController.abort();
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
async getChanges(_since) {
|
|
623
|
+
const entries = await this.getEntries();
|
|
624
|
+
return {
|
|
625
|
+
cursor: Date.now().toString(),
|
|
626
|
+
added: [],
|
|
627
|
+
updated: entries,
|
|
628
|
+
deleted: []
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
/**
|
|
633
|
+
* Create a file system source
|
|
634
|
+
*/
|
|
635
|
+
function fileSource(options, contentRoot) {
|
|
636
|
+
return new FileSource(options, contentRoot);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
//#endregion
|
|
640
|
+
//#region ../ssg/src/sources/git.ts
|
|
641
|
+
const execAsync = promisify(exec);
|
|
642
|
+
/**
|
|
643
|
+
* Git source for collections
|
|
644
|
+
*/
|
|
645
|
+
var GitSource = class extends BaseSource {
|
|
646
|
+
constructor(options, cwd = process.cwd()) {
|
|
647
|
+
super();
|
|
648
|
+
this.options = options;
|
|
649
|
+
this.cwd = cwd;
|
|
650
|
+
this.id = `git:${options.type}`;
|
|
651
|
+
}
|
|
652
|
+
async getEntries() {
|
|
653
|
+
if (this.options.type === "commits") return this.getCommits(this.options);
|
|
654
|
+
else return this.getTags(this.options);
|
|
655
|
+
}
|
|
656
|
+
async getCommits(options) {
|
|
657
|
+
const args = ["log", "--format=%H|%s|%an|%ae|%aI"];
|
|
658
|
+
if (options.filter?.since) args.push(`--since=${options.filter.since}`);
|
|
659
|
+
if (options.filter?.until) args.push(`--until=${options.filter.until}`);
|
|
660
|
+
if (options.filter?.author) args.push(`--author=${options.filter.author}`);
|
|
661
|
+
if (options.limit) args.push(`-n`, options.limit.toString());
|
|
662
|
+
if (options.filter?.paths?.length) args.push("--", ...options.filter.paths);
|
|
663
|
+
const { stdout } = await execAsync(`git ${args.join(" ")}`, { cwd: this.cwd });
|
|
664
|
+
return stdout.trim().split("\n").filter(Boolean).map((line) => {
|
|
665
|
+
const parts = line.split("|");
|
|
666
|
+
const hash = parts[0] ?? "";
|
|
667
|
+
const message = parts[1] ?? "";
|
|
668
|
+
const author = parts[2] ?? "";
|
|
669
|
+
const email = parts[3] ?? "";
|
|
670
|
+
const dateStr = parts[4] ?? "";
|
|
671
|
+
const data = {
|
|
672
|
+
hash,
|
|
673
|
+
message,
|
|
674
|
+
author,
|
|
675
|
+
email,
|
|
676
|
+
date: new Date(dateStr)
|
|
677
|
+
};
|
|
678
|
+
return {
|
|
679
|
+
id: hash,
|
|
680
|
+
slug: hash.slice(0, 7),
|
|
681
|
+
data,
|
|
682
|
+
body: message,
|
|
683
|
+
render: async () => ({ Content: () => {
|
|
684
|
+
throw new Error("Git commits cannot be rendered as content");
|
|
685
|
+
} })
|
|
686
|
+
};
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
async getTags(options) {
|
|
690
|
+
const { stdout } = await execAsync(`git tag -l "${options.pattern ?? "*"}" --format="%(refname:short)|%(objectname:short)|%(creatordate:iso)|%(contents:subject)"`, { cwd: this.cwd });
|
|
691
|
+
return stdout.trim().split("\n").filter(Boolean).map((line) => {
|
|
692
|
+
const parts = line.split("|");
|
|
693
|
+
const tag = parts[0] ?? "";
|
|
694
|
+
const hash = parts[1] ?? "";
|
|
695
|
+
const dateStr = parts[2] ?? "";
|
|
696
|
+
const message = parts[3] ?? "";
|
|
697
|
+
return {
|
|
698
|
+
id: tag,
|
|
699
|
+
slug: tag,
|
|
700
|
+
data: {
|
|
701
|
+
tag,
|
|
702
|
+
hash,
|
|
703
|
+
date: new Date(dateStr),
|
|
704
|
+
message: message || void 0
|
|
705
|
+
},
|
|
706
|
+
body: message,
|
|
707
|
+
render: async () => ({ Content: () => {
|
|
708
|
+
throw new Error("Git tags cannot be rendered as content");
|
|
709
|
+
} })
|
|
710
|
+
};
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
/**
|
|
715
|
+
* Create a Git source
|
|
716
|
+
*/
|
|
717
|
+
function gitSource(options, cwd) {
|
|
718
|
+
return new GitSource(options, cwd);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
//#endregion
|
|
722
|
+
//#region ../ssg/src/sources/remote.ts
|
|
723
|
+
/**
|
|
724
|
+
* Remote API source for collections
|
|
725
|
+
*/
|
|
726
|
+
var RemoteSource = class extends BaseSource {
|
|
727
|
+
constructor(options, id = "remote") {
|
|
728
|
+
super();
|
|
729
|
+
this.options = options;
|
|
730
|
+
this.id = `remote:${id}`;
|
|
731
|
+
}
|
|
732
|
+
async getEntries() {
|
|
733
|
+
return (await this.options.fetch()).map((item, index) => {
|
|
734
|
+
const id = item.id?.toString() ?? index.toString();
|
|
735
|
+
return {
|
|
736
|
+
id,
|
|
737
|
+
slug: item.slug?.toString() ?? id,
|
|
738
|
+
data: item,
|
|
739
|
+
body: item.content?.toString() ?? "",
|
|
740
|
+
render: async () => ({ Content: () => {
|
|
741
|
+
throw new Error("Remote content rendering not yet implemented");
|
|
742
|
+
} })
|
|
743
|
+
};
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
async getEntry(id) {
|
|
747
|
+
if (this.options.fetchOne) {
|
|
748
|
+
const item = await this.options.fetchOne(id);
|
|
749
|
+
if (!item) return null;
|
|
750
|
+
return {
|
|
751
|
+
id,
|
|
752
|
+
slug: item.slug?.toString() ?? id,
|
|
753
|
+
data: item,
|
|
754
|
+
body: item.content?.toString() ?? "",
|
|
755
|
+
render: async () => ({ Content: () => {
|
|
756
|
+
throw new Error("Remote content rendering not yet implemented");
|
|
757
|
+
} })
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
return super.getEntry(id);
|
|
761
|
+
}
|
|
762
|
+
watch(callback) {
|
|
763
|
+
if (this.options.pollInterval) {
|
|
764
|
+
this.pollTimer = setInterval(async () => {
|
|
765
|
+
const entries = await this.getEntries();
|
|
766
|
+
callback({
|
|
767
|
+
cursor: Date.now().toString(),
|
|
768
|
+
added: [],
|
|
769
|
+
updated: entries,
|
|
770
|
+
deleted: []
|
|
771
|
+
});
|
|
772
|
+
}, this.options.pollInterval);
|
|
773
|
+
return () => {
|
|
774
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
return () => {};
|
|
778
|
+
}
|
|
779
|
+
async getChanges(since) {
|
|
780
|
+
if (this.options.fetchChanges) return this.options.fetchChanges(since);
|
|
781
|
+
const entries = await this.getEntries();
|
|
782
|
+
return {
|
|
783
|
+
cursor: Date.now().toString(),
|
|
784
|
+
added: [],
|
|
785
|
+
updated: entries,
|
|
786
|
+
deleted: []
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Get webhook configuration for external integration
|
|
791
|
+
*/
|
|
792
|
+
getWebhookConfig() {
|
|
793
|
+
return this.options.webhook;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
/**
|
|
797
|
+
* Create a remote API source
|
|
798
|
+
*/
|
|
799
|
+
function remoteSource(options, id) {
|
|
800
|
+
return new RemoteSource(options, id);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
//#endregion
|
|
804
|
+
//#region ../ssg/src/sources/custom.ts
|
|
805
|
+
/**
|
|
806
|
+
* Custom source for collections
|
|
807
|
+
*/
|
|
808
|
+
var CustomSource = class extends BaseSource {
|
|
809
|
+
constructor(options) {
|
|
810
|
+
super();
|
|
811
|
+
this.options = options;
|
|
812
|
+
this.id = options.id;
|
|
813
|
+
}
|
|
814
|
+
async getEntries() {
|
|
815
|
+
return (await this.options.getEntries()).map((item, index) => {
|
|
816
|
+
const id = item.id?.toString() ?? index.toString();
|
|
817
|
+
return {
|
|
818
|
+
id,
|
|
819
|
+
slug: item.slug?.toString() ?? id,
|
|
820
|
+
data: item,
|
|
821
|
+
body: item.body?.toString() ?? "",
|
|
822
|
+
render: async () => ({ Content: () => {
|
|
823
|
+
throw new Error("Custom content rendering not yet implemented");
|
|
824
|
+
} })
|
|
825
|
+
};
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
async getEntry(id) {
|
|
829
|
+
if (this.options.getEntry) {
|
|
830
|
+
const item = await this.options.getEntry(id);
|
|
831
|
+
if (!item) return null;
|
|
832
|
+
return {
|
|
833
|
+
id,
|
|
834
|
+
slug: item.slug?.toString() ?? id,
|
|
835
|
+
data: item,
|
|
836
|
+
body: item.body?.toString() ?? "",
|
|
837
|
+
render: async () => ({ Content: () => {
|
|
838
|
+
throw new Error("Custom content rendering not yet implemented");
|
|
839
|
+
} })
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
return super.getEntry(id);
|
|
843
|
+
}
|
|
844
|
+
watch(callback) {
|
|
845
|
+
if (this.options.watch) return this.options.watch(callback);
|
|
846
|
+
return () => {};
|
|
847
|
+
}
|
|
848
|
+
async getChanges(since) {
|
|
849
|
+
if (this.options.getChanges) return this.options.getChanges(since);
|
|
850
|
+
const entries = await this.getEntries();
|
|
851
|
+
return {
|
|
852
|
+
cursor: Date.now().toString(),
|
|
853
|
+
added: [],
|
|
854
|
+
updated: entries,
|
|
855
|
+
deleted: []
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
/**
|
|
860
|
+
* Create a custom source
|
|
861
|
+
*/
|
|
862
|
+
function createSource(options) {
|
|
863
|
+
return new CustomSource(options);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
//#endregion
|
|
867
|
+
export { DefaultDocument as _, remoteSource as a, FileSource as c, defineCollection as d, SSG as f, RawHTML as g, createMDXProcessor as h, RemoteSource as i, fileSource as l, MDXProcessor as m, CustomSource as n, GitSource as o, createSSG as p, createSource as r, gitSource as s, z$1 as t, BaseSource as u, __exportAll as v, __require as y };
|
|
868
|
+
//# sourceMappingURL=src-DR-EWgVP.mjs.map
|