@zvndev/darkmown 2.2.0 → 2.3.1-next.1.g3a4a8dc
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 +13 -0
- package/README.md +34 -2
- package/docs/spec-alignment.md +10 -0
- package/package.json +16 -11
- package/site/pages/docs/index.wd +14 -0
- package/site/pages/playground/index.js +47 -46
- package/src/catalog.js +16 -1
- package/src/compiler/actions.js +42 -22
- package/src/compiler/body.js +36 -14
- package/src/compiler/collections.js +16 -10
- package/src/compiler/context.js +39 -10
- package/src/compiler/fetch.js +39 -15
- package/src/compiler/format.js +5 -2
- package/src/compiler/forms.js +91 -26
- package/src/compiler/frontmatter.js +11 -2
- package/src/compiler/fs-reader.js +2 -1
- package/src/compiler/image-size.js +340 -0
- package/src/compiler/includes.js +8 -4
- package/src/compiler/interpolation.js +15 -7
- package/src/compiler/loops.js +63 -35
- package/src/compiler/markdown.js +4 -3
- package/src/compiler/media.js +17 -3
- package/src/compiler/page.js +8 -6
- package/src/compiler/predicates.js +49 -24
- package/src/compiler/reader.js +12 -2
- package/src/compiler/state.js +16 -2
- package/src/compiler/structure.js +24 -14
- package/src/deploy.js +8 -4
- package/src/errors.js +1156 -0
- package/src/router.js +7 -4
- package/src/scaffold.js +4 -2
- package/src/skin.js +17 -6
- package/types/api-runner.d.ts +94 -0
- package/types/builder.d.ts +141 -10
- package/types/catalog.d.ts +97 -0
- package/types/compiler/actions.d.ts +41 -0
- package/types/compiler/body.d.ts +11 -0
- package/types/compiler/collections.d.ts +76 -0
- package/types/compiler/context.d.ts +647 -0
- package/types/compiler/directives.d.ts +6 -0
- package/types/compiler/expr-ast.d.ts +20 -0
- package/types/compiler/fetch.d.ts +29 -0
- package/types/compiler/format.d.ts +49 -0
- package/types/compiler/forms.d.ts +94 -0
- package/types/compiler/frontmatter.d.ts +33 -0
- package/types/compiler/fs-reader.d.ts +7 -0
- package/types/compiler/image-size.d.ts +14 -0
- package/types/compiler/includes.d.ts +100 -0
- package/types/compiler/index.d.ts +5 -0
- package/types/compiler/interpolation.d.ts +115 -0
- package/types/compiler/loops.d.ts +36 -0
- package/types/compiler/markdown.d.ts +34 -0
- package/types/compiler/media.d.ts +32 -0
- package/types/compiler/page.d.ts +109 -0
- package/types/compiler/predicates.d.ts +50 -0
- package/types/compiler/reader.d.ts +48 -0
- package/types/compiler/state.d.ts +68 -0
- package/types/compiler/structure.d.ts +56 -0
- package/types/compiler.d.ts +35 -223
- package/types/dev.d.ts +47 -2
- package/types/errors.d.ts +100 -0
- package/types/feeds.d.ts +150 -0
- package/types/headers.d.ts +44 -0
- package/types/highlight.d.ts +24 -0
- package/types/router.d.ts +42 -3
- package/types/scaffold.d.ts +15 -3
- package/types/skin.d.ts +28 -1
- package/types/src/api-runner.d.ts +94 -0
- package/types/src/builder.d.ts +170 -0
- package/types/src/catalog.d.ts +97 -0
- package/types/src/compiler/actions.d.ts +41 -0
- package/types/src/compiler/body.d.ts +11 -0
- package/types/src/compiler/collections.d.ts +76 -0
- package/types/src/compiler/context.d.ts +647 -0
- package/types/src/compiler/directives.d.ts +6 -0
- package/types/src/compiler/expr-ast.d.ts +20 -0
- package/types/src/compiler/fetch.d.ts +29 -0
- package/types/src/compiler/format.d.ts +49 -0
- package/types/src/compiler/forms.d.ts +94 -0
- package/types/src/compiler/frontmatter.d.ts +33 -0
- package/types/src/compiler/fs-reader.d.ts +7 -0
- package/types/src/compiler/image-size.d.ts +14 -0
- package/types/src/compiler/includes.d.ts +100 -0
- package/types/src/compiler/index.d.ts +5 -0
- package/types/src/compiler/interpolation.d.ts +115 -0
- package/types/src/compiler/loops.d.ts +36 -0
- package/types/src/compiler/markdown.d.ts +34 -0
- package/types/src/compiler/media.d.ts +32 -0
- package/types/src/compiler/page.d.ts +109 -0
- package/types/src/compiler/predicates.d.ts +50 -0
- package/types/src/compiler/reader.d.ts +48 -0
- package/types/src/compiler/state.d.ts +68 -0
- package/types/src/compiler/structure.d.ts +56 -0
- package/types/src/compiler.d.ts +48 -0
- package/types/src/config.d.ts +45 -0
- package/types/src/dev.d.ts +58 -0
- package/types/src/errors.d.ts +100 -0
- package/types/src/feeds.d.ts +150 -0
- package/types/src/headers.d.ts +44 -0
- package/types/src/highlight.d.ts +24 -0
- package/types/src/router.d.ts +78 -0
- package/types/src/scaffold.d.ts +20 -0
- package/types/src/skin.d.ts +48 -0
- package/types/src/statics.d.ts +24 -0
- package/types/statics.d.ts +2 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile the whole site under `cwd` into `dist`, returning the route manifest.
|
|
3
|
+
*
|
|
4
|
+
* The build is always 100% static, CDN-cacheable HTML. Backend `api/*.js`
|
|
5
|
+
* functions are NOT compiled — they are the host's concern. `target` only
|
|
6
|
+
* decides the small amount of host glue Darkmown emits alongside the static
|
|
7
|
+
* output: the default (`vercel`/anything) leaves `api/` for the platform to pick
|
|
8
|
+
* up natively; `cloudflare` emits a `dist/_worker.js/` module that routes
|
|
9
|
+
* `/api/*` to those same functions and serves everything else as a static asset.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} [cwd] Project working directory (defaults to `process.cwd()`).
|
|
12
|
+
* @param {{ target?: string, includeDrafts?: boolean, depMap?: boolean, changed?: string[], quietFeedHints?: boolean }} [options]
|
|
13
|
+
* `target: "cloudflare"` emits the Pages worker. `includeDrafts: true` keeps
|
|
14
|
+
* `draft: true` pages in the build + feeds (dev / `build --drafts`); default
|
|
15
|
+
* excludes them at route discovery so feeds never see a draft. `depMap: true`
|
|
16
|
+
* (dev builds) writes the per-route dependency map to `dist/.wd-dev-deps.json`.
|
|
17
|
+
* `changed` (project-relative paths, dev only; implies `depMap`) attempts an
|
|
18
|
+
* incremental rebuild of just the affected routes, falling back to a full
|
|
19
|
+
* rebuild on ANY uncertainty — a stale page is worse than a slow rebuild.
|
|
20
|
+
* @returns {BuildResult}
|
|
21
|
+
*/
|
|
22
|
+
export function buildSite(cwd?: string, options?: {
|
|
23
|
+
target?: string;
|
|
24
|
+
includeDrafts?: boolean;
|
|
25
|
+
depMap?: boolean;
|
|
26
|
+
changed?: string[];
|
|
27
|
+
quietFeedHints?: boolean;
|
|
28
|
+
}): BuildResult;
|
|
29
|
+
/**
|
|
30
|
+
* Strip developer comments from the runtime before it ships. The source keeps
|
|
31
|
+
* full JSDoc type annotations (for `checkJs` + `.d.ts`) and explanatory comments
|
|
32
|
+
* so it stays readable; the browser downloads neither. This keeps the shipped
|
|
33
|
+
* runtime lean and the gzip budget honest (measured against what users receive),
|
|
34
|
+
* WITHOUT minifying — identifiers, structure, and whitespace are all preserved.
|
|
35
|
+
*
|
|
36
|
+
* Two passes, each conservative: `/** ... *\/` JSDoc blocks, then whole-line
|
|
37
|
+
* `//` comments (a line that is nothing but a comment). Trailing `//` after code
|
|
38
|
+
* and `//` inside strings/URLs are deliberately left untouched, so no string
|
|
39
|
+
* literal is ever harmed.
|
|
40
|
+
* @param {string} source
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
export function stripRuntimeComments(source: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Render the Cloudflare Pages `_headers` file from the route manifest.
|
|
46
|
+
*
|
|
47
|
+
* Cloudflare applies every matching block in order; when blocks set the same
|
|
48
|
+
* header, the later block wins. So we emit the catch-all `/*` first (baseline
|
|
49
|
+
* security headers + the reactive CSP, which since 2.1 is eval-free and satisfies
|
|
50
|
+
* every page), then one block per static route that re-states the same eval-free
|
|
51
|
+
* CSP as defense-in-depth. Reactive routes need no override — the catch-all
|
|
52
|
+
* already carries the eval-free CSP.
|
|
53
|
+
*
|
|
54
|
+
* Clean URLs mean a route like `/docs/` is served at both `/docs` and `/docs/`,
|
|
55
|
+
* so each static route emits a path glob (`/docs`, `/docs/*`) that covers both.
|
|
56
|
+
* @param {RouteManifestEntry[]} manifest
|
|
57
|
+
* @returns {string}
|
|
58
|
+
*/
|
|
59
|
+
export function renderCloudflareHeaders(manifest: RouteManifestEntry[]): string;
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {import("./config.js").Paths} Paths
|
|
62
|
+
* @typedef {import("./compiler.js").Assets} Assets
|
|
63
|
+
* @typedef {import("./compiler.js").Meta} Meta
|
|
64
|
+
* @typedef {import("./router.js").Route} Route
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* A built route entry written to `dist/routes.json`.
|
|
68
|
+
* @typedef {object} RouteManifestEntry
|
|
69
|
+
* @property {string} route Public route path.
|
|
70
|
+
* @property {string} file Source file path, relative to cwd, POSIX-separated.
|
|
71
|
+
* @property {{ skins: string[], scripts: string[], runtime: boolean }} assets
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* One source route's record in the dev dependency map (`dist/.wd-dev-deps.json`),
|
|
75
|
+
* written by dev builds so a later `--changed` build can rebuild only the routes
|
|
76
|
+
* whose dependency graph contains the changed file.
|
|
77
|
+
* @typedef {object} DepMapEntry
|
|
78
|
+
* @property {string} file Source file, project-relative, POSIX-separated.
|
|
79
|
+
* @property {string[]} deps Every source file this route's compile read (the page
|
|
80
|
+
* itself, includes, loop JSON data files, colocated `.skin`/`.js`) —
|
|
81
|
+
* project-relative, POSIX-separated, sorted.
|
|
82
|
+
* @property {string[]} collections Collection names the route loops, so a change
|
|
83
|
+
* to any entry of the collection rebuilds this route.
|
|
84
|
+
* @property {RouteManifestEntry[]} pages The manifest entries this route emitted
|
|
85
|
+
* (one, or one per pagination page), so `routes.json`/`_headers`/the sitemap
|
|
86
|
+
* can be reassembled globally without recompiling untouched routes.
|
|
87
|
+
*/
|
|
88
|
+
/** The dev dependency map's filename under `dist/`. */
|
|
89
|
+
export const DEP_MAP_FILE: ".wd-dev-deps.json";
|
|
90
|
+
/**
|
|
91
|
+
* The value `buildSite` returns. `incremental` is present only when a `changed`
|
|
92
|
+
* build actually rebuilt a subset of routes (absent on every full rebuild).
|
|
93
|
+
*/
|
|
94
|
+
export type BuildResult = {
|
|
95
|
+
routes: RouteManifestEntry[];
|
|
96
|
+
distRoot: string;
|
|
97
|
+
feeds: {
|
|
98
|
+
sitemap: number | null;
|
|
99
|
+
rss: number | null;
|
|
100
|
+
};
|
|
101
|
+
incremental?: {
|
|
102
|
+
changed: string[];
|
|
103
|
+
rebuilt: string[];
|
|
104
|
+
total: number;
|
|
105
|
+
} | undefined;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* A compiled page bound for a concrete output route. Mirrors `CompiledPage` plus
|
|
109
|
+
* the public `route` it's written to — for a paginated listing, page 1 keeps the
|
|
110
|
+
* listing route and pages 2+ get `/<route>/page/<n>/`.
|
|
111
|
+
*/
|
|
112
|
+
export type EmittedPage = {
|
|
113
|
+
/**
|
|
114
|
+
* Public route path this page is written to.
|
|
115
|
+
*/
|
|
116
|
+
route: string;
|
|
117
|
+
html: string;
|
|
118
|
+
assets: import("./compiler.js").Assets;
|
|
119
|
+
warnings: string[];
|
|
120
|
+
};
|
|
121
|
+
export type Paths = import("./config.js").Paths;
|
|
122
|
+
export type Assets = import("./compiler.js").Assets;
|
|
123
|
+
export type Meta = import("./compiler.js").Meta;
|
|
124
|
+
export type Route = import("./router.js").Route;
|
|
125
|
+
/**
|
|
126
|
+
* A built route entry written to `dist/routes.json`.
|
|
127
|
+
*/
|
|
128
|
+
export type RouteManifestEntry = {
|
|
129
|
+
/**
|
|
130
|
+
* Public route path.
|
|
131
|
+
*/
|
|
132
|
+
route: string;
|
|
133
|
+
/**
|
|
134
|
+
* Source file path, relative to cwd, POSIX-separated.
|
|
135
|
+
*/
|
|
136
|
+
file: string;
|
|
137
|
+
assets: {
|
|
138
|
+
skins: string[];
|
|
139
|
+
scripts: string[];
|
|
140
|
+
runtime: boolean;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* One source route's record in the dev dependency map (`dist/.wd-dev-deps.json`),
|
|
145
|
+
* written by dev builds so a later `--changed` build can rebuild only the routes
|
|
146
|
+
* whose dependency graph contains the changed file.
|
|
147
|
+
*/
|
|
148
|
+
export type DepMapEntry = {
|
|
149
|
+
/**
|
|
150
|
+
* Source file, project-relative, POSIX-separated.
|
|
151
|
+
*/
|
|
152
|
+
file: string;
|
|
153
|
+
/**
|
|
154
|
+
* Every source file this route's compile read (the page
|
|
155
|
+
* itself, includes, loop JSON data files, colocated `.skin`/`.js`) —
|
|
156
|
+
* project-relative, POSIX-separated, sorted.
|
|
157
|
+
*/
|
|
158
|
+
deps: string[];
|
|
159
|
+
/**
|
|
160
|
+
* Collection names the route loops, so a change
|
|
161
|
+
* to any entry of the collection rebuilds this route.
|
|
162
|
+
*/
|
|
163
|
+
collections: string[];
|
|
164
|
+
/**
|
|
165
|
+
* The manifest entries this route emitted
|
|
166
|
+
* (one, or one per pagination page), so `routes.json`/`_headers`/the sitemap
|
|
167
|
+
* can be reassembled globally without recompiling untouched routes.
|
|
168
|
+
*/
|
|
169
|
+
pages: RouteManifestEntry[];
|
|
170
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The structured, machine-readable catalog of the whole `.wd` authoring surface.
|
|
3
|
+
* @returns {DirectiveCatalog}
|
|
4
|
+
*/
|
|
5
|
+
export function directiveCatalog(): DirectiveCatalog;
|
|
6
|
+
/**
|
|
7
|
+
* Render the catalog as a compact llms.txt-style markdown cheatsheet — the
|
|
8
|
+
* artifact an app pastes into a small model's system prompt. Generated entirely
|
|
9
|
+
* from {@link directiveCatalog}, so it can never disagree with what compiles.
|
|
10
|
+
* @returns {string}
|
|
11
|
+
*/
|
|
12
|
+
export function llmsText(): string;
|
|
13
|
+
/** The action tokens the catalog exposes — used by the drift guard. */
|
|
14
|
+
export const CATALOG_ACTION_TOKENS: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Whether the directive
|
|
17
|
+
* ships zero JS (static), needs the reactive runtime (reactive), or can be
|
|
18
|
+
* either depending on whether it reads `:state`/`:store` (either).
|
|
19
|
+
*/
|
|
20
|
+
export type Reactivity = "static" | "reactive" | "either";
|
|
21
|
+
export type DirectiveEntry = {
|
|
22
|
+
/**
|
|
23
|
+
* The directive token (`@loop`, `:state`, `:::`, …).
|
|
24
|
+
*/
|
|
25
|
+
name: string;
|
|
26
|
+
/**
|
|
27
|
+
* A single line, or an opener with a closer.
|
|
28
|
+
*/
|
|
29
|
+
kind: "line" | "block";
|
|
30
|
+
/**
|
|
31
|
+
* One-line schematic (`[…]` = optional, `<…>` = slot).
|
|
32
|
+
*/
|
|
33
|
+
syntax: string;
|
|
34
|
+
/**
|
|
35
|
+
* One-line, plain-language summary.
|
|
36
|
+
*/
|
|
37
|
+
description: string;
|
|
38
|
+
/**
|
|
39
|
+
* One concrete, compilable line.
|
|
40
|
+
*/
|
|
41
|
+
example: string;
|
|
42
|
+
reactive: Reactivity;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A clause / action-op / pipe / operator entry.
|
|
46
|
+
*/
|
|
47
|
+
export type CatalogEntry = {
|
|
48
|
+
name: string;
|
|
49
|
+
syntax?: string | undefined;
|
|
50
|
+
description: string;
|
|
51
|
+
example?: string | undefined;
|
|
52
|
+
};
|
|
53
|
+
export type DirectiveCatalog = {
|
|
54
|
+
/**
|
|
55
|
+
* The installed Darkmown version.
|
|
56
|
+
*/
|
|
57
|
+
version: string;
|
|
58
|
+
/**
|
|
59
|
+
* Always `.wd` — the file extension that gates directives.
|
|
60
|
+
*/
|
|
61
|
+
format: string;
|
|
62
|
+
directives: DirectiveEntry[];
|
|
63
|
+
/**
|
|
64
|
+
* Clauses of the `@loop` header (fixed order).
|
|
65
|
+
*/
|
|
66
|
+
loopClauses: CatalogEntry[];
|
|
67
|
+
/**
|
|
68
|
+
* Per-row meta variables valid in a loop body.
|
|
69
|
+
*/
|
|
70
|
+
loopVariables: CatalogEntry[];
|
|
71
|
+
/**
|
|
72
|
+
* The `:button`/`:effect`/`:every` action vocabulary.
|
|
73
|
+
*/
|
|
74
|
+
actionOps: CatalogEntry[];
|
|
75
|
+
/**
|
|
76
|
+
* The `{ value | pipe }` formatter whitelist.
|
|
77
|
+
*/
|
|
78
|
+
formatPipes: CatalogEntry[];
|
|
79
|
+
/**
|
|
80
|
+
* Comparison operators for `where`/`:if`/`when`.
|
|
81
|
+
*/
|
|
82
|
+
predicateOps: CatalogEntry[];
|
|
83
|
+
/**
|
|
84
|
+
* Logical joiners (`and`/`or`/`not`).
|
|
85
|
+
*/
|
|
86
|
+
predicateJoiners: string[];
|
|
87
|
+
/**
|
|
88
|
+
* The `WDxxx` code blocks.
|
|
89
|
+
*/
|
|
90
|
+
errorAreas: import("./errors.js").ErrorArea[];
|
|
91
|
+
/**
|
|
92
|
+
* Every stable compile-error
|
|
93
|
+
* code, with its cause and fix. A thrown error's message starts with its code
|
|
94
|
+
* (`[WD201] …`) and mirrors it on `err.wd.code`.
|
|
95
|
+
*/
|
|
96
|
+
errors: import("./errors.js").ErrorEntry[];
|
|
97
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} line
|
|
3
|
+
* @param {Ctx} ctx
|
|
4
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
5
|
+
* @returns {string}
|
|
6
|
+
*/
|
|
7
|
+
export function handleButton(line: string, ctx: Ctx, index: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Parse `:effect <watched> -> <actions>` into a zero-output marker the runtime
|
|
10
|
+
* watches: when `<watched>` state changes, it runs `<actions>` (the same `:button`
|
|
11
|
+
* action vocabulary, `;`-chained). For arbitrary side effects beyond `:computed`
|
|
12
|
+
* (derive state) and fetch deps (auto-refetch).
|
|
13
|
+
* @param {string} line
|
|
14
|
+
* @param {Ctx} ctx
|
|
15
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export function handleEffect(line: string, ctx: Ctx, index: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Parse `:every <duration> -> <actions>` into a marker the runtime drives on a
|
|
21
|
+
* timer: every `<duration>` it runs `<actions>` (the same `:button` vocabulary,
|
|
22
|
+
* `;`-chained), and the interval auto-pauses while the tab is hidden. The one time
|
|
23
|
+
* primitive — behind live polling (`:every 5s -> board refetch`), clocks and
|
|
24
|
+
* countdowns (`:every 1s -> seconds++`), and slideshow autoplay (`:every 4s -> slide++`).
|
|
25
|
+
* @param {string} line
|
|
26
|
+
* @param {Ctx} ctx
|
|
27
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
export function handleEvery(line: string, ctx: Ctx, index: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {import("./context.js").Ctx} Ctx
|
|
33
|
+
* @typedef {import("./context.js").Action} Action
|
|
34
|
+
*/
|
|
35
|
+
export const BUTTON_EXAMPLE: ":button \"Add one\" -> count++";
|
|
36
|
+
export const EFFECT_EXAMPLE: ":effect query -> searches++";
|
|
37
|
+
export const EVERY_EXAMPLE: ":every 5s -> seconds++";
|
|
38
|
+
export const ACTION_EXAMPLE: "count++";
|
|
39
|
+
export const ACTION_USE: "Use: name++, name--, n += k, n -= k, name = v, flag toggle, list append/prepend v, list toggle v, list remove v, x clear, obj merge other, obj delete key, name reset — chain with \";\" — e.g. count++";
|
|
40
|
+
export type Ctx = import("./context.js").Ctx;
|
|
41
|
+
export type Action = import("./context.js").Action;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("./context.js").Ctx} Ctx
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parse a `.wd` body line-by-line into HTML, mixing directives and prose.
|
|
6
|
+
* @param {string[]} lines
|
|
7
|
+
* @param {Ctx} ctx
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
export function compileBody(lines: string[], ctx: Ctx): string;
|
|
11
|
+
export type Ctx = import("./context.js").Ctx;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the collection index from the router's discovered routes: one entry per
|
|
3
|
+
* `site/pages/<name>/…` route, grouped under the FIRST path segment (the
|
|
4
|
+
* collection name). The home route, top-level pages, and the synthetic `/404/`
|
|
5
|
+
* route are not entries. Reuses each route's already-parsed `meta` (no re-parse)
|
|
6
|
+
* and reads the `.md` body only for the excerpt fallback. When a collection has
|
|
7
|
+
* a `_schema.wd`, every entry is validated against it here (throwing on the
|
|
8
|
+
* first violation), so a malformed entry fails the build with a `file:line`.
|
|
9
|
+
*
|
|
10
|
+
* @param {Route[]} routes Post-draft-filter routes from `discoverRoutes`.
|
|
11
|
+
* @param {Paths} paths Resolved project paths (`routesRoot` for `_schema.wd`).
|
|
12
|
+
* @param {import("./reader.js").Reader} [reader] Source reader (fs-backed by
|
|
13
|
+
* default; pass an in-memory reader to build collections without a filesystem).
|
|
14
|
+
* @returns {Map<string, CollectionRow[]>} Collection name → entry rows.
|
|
15
|
+
*/
|
|
16
|
+
export function buildCollections(routes: Route[], paths: Paths, reader?: import("./reader.js").Reader): Map<string, CollectionRow[]>;
|
|
17
|
+
/**
|
|
18
|
+
* A parsed `_schema.wd` field rule.
|
|
19
|
+
* @typedef {object} SchemaField
|
|
20
|
+
* @property {string} name Field name.
|
|
21
|
+
* @property {string} type One of {@link SCHEMA_TYPES}.
|
|
22
|
+
* @property {boolean} optional Whether the field may be absent (`?` modifier).
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Read + parse a collection's `_schema.wd`, or null when the file is absent
|
|
26
|
+
* (validation is opt-in). The schema is frontmatter-shaped — one `field: type`
|
|
27
|
+
* line per rule inside the `---` block — so authors write it exactly like the
|
|
28
|
+
* frontmatter it validates. Each type must be in the closed {@link SCHEMA_TYPES}
|
|
29
|
+
* vocabulary (`?` suffix = optional); an unknown token is a compile error in the
|
|
30
|
+
* schema file itself, pointing at the offending line.
|
|
31
|
+
* @param {string} name Collection name.
|
|
32
|
+
* @param {Paths} paths
|
|
33
|
+
* @param {import("./reader.js").Reader} [reader] Source reader (fs-backed by default).
|
|
34
|
+
* @returns {SchemaField[] | null}
|
|
35
|
+
*/
|
|
36
|
+
export function readSchema(name: string, paths: Paths, reader?: import("./reader.js").Reader): SchemaField[] | null;
|
|
37
|
+
/**
|
|
38
|
+
* Parse a `_schema.wd` source into field rules. The schema fields live in the
|
|
39
|
+
* frontmatter block; the body (if any) is ignored, so a schema file can carry a
|
|
40
|
+
* prose note after its `---` fence. Each field line is `name: type` where type
|
|
41
|
+
* is a closed token with an optional trailing `?`.
|
|
42
|
+
* @param {string} raw `_schema.wd` file contents.
|
|
43
|
+
* @param {string} file Absolute path, for `file:line` errors.
|
|
44
|
+
* @returns {SchemaField[]}
|
|
45
|
+
*/
|
|
46
|
+
export function parseSchema(raw: string, file: string): SchemaField[];
|
|
47
|
+
/**
|
|
48
|
+
* A parsed `_schema.wd` field rule.
|
|
49
|
+
*/
|
|
50
|
+
export type SchemaField = {
|
|
51
|
+
/**
|
|
52
|
+
* Field name.
|
|
53
|
+
*/
|
|
54
|
+
name: string;
|
|
55
|
+
/**
|
|
56
|
+
* One of {@link SCHEMA_TYPES}.
|
|
57
|
+
*/
|
|
58
|
+
type: string;
|
|
59
|
+
/**
|
|
60
|
+
* Whether the field may be absent (`?` modifier).
|
|
61
|
+
*/
|
|
62
|
+
optional: boolean;
|
|
63
|
+
};
|
|
64
|
+
export type Paths = import("./context.js").Paths;
|
|
65
|
+
export type Meta = import("./context.js").Meta;
|
|
66
|
+
export type Route = import("../router.js").Route;
|
|
67
|
+
/**
|
|
68
|
+
* A collection entry row: every frontmatter field, plus derived `url`/`slug`/
|
|
69
|
+
* `excerpt`. Keyed loosely so authors' custom frontmatter keys pass through to
|
|
70
|
+
* `{ post.whatever }` and `where`/`sort` without a closed schema here.
|
|
71
|
+
*/
|
|
72
|
+
export type CollectionRow = Record<string, unknown> & {
|
|
73
|
+
url: string;
|
|
74
|
+
slug: string;
|
|
75
|
+
excerpt: string;
|
|
76
|
+
};
|