@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.
Files changed (105) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +34 -2
  3. package/docs/spec-alignment.md +10 -0
  4. package/package.json +16 -11
  5. package/site/pages/docs/index.wd +14 -0
  6. package/site/pages/playground/index.js +47 -46
  7. package/src/catalog.js +16 -1
  8. package/src/compiler/actions.js +42 -22
  9. package/src/compiler/body.js +36 -14
  10. package/src/compiler/collections.js +16 -10
  11. package/src/compiler/context.js +39 -10
  12. package/src/compiler/fetch.js +39 -15
  13. package/src/compiler/format.js +5 -2
  14. package/src/compiler/forms.js +91 -26
  15. package/src/compiler/frontmatter.js +11 -2
  16. package/src/compiler/fs-reader.js +2 -1
  17. package/src/compiler/image-size.js +340 -0
  18. package/src/compiler/includes.js +8 -4
  19. package/src/compiler/interpolation.js +15 -7
  20. package/src/compiler/loops.js +63 -35
  21. package/src/compiler/markdown.js +4 -3
  22. package/src/compiler/media.js +17 -3
  23. package/src/compiler/page.js +8 -6
  24. package/src/compiler/predicates.js +49 -24
  25. package/src/compiler/reader.js +12 -2
  26. package/src/compiler/state.js +16 -2
  27. package/src/compiler/structure.js +24 -14
  28. package/src/deploy.js +8 -4
  29. package/src/errors.js +1156 -0
  30. package/src/router.js +7 -4
  31. package/src/scaffold.js +4 -2
  32. package/src/skin.js +17 -6
  33. package/types/api-runner.d.ts +94 -0
  34. package/types/builder.d.ts +141 -10
  35. package/types/catalog.d.ts +97 -0
  36. package/types/compiler/actions.d.ts +41 -0
  37. package/types/compiler/body.d.ts +11 -0
  38. package/types/compiler/collections.d.ts +76 -0
  39. package/types/compiler/context.d.ts +647 -0
  40. package/types/compiler/directives.d.ts +6 -0
  41. package/types/compiler/expr-ast.d.ts +20 -0
  42. package/types/compiler/fetch.d.ts +29 -0
  43. package/types/compiler/format.d.ts +49 -0
  44. package/types/compiler/forms.d.ts +94 -0
  45. package/types/compiler/frontmatter.d.ts +33 -0
  46. package/types/compiler/fs-reader.d.ts +7 -0
  47. package/types/compiler/image-size.d.ts +14 -0
  48. package/types/compiler/includes.d.ts +100 -0
  49. package/types/compiler/index.d.ts +5 -0
  50. package/types/compiler/interpolation.d.ts +115 -0
  51. package/types/compiler/loops.d.ts +36 -0
  52. package/types/compiler/markdown.d.ts +34 -0
  53. package/types/compiler/media.d.ts +32 -0
  54. package/types/compiler/page.d.ts +109 -0
  55. package/types/compiler/predicates.d.ts +50 -0
  56. package/types/compiler/reader.d.ts +48 -0
  57. package/types/compiler/state.d.ts +68 -0
  58. package/types/compiler/structure.d.ts +56 -0
  59. package/types/compiler.d.ts +35 -223
  60. package/types/dev.d.ts +47 -2
  61. package/types/errors.d.ts +100 -0
  62. package/types/feeds.d.ts +150 -0
  63. package/types/headers.d.ts +44 -0
  64. package/types/highlight.d.ts +24 -0
  65. package/types/router.d.ts +42 -3
  66. package/types/scaffold.d.ts +15 -3
  67. package/types/skin.d.ts +28 -1
  68. package/types/src/api-runner.d.ts +94 -0
  69. package/types/src/builder.d.ts +170 -0
  70. package/types/src/catalog.d.ts +97 -0
  71. package/types/src/compiler/actions.d.ts +41 -0
  72. package/types/src/compiler/body.d.ts +11 -0
  73. package/types/src/compiler/collections.d.ts +76 -0
  74. package/types/src/compiler/context.d.ts +647 -0
  75. package/types/src/compiler/directives.d.ts +6 -0
  76. package/types/src/compiler/expr-ast.d.ts +20 -0
  77. package/types/src/compiler/fetch.d.ts +29 -0
  78. package/types/src/compiler/format.d.ts +49 -0
  79. package/types/src/compiler/forms.d.ts +94 -0
  80. package/types/src/compiler/frontmatter.d.ts +33 -0
  81. package/types/src/compiler/fs-reader.d.ts +7 -0
  82. package/types/src/compiler/image-size.d.ts +14 -0
  83. package/types/src/compiler/includes.d.ts +100 -0
  84. package/types/src/compiler/index.d.ts +5 -0
  85. package/types/src/compiler/interpolation.d.ts +115 -0
  86. package/types/src/compiler/loops.d.ts +36 -0
  87. package/types/src/compiler/markdown.d.ts +34 -0
  88. package/types/src/compiler/media.d.ts +32 -0
  89. package/types/src/compiler/page.d.ts +109 -0
  90. package/types/src/compiler/predicates.d.ts +50 -0
  91. package/types/src/compiler/reader.d.ts +48 -0
  92. package/types/src/compiler/state.d.ts +68 -0
  93. package/types/src/compiler/structure.d.ts +56 -0
  94. package/types/src/compiler.d.ts +48 -0
  95. package/types/src/config.d.ts +45 -0
  96. package/types/src/dev.d.ts +58 -0
  97. package/types/src/errors.d.ts +100 -0
  98. package/types/src/feeds.d.ts +150 -0
  99. package/types/src/headers.d.ts +44 -0
  100. package/types/src/highlight.d.ts +24 -0
  101. package/types/src/router.d.ts +78 -0
  102. package/types/src/scaffold.d.ts +20 -0
  103. package/types/src/skin.d.ts +48 -0
  104. package/types/src/statics.d.ts +24 -0
  105. package/types/statics.d.ts +2 -1
