@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,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile a page source file into a full HTML document plus its assets.
|
|
3
|
+
* @param {string} file Absolute path to the source `.md`/`.wd` file.
|
|
4
|
+
* @param {Paths} context Resolved project paths.
|
|
5
|
+
* @param {{ feed?: { href: string, title: string }, collections?: Map<string, import("./collections.js").CollectionRow[]>, vars?: Record<string, unknown>, reader?: import("./reader.js").Reader }} [options]
|
|
6
|
+
* When a site-wide RSS feed is emitted (the home page set `site_url` and the
|
|
7
|
+
* site has dated posts), `feed` carries its absolute href + title so every page
|
|
8
|
+
* links it. `collections` is the build-time collection index a bare-name
|
|
9
|
+
* `@loop` resolves against; `vars` seeds the document scope (the pager `page`
|
|
10
|
+
* object on a paginated route). `reader` is the source reader (fs-backed by
|
|
11
|
+
* default via `src/compiler.js`; in-memory for `compileFromMemory`).
|
|
12
|
+
* @returns {CompiledPage}
|
|
13
|
+
*/
|
|
14
|
+
export function compilePage(file: string, context: Paths, options?: {
|
|
15
|
+
feed?: {
|
|
16
|
+
href: string;
|
|
17
|
+
title: string;
|
|
18
|
+
};
|
|
19
|
+
collections?: Map<string, import("./collections.js").CollectionRow[]>;
|
|
20
|
+
vars?: Record<string, unknown>;
|
|
21
|
+
reader?: import("./reader.js").Reader;
|
|
22
|
+
}): CompiledPage;
|
|
23
|
+
/**
|
|
24
|
+
* Harden every `<img>` in the assembled page body — compile-time only, zero
|
|
25
|
+
* runtime JS. Bare markdown images reflow the page as they decode (cumulative
|
|
26
|
+
* layout shift — the literal "jump" on navigation) and load eagerly. This
|
|
27
|
+
* stamps intrinsic `width`/`height` (read from the file on disk so the browser
|
|
28
|
+
* reserves space), `decoding="async"` on all, and a load-priority split: the
|
|
29
|
+
* first image is the LCP candidate (eager + `fetchpriority="high"`), the rest
|
|
30
|
+
* lazy-load. Author-set attributes are never overwritten.
|
|
31
|
+
* @param {string} html Assembled page body HTML.
|
|
32
|
+
* @param {Paths} paths Resolved project paths.
|
|
33
|
+
* @param {import("./reader.js").Reader} reader Source reader for the image bytes.
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
export function enhanceImages(html: string, paths: Paths, reader: import("./reader.js").Reader): string;
|
|
37
|
+
/**
|
|
38
|
+
* Compile a source file into its body HTML, frontmatter, and assets (no page shell).
|
|
39
|
+
* @param {string} file Absolute path to the source file.
|
|
40
|
+
* @param {Paths} context Resolved project paths.
|
|
41
|
+
* @param {string[]} [stack] Include stack for cycle detection.
|
|
42
|
+
* @param {Record<string, unknown>} [vars] Initial static scope variables.
|
|
43
|
+
* @param {Map<string, import("./collections.js").CollectionRow[]>} [collections]
|
|
44
|
+
* Build-time collection index a bare-name `@loop` resolves against.
|
|
45
|
+
* @param {import("./reader.js").Reader} [reader] Source reader (fs-backed when
|
|
46
|
+
* omitted via `src/compiler.js`; in-memory for `compileFromMemory`).
|
|
47
|
+
* @returns {CompiledDocument}
|
|
48
|
+
*/
|
|
49
|
+
export function compileDocument(file: string, context: Paths, stack?: string[], vars?: Record<string, unknown>, collections?: Map<string, import("./collections.js").CollectionRow[]>, reader?: import("./reader.js").Reader): CompiledDocument;
|
|
50
|
+
/**
|
|
51
|
+
* Compile a single file: parse frontmatter, collect assets, render body.
|
|
52
|
+
* @param {string} file
|
|
53
|
+
* @param {Paths} context
|
|
54
|
+
* @param {string[]} stack
|
|
55
|
+
* @param {Scope} scope
|
|
56
|
+
* @param {Compilation} comp
|
|
57
|
+
* @param {string[]} sections
|
|
58
|
+
* @param {string | null} loopItem
|
|
59
|
+
* @param {number} [reactiveDepth] Enclosing REACTIVE `@loop` levels, threaded in
|
|
60
|
+
* from the including page so an include's body can't bypass the two-level
|
|
61
|
+
* reactive-nesting limit at the `@include` boundary.
|
|
62
|
+
* @param {{ at: string, line: string } | null} [loopOpener] The enclosing `@loop`
|
|
63
|
+
* opener, threaded in so a depth error inside the include names the right opener.
|
|
64
|
+
* @returns {{ meta: Meta, html: string }}
|
|
65
|
+
*/
|
|
66
|
+
export function compileFile(file: string, context: Paths, stack: string[], scope: Scope, comp: Compilation, sections: string[], loopItem: string | null, reactiveDepth?: number, loopOpener?: {
|
|
67
|
+
at: string;
|
|
68
|
+
line: string;
|
|
69
|
+
} | null): {
|
|
70
|
+
meta: Meta;
|
|
71
|
+
html: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Compile a page entirely from an in-memory file map — no filesystem, no
|
|
75
|
+
* `node:fs`. `files` maps PROJECT-RELATIVE POSIX paths (`site/pages/index.wd`,
|
|
76
|
+
* `site/_/nav.wd`) to their source strings; `entryPath` is the project-relative
|
|
77
|
+
* path of the page to compile. Includes, colocated `.skin`/`.js` detection, and
|
|
78
|
+
* `@loop` JSON-data reads all resolve against the same map (anything not in it
|
|
79
|
+
* is simply "absent"), so `@include`s work as long as their targets are present.
|
|
80
|
+
*
|
|
81
|
+
* This is the strategic fs-free entry point the browser playground and a planned
|
|
82
|
+
* mobile host use: the entire module graph reachable from here is free of
|
|
83
|
+
* `node:fs`, so it bundles for the browser. It returns the same
|
|
84
|
+
* {@link CompiledPage} shape as {@link compilePage} and throws the same
|
|
85
|
+
* `file:line` compile errors, so the error DX is identical in-browser.
|
|
86
|
+
* @param {Record<string, string> | Map<string, string>} files Project-relative
|
|
87
|
+
* path → source content.
|
|
88
|
+
* @param {string} entryPath Project-relative path of the page to compile.
|
|
89
|
+
* @param {{ feed?: { href: string, title: string }, collections?: Map<string, import("./collections.js").CollectionRow[]>, vars?: Record<string, unknown>, cwd?: string }} [options]
|
|
90
|
+
* Same shell options as {@link compilePage}; `cwd` overrides the virtual
|
|
91
|
+
* project root the relative keys resolve against (defaults to `/`).
|
|
92
|
+
* @returns {CompiledPage}
|
|
93
|
+
*/
|
|
94
|
+
export function compileFromMemory(files: Record<string, string> | Map<string, string>, entryPath: string, options?: {
|
|
95
|
+
feed?: {
|
|
96
|
+
href: string;
|
|
97
|
+
title: string;
|
|
98
|
+
};
|
|
99
|
+
collections?: Map<string, import("./collections.js").CollectionRow[]>;
|
|
100
|
+
vars?: Record<string, unknown>;
|
|
101
|
+
cwd?: string;
|
|
102
|
+
}): CompiledPage;
|
|
103
|
+
export type Paths = import("./context.js").Paths;
|
|
104
|
+
export type Meta = import("./context.js").Meta;
|
|
105
|
+
export type Scope = import("./context.js").Scope;
|
|
106
|
+
export type Compilation = import("./context.js").Compilation;
|
|
107
|
+
export type Ctx = import("./context.js").Ctx;
|
|
108
|
+
export type CompiledDocument = import("./context.js").CompiledDocument;
|
|
109
|
+
export type CompiledPage = import("./context.js").CompiledPage;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} raw
|
|
3
|
+
* @param {string} itemName
|
|
4
|
+
* @param {Ctx} ctx
|
|
5
|
+
* @returns {Predicate}
|
|
6
|
+
*/
|
|
7
|
+
export function compilePredicate(raw: string, itemName: string, ctx: Ctx): Predicate;
|
|
8
|
+
/**
|
|
9
|
+
* Evaluate a compiled predicate against a row at build time by walking its AST —
|
|
10
|
+
* the same closed evaluator the runtime uses, so the fold matches. No eval.
|
|
11
|
+
* @param {string} body
|
|
12
|
+
* @param {unknown} item
|
|
13
|
+
* @param {Ctx} ctx
|
|
14
|
+
* @returns {boolean}
|
|
15
|
+
*/
|
|
16
|
+
export function evalPredicate(body: string, item: unknown, ctx: Ctx): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Compile a `::: … .class when <predicate>`. Allows `:if`-style bare truthy
|
|
19
|
+
* paths and `where`-style `left <op> right` conditions joined by `and`/`or`.
|
|
20
|
+
* Folds to a static verdict when every operand is build-known, else returns a
|
|
21
|
+
* runtime body over I()/S()/C() plus whether it reads the reactive loop item
|
|
22
|
+
* (which decides data-wd-each-class vs the global data-wd-class).
|
|
23
|
+
* @param {string} raw
|
|
24
|
+
* @param {Ctx} ctx
|
|
25
|
+
* @param {string} [what] Directive label for error messages.
|
|
26
|
+
* @returns {{ static: true, value: boolean } | { static: false, body: string, item: boolean }}
|
|
27
|
+
*/
|
|
28
|
+
export function compileWhen(raw: string, ctx: Ctx, what?: string): {
|
|
29
|
+
static: true;
|
|
30
|
+
value: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
static: false;
|
|
33
|
+
body: string;
|
|
34
|
+
item: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Compile a `:computed` expression into safe JS over the `S(key, path)` reader.
|
|
38
|
+
* @param {string} raw
|
|
39
|
+
* @param {Ctx} ctx
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
export function compileComputedExpr(raw: string, ctx: Ctx): string;
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {import("./context.js").Ctx} Ctx
|
|
45
|
+
* @typedef {import("./context.js").Predicate} Predicate
|
|
46
|
+
*/
|
|
47
|
+
export const PREDICATE_OPS: string[];
|
|
48
|
+
export const PREDICATE_JOINERS: string[];
|
|
49
|
+
export type Ctx = import("./context.js").Ctx;
|
|
50
|
+
export type Predicate = import("./context.js").Predicate;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The narrow filesystem surface the compiler needs. Every method takes an
|
|
3
|
+
* ABSOLUTE path (the compiler resolves includes/assets to absolute paths before
|
|
4
|
+
* reading), so a reader only has to map absolute paths to bytes/existence.
|
|
5
|
+
* @typedef {object} Reader
|
|
6
|
+
* @property {(absPath: string) => string} readText Read a UTF-8 text file.
|
|
7
|
+
* @property {(absPath: string) => Uint8Array} readBinary Read raw bytes (images).
|
|
8
|
+
* @property {(absPath: string) => boolean} exists Whether the path exists.
|
|
9
|
+
* @property {(absPath: string) => string} realpath Canonical path (symlinks
|
|
10
|
+
* resolved on a real fs; a no-op normalize in memory) — used for cycle keys.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A reader backed by an in-memory map of PROJECT-RELATIVE path → content. Keys
|
|
14
|
+
* are POSIX, project-relative (e.g. `site/pages/index.wd`, `site/_/nav.wd`);
|
|
15
|
+
* lookups translate an absolute compile path back to its key via `cwd`. There
|
|
16
|
+
* are no symlinks in memory, so `realpath` just normalizes. Binary reads are
|
|
17
|
+
* unsupported (the playground has no image files, and image measuring degrades
|
|
18
|
+
* to "no dimensions" on a throw), so `readBinary` throws — callers already
|
|
19
|
+
* try/catch it.
|
|
20
|
+
* @param {Record<string, string> | Map<string, string>} files
|
|
21
|
+
* @param {string} [cwd] Virtual project root the keys are relative to.
|
|
22
|
+
* @returns {Reader}
|
|
23
|
+
*/
|
|
24
|
+
export function memoryReader(files: Record<string, string> | Map<string, string>, cwd?: string): Reader;
|
|
25
|
+
/**
|
|
26
|
+
* The narrow filesystem surface the compiler needs. Every method takes an
|
|
27
|
+
* ABSOLUTE path (the compiler resolves includes/assets to absolute paths before
|
|
28
|
+
* reading), so a reader only has to map absolute paths to bytes/existence.
|
|
29
|
+
*/
|
|
30
|
+
export type Reader = {
|
|
31
|
+
/**
|
|
32
|
+
* Read a UTF-8 text file.
|
|
33
|
+
*/
|
|
34
|
+
readText: (absPath: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Read raw bytes (images).
|
|
37
|
+
*/
|
|
38
|
+
readBinary: (absPath: string) => Uint8Array;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the path exists.
|
|
41
|
+
*/
|
|
42
|
+
exists: (absPath: string) => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Canonical path (symlinks
|
|
45
|
+
* resolved on a real fs; a no-op normalize in memory) — used for cycle keys.
|
|
46
|
+
*/
|
|
47
|
+
realpath: (absPath: string) => string;
|
|
48
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
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 handleState(line: string, ctx: Ctx, index: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Register a state key in the current section scope, enabling the runtime.
|
|
10
|
+
* @param {string} name
|
|
11
|
+
* @param {unknown} value
|
|
12
|
+
* @param {Ctx} ctx
|
|
13
|
+
* @returns {string} The fully-qualified state key.
|
|
14
|
+
*/
|
|
15
|
+
export function declareState(name: string, value: unknown, ctx: Ctx): string;
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} line
|
|
18
|
+
* @param {Ctx} ctx
|
|
19
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
export function handleStore(line: string, ctx: Ctx, index: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Register a page-global store. The bare name is added to `comp.state` so every
|
|
25
|
+
* resolver (interpolation, :if, @loop, :computed, actions) sees it, and tracked
|
|
26
|
+
* in `comp.stores` for collision checks. Never section-scoped.
|
|
27
|
+
* @param {string} name
|
|
28
|
+
* @param {unknown} value
|
|
29
|
+
* @param {Ctx} ctx
|
|
30
|
+
* @returns {string} The store name (also its bare state key).
|
|
31
|
+
*/
|
|
32
|
+
export function declareStore(name: string, value: unknown, ctx: Ctx): string;
|
|
33
|
+
/**
|
|
34
|
+
* Seed a `<name>_error` state key (null) if absent. Shared by :fetch and the
|
|
35
|
+
* round-trip :form so error fallbacks have a key to bind.
|
|
36
|
+
* @param {string} key
|
|
37
|
+
* @param {Ctx} ctx
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
export function declareErrorState(key: string, ctx: Ctx): void;
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} line
|
|
43
|
+
* @param {Ctx} ctx
|
|
44
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export function handleComputed(line: string, ctx: Ctx, index: number): string;
|
|
48
|
+
/**
|
|
49
|
+
* `:theme [name] [= "auto"]` declares a durable `:store` (default name `theme`,
|
|
50
|
+
* seed `"auto"`) and reflects its value onto `<html data-theme>`. This layers a
|
|
51
|
+
* manual light/dark switch over the OS preference: `"auto"` follows the skin's
|
|
52
|
+
* `tokens dark` media query, while `"light"`/`"dark"` force the matching
|
|
53
|
+
* `:root[data-theme]` scope. Wire a switch with ordinary store actions —
|
|
54
|
+
* `:button "Dark" -> theme = "dark"`. Durable, so the choice survives reloads.
|
|
55
|
+
* @param {string} line
|
|
56
|
+
* @param {Ctx} ctx
|
|
57
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
58
|
+
* @returns {string}
|
|
59
|
+
*/
|
|
60
|
+
export function handleTheme(line: string, ctx: Ctx, index: number): string;
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {import("./context.js").Ctx} Ctx
|
|
63
|
+
*/
|
|
64
|
+
export const STATE_EXAMPLE: ":state count = 0";
|
|
65
|
+
export const STORE_EXAMPLE: ":store cart = []";
|
|
66
|
+
export const COMPUTED_EXAMPLE: ":computed total = items.length * 4";
|
|
67
|
+
export const THEME_EXAMPLE: ":theme";
|
|
68
|
+
export type Ctx = import("./context.js").Ctx;
|
|
@@ -0,0 +1,56 @@
|
|
|
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 handleInclude(line: string, ctx: Ctx, index: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} header
|
|
10
|
+
* @param {string[]} bodyLines
|
|
11
|
+
* @param {Ctx} ctx
|
|
12
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
export function handleContainer(header: string, bodyLines: string[], ctx: Ctx, index: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* `:carousel [autoplay=N]` … `:endcarousel` — a horizontally scroll-snapping
|
|
18
|
+
* carousel. Contract: each DIRECT child element of the track is one slide, so put
|
|
19
|
+
* each slide in its own block (e.g. a `::: slide` container) and give that block
|
|
20
|
+
* the slide sizing in your skin — loose prose lines would each count as a slide.
|
|
21
|
+
* Registers the `carousel` behavior (prev/next, dot nav, optional autoplay, mouse
|
|
22
|
+
* drag); native CSS scroll-snap + the page skin handle layout and touch swipe.
|
|
23
|
+
* `autoplay` is suppressed under `prefers-reduced-motion`. No runtime required.
|
|
24
|
+
* @param {string} line
|
|
25
|
+
* @param {string[]} bodyLines
|
|
26
|
+
* @param {Ctx} ctx
|
|
27
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
export function handleCarousel(line: string, bodyLines: string[], ctx: Ctx, index: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} line
|
|
33
|
+
* @param {string[]} truthyLines
|
|
34
|
+
* @param {string[]} falsyLines
|
|
35
|
+
* @param {Ctx} ctx
|
|
36
|
+
* @param {number} index 0-based line index for `file:line` errors.
|
|
37
|
+
* @param {number} [falsyStart] 0-based index the falsy body starts at in the
|
|
38
|
+
* current slice, so nested errors in that branch report the true file line.
|
|
39
|
+
* @returns {string}
|
|
40
|
+
*/
|
|
41
|
+
export function handleIf(line: string, truthyLines: string[], falsyLines: string[], ctx: Ctx, index: number, falsyStart?: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Render the documentation-demo directives (`:try`, `:note`, `:sprint`).
|
|
44
|
+
* @param {string} line
|
|
45
|
+
* @param {Ctx} ctx
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
export function renderDemoDirective(line: string, ctx: Ctx): string;
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {import("./context.js").Ctx} Ctx
|
|
51
|
+
*/
|
|
52
|
+
export const INCLUDE_EXAMPLE: "@include /header.wd";
|
|
53
|
+
export const CONTAINER_EXAMPLE: "::: card .featured";
|
|
54
|
+
export const IF_EXAMPLE: ":if count > 0";
|
|
55
|
+
export const CAROUSEL_EXAMPLE: ":carousel autoplay=3000";
|
|
56
|
+
export type Ctx = import("./context.js").Ctx;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile a page source file into a full HTML document plus its assets, reading
|
|
3
|
+
* from the real filesystem by default. Pass `options.reader` to compile against
|
|
4
|
+
* a different source (see `compileFromMemory`).
|
|
5
|
+
* @param {string} file Absolute path to the source `.md`/`.wd` file.
|
|
6
|
+
* @param {import("./config.js").Paths} context Resolved project paths.
|
|
7
|
+
* @param {{ feed?: { href: string, title: string }, collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>, vars?: Record<string, unknown>, reader?: import("./compiler/reader.js").Reader }} [options]
|
|
8
|
+
* @returns {CompiledPage}
|
|
9
|
+
*/
|
|
10
|
+
export function compilePage(file: string, context: import("./config.js").Paths, options?: {
|
|
11
|
+
feed?: {
|
|
12
|
+
href: string;
|
|
13
|
+
title: string;
|
|
14
|
+
};
|
|
15
|
+
collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>;
|
|
16
|
+
vars?: Record<string, unknown>;
|
|
17
|
+
reader?: import("./compiler/reader.js").Reader;
|
|
18
|
+
}): CompiledPage;
|
|
19
|
+
/**
|
|
20
|
+
* Compile a source file into its body HTML, frontmatter, and assets (no page
|
|
21
|
+
* shell), reading from the real filesystem by default.
|
|
22
|
+
* @param {string} file Absolute path to the source file.
|
|
23
|
+
* @param {import("./config.js").Paths} context Resolved project paths.
|
|
24
|
+
* @param {string[]} [stack] Include stack for cycle detection.
|
|
25
|
+
* @param {Record<string, unknown>} [vars] Initial static scope variables.
|
|
26
|
+
* @param {Map<string, import("./compiler/collections.js").CollectionRow[]>} [collections]
|
|
27
|
+
* @param {import("./compiler/reader.js").Reader} [reader] Source reader.
|
|
28
|
+
* @returns {CompiledDocument}
|
|
29
|
+
*/
|
|
30
|
+
export function compileDocument(file: string, context: import("./config.js").Paths, stack?: string[], vars?: Record<string, unknown>, collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>, reader?: import("./compiler/reader.js").Reader): CompiledDocument;
|
|
31
|
+
/**
|
|
32
|
+
* Harden every `<img>` in an assembled page body, reading intrinsic dimensions
|
|
33
|
+
* from the real filesystem by default.
|
|
34
|
+
* @param {string} html Assembled page body HTML.
|
|
35
|
+
* @param {import("./config.js").Paths} paths Resolved project paths.
|
|
36
|
+
* @param {import("./compiler/reader.js").Reader} [reader] Source reader for image bytes.
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
export function enhanceImages(html: string, paths: import("./config.js").Paths, reader?: import("./compiler/reader.js").Reader): string;
|
|
40
|
+
export type Meta = import("./compiler/context.js").Meta;
|
|
41
|
+
export type FrontmatterValue = import("./compiler/context.js").FrontmatterValue;
|
|
42
|
+
export type Assets = import("./compiler/context.js").Assets;
|
|
43
|
+
export type Compilation = import("./compiler/context.js").Compilation;
|
|
44
|
+
export type Scope = import("./compiler/context.js").Scope;
|
|
45
|
+
export type Ctx = import("./compiler/context.js").Ctx;
|
|
46
|
+
export type CompiledDocument = import("./compiler/context.js").CompiledDocument;
|
|
47
|
+
export type CompiledPage = import("./compiler/context.js").CompiledPage;
|
|
48
|
+
export { compileFromMemory, escapeHtml, loopKeyOf, parseFrontmatter, stampScope } from "./compiler/index.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved project paths used across the build pipeline.
|
|
3
|
+
* @typedef {object} Paths
|
|
4
|
+
* @property {string} cwd Project working directory.
|
|
5
|
+
* @property {string} routesRoot Absolute path to `site/pages`.
|
|
6
|
+
* @property {string} shelfRoot Absolute path to the include shelf `site/_`.
|
|
7
|
+
* @property {string} distRoot Absolute path to the build output `dist`.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Build the absolute project paths for a given working directory.
|
|
11
|
+
* @param {string} [cwd] Project working directory (defaults to `process.cwd()`).
|
|
12
|
+
* @returns {Paths}
|
|
13
|
+
*/
|
|
14
|
+
export function createPaths(cwd?: string): Paths;
|
|
15
|
+
/**
|
|
16
|
+
* Whether a file or directory name is hidden from routing (starts with `.`, `-`, or `_`).
|
|
17
|
+
* @param {string} name
|
|
18
|
+
* @returns {boolean}
|
|
19
|
+
*/
|
|
20
|
+
export function isHiddenName(name: string): boolean;
|
|
21
|
+
export const routesDir: "site/pages";
|
|
22
|
+
export const shelfDir: "site/_";
|
|
23
|
+
export const distDir: "dist";
|
|
24
|
+
export const pageExtensions: Set<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Resolved project paths used across the build pipeline.
|
|
27
|
+
*/
|
|
28
|
+
export type Paths = {
|
|
29
|
+
/**
|
|
30
|
+
* Project working directory.
|
|
31
|
+
*/
|
|
32
|
+
cwd: string;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute path to `site/pages`.
|
|
35
|
+
*/
|
|
36
|
+
routesRoot: string;
|
|
37
|
+
/**
|
|
38
|
+
* Absolute path to the include shelf `site/_`.
|
|
39
|
+
*/
|
|
40
|
+
shelfRoot: string;
|
|
41
|
+
/**
|
|
42
|
+
* Absolute path to the build output `dist`.
|
|
43
|
+
*/
|
|
44
|
+
distRoot: string;
|
|
45
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize the dev server's rebuilds: at most ONE child build runs at a time.
|
|
3
|
+
* Every build read-modify-writes the dependency map (`dist/.wd-dev-deps.json`),
|
|
4
|
+
* so overlapping children could persist a stale map missing deps a concurrent
|
|
5
|
+
* build just recorded — after which the affected routes silently stop
|
|
6
|
+
* rebuilding. Changes debounce into a batch; changes arriving MID-build
|
|
7
|
+
* accumulate into the next batch (duplicate paths coalesce via the Set, and a
|
|
8
|
+
* `null` — a `src/` change or an unattributable event, forcing a full rebuild —
|
|
9
|
+
* swallows the whole batch into one full build).
|
|
10
|
+
* @param {(changed: string[]) => Promise<void> | void} runBuild Runs one child
|
|
11
|
+
* build over the changed `site/` paths (`[]` = full rebuild). Build failures
|
|
12
|
+
* are its own concern (report + resolve); a rejection still frees the queue.
|
|
13
|
+
* @param {number} [debounceMs] Debounce window for batching change events.
|
|
14
|
+
* @returns {{ change: (path: string | null) => void, close: () => void }}
|
|
15
|
+
*/
|
|
16
|
+
export function createRebuildQueue(runBuild: (changed: string[]) => Promise<void> | void, debounceMs?: number): {
|
|
17
|
+
change: (path: string | null) => void;
|
|
18
|
+
close: () => void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Inject the dev-client `<script>` before `</body>` (or append it if absent),
|
|
22
|
+
* plus — for a `draft: true` page — an inline draft-banner script. Both are
|
|
23
|
+
* injected at dev-SERVE time only, so neither ever touches the shipped HTML on
|
|
24
|
+
* disk (a production build excludes drafts entirely; a `build --drafts` staging
|
|
25
|
+
* build emits clean HTML with no banner).
|
|
26
|
+
* @param {string} html Page HTML to augment.
|
|
27
|
+
* @param {{ draft?: boolean }} [options] `draft: true` adds the visible banner.
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
export function injectDevClient(html: string, options?: {
|
|
31
|
+
draft?: boolean;
|
|
32
|
+
}): string;
|
|
33
|
+
/**
|
|
34
|
+
* The inline dev-only draft banner: a fixed bar marking the page as an unpublished
|
|
35
|
+
* draft, so it's unmistakable in `darkmown dev` that this content is excluded from
|
|
36
|
+
* a production build. Inert (`pointer-events:none`) and high-z so it never blocks
|
|
37
|
+
* the page; dev-serve-injected, so it's never in shipped output.
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
40
|
+
export function draftBannerScript(): string;
|
|
41
|
+
/**
|
|
42
|
+
* The page the dev server serves for a route with no dist output while the last
|
|
43
|
+
* build is FAILED — the honest alternative to the production 404 copy, which
|
|
44
|
+
* would claim the route "is hidden or has not been created" when the real cause
|
|
45
|
+
* is a compile error. The message renders inline (works without JS) and the
|
|
46
|
+
* injected dev client replays the `builderror` overlay on connect, then reloads
|
|
47
|
+
* the real page on the next successful build.
|
|
48
|
+
* @param {string} message The recorded build failure.
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
export function buildFailedPage(message: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* The dev-client browser script that opens the SSE channel for live reload.
|
|
54
|
+
* @returns {string}
|
|
55
|
+
*/
|
|
56
|
+
export function devClientScript(): string;
|
|
57
|
+
export const devClientPath: "/__wd/dev-client.js";
|
|
58
|
+
export const devEventsPath: "/__wd/dev-events";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The full error-code registry, in code order. Each entry carries the stable
|
|
3
|
+
* code, its subsystem, a short title, what causes it, and how to fix it.
|
|
4
|
+
* @returns {ErrorEntry[]}
|
|
5
|
+
*/
|
|
6
|
+
export function errorCatalog(): ErrorEntry[];
|
|
7
|
+
/**
|
|
8
|
+
* Look up one code, or undefined when it is not registered.
|
|
9
|
+
* @param {string} code
|
|
10
|
+
* @returns {ErrorEntry | undefined}
|
|
11
|
+
*/
|
|
12
|
+
export function errorForCode(code: string): ErrorEntry | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Render `docs/errors.md` from the registry. Generated, never hand-edited, so
|
|
15
|
+
* the reference page cannot drift from the codes the compiler actually throws
|
|
16
|
+
* (`scripts/gen-errors.mjs` writes it; tests/error-codes.test.js re-checks it).
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
export function errorsMarkdown(): string;
|
|
20
|
+
/**
|
|
21
|
+
* One subsystem block of the numbering scheme.
|
|
22
|
+
* @typedef {object} ErrorArea
|
|
23
|
+
* @property {number} block The hundreds digit (0-9).
|
|
24
|
+
* @property {string} range Human label for the block, e.g. `WD1xx`.
|
|
25
|
+
* @property {string} name Short machine name, e.g. `loops`.
|
|
26
|
+
* @property {string} title One-line description of what the block covers.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* A registered error code.
|
|
30
|
+
* @typedef {object} ErrorEntry
|
|
31
|
+
* @property {string} code The stable `WDxxx` identifier.
|
|
32
|
+
* @property {string} area The subsystem name (derived from the hundreds digit).
|
|
33
|
+
* @property {string} title Short name for the mistake.
|
|
34
|
+
* @property {string} cause What the author wrote that triggers it.
|
|
35
|
+
* @property {string} fix The corrective action, in one line.
|
|
36
|
+
* @property {string} [example] A concrete, compilable line, sourced from the
|
|
37
|
+
* compiler's own `*_EXAMPLE` constants.
|
|
38
|
+
*/
|
|
39
|
+
/** The subsystem blocks, in code order. */
|
|
40
|
+
/** @type {ErrorArea[]} */
|
|
41
|
+
export const ERROR_AREAS: ErrorArea[];
|
|
42
|
+
/**
|
|
43
|
+
* Codes that were withdrawn. They are NEVER reused: a retired number stays
|
|
44
|
+
* listed here so the next free number in its block is always genuinely free,
|
|
45
|
+
* and so an old error message found in a log or an issue still resolves to a
|
|
46
|
+
* meaningful (if historical) entry. Empty today.
|
|
47
|
+
* @type {string[]}
|
|
48
|
+
*/
|
|
49
|
+
export const RETIRED_CODES: string[];
|
|
50
|
+
/**
|
|
51
|
+
* One subsystem block of the numbering scheme.
|
|
52
|
+
*/
|
|
53
|
+
export type ErrorArea = {
|
|
54
|
+
/**
|
|
55
|
+
* The hundreds digit (0-9).
|
|
56
|
+
*/
|
|
57
|
+
block: number;
|
|
58
|
+
/**
|
|
59
|
+
* Human label for the block, e.g. `WD1xx`.
|
|
60
|
+
*/
|
|
61
|
+
range: string;
|
|
62
|
+
/**
|
|
63
|
+
* Short machine name, e.g. `loops`.
|
|
64
|
+
*/
|
|
65
|
+
name: string;
|
|
66
|
+
/**
|
|
67
|
+
* One-line description of what the block covers.
|
|
68
|
+
*/
|
|
69
|
+
title: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* A registered error code.
|
|
73
|
+
*/
|
|
74
|
+
export type ErrorEntry = {
|
|
75
|
+
/**
|
|
76
|
+
* The stable `WDxxx` identifier.
|
|
77
|
+
*/
|
|
78
|
+
code: string;
|
|
79
|
+
/**
|
|
80
|
+
* The subsystem name (derived from the hundreds digit).
|
|
81
|
+
*/
|
|
82
|
+
area: string;
|
|
83
|
+
/**
|
|
84
|
+
* Short name for the mistake.
|
|
85
|
+
*/
|
|
86
|
+
title: string;
|
|
87
|
+
/**
|
|
88
|
+
* What the author wrote that triggers it.
|
|
89
|
+
*/
|
|
90
|
+
cause: string;
|
|
91
|
+
/**
|
|
92
|
+
* The corrective action, in one line.
|
|
93
|
+
*/
|
|
94
|
+
fix: string;
|
|
95
|
+
/**
|
|
96
|
+
* A concrete, compilable line, sourced from the
|
|
97
|
+
* compiler's own `*_EXAMPLE` constants.
|
|
98
|
+
*/
|
|
99
|
+
example?: string | undefined;
|
|
100
|
+
};
|