@voltro/content 0.54.0 → 0.56.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.
- package/CHANGELOG.md +639 -2
- package/dist/get-BZwQfLp6.js +105 -0
- package/dist/index.js +15 -115
- package/dist/markdown.js +42 -16
- package/dist/serverLoad.d.ts +98 -0
- package/dist/serverLoad.js +78 -0
- package/package.json +4 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Schema as e } from "effect";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var t = Object.defineProperty, n = /* @__PURE__ */ ((e, n) => {
|
|
4
|
+
let r = {};
|
|
5
|
+
for (var i in e) t(r, i, {
|
|
6
|
+
get: e[i],
|
|
7
|
+
enumerable: !0
|
|
8
|
+
});
|
|
9
|
+
return n || t(r, Symbol.toStringTag, { value: "Module" }), r;
|
|
10
|
+
})({
|
|
11
|
+
ReferenceTarget: () => u,
|
|
12
|
+
defineCollection: () => a,
|
|
13
|
+
reference: () => d,
|
|
14
|
+
referenceFieldsOf: () => p,
|
|
15
|
+
referenceTargetOf: () => f,
|
|
16
|
+
registeredCollection: () => s,
|
|
17
|
+
registeredCollections: () => o,
|
|
18
|
+
resetCollectionsForTest: () => c,
|
|
19
|
+
slugFromRelativePath: () => l
|
|
20
|
+
}), r = Symbol.for("@voltro/content:collections"), i = () => {
|
|
21
|
+
let e = globalThis;
|
|
22
|
+
return e[r] ??= /* @__PURE__ */ new Map();
|
|
23
|
+
}, a = (e) => {
|
|
24
|
+
let t = i().get(e.name);
|
|
25
|
+
if (t !== void 0 && t.directory !== e.directory) throw Error(`defineCollection('${e.name}') is declared twice with different directories ('${t.directory}' vs '${e.directory}') — collection names are global.`);
|
|
26
|
+
return i().set(e.name, e), e;
|
|
27
|
+
}, o = () => [...i().values()], s = (e) => i().get(e), c = () => {
|
|
28
|
+
i().clear();
|
|
29
|
+
}, l = (e) => e.replace(/\\/g, "/").replace(/\.(md|mdx|json)$/i, ""), u = Symbol.for("@voltro/content:reference-target"), d = (t) => e.String.annotations({ [u]: t }), f = (e) => {
|
|
30
|
+
let t = e.annotations?.[u];
|
|
31
|
+
return typeof t == "string" ? t : void 0;
|
|
32
|
+
}, p = (e) => {
|
|
33
|
+
let t = /* @__PURE__ */ new Map(), n = e.schema.ast;
|
|
34
|
+
for (let e of n?.propertySignatures ?? []) {
|
|
35
|
+
let n = [e.type, ...e.type.types ?? []];
|
|
36
|
+
for (let r of n) {
|
|
37
|
+
let n = f(r);
|
|
38
|
+
n !== void 0 && typeof e.name == "string" && t.set(e.name, n);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return t;
|
|
42
|
+
}, m = typeof globalThis.process?.versions?.node == "string", h = Symbol.for("@voltro/content:root"), g = (e) => {
|
|
43
|
+
let t = globalThis;
|
|
44
|
+
t[h] = e;
|
|
45
|
+
}, _ = () => globalThis[h] ?? null, v = Symbol.for("@voltro/content:assetResolver"), y = (e) => {
|
|
46
|
+
let t = globalThis;
|
|
47
|
+
t[v] = e;
|
|
48
|
+
}, b = () => globalThis[v] ?? null, x = Symbol.for("@voltro/content:cache"), S = () => {
|
|
49
|
+
let e = globalThis;
|
|
50
|
+
return e[x] ??= /* @__PURE__ */ new Map();
|
|
51
|
+
}, C = (e) => {
|
|
52
|
+
if (e === void 0) {
|
|
53
|
+
S().clear();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (let t of [...S().keys()]) (t === e || t.startsWith(`${e}|`)) && S().delete(t);
|
|
57
|
+
}, w = (e, t) => {
|
|
58
|
+
let n = t === void 0 ? e.name : `${e.name}|${t}`, r = S().get(n);
|
|
59
|
+
return r === void 0 &&
|
|
60
|
+
// @vite-ignore keeps the whole render pipeline (marked + shiki grammars)
|
|
61
|
+
(r = import(
|
|
62
|
+
/* @vite-ignore */
|
|
63
|
+
"./serverLoad"
|
|
64
|
+
).then(({ loadServerCollection: n }) => n(e, t)), S().set(n, r)), r;
|
|
65
|
+
}, T = (e, t, n) => {
|
|
66
|
+
let r = t === void 0 ? e : `${e}.${t}`;
|
|
67
|
+
return n === void 0 ? `/assets/content/${r}/index.json` : `/assets/content/${r}/${n}.json`;
|
|
68
|
+
}, E = async (e) => {
|
|
69
|
+
let t = await fetch(e);
|
|
70
|
+
return t.ok ? await t.json() : null;
|
|
71
|
+
}, D = (e, t) => {
|
|
72
|
+
let n = s(e);
|
|
73
|
+
return n?.i18n === void 0 ? t : t ?? n.i18n.defaultLocale;
|
|
74
|
+
}, O = async (e, t = {}) => {
|
|
75
|
+
if (m) {
|
|
76
|
+
let n = s(e);
|
|
77
|
+
if (n === void 0) throw Error(`getCollection('${e}'): no such collection is defined — export a defineCollection({ name: '${e}', … }) from a *.collection.ts.`);
|
|
78
|
+
return (await w(n, t.locale)).entries;
|
|
79
|
+
}
|
|
80
|
+
return await E(T(e, D(e, t.locale))) ?? [];
|
|
81
|
+
}, k = async (e, t, n = {}) => {
|
|
82
|
+
if (m) {
|
|
83
|
+
let r = s(e);
|
|
84
|
+
if (r === void 0) throw Error(`getEntry('${e}'): no such collection is defined.`);
|
|
85
|
+
return (await w(r, n.locale)).bySlug.get(t) ?? null;
|
|
86
|
+
}
|
|
87
|
+
return await E(T(e, D(e, n.locale), t));
|
|
88
|
+
}, A = async () => {
|
|
89
|
+
let { referenceFieldsOf: e, registeredCollections: t } = await Promise.resolve().then(() => n), r = [];
|
|
90
|
+
for (let n of t()) {
|
|
91
|
+
let t = e(n);
|
|
92
|
+
if (t.size === 0) continue;
|
|
93
|
+
let i = n.i18n?.locales ?? [void 0];
|
|
94
|
+
for (let e of i) {
|
|
95
|
+
let i = await O(n.name, e === void 0 ? {} : { locale: e });
|
|
96
|
+
for (let e of i) for (let [i, a] of t) {
|
|
97
|
+
let t = e.data[i];
|
|
98
|
+
typeof t == "string" && t !== "" && await k(a, t) === null && r.push(`collection '${n.name}', entry '${e.slug}': field '${i}' references '${t}' in collection '${a}' — no such entry.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (r.length > 0) throw Error(`dangling content reference(s):\n${r.join("\n")}`);
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
export { c as _, k as a, g as c, a as d, d as f, o as g, s as h, O as i, A as l, f as m, b as n, C as o, p, _ as r, y as s, T as t, u, l as v };
|
package/dist/index.js
CHANGED
|
@@ -1,119 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region
|
|
3
|
-
var
|
|
4
|
-
let r = {};
|
|
5
|
-
for (var i in e) t(r, i, {
|
|
6
|
-
get: e[i],
|
|
7
|
-
enumerable: !0
|
|
8
|
-
});
|
|
9
|
-
return n || t(r, Symbol.toStringTag, { value: "Module" }), r;
|
|
10
|
-
})({
|
|
11
|
-
ReferenceTarget: () => u,
|
|
12
|
-
defineCollection: () => a,
|
|
13
|
-
reference: () => d,
|
|
14
|
-
referenceFieldsOf: () => p,
|
|
15
|
-
referenceTargetOf: () => f,
|
|
16
|
-
registeredCollection: () => s,
|
|
17
|
-
registeredCollections: () => o,
|
|
18
|
-
resetCollectionsForTest: () => c,
|
|
19
|
-
slugFromRelativePath: () => l
|
|
20
|
-
}), r = Symbol.for("@voltro/content:collections"), i = () => {
|
|
21
|
-
let e = globalThis;
|
|
22
|
-
return e[r] ??= /* @__PURE__ */ new Map();
|
|
23
|
-
}, a = (e) => {
|
|
24
|
-
let t = i().get(e.name);
|
|
25
|
-
if (t !== void 0 && t.directory !== e.directory) throw Error(`defineCollection('${e.name}') is declared twice with different directories ('${t.directory}' vs '${e.directory}') — collection names are global.`);
|
|
26
|
-
return i().set(e.name, e), e;
|
|
27
|
-
}, o = () => [...i().values()], s = (e) => i().get(e), c = () => {
|
|
28
|
-
i().clear();
|
|
29
|
-
}, l = (e) => e.replace(/\\/g, "/").replace(/\.(md|mdx|json)$/i, ""), u = Symbol.for("@voltro/content:reference-target"), d = (t) => e.String.annotations({ [u]: t }), f = (e) => {
|
|
30
|
-
let t = e.annotations?.[u];
|
|
31
|
-
return typeof t == "string" ? t : void 0;
|
|
32
|
-
}, p = (e) => {
|
|
33
|
-
let t = /* @__PURE__ */ new Map(), n = e.schema.ast;
|
|
34
|
-
for (let e of n?.propertySignatures ?? []) {
|
|
35
|
-
let n = [e.type, ...e.type.types ?? []];
|
|
36
|
-
for (let r of n) {
|
|
37
|
-
let n = f(r);
|
|
38
|
-
n !== void 0 && typeof e.name == "string" && t.set(e.name, n);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return t;
|
|
42
|
-
}, m = typeof globalThis.process?.versions?.node == "string", h = Symbol.for("@voltro/content:root"), g = (e) => {
|
|
43
|
-
let t = globalThis;
|
|
44
|
-
t[h] = e;
|
|
45
|
-
}, _ = () => globalThis[h] ?? null, v = Symbol.for("@voltro/content:assetResolver"), y = (e) => {
|
|
46
|
-
let t = globalThis;
|
|
47
|
-
t[v] = e;
|
|
48
|
-
}, b = () => globalThis[v] ?? null, x = Symbol.for("@voltro/content:cache"), S = () => {
|
|
49
|
-
let e = globalThis;
|
|
50
|
-
return e[x] ??= /* @__PURE__ */ new Map();
|
|
51
|
-
}, C = (e) => {
|
|
52
|
-
if (e === void 0) {
|
|
53
|
-
S().clear();
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
for (let t of [...S().keys()]) (t === e || t.startsWith(`${e}|`)) && S().delete(t);
|
|
57
|
-
}, w = (e, t) => {
|
|
58
|
-
let n = t === void 0 ? e.name : `${e.name}|${t}`, r = S().get(n);
|
|
59
|
-
return r === void 0 &&
|
|
60
|
-
// @vite-ignore keeps the whole render pipeline (marked + shiki grammars)
|
|
61
|
-
(r = import(
|
|
62
|
-
/* @vite-ignore */
|
|
63
|
-
"./serverLoad"
|
|
64
|
-
).then(({ loadServerCollection: n }) => n(e, t)), S().set(n, r)), r;
|
|
65
|
-
}, T = (e, t, n) => {
|
|
66
|
-
let r = t === void 0 ? e : `${e}.${t}`;
|
|
67
|
-
return n === void 0 ? `/assets/content/${r}/index.json` : `/assets/content/${r}/${n}.json`;
|
|
68
|
-
}, E = async (e) => {
|
|
69
|
-
let t = await fetch(e);
|
|
70
|
-
return t.ok ? await t.json() : null;
|
|
71
|
-
}, D = (e, t) => {
|
|
72
|
-
let n = s(e);
|
|
73
|
-
return n?.i18n === void 0 ? t : t ?? n.i18n.defaultLocale;
|
|
74
|
-
}, O = async (e, t = {}) => {
|
|
75
|
-
if (m) {
|
|
76
|
-
let n = s(e);
|
|
77
|
-
if (n === void 0) throw Error(`getCollection('${e}'): no such collection is defined — export a defineCollection({ name: '${e}', … }) from a *.collection.ts.`);
|
|
78
|
-
return (await w(n, t.locale)).entries;
|
|
79
|
-
}
|
|
80
|
-
return await E(T(e, D(e, t.locale))) ?? [];
|
|
81
|
-
}, k = async (e, t, n = {}) => {
|
|
82
|
-
if (m) {
|
|
83
|
-
let r = s(e);
|
|
84
|
-
if (r === void 0) throw Error(`getEntry('${e}'): no such collection is defined.`);
|
|
85
|
-
return (await w(r, n.locale)).bySlug.get(t) ?? null;
|
|
86
|
-
}
|
|
87
|
-
return await E(T(e, D(e, n.locale), t));
|
|
88
|
-
}, A = async () => {
|
|
89
|
-
let { referenceFieldsOf: e, registeredCollections: t } = await Promise.resolve().then(() => n), r = [];
|
|
90
|
-
for (let n of t()) {
|
|
91
|
-
let t = e(n);
|
|
92
|
-
if (t.size === 0) continue;
|
|
93
|
-
let i = n.i18n?.locales ?? [void 0];
|
|
94
|
-
for (let e of i) {
|
|
95
|
-
let i = await O(n.name, e === void 0 ? {} : { locale: e });
|
|
96
|
-
for (let e of i) for (let [i, a] of t) {
|
|
97
|
-
let t = e.data[i];
|
|
98
|
-
typeof t == "string" && t !== "" && await k(a, t) === null && r.push(`collection '${n.name}', entry '${e.slug}': field '${i}' references '${t}' in collection '${a}' — no such entry.`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (r.length > 0) throw Error(`dangling content reference(s):\n${r.join("\n")}`);
|
|
103
|
-
}, j = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"), M = (e) => {
|
|
1
|
+
import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./get-BZwQfLp6.js";
|
|
2
|
+
//#region src/feed.ts
|
|
3
|
+
var v = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"), y = (e) => {
|
|
104
4
|
let t = e instanceof Date ? e : new Date(e);
|
|
105
5
|
return Number.isNaN(t.getTime()) ? String(e) : t.toUTCString();
|
|
106
|
-
},
|
|
6
|
+
}, b = (e, t) => {
|
|
107
7
|
let n = t.siteUrl.replace(/\/+$/, ""), r = e.map((e) => t.item(e)).filter((e) => e !== null).sort((e, t) => new Date(t.date).getTime() - new Date(e.date).getTime()).map((e) => {
|
|
108
8
|
let t = e.link.startsWith("http") ? e.link : `${n}/${e.link.replace(/^\/+/, "")}`;
|
|
109
9
|
return [
|
|
110
10
|
" <item>",
|
|
111
|
-
` <title>${
|
|
112
|
-
` <link>${
|
|
113
|
-
` <guid isPermaLink="${e.guid === void 0 ? "true" : "false"}">${
|
|
114
|
-
` <pubDate>${
|
|
115
|
-
...e.description === void 0 ? [] : [` <description>${
|
|
116
|
-
...(e.categories ?? []).map((e) => ` <category>${
|
|
11
|
+
` <title>${v(e.title)}</title>`,
|
|
12
|
+
` <link>${v(t)}</link>`,
|
|
13
|
+
` <guid isPermaLink="${e.guid === void 0 ? "true" : "false"}">${v(e.guid ?? t)}</guid>`,
|
|
14
|
+
` <pubDate>${v(y(e.date))}</pubDate>`,
|
|
15
|
+
...e.description === void 0 ? [] : [` <description>${v(e.description)}</description>`],
|
|
16
|
+
...(e.categories ?? []).map((e) => ` <category>${v(e)}</category>`),
|
|
117
17
|
" </item>"
|
|
118
18
|
].join("\n");
|
|
119
19
|
}).join("\n");
|
|
@@ -121,10 +21,10 @@ var t = Object.defineProperty, n = /* @__PURE__ */ ((e, n) => {
|
|
|
121
21
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
|
122
22
|
"<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">",
|
|
123
23
|
" <channel>",
|
|
124
|
-
` <title>${
|
|
125
|
-
` <link>${
|
|
126
|
-
...t.description === void 0 ? [" <description></description>"] : [` <description>${
|
|
127
|
-
` <atom:link href="${
|
|
24
|
+
` <title>${v(t.title)}</title>`,
|
|
25
|
+
` <link>${v(n)}</link>`,
|
|
26
|
+
...t.description === void 0 ? [" <description></description>"] : [` <description>${v(t.description)}</description>`],
|
|
27
|
+
` <atom:link href="${v(`${n}${t.feedPath ?? "/rss.xml"}`)}" rel="self" type="application/rss+xml" />`,
|
|
128
28
|
...r === "" ? [] : [r],
|
|
129
29
|
" </channel>",
|
|
130
30
|
"</rss>",
|
|
@@ -132,4 +32,4 @@ var t = Object.defineProperty, n = /* @__PURE__ */ ((e, n) => {
|
|
|
132
32
|
].join("\n");
|
|
133
33
|
};
|
|
134
34
|
//#endregion
|
|
135
|
-
export {
|
|
35
|
+
export { g as ReferenceTarget, b as buildFeed, h as contentArtifactPath, u as contentAssetResolver, p as contentRoot, r as defineCollection, s as getCollection, t as getEntry, d as invalidateContentCache, i as reference, f as referenceFieldsOf, l as referenceTargetOf, o as registeredCollection, a as registeredCollections, e as resetCollectionsForTest, m as setContentAssetResolver, n as setContentRoot, _ as slugFromRelativePath, c as validateReferences };
|
package/dist/markdown.js
CHANGED
|
@@ -40,12 +40,38 @@ var t = typeof globalThis.process?.versions?.node == "string", n = (e) => {
|
|
|
40
40
|
"diff",
|
|
41
41
|
"text",
|
|
42
42
|
"txt"
|
|
43
|
-
], u = () => t ? (c ??=
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
], u = (e) => import(e), d = (e) => e.default ?? e, f = () => t ? (c ??= (async () => {
|
|
44
|
+
let [e, t, n, r, i, ...a] = await Promise.all([
|
|
45
|
+
u("shiki/core"),
|
|
46
|
+
u("shiki/engine/oniguruma"),
|
|
47
|
+
u("shiki/wasm"),
|
|
48
|
+
u("@shikijs/themes/github-light"),
|
|
49
|
+
u("@shikijs/themes/github-dark-dimmed"),
|
|
50
|
+
...[
|
|
51
|
+
"typescript",
|
|
52
|
+
"tsx",
|
|
53
|
+
"javascript",
|
|
54
|
+
"jsx",
|
|
55
|
+
"json",
|
|
56
|
+
"bash",
|
|
57
|
+
"css",
|
|
58
|
+
"html",
|
|
59
|
+
"sql",
|
|
60
|
+
"yaml",
|
|
61
|
+
"toml",
|
|
62
|
+
"markdown",
|
|
63
|
+
"mdx",
|
|
64
|
+
"diff"
|
|
65
|
+
].map((e) => u(`@shikijs/langs/${e}`))
|
|
66
|
+
]), o = e.createHighlighterCore, s = t.createOnigurumaEngine;
|
|
67
|
+
return o({
|
|
68
|
+
themes: [d(r), d(i)],
|
|
69
|
+
langs: a.map(d),
|
|
70
|
+
engine: s(d(n))
|
|
71
|
+
});
|
|
72
|
+
})().catch(() => null), c) : Promise.resolve(null), p = async (t, n = {}) => {
|
|
73
|
+
let r = [], c = /* @__PURE__ */ new Map(), u = n.highlight === !1 ? null : await f(), d = new e.Renderer();
|
|
74
|
+
if (d.heading = ({ depth: t, tokens: n }) => {
|
|
49
75
|
let a = e.Parser.parseInline(n), o = i(n), l = s(o), u = c.get(l) ?? 0;
|
|
50
76
|
c.set(l, u + 1);
|
|
51
77
|
let d = u === 0 ? l : `${l}-${u}`;
|
|
@@ -56,22 +82,22 @@ var t = typeof globalThis.process?.versions?.node == "string", n = (e) => {
|
|
|
56
82
|
}), `<h${t} id="${d}"><a class="heading-anchor" href="#${d}" aria-hidden="true">#</a>${a}</h${t}>\n`;
|
|
57
83
|
}, n.resolveLink !== void 0) {
|
|
58
84
|
let t = n.resolveLink;
|
|
59
|
-
|
|
85
|
+
d.link = ({ href: n, title: r, tokens: i }) => {
|
|
60
86
|
let a = e.Parser.parseInline(i);
|
|
61
87
|
return `<a href="${t(n)}"${r ? ` title="${r}"` : ""}>${a}</a>`;
|
|
62
88
|
};
|
|
63
89
|
}
|
|
64
90
|
if (n.resolveImage !== void 0) {
|
|
65
91
|
let e = n.resolveImage;
|
|
66
|
-
|
|
92
|
+
d.image = ({ href: t, title: n, text: r }) => {
|
|
67
93
|
let i = a(t) ? e(t) : t, s = n ? ` title="${o(n)}"` : "";
|
|
68
94
|
return `<img src="${o(i)}" alt="${o(r ?? "")}"${s} loading="lazy" decoding="async">`;
|
|
69
95
|
};
|
|
70
96
|
}
|
|
71
|
-
return
|
|
97
|
+
return d.code = ({ text: e, lang: t }) => {
|
|
72
98
|
let r = (t ?? "").trim(), i = (r.split(/\s+/)[0] ?? "").toLowerCase(), a;
|
|
73
|
-
if (
|
|
74
|
-
a =
|
|
99
|
+
if (u !== null && l.includes(i)) try {
|
|
100
|
+
a = u.codeToHtml(e, {
|
|
75
101
|
lang: i,
|
|
76
102
|
themes: {
|
|
77
103
|
light: "github-light",
|
|
@@ -92,12 +118,12 @@ var t = typeof globalThis.process?.versions?.node == "string", n = (e) => {
|
|
|
92
118
|
html: await e.parse(t, {
|
|
93
119
|
async: !0,
|
|
94
120
|
gfm: !0,
|
|
95
|
-
renderer:
|
|
121
|
+
renderer: d
|
|
96
122
|
}),
|
|
97
123
|
headings: r
|
|
98
124
|
};
|
|
99
|
-
},
|
|
100
|
-
let n = await
|
|
125
|
+
}, m = async (e, t) => {
|
|
126
|
+
let n = await f(), r = (t ?? "").trim().split(/\s+/)[0]?.toLowerCase() ?? "";
|
|
101
127
|
if (n !== null && l.includes(r)) try {
|
|
102
128
|
return n.codeToHtml(e, {
|
|
103
129
|
lang: r,
|
|
@@ -108,7 +134,7 @@ var t = typeof globalThis.process?.versions?.node == "string", n = (e) => {
|
|
|
108
134
|
});
|
|
109
135
|
} catch {}
|
|
110
136
|
return `<pre><code>${e.replace(/&/g, "&").replace(/</g, "<")}</code></pre>`;
|
|
111
|
-
},
|
|
137
|
+
}, h = (t) => {
|
|
112
138
|
let n = [], r = /* @__PURE__ */ new Map();
|
|
113
139
|
for (let a of e.lexer(t)) {
|
|
114
140
|
if (a.type !== "heading") continue;
|
|
@@ -122,4 +148,4 @@ var t = typeof globalThis.process?.versions?.node == "string", n = (e) => {
|
|
|
122
148
|
return n;
|
|
123
149
|
};
|
|
124
150
|
//#endregion
|
|
125
|
-
export {
|
|
151
|
+
export { h as extractHeadings, m as highlightCode, a as isRelativeAsset, r as parseFrontmatter, p as renderMarkdown, s as slugifyHeading };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
|
|
3
|
+
declare interface CollectionDefinition<A = Record<string, unknown>> {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
/** App-root-relative content directory (`content/posts`). */
|
|
6
|
+
readonly directory: string;
|
|
7
|
+
/** Frontmatter schema (markdown collections) or file schema (data
|
|
8
|
+
* collections). Violations are BUILD/BOOT errors naming file + field. */
|
|
9
|
+
readonly schema: Schema.Schema<A, any, never>;
|
|
10
|
+
/** `'markdown'` (default): every `.md` under the directory, frontmatter +
|
|
11
|
+
* rendered body. `'data'`: every `.json`, decoded whole — the
|
|
12
|
+
* authors.json case, no render path. */
|
|
13
|
+
readonly kind?: 'markdown' | 'data';
|
|
14
|
+
readonly i18n?: CollectionLocales;
|
|
15
|
+
/** Render options for this collection's markdown bodies (link rewriting,
|
|
16
|
+
* a code-fence hook, …) — applied wherever the SERVER renders an entry. */
|
|
17
|
+
readonly markdown?: RenderMarkdownOptions;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare interface CollectionLocales {
|
|
21
|
+
/** The locale trees this collection carries (first path segment). */
|
|
22
|
+
readonly locales: ReadonlyArray<string>;
|
|
23
|
+
/**
|
|
24
|
+
* What a missing translation does: `'fallback'` (default) serves the
|
|
25
|
+
* defaultLocale's entry under the requested locale; `'missing'` omits it
|
|
26
|
+
* (the page 404s). Incomplete translations are the normal case — decide
|
|
27
|
+
* per collection instead of improvising per page.
|
|
28
|
+
*/
|
|
29
|
+
readonly missing?: 'fallback' | 'missing';
|
|
30
|
+
readonly defaultLocale: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare interface ContentEntry<A = Record<string, unknown>> {
|
|
34
|
+
readonly slug: string;
|
|
35
|
+
/** The locale tree this entry came from (localized collections only). When
|
|
36
|
+
* the missing-policy substituted the default locale's entry, `locale` is
|
|
37
|
+
* the REQUESTED locale and `fallback` is true. */
|
|
38
|
+
readonly locale?: string;
|
|
39
|
+
readonly fallback?: boolean;
|
|
40
|
+
readonly data: A;
|
|
41
|
+
/** Markdown collections: the rendered HTML (shiki included, server-rendered). */
|
|
42
|
+
readonly html?: string;
|
|
43
|
+
readonly headings?: ReadonlyArray<ContentHeading>;
|
|
44
|
+
/** Raw markdown body (server side; omitted from client artifacts by default). */
|
|
45
|
+
readonly body?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
declare interface ContentHeading {
|
|
49
|
+
readonly depth: number;
|
|
50
|
+
readonly slug: string;
|
|
51
|
+
readonly text: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export declare interface LoadedCollection {
|
|
55
|
+
readonly entries: ReadonlyArray<ContentEntry>;
|
|
56
|
+
readonly bySlug: ReadonlyMap<string, ContentEntry>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export declare const loadServerCollection: (definition: CollectionDefinition, locale: string | undefined) => Promise<LoadedCollection>;
|
|
60
|
+
|
|
61
|
+
declare interface RenderMarkdownOptions {
|
|
62
|
+
/** Rewrite relative links (`./sibling.md`, `../other/page.md`) into route
|
|
63
|
+
* paths. Receives the raw href; return the replacement (or the input). */
|
|
64
|
+
readonly resolveLink?: (href: string) => string;
|
|
65
|
+
/**
|
|
66
|
+
* Rewrite a relative IMAGE source (`./cover.png`, `../img/x.jpg`) into a URL
|
|
67
|
+
* the built site can serve. Receives the raw src; return the replacement.
|
|
68
|
+
*
|
|
69
|
+
* Separate from `resolveLink` because the two answer different questions: a
|
|
70
|
+
* link resolves to a ROUTE, an image resolves to an ASSET that has to exist
|
|
71
|
+
* under `dist` — and without this hook a relative reference was emitted
|
|
72
|
+
* verbatim into the HTML, pointing at a path that is never copied. A built
|
|
73
|
+
* blog rendered broken images while the docs said the content pipeline copied
|
|
74
|
+
* and hashed them.
|
|
75
|
+
*
|
|
76
|
+
* Absolute (`/x.png`) and remote (`https://…`) sources are passed through
|
|
77
|
+
* untouched by the renderer and never reach this hook.
|
|
78
|
+
*/
|
|
79
|
+
readonly resolveImage?: (src: string) => string;
|
|
80
|
+
/** Highlight code fences with shiki (node only; a browser call renders
|
|
81
|
+
* plain `<pre>`). Default true. */
|
|
82
|
+
readonly highlight?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Post-process one rendered code fence. Receives the raw code, the resolved
|
|
85
|
+
* language (first info-string token, lowercased), the FULL info string
|
|
86
|
+
* (` ```ts preview=data-table ` ⇒ `'ts preview=data-table'`), and the
|
|
87
|
+
* rendered html. Return the replacement html — e.g. append a live-demo
|
|
88
|
+
* mount point derived from the info string.
|
|
89
|
+
*/
|
|
90
|
+
readonly codeFence?: (fence: {
|
|
91
|
+
readonly text: string;
|
|
92
|
+
readonly lang: string;
|
|
93
|
+
readonly info: string;
|
|
94
|
+
readonly html: string;
|
|
95
|
+
}) => string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { }
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { n as e, r as t, v as n } from "./get-BZwQfLp6.js";
|
|
2
|
+
import { parseFrontmatter as r, renderMarkdown as i } from "./markdown.js";
|
|
3
|
+
import { Schema as a } from "effect";
|
|
4
|
+
//#region src/serverLoad.ts
|
|
5
|
+
var o = (e, t, n) => {
|
|
6
|
+
let r = a.decodeUnknownEither(e.schema)(n);
|
|
7
|
+
if (r._tag === "Left") throw Error(`collection '${e.name}': ${t} does not match the declared schema:\n` + String(r.left));
|
|
8
|
+
return r.right;
|
|
9
|
+
}, s = async (e) => {
|
|
10
|
+
let { readdir: t } = await import("node:fs/promises"), n = [], r = async (e, i) => {
|
|
11
|
+
let a;
|
|
12
|
+
try {
|
|
13
|
+
a = await t(e, { withFileTypes: !0 });
|
|
14
|
+
} catch {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
for (let t of a) t.name.startsWith(".") || (t.isDirectory() ? await r(`${e}/${t.name}`, `${i}${t.name}/`) : n.push(`${i}${t.name}`));
|
|
18
|
+
};
|
|
19
|
+
return await r(e, ""), n.sort();
|
|
20
|
+
}, c = async (a, c) => {
|
|
21
|
+
let l = t();
|
|
22
|
+
if (l === null) throw Error(`getCollection('${a.name}') ran on the server without a registered content root — the boot path calls setContentRoot(appRoot). If you see this, the wiring is broken; report it.`);
|
|
23
|
+
let { readFile: u } = await import("node:fs/promises"), { join: d } = await import("node:path"), f = a.kind ?? "markdown", p = f === "data" ? /\.json$/i : /\.(md|mdx)$/i, m = d(l, a.directory), h = (await s(m)).filter((e) => p.test(e)), g = a.i18n === void 0 ? void 0 : c ?? a.i18n.defaultLocale, _ = [], v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map();
|
|
24
|
+
for (let t of h) {
|
|
25
|
+
let s, c = t;
|
|
26
|
+
if (a.i18n !== void 0) {
|
|
27
|
+
let [e, ...n] = t.split("/");
|
|
28
|
+
if (e === void 0 || !a.i18n.locales.includes(e)) continue;
|
|
29
|
+
s = e, c = n.join("/");
|
|
30
|
+
}
|
|
31
|
+
if (a.i18n !== void 0 && s !== g && s !== a.i18n.defaultLocale) continue;
|
|
32
|
+
let l = n(c), p = await u(d(m, t), "utf8"), h;
|
|
33
|
+
if (f === "data") {
|
|
34
|
+
let e = o(a, t, JSON.parse(p));
|
|
35
|
+
h = {
|
|
36
|
+
slug: l,
|
|
37
|
+
...s === void 0 ? {} : { locale: s },
|
|
38
|
+
data: e
|
|
39
|
+
};
|
|
40
|
+
} else {
|
|
41
|
+
let { data: n, body: c } = r(p), u = o(a, t, n), f = e(), g = d(m, t), _ = await i(c, {
|
|
42
|
+
...a.markdown ?? {},
|
|
43
|
+
...f !== null && a.markdown?.resolveImage === void 0 ? { resolveImage: (e) => f({
|
|
44
|
+
src: e,
|
|
45
|
+
entryFile: g
|
|
46
|
+
}) } : {}
|
|
47
|
+
});
|
|
48
|
+
h = {
|
|
49
|
+
slug: l,
|
|
50
|
+
...s === void 0 ? {} : { locale: s },
|
|
51
|
+
data: u,
|
|
52
|
+
html: _.html,
|
|
53
|
+
headings: _.headings,
|
|
54
|
+
body: c
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (a.i18n !== void 0 && s === a.i18n.defaultLocale && y.set(l, h), a.i18n === void 0 || s === g) {
|
|
58
|
+
if (v.get(l) !== void 0) throw Error(`collection '${a.name}': duplicate slug '${l}' — two files resolve to one slug (a rename left both, or two extensions share a name). Every slug must be unique.`);
|
|
59
|
+
v.set(l, h), _.push(h);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (a.i18n !== void 0 && g !== a.i18n.defaultLocale && (a.i18n.missing ?? "fallback") === "fallback") {
|
|
63
|
+
for (let [e, t] of y) if (!v.has(e)) {
|
|
64
|
+
let n = {
|
|
65
|
+
...t,
|
|
66
|
+
locale: g,
|
|
67
|
+
fallback: !0
|
|
68
|
+
};
|
|
69
|
+
v.set(e, n), _.push(n);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return _.sort((e, t) => e.slug < t.slug ? -1 : +(e.slug > t.slug)), {
|
|
73
|
+
entries: _,
|
|
74
|
+
bySlug: v
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
78
|
+
export { c as loadServerCollection };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/content",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.0",
|
|
4
4
|
"description": "Content collections — file-based, schema-typed markdown content (defineCollection over content/<name>/**/*.md with effect/Schema frontmatter), an isomorphic getCollection/getEntry (server: FS + rendered HTML with node-gated shiki; client: fetches the build-emitted JSON artifacts), heading extraction, locale trees with fallback, data collections, and a generic feed builder.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
"marked": "^18.0.9"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
|
-
"shiki": "^4.4.3"
|
|
41
|
+
"shiki": "^4.4.3",
|
|
42
|
+
"@shikijs/langs": "^4.4.3",
|
|
43
|
+
"@shikijs/themes": "^4.4.3"
|
|
42
44
|
},
|
|
43
45
|
"peerDependencies": {
|
|
44
46
|
"effect": "^3.22.0"
|