@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.
@@ -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 { 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
- }, j = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;"), 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;"), 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
- }, N = (e, t) => {
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>${j(e.title)}</title>`,
112
- ` <link>${j(t)}</link>`,
113
- ` <guid isPermaLink="${e.guid === void 0 ? "true" : "false"}">${j(e.guid ?? t)}</guid>`,
114
- ` <pubDate>${j(M(e.date))}</pubDate>`,
115
- ...e.description === void 0 ? [] : [` <description>${j(e.description)}</description>`],
116
- ...(e.categories ?? []).map((e) => ` <category>${j(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>${j(t.title)}</title>`,
125
- ` <link>${j(n)}</link>`,
126
- ...t.description === void 0 ? [" <description></description>"] : [` <description>${j(t.description)}</description>`],
127
- ` <atom:link href="${j(`${n}${t.feedPath ?? "/rss.xml"}`)}" rel="self" type="application/rss+xml" />`,
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 { u as ReferenceTarget, N as buildFeed, T as contentArtifactPath, b as contentAssetResolver, _ as contentRoot, a as defineCollection, O as getCollection, k as getEntry, C as invalidateContentCache, d as reference, p as referenceFieldsOf, f as referenceTargetOf, s as registeredCollection, o as registeredCollections, c as resetCollectionsForTest, y as setContentAssetResolver, g as setContentRoot, l as slugFromRelativePath, A as validateReferences };
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 ??= import("shiki").then((e) => e.createHighlighter({
44
- themes: ["github-light", "github-dark-dimmed"],
45
- langs: [...l]
46
- })).catch(() => null), c) : Promise.resolve(null), d = async (t, n = {}) => {
47
- let r = [], c = /* @__PURE__ */ new Map(), d = n.highlight === !1 ? null : await u(), f = new e.Renderer();
48
- if (f.heading = ({ depth: t, tokens: n }) => {
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
- f.link = ({ href: n, title: r, tokens: i }) => {
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
- f.image = ({ href: t, title: n, text: r }) => {
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 f.code = ({ text: e, lang: t }) => {
97
+ return d.code = ({ text: e, lang: t }) => {
72
98
  let r = (t ?? "").trim(), i = (r.split(/\s+/)[0] ?? "").toLowerCase(), a;
73
- if (d !== null && l.includes(i)) try {
74
- a = d.codeToHtml(e, {
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: f
121
+ renderer: d
96
122
  }),
97
123
  headings: r
98
124
  };
99
- }, f = async (e, t) => {
100
- let n = await u(), r = (t ?? "").trim().split(/\s+/)[0]?.toLowerCase() ?? "";
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, "&amp;").replace(/</g, "&lt;")}</code></pre>`;
111
- }, p = (t) => {
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 { p as extractHeadings, f as highlightCode, a as isRelativeAsset, r as parseFrontmatter, d as renderMarkdown, s as slugifyHeading };
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.54.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"