@@ -0,0 +1,647 @@
1
+ /**
2
+ * @param {import("./reader.js").Reader} reader The source reader for this
3
+ * compile (fs-backed by default; in-memory for `compileFromMemory`).
4
+ * @returns {Compilation}
5
+ */
6
+ export function createCompilation(reader: import("./reader.js").Reader): Compilation;
7
+ /**
8
+ * @param {Scope | null} parent
9
+ * @param {Record<string, unknown>} [vars]
10
+ * @returns {Scope}
11
+ */
12
+ export function createScope(parent: Scope | null, vars?: Record<string, unknown>): Scope;
13
+ /**
14
+ * Format a source location as `file:line` (1-based) for compile errors. Keeps the
15
+ * file path intact so existing message matchers still pass, while pointing at the
16
+ * directive's (or unclosed opener's) line. `index` is 0-based into the current
17
+ * `compileBody` slice; `ctx.lineOffset` (where that slice starts in the body,
18
+ * accumulated by {@link nestedCtx} as block handlers recurse) and `ctx.bodyLine`
19
+ * (the frontmatter offset) shift it back to the true file line.
20
+ * @param {Pick<Ctx, "file" | "bodyLine" | "lineOffset">} ctx
21
+ * @param {number} index 0-based line index into the current body slice.
22
+ * @returns {string}
23
+ */
24
+ export function at(ctx: Pick<Ctx, "file" | "bodyLine" | "lineOffset">, index: number): string;
25
+ /**
26
+ * The 1-based true file line for a body-slice `index` — the numeric half of
27
+ * {@link at}, exposed so {@link wdError} can populate the structured `wd.line`.
28
+ * @param {Pick<Ctx, "bodyLine" | "lineOffset">} ctx
29
+ * @param {number} index 0-based line index into the current body slice.
30
+ * @returns {number}
31
+ */
32
+ export function lineOf(ctx: Pick<Ctx, "bodyLine" | "lineOffset">, index: number): number;
33
+ /**
34
+ * Build a compile `Error` carrying a structured {@link WdErrorInfo} on `err.wd`
35
+ * — so an AI edit-loop (or an editor) gets code/file/line/hint/example without
36
+ * re-parsing the prose. The string message is the caller's text prefixed with
37
+ * the stable `[WDxxx]` code, so a user can search the code straight out of the
38
+ * terminal; everything after the prefix (the `file:line`, the corrective `Use:`
39
+ * template, the concrete `e.g.` example) is unchanged.
40
+ *
41
+ * Every author-facing compile error is built here, so no error can ship without
42
+ * a code. See `src/errors.js` for the registry and the numbering scheme.
43
+ * @param {string} message The user-facing error text, without the code prefix.
44
+ * @param {WdErrorInfo} wd The structured mirror (its `code` becomes the prefix).
45
+ * @returns {Error & { wd: WdErrorInfo }}
46
+ */
47
+ export function wdError(message: string, wd: WdErrorInfo): Error & {
48
+ wd: WdErrorInfo;
49
+ };
50
+ /**
51
+ * The compile context for a nested block body that starts `start` lines into the
52
+ * current slice. The offset accumulates, so errors inside arbitrarily nested
53
+ * blocks (`::: container`, `:form`, `@loop`, `:if`, `:carousel`) still report
54
+ * the true file line through {@link at}.
55
+ * @template {Pick<Ctx, "lineOffset">} T
56
+ * @param {T} ctx
57
+ * @param {number} start 0-based index the nested body starts at in the current slice.
58
+ * @returns {T}
59
+ */
60
+ export function nestedCtx<T extends Pick<Ctx, "lineOffset">>(ctx: T, start: number): T;
61
+ /**
62
+ * @typedef {import("../config.js").Paths} Paths
63
+ */
64
+ /**
65
+ * Frontmatter values are scalars or inline arrays of scalars.
66
+ * @typedef {string | number | boolean | null | Array<string | number | boolean | null>} FrontmatterValue
67
+ */
68
+ /**
69
+ * Parsed page frontmatter, keyed by field name.
70
+ * @typedef {Record<string, FrontmatterValue>} Meta
71
+ */
72
+ /**
73
+ * Collected output assets for a compiled document.
74
+ * @typedef {object} Assets
75
+ * @property {Set<string>} skins Public hrefs of compiled skin stylesheets.
76
+ * @property {Set<string>} scripts Public hrefs of colocated page scripts.
77
+ * @property {Map<string, string>} files Source path → public href for emitted assets.
78
+ * @property {boolean} runtime Whether the reactive runtime is required.
79
+ * @property {Set<string>} behaviors Names of framework behavior modules this page
80
+ * needs (`slider` is compile-time only and never appears here; `sortable`,
81
+ * `carousel` each emit a pay-for-what-you-use `/__wd/behaviors/<name>.js`).
82
+ * @property {boolean} hasCode Whether the page has a build-time-highlighted code
83
+ * block, so the framework highlight stylesheet (`/__wd/highlight.css`) is
84
+ * emitted and linked — pay-for-what-you-use, zero JS.
85
+ * @property {Set<string>} scopedSkins Source paths of colocated `.skin` files
86
+ * that opted into scoping (`scoped` first line). The builder emits these with
87
+ * the scope attribute and runs the unused-selector warning against the stamped
88
+ * subtree; the HTML stamp uses them to scope the matching page/include subtree.
89
+ */
90
+ /**
91
+ * The pagination intent a `@loop … paginate N` records during compile, so the
92
+ * builder can multiply routes (page 1 at the listing route, 2+ at
93
+ * `/<route>/page/<n>/`). `total` is the post-`where`/`sort` page count for the
94
+ * collection the loop drew from.
95
+ * @typedef {object} Pagination
96
+ * @property {number} perPage Rows per page (the `paginate N` value).
97
+ * @property {number} total Total page count (≥ 1).
98
+ * @property {string} collection Collection name the loop paginated.
99
+ */
100
+ /**
101
+ * Per-document compilation accumulator shared across includes/sections.
102
+ * @typedef {object} Compilation
103
+ * @property {Assets} assets
104
+ * @property {Map<string, unknown>} state Declared state keys → initial values.
105
+ * @property {Set<string>} stores Page-global store names (a subset of state keys).
106
+ * @property {Set<string>} fetchKeys Base state keys declared by `:fetch`, so
107
+ * bare `:if <key>_loading` / `:if <key>_error` regions get compile-time
108
+ * `role`/`aria-live` announcements.
109
+ * @property {string[]} warnings Non-fatal authoring hints.
110
+ * @property {number} sectionCounter Counter for auto-generated section ids.
111
+ * @property {Map<string, number>} headingSlugs Heading-slug occurrence counts,
112
+ * shared across prose chunks and includes so anchor ids dedupe document-wide.
113
+ * @property {Map<string, import("./collections.js").CollectionRow[]>} collections
114
+ * Collection name → entry rows, built from the router's routes and threaded in
115
+ * so a bare-name `@loop blog into post` resolves to its entries at build time.
116
+ * @property {import("./context.js").Pagination | null} pagination The pagination
117
+ * intent a `@loop … paginate N` recorded this compile, or null. The builder
118
+ * reads it to multiply routes; one paginated loop per page is supported.
119
+ * @property {Set<string>} deps Absolute paths of every source file this compile
120
+ * read: the page itself, every `@include` target, and every `@loop` JSON data
121
+ * file. The dev builder unions these (plus colocated assets) into the per-route
122
+ * dependency map that drives incremental rebuilds.
123
+ * @property {Set<string>} collectionsUsed Names of the collections this compile
124
+ * looped, so a change to any entry of a collection rebuilds its consumers.
125
+ * @property {import("./reader.js").Reader} reader The file reader every source
126
+ * read threads through — the real filesystem by default, or an in-memory map
127
+ * for `compileFromMemory`. Set once by `createCompilation` and reached via
128
+ * `ctx.comp.reader` in the directive handlers (includes, loop data).
129
+ */
130
+ /**
131
+ * A lexical scope chain for static interpolation values (include args, loop vars).
132
+ * @typedef {object} Scope
133
+ * @property {Scope | null} parent
134
+ * @property {Record<string, unknown>} vars
135
+ */
136
+ /**
137
+ * Per-file compile context threaded through the directive handlers.
138
+ * @typedef {object} Ctx
139
+ * @property {string} file Absolute path to the file being compiled.
140
+ * @property {number} [bodyLine] 0-based file line the compiled body starts on
141
+ * (the frontmatter offset), so `at` reports true file line numbers.
142
+ * @property {number} [lineOffset] 0-based body line the current `compileBody`
143
+ * slice starts on. Block handlers recurse with {@link nestedCtx}, so a line
144
+ * index inside a nested block body still maps to the true file line.
145
+ * @property {Paths} context Resolved project paths.
146
+ * @property {string[]} stack Include stack (real paths) for cycle detection.
147
+ * @property {Scope} scope Static value scope chain.
148
+ * @property {Compilation} comp Shared compilation accumulator.
149
+ * @property {string[]} sections Active section-id scope chain.
150
+ * @property {string | null} loopItem Name of the current reactive loop item, if any.
151
+ * @property {string} [loopKey] State key of the list being looped, if any.
152
+ * @property {number} [reactiveDepth] Number of enclosing REACTIVE `@loop` levels
153
+ * (0 at top level). The runtime reconciles at most two nested `data-wd-loop`
154
+ * levels — a third paints empty — so a third reactive level is rejected at
155
+ * compile time. Static (build-unrolled) loops flatten to markup and don't add
156
+ * a level, so they carry the count through without incrementing it.
157
+ * @property {{ at: string, line: string }} [loopOpener] The current `@loop`
158
+ * opener's `file:line` + raw text, set when descending into a loop body so the
159
+ * reactive-nesting-depth error can point at the offending opener.
160
+ * @property {boolean} [loopMeta] Inside a loop body, so `$index`/`$first`/… are valid.
161
+ * @property {import("markdown-it").default} [md] Markdown-it instance selected for this file.
162
+ * @property {(lines: string[], ctx: Ctx) => string} compileBody The body
163
+ * dispatcher, threaded through the context so block handlers (`:if`, `:::`,
164
+ * `:form`, `@loop`, …) recurse into nested bodies without importing the
165
+ * dispatcher back — the module graph stays an import-cycle-free DAG.
166
+ * @property {(file: string, context: Paths, stack: string[], scope: Scope, comp: Compilation, sections: string[], loopItem: string | null, reactiveDepth?: number, loopOpener?: { at: string, line: string } | null) => { meta: Meta, html: string }} compileFile
167
+ * The per-file compile, threaded for the same reason so `@include` can
168
+ * compile its target file. `reactiveDepth`/`loopOpener` carry the enclosing
169
+ * reactive-loop nesting across the include boundary so the depth guard holds.
170
+ */
171
+ /**
172
+ * A compiled page document.
173
+ * @typedef {object} CompiledDocument
174
+ * @property {Meta} meta
175
+ * @property {string} html
176
+ * @property {Assets} assets
177
+ * @property {string[]} warnings
178
+ * @property {Pagination | null} pagination The pagination intent a paginated
179
+ * `@loop` recorded, or null. The builder reads it to multiply routes.
180
+ * @property {Set<string>} deps Absolute source-file dependencies of this compile.
181
+ * @property {Set<string>} collectionsUsed Collection names this compile looped.
182
+ */
183
+ /**
184
+ * A compiled page: the document plus its full HTML shell.
185
+ * @typedef {object} CompiledPage
186
+ * @property {Meta} meta
187
+ * @property {string} html
188
+ * @property {Assets} assets
189
+ * @property {string[]} warnings
190
+ * @property {Pagination | null} pagination The pagination intent a paginated
191
+ * `@loop` recorded, or null. The builder reads it to multiply routes.
192
+ * @property {Set<string>} deps Absolute source-file dependencies of this compile.
193
+ * @property {Set<string>} collectionsUsed Collection names this compile looped.
194
+ */
195
+ /**
196
+ * Structured, machine-readable companion to a compile error's string message.
197
+ * The string `message` contract is unchanged; `wd` gives an AI edit-loop (or an
198
+ * editor) the same facts without re-parsing the prose: which code, which
199
+ * file/line, the corrective `Use:` template, and one concrete compilable
200
+ * example line.
201
+ * @typedef {object} WdErrorInfo
202
+ * @property {string} code Stable error code (`WD` + three digits, e.g. `WD201`).
203
+ * Every code is registered in `src/errors.js` with a title, cause, and fix,
204
+ * and documented in `docs/errors.md`. {@link wdError} prefixes the string
205
+ * message with `[<code>] `, so the code is greppable from the message too.
206
+ * @property {string} [file] Absolute path of the source file the error is in,
207
+ * when the throwing layer knows one (`compileSkin` is a pure string→string
208
+ * pass and a collection-row check names the entry route instead).
209
+ * @property {number} [line] 1-based file line the error points at, when known
210
+ * (some errors — e.g. a bad `where` operand — are file-scoped only, matching
211
+ * the string message, which likewise omits the line there).
212
+ * @property {string} [hint] The corrective `Use:` template (without the `Use: ` prefix).
213
+ * @property {string} [example] One concrete, compilable directive line.
214
+ */
215
+ /**
216
+ * A compiled `@loop … where` predicate.
217
+ * @typedef {object} Predicate
218
+ * @property {string} body Safe JS boolean expression over `I()`/`S()`/`C()`.
219
+ * @property {boolean} refsState Whether the predicate reads declared state.
220
+ */
221
+ /**
222
+ * A loop offset/limit argument: a non-negative integer literal or a state key.
223
+ * @typedef {{ kind: "literal", value: number } | { kind: "key", value: string }} NumArg
224
+ */
225
+ /**
226
+ * Loop clause configuration shared by the static and reactive paths.
227
+ * @typedef {object} LoopOpts
228
+ * @property {Predicate | null} where
229
+ * @property {{ key: string, keyKind: "literal" | "key", dir: string, dirKind: "literal" | "key" } | null} sort A literal item field + asc/desc, or a `:state`/`:store` key for either (reactive, clickable-header sort).
230
+ * @property {boolean} reverse
231
+ * @property {NumArg | null} offset
232
+ * @property {NumArg | null} limit
233
+ * @property {string[] | null} empty Empty-branch body lines, if any.
234
+ * @property {number} [emptyStart] 0-based index the empty branch starts at
235
+ * within the loop body, so its nested errors report the true file line.
236
+ * @property {boolean} clauseRefsState Whether offset/limit reference state.
237
+ * @property {boolean} sortable Drag-to-reorder the underlying :state/:store list
238
+ * (the `sortable` clause). Only valid on a plain reactive state-key loop.
239
+ * @property {number | null} paginate Rows-per-page for a `paginate N` clause, or
240
+ * null. Only valid on a collection loop; multiplies the listing into static
241
+ * pages (page 1 at the route, 2+ at `/<route>/page/<n>/`) and exposes a `page`
242
+ * pager to the template scope.
243
+ */
244
+ /**
245
+ * A parsed `:button` action.
246
+ * @typedef {object} Action
247
+ * @property {string} op Runtime operation (inc/dec/add/sub/append/prepend/set/toggle/member-toggle/remove/remove-value/clear/merge/delete/reset/append-row).
248
+ * @property {string} target State key (possibly dotted) the action mutates.
249
+ * @property {unknown} [value] Literal value for value-carrying ops.
250
+ */
251
+ export const pageIncludeExtensions: string[];
252
+ /** @type {Record<string, string>} */
253
+ export const LOOP_META: Record<string, string>;
254
+ export type Paths = import("../config.js").Paths;
255
+ /**
256
+ * Frontmatter values are scalars or inline arrays of scalars.
257
+ */
258
+ export type FrontmatterValue = string | number | boolean | null | Array<string | number | boolean | null>;
259
+ /**
260
+ * Parsed page frontmatter, keyed by field name.
261
+ */
262
+ export type Meta = Record<string, FrontmatterValue>;
263
+ /**
264
+ * Collected output assets for a compiled document.
265
+ */
266
+ export type Assets = {
267
+ /**
268
+ * Public hrefs of compiled skin stylesheets.
269
+ */
270
+ skins: Set<string>;
271
+ /**
272
+ * Public hrefs of colocated page scripts.
273
+ */
274
+ scripts: Set<string>;
275
+ /**
276
+ * Source path → public href for emitted assets.
277
+ */
278
+ files: Map<string, string>;
279
+ /**
280
+ * Whether the reactive runtime is required.
281
+ */
282
+ runtime: boolean;
283
+ /**
284
+ * Names of framework behavior modules this page
285
+ * needs (`slider` is compile-time only and never appears here; `sortable`,
286
+ * `carousel` each emit a pay-for-what-you-use `/__wd/behaviors/<name>.js`).
287
+ */
288
+ behaviors: Set<string>;
289
+ /**
290
+ * Whether the page has a build-time-highlighted code
291
+ * block, so the framework highlight stylesheet (`/__wd/highlight.css`) is
292
+ * emitted and linked — pay-for-what-you-use, zero JS.
293
+ */
294
+ hasCode: boolean;
295
+ /**
296
+ * Source paths of colocated `.skin` files
297
+ * that opted into scoping (`scoped` first line). The builder emits these with
298
+ * the scope attribute and runs the unused-selector warning against the stamped
299
+ * subtree; the HTML stamp uses them to scope the matching page/include subtree.
300
+ */
301
+ scopedSkins: Set<string>;
302
+ };
303
+ /**
304
+ * The pagination intent a `@loop … paginate N` records during compile, so the
305
+ * builder can multiply routes (page 1 at the listing route, 2+ at
306
+ * `/<route>/page/<n>/`). `total` is the post-`where`/`sort` page count for the
307
+ * collection the loop drew from.
308
+ */
309
+ export type Pagination = {
310
+ /**
311
+ * Rows per page (the `paginate N` value).
312
+ */
313
+ perPage: number;
314
+ /**
315
+ * Total page count (≥ 1).
316
+ */
317
+ total: number;
318
+ /**
319
+ * Collection name the loop paginated.
320
+ */
321
+ collection: string;
322
+ };
323
+ /**
324
+ * Per-document compilation accumulator shared across includes/sections.
325
+ */
326
+ export type Compilation = {
327
+ assets: Assets;
328
+ /**
329
+ * Declared state keys → initial values.
330
+ */
331
+ state: Map<string, unknown>;
332
+ /**
333
+ * Page-global store names (a subset of state keys).
334
+ */
335
+ stores: Set<string>;
336
+ /**
337
+ * Base state keys declared by `:fetch`, so
338
+ * bare `:if <key>_loading` / `:if <key>_error` regions get compile-time
339
+ * `role`/`aria-live` announcements.
340
+ */
341
+ fetchKeys: Set<string>;
342
+ /**
343
+ * Non-fatal authoring hints.
344
+ */
345
+ warnings: string[];
346
+ /**
347
+ * Counter for auto-generated section ids.
348
+ */
349
+ sectionCounter: number;
350
+ /**
351
+ * Heading-slug occurrence counts,
352
+ * shared across prose chunks and includes so anchor ids dedupe document-wide.
353
+ */
354
+ headingSlugs: Map<string, number>;
355
+ /**
356
+ * Collection name → entry rows, built from the router's routes and threaded in
357
+ * so a bare-name `@loop blog into post` resolves to its entries at build time.
358
+ */
359
+ collections: Map<string, import("./collections.js").CollectionRow[]>;
360
+ /**
361
+ * The pagination
362
+ * intent a `@loop … paginate N` recorded this compile, or null. The builder
363
+ * reads it to multiply routes; one paginated loop per page is supported.
364
+ */
365
+ pagination: import("./context.js").Pagination | null;
366
+ /**
367
+ * Absolute paths of every source file this compile
368
+ * read: the page itself, every `@include` target, and every `@loop` JSON data
369
+ * file. The dev builder unions these (plus colocated assets) into the per-route
370
+ * dependency map that drives incremental rebuilds.
371
+ */
372
+ deps: Set<string>;
373
+ /**
374
+ * Names of the collections this compile
375
+ * looped, so a change to any entry of a collection rebuilds its consumers.
376
+ */
377
+ collectionsUsed: Set<string>;
378
+ /**
379
+ * The file reader every source
380
+ * read threads through — the real filesystem by default, or an in-memory map
381
+ * for `compileFromMemory`. Set once by `createCompilation` and reached via
382
+ * `ctx.comp.reader` in the directive handlers (includes, loop data).
383
+ */
384
+ reader: import("./reader.js").Reader;
385
+ };
386
+ /**
387
+ * A lexical scope chain for static interpolation values (include args, loop vars).
388
+ */
389
+ export type Scope = {
390
+ parent: Scope | null;
391
+ vars: Record<string, unknown>;
392
+ };
393
+ /**
394
+ * Per-file compile context threaded through the directive handlers.
395
+ */
396
+ export type Ctx = {
397
+ /**
398
+ * Absolute path to the file being compiled.
399
+ */
400
+ file: string;
401
+ /**
402
+ * 0-based file line the compiled body starts on
403
+ * (the frontmatter offset), so `at` reports true file line numbers.
404
+ */
405
+ bodyLine?: number | undefined;
406
+ /**
407
+ * 0-based body line the current `compileBody`
408
+ * slice starts on. Block handlers recurse with {@link nestedCtx}, so a line
409
+ * index inside a nested block body still maps to the true file line.
410
+ */
411
+ lineOffset?: number | undefined;
412
+ /**
413
+ * Resolved project paths.
414
+ */
415
+ context: Paths;
416
+ /**
417
+ * Include stack (real paths) for cycle detection.
418
+ */
419
+ stack: string[];
420
+ /**
421
+ * Static value scope chain.
422
+ */
423
+ scope: Scope;
424
+ /**
425
+ * Shared compilation accumulator.
426
+ */
427
+ comp: Compilation;
428
+ /**
429
+ * Active section-id scope chain.
430
+ */
431
+ sections: string[];
432
+ /**
433
+ * Name of the current reactive loop item, if any.
434
+ */
435
+ loopItem: string | null;
436
+ /**
437
+ * State key of the list being looped, if any.
438
+ */
439
+ loopKey?: string | undefined;
440
+ /**
441
+ * Number of enclosing REACTIVE `@loop` levels
442
+ * (0 at top level). The runtime reconciles at most two nested `data-wd-loop`
443
+ * levels — a third paints empty — so a third reactive level is rejected at
444
+ * compile time. Static (build-unrolled) loops flatten to markup and don't add
445
+ * a level, so they carry the count through without incrementing it.
446
+ */
447
+ reactiveDepth?: number | undefined;
448
+ /**
449
+ * The current `@loop`
450
+ * opener's `file:line` + raw text, set when descending into a loop body so the
451
+ * reactive-nesting-depth error can point at the offending opener.
452
+ */
453
+ loopOpener?: {
454
+ at: string;
455
+ line: string;
456
+ } | undefined;
457
+ /**
458
+ * Inside a loop body, so `$index`/`$first`/… are valid.
459
+ */
460
+ loopMeta?: boolean | undefined;
461
+ /**
462
+ * Markdown-it instance selected for this file.
463
+ */
464
+ md?: import("markdown-it").default | undefined;
465
+ /**
466
+ * The body
467
+ * dispatcher, threaded through the context so block handlers (`:if`, `:::`,
468
+ * `:form`, `@loop`, …) recurse into nested bodies without importing the
469
+ * dispatcher back — the module graph stays an import-cycle-free DAG.
470
+ */
471
+ compileBody: (lines: string[], ctx: Ctx) => string;
472
+ /**
473
+ * The per-file compile, threaded for the same reason so `@include` can
474
+ * compile its target file. `reactiveDepth`/`loopOpener` carry the enclosing
475
+ * reactive-loop nesting across the include boundary so the depth guard holds.
476
+ */
477
+ compileFile: (file: string, context: Paths, stack: string[], scope: Scope, comp: Compilation, sections: string[], loopItem: string | null, reactiveDepth?: number, loopOpener?: {
478
+ at: string;
479
+ line: string;
480
+ } | null) => {
481
+ meta: Meta;
482
+ html: string;
483
+ };
484
+ };
485
+ /**
486
+ * A compiled page document.
487
+ */
488
+ export type CompiledDocument = {
489
+ meta: Meta;
490
+ html: string;
491
+ assets: Assets;
492
+ warnings: string[];
493
+ /**
494
+ * The pagination intent a paginated
495
+ * `@loop` recorded, or null. The builder reads it to multiply routes.
496
+ */
497
+ pagination: Pagination | null;
498
+ /**
499
+ * Absolute source-file dependencies of this compile.
500
+ */
501
+ deps: Set<string>;
502
+ /**
503
+ * Collection names this compile looped.
504
+ */
505
+ collectionsUsed: Set<string>;
506
+ };
507
+ /**
508
+ * A compiled page: the document plus its full HTML shell.
509
+ */
510
+ export type CompiledPage = {
511
+ meta: Meta;
512
+ html: string;
513
+ assets: Assets;
514
+ warnings: string[];
515
+ /**
516
+ * The pagination intent a paginated
517
+ * `@loop` recorded, or null. The builder reads it to multiply routes.
518
+ */
519
+ pagination: Pagination | null;
520
+ /**
521
+ * Absolute source-file dependencies of this compile.
522
+ */
523
+ deps: Set<string>;
524
+ /**
525
+ * Collection names this compile looped.
526
+ */
527
+ collectionsUsed: Set<string>;
528
+ };
529
+ /**
530
+ * Structured, machine-readable companion to a compile error's string message.
531
+ * The string `message` contract is unchanged; `wd` gives an AI edit-loop (or an
532
+ * editor) the same facts without re-parsing the prose: which code, which
533
+ * file/line, the corrective `Use:` template, and one concrete compilable
534
+ * example line.
535
+ */
536
+ export type WdErrorInfo = {
537
+ /**
538
+ * Stable error code (`WD` + three digits, e.g. `WD201`).
539
+ * Every code is registered in `src/errors.js` with a title, cause, and fix,
540
+ * and documented in `docs/errors.md`. {@link wdError} prefixes the string
541
+ * message with `[<code>] `, so the code is greppable from the message too.
542
+ */
543
+ code: string;
544
+ /**
545
+ * Absolute path of the source file the error is in,
546
+ * when the throwing layer knows one (`compileSkin` is a pure string→string
547
+ * pass and a collection-row check names the entry route instead).
548
+ */
549
+ file?: string | undefined;
550
+ /**
551
+ * 1-based file line the error points at, when known
552
+ * (some errors — e.g. a bad `where` operand — are file-scoped only, matching
553
+ * the string message, which likewise omits the line there).
554
+ */
555
+ line?: number | undefined;
556
+ /**
557
+ * The corrective `Use:` template (without the `Use: ` prefix).
558
+ */
559
+ hint?: string | undefined;
560
+ /**
561
+ * One concrete, compilable directive line.
562
+ */
563
+ example?: string | undefined;
564
+ };
565
+ /**
566
+ * A compiled `@loop … where` predicate.
567
+ */
568
+ export type Predicate = {
569
+ /**
570
+ * Safe JS boolean expression over `I()`/`S()`/`C()`.
571
+ */
572
+ body: string;
573
+ /**
574
+ * Whether the predicate reads declared state.
575
+ */
576
+ refsState: boolean;
577
+ };
578
+ /**
579
+ * A loop offset/limit argument: a non-negative integer literal or a state key.
580
+ */
581
+ export type NumArg = {
582
+ kind: "literal";
583
+ value: number;
584
+ } | {
585
+ kind: "key";
586
+ value: string;
587
+ };
588
+ /**
589
+ * Loop clause configuration shared by the static and reactive paths.
590
+ */
591
+ export type LoopOpts = {
592
+ where: Predicate | null;
593
+ /**
594
+ * A literal item field + asc/desc, or a `:state`/`:store` key for either (reactive, clickable-header sort).
595
+ */
596
+ sort: {
597
+ key: string;
598
+ keyKind: "literal" | "key";
599
+ dir: string;
600
+ dirKind: "literal" | "key";
601
+ } | null;
602
+ reverse: boolean;
603
+ offset: NumArg | null;
604
+ limit: NumArg | null;
605
+ /**
606
+ * Empty-branch body lines, if any.
607
+ */
608
+ empty: string[] | null;
609
+ /**
610
+ * 0-based index the empty branch starts at
611
+ * within the loop body, so its nested errors report the true file line.
612
+ */
613
+ emptyStart?: number | undefined;
614
+ /**
615
+ * Whether offset/limit reference state.
616
+ */
617
+ clauseRefsState: boolean;
618
+ /**
619
+ * Drag-to-reorder the underlying :state/:store list
620
+ * (the `sortable` clause). Only valid on a plain reactive state-key loop.
621
+ */
622
+ sortable: boolean;
623
+ /**
624
+ * Rows-per-page for a `paginate N` clause, or
625
+ * null. Only valid on a collection loop; multiplies the listing into static
626
+ * pages (page 1 at the route, 2+ at `/<route>/page/<n>/`) and exposes a `page`
627
+ * pager to the template scope.
628
+ */
629
+ paginate: number | null;
630
+ };
631
+ /**
632
+ * A parsed `:button` action.
633
+ */
634
+ export type Action = {
635
+ /**
636
+ * Runtime operation (inc/dec/add/sub/append/prepend/set/toggle/member-toggle/remove/remove-value/clear/merge/delete/reset/append-row).
637
+ */
638
+ op: string;
639
+ /**
640
+ * State key (possibly dotted) the action mutates.
641
+ */
642
+ target: string;
643
+ /**
644
+ * Literal value for value-carrying ops.
645
+ */
646
+ value?: unknown;
647
+ };
@@ -0,0 +1,6 @@
1
+ export { handleFetch } from "./fetch.js";
2
+ export { handleButton, handleEffect, handleEvery } from "./actions.js";
3
+ export { handleBind, handleChoiceGroup, handleForm, handleInput, handleSelect, handleSlider, handleSubmit, handleTextarea } from "./forms.js";
4
+ export { handleEmbed, handleMedia } from "./media.js";
5
+ export { handleComputed, handleState, handleStore, handleTheme } from "./state.js";
6
+ export { handleCarousel, handleContainer, handleIf, handleInclude, renderDemoDirective } from "./structure.js";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Re-parse a validated compiled expression (JS fragment over I()/S()/C()/A())
3
+ * into a compact AST. Throws on anything outside the closed grammar.
4
+ * @param {string} code
5
+ * @returns {any[]}
6
+ */
7
+ export function astOf(code: string): any[];
8
+ /**
9
+ * Build-time mirror of the runtime AST walker — same operators, so a `:computed`
10
+ * or `where`/`when` predicate folds to the SAME value the runtime will recompute.
11
+ * `state` reads come from the compilation's declared-state map. No eval.
12
+ * @param {any[]} node
13
+ * @param {unknown} item Loop row for I(); undefined otherwise.
14
+ * @param {{ state: Map<string, unknown> }} comp
15
+ * @returns {any}
16
+ */
17
+ export function evalAst(node: any[], item: unknown, comp: {
18
+ state: Map<string, unknown>;
19
+ }): any;
20
+ export function serializeExpr(code: string): string;