@zvndev/darkmown 2.3.1-next.1.g3a4a8dc → 2.3.1-next.2.ga0699da
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/package.json +1 -1
- package/types/compiler/context.d.ts +74 -60
- package/types/compiler/reader.d.ts +10 -2
- package/types/src/api-runner.d.ts +0 -94
- package/types/src/builder.d.ts +0 -170
- package/types/src/catalog.d.ts +0 -97
- package/types/src/compiler/actions.d.ts +0 -41
- package/types/src/compiler/body.d.ts +0 -11
- package/types/src/compiler/collections.d.ts +0 -76
- package/types/src/compiler/context.d.ts +0 -647
- package/types/src/compiler/directives.d.ts +0 -6
- package/types/src/compiler/expr-ast.d.ts +0 -20
- package/types/src/compiler/fetch.d.ts +0 -29
- package/types/src/compiler/format.d.ts +0 -49
- package/types/src/compiler/forms.d.ts +0 -94
- package/types/src/compiler/frontmatter.d.ts +0 -33
- package/types/src/compiler/fs-reader.d.ts +0 -7
- package/types/src/compiler/image-size.d.ts +0 -14
- package/types/src/compiler/includes.d.ts +0 -100
- package/types/src/compiler/index.d.ts +0 -5
- package/types/src/compiler/interpolation.d.ts +0 -115
- package/types/src/compiler/loops.d.ts +0 -36
- package/types/src/compiler/markdown.d.ts +0 -34
- package/types/src/compiler/media.d.ts +0 -32
- package/types/src/compiler/page.d.ts +0 -109
- package/types/src/compiler/predicates.d.ts +0 -50
- package/types/src/compiler/reader.d.ts +0 -48
- package/types/src/compiler/state.d.ts +0 -68
- package/types/src/compiler/structure.d.ts +0 -56
- package/types/src/compiler.d.ts +0 -48
- package/types/src/config.d.ts +0 -45
- package/types/src/dev.d.ts +0 -58
- package/types/src/errors.d.ts +0 -100
- package/types/src/feeds.d.ts +0 -150
- package/types/src/headers.d.ts +0 -44
- package/types/src/highlight.d.ts +0 -24
- package/types/src/router.d.ts +0 -78
- package/types/src/scaffold.d.ts +0 -20
- package/types/src/skin.d.ts +0 -48
- package/types/src/statics.d.ts +0 -24
package/package.json
CHANGED
|
@@ -1,63 +1,3 @@
|
|
|
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
1
|
/**
|
|
62
2
|
* @typedef {import("../config.js").Paths} Paths
|
|
63
3
|
*/
|
|
@@ -248,6 +188,80 @@ export function nestedCtx<T extends Pick<Ctx, "lineOffset">>(ctx: T, start: numb
|
|
|
248
188
|
* @property {string} target State key (possibly dotted) the action mutates.
|
|
249
189
|
* @property {unknown} [value] Literal value for value-carrying ops.
|
|
250
190
|
*/
|
|
191
|
+
/**
|
|
192
|
+
* Normalize CRLF/CR line endings to LF.
|
|
193
|
+
*
|
|
194
|
+
* Every line-structured parser in the project (frontmatter delimiters, the `.wd`
|
|
195
|
+
* directive dispatcher, `.skin` indentation) tests LF-shaped text. Source files
|
|
196
|
+
* authored on Windows — or checked out anywhere with git's `core.autocrlf`, the
|
|
197
|
+
* default on Windows — arrive CRLF-terminated, and an un-normalized `\r` turns
|
|
198
|
+
* `---` into `---\r` and silently defeats those tests. Applied at the reader
|
|
199
|
+
* boundary and again at the two entry points that accept raw strings from
|
|
200
|
+
* callers that bypass the reader; it is idempotent, so doubling up is free.
|
|
201
|
+
* @param {string} text
|
|
202
|
+
* @returns {string}
|
|
203
|
+
*/
|
|
204
|
+
export function normalizeNewlines(text: string): string;
|
|
205
|
+
/**
|
|
206
|
+
* @param {import("./reader.js").Reader} reader The source reader for this
|
|
207
|
+
* compile (fs-backed by default; in-memory for `compileFromMemory`).
|
|
208
|
+
* @returns {Compilation}
|
|
209
|
+
*/
|
|
210
|
+
export function createCompilation(reader: import("./reader.js").Reader): Compilation;
|
|
211
|
+
/**
|
|
212
|
+
* @param {Scope | null} parent
|
|
213
|
+
* @param {Record<string, unknown>} [vars]
|
|
214
|
+
* @returns {Scope}
|
|
215
|
+
*/
|
|
216
|
+
export function createScope(parent: Scope | null, vars?: Record<string, unknown>): Scope;
|
|
217
|
+
/**
|
|
218
|
+
* Format a source location as `file:line` (1-based) for compile errors. Keeps the
|
|
219
|
+
* file path intact so existing message matchers still pass, while pointing at the
|
|
220
|
+
* directive's (or unclosed opener's) line. `index` is 0-based into the current
|
|
221
|
+
* `compileBody` slice; `ctx.lineOffset` (where that slice starts in the body,
|
|
222
|
+
* accumulated by {@link nestedCtx} as block handlers recurse) and `ctx.bodyLine`
|
|
223
|
+
* (the frontmatter offset) shift it back to the true file line.
|
|
224
|
+
* @param {Pick<Ctx, "file" | "bodyLine" | "lineOffset">} ctx
|
|
225
|
+
* @param {number} index 0-based line index into the current body slice.
|
|
226
|
+
* @returns {string}
|
|
227
|
+
*/
|
|
228
|
+
export function at(ctx: Pick<Ctx, "file" | "bodyLine" | "lineOffset">, index: number): string;
|
|
229
|
+
/**
|
|
230
|
+
* The 1-based true file line for a body-slice `index` — the numeric half of
|
|
231
|
+
* {@link at}, exposed so {@link wdError} can populate the structured `wd.line`.
|
|
232
|
+
* @param {Pick<Ctx, "bodyLine" | "lineOffset">} ctx
|
|
233
|
+
* @param {number} index 0-based line index into the current body slice.
|
|
234
|
+
* @returns {number}
|
|
235
|
+
*/
|
|
236
|
+
export function lineOf(ctx: Pick<Ctx, "bodyLine" | "lineOffset">, index: number): number;
|
|
237
|
+
/**
|
|
238
|
+
* Build a compile `Error` carrying a structured {@link WdErrorInfo} on `err.wd`
|
|
239
|
+
* — so an AI edit-loop (or an editor) gets code/file/line/hint/example without
|
|
240
|
+
* re-parsing the prose. The string message is the caller's text prefixed with
|
|
241
|
+
* the stable `[WDxxx]` code, so a user can search the code straight out of the
|
|
242
|
+
* terminal; everything after the prefix (the `file:line`, the corrective `Use:`
|
|
243
|
+
* template, the concrete `e.g.` example) is unchanged.
|
|
244
|
+
*
|
|
245
|
+
* Every author-facing compile error is built here, so no error can ship without
|
|
246
|
+
* a code. See `src/errors.js` for the registry and the numbering scheme.
|
|
247
|
+
* @param {string} message The user-facing error text, without the code prefix.
|
|
248
|
+
* @param {WdErrorInfo} wd The structured mirror (its `code` becomes the prefix).
|
|
249
|
+
* @returns {Error & { wd: WdErrorInfo }}
|
|
250
|
+
*/
|
|
251
|
+
export function wdError(message: string, wd: WdErrorInfo): Error & {
|
|
252
|
+
wd: WdErrorInfo;
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* The compile context for a nested block body that starts `start` lines into the
|
|
256
|
+
* current slice. The offset accumulates, so errors inside arbitrarily nested
|
|
257
|
+
* blocks (`::: container`, `:form`, `@loop`, `:if`, `:carousel`) still report
|
|
258
|
+
* the true file line through {@link at}.
|
|
259
|
+
* @template {Pick<Ctx, "lineOffset">} T
|
|
260
|
+
* @param {T} ctx
|
|
261
|
+
* @param {number} start 0-based index the nested body starts at in the current slice.
|
|
262
|
+
* @returns {T}
|
|
263
|
+
*/
|
|
264
|
+
export function nestedCtx<T extends Pick<Ctx, "lineOffset">>(ctx: T, start: number): T;
|
|
251
265
|
export const pageIncludeExtensions: string[];
|
|
252
266
|
/** @type {Record<string, string>} */
|
|
253
267
|
export const LOOP_META: Record<string, string>;
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
* ABSOLUTE path (the compiler resolves includes/assets to absolute paths before
|
|
4
4
|
* reading), so a reader only has to map absolute paths to bytes/existence.
|
|
5
5
|
* @typedef {object} Reader
|
|
6
|
-
* @property {(absPath: string) => string} readText Read a UTF-8 text file.
|
|
6
|
+
* @property {(absPath: string) => string} readText Read a UTF-8 text file. The
|
|
7
|
+
* result is ALWAYS LF-normalized: every parser downstream is line-structured
|
|
8
|
+
* and LF-shaped, so a CRLF source (Windows, or any `core.autocrlf` checkout)
|
|
9
|
+
* would otherwise fail to match delimiters like `---`. A custom reader must
|
|
10
|
+
* uphold this.
|
|
7
11
|
* @property {(absPath: string) => Uint8Array} readBinary Read raw bytes (images).
|
|
8
12
|
* @property {(absPath: string) => boolean} exists Whether the path exists.
|
|
9
13
|
* @property {(absPath: string) => string} realpath Canonical path (symlinks
|
|
@@ -29,7 +33,11 @@ export function memoryReader(files: Record<string, string> | Map<string, string>
|
|
|
29
33
|
*/
|
|
30
34
|
export type Reader = {
|
|
31
35
|
/**
|
|
32
|
-
* Read a UTF-8 text file.
|
|
36
|
+
* Read a UTF-8 text file. The
|
|
37
|
+
* result is ALWAYS LF-normalized: every parser downstream is line-structured
|
|
38
|
+
* and LF-shaped, so a CRLF source (Windows, or any `core.autocrlf` checkout)
|
|
39
|
+
* would otherwise fail to match delimiters like `---`. A custom reader must
|
|
40
|
+
* uphold this.
|
|
33
41
|
*/
|
|
34
42
|
readText: (absPath: string) => string;
|
|
35
43
|
/**
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The local-dev serverless API runner. Gives `darkmown dev` the SAME `/api/*`
|
|
3
|
-
* behavior a project gets on Vercel / Cloudflare in production, so a `:fetch
|
|
4
|
-
* /api/x` or a form POST works identically before you ever deploy.
|
|
5
|
-
*
|
|
6
|
-
* The convention is deliberately plain: a backend endpoint is a plain-JS file
|
|
7
|
-
* under the project's top-level `api/` directory that default-exports a
|
|
8
|
-
* Web-standard handler `(request: Request, context) => Response | Promise<Response>`.
|
|
9
|
-
* That is the exact signature Vercel Edge, Cloudflare Pages, Netlify Edge and
|
|
10
|
-
* Deno already run — Darkmown owns no server, it just emulates the host locally.
|
|
11
|
-
*
|
|
12
|
-
* File → route, rooted at the `/api` URL prefix (matching Vercel's `api/`):
|
|
13
|
-
* api/echo.js → /api/echo
|
|
14
|
-
* api/users/index.js → /api/users
|
|
15
|
-
* api/users/list.js → /api/users/list
|
|
16
|
-
* api/users/[id].js → /api/users/:id (context.params.id)
|
|
17
|
-
*
|
|
18
|
-
* Nothing here mutates module state: routes are discovered per call so a newly
|
|
19
|
-
* added function is picked up without a restart, and each handler is imported
|
|
20
|
-
* with an mtime cache-buster so edits hot-reload.
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* A discovered API route.
|
|
24
|
-
* @typedef {object} ApiRoute
|
|
25
|
-
* @property {string} file Absolute path to the handler module.
|
|
26
|
-
* @property {string[]} segments Route segments after `/api`; a dynamic segment
|
|
27
|
-
* is stored as `[name]` (e.g. `["users", "[id]"]`).
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* Walk `apiDir` and return every `.js`/`.mjs` handler as an {@link ApiRoute}.
|
|
31
|
-
* Files/dirs whose name starts with `.`, `_`, or `-` are treated as private
|
|
32
|
-
* (helpers, fixtures) and never routed, matching the router's hidden-path rule.
|
|
33
|
-
* Returns `[]` when `apiDir` does not exist.
|
|
34
|
-
* @param {string} apiDir Absolute path to the project's `api/` directory.
|
|
35
|
-
* @returns {ApiRoute[]}
|
|
36
|
-
*/
|
|
37
|
-
export function discoverApiRoutes(apiDir: string): ApiRoute[];
|
|
38
|
-
/**
|
|
39
|
-
* Match a request pathname against discovered routes. The pathname is expected
|
|
40
|
-
* to start with `/api`; anything else returns `null` (caller serves static).
|
|
41
|
-
* @param {ApiRoute[]} routes
|
|
42
|
-
* @param {string} pathname Request pathname (no query string).
|
|
43
|
-
* @returns {{ file: string, params: Record<string, string> } | null}
|
|
44
|
-
*/
|
|
45
|
-
export function matchApiRoute(routes: ApiRoute[], pathname: string): {
|
|
46
|
-
file: string;
|
|
47
|
-
params: Record<string, string>;
|
|
48
|
-
} | null;
|
|
49
|
-
/**
|
|
50
|
-
* Build a Web-standard `Request` from a Node `IncomingMessage`. The body (for
|
|
51
|
-
* methods that carry one) is buffered fully — dev endpoints are small and this
|
|
52
|
-
* avoids the `duplex: "half"` streaming dance.
|
|
53
|
-
* @param {import("node:http").IncomingMessage} req
|
|
54
|
-
* @returns {Promise<Request>}
|
|
55
|
-
*/
|
|
56
|
-
export function nodeRequestToWeb(req: import("node:http").IncomingMessage): Promise<Request>;
|
|
57
|
-
/**
|
|
58
|
-
* Write a Web-standard `Response` back onto a Node `ServerResponse`.
|
|
59
|
-
* @param {Response} response
|
|
60
|
-
* @param {import("node:http").ServerResponse} res
|
|
61
|
-
* @returns {Promise<void>}
|
|
62
|
-
*/
|
|
63
|
-
export function writeWebResponse(response: Response, res: import("node:http").ServerResponse): Promise<void>;
|
|
64
|
-
/**
|
|
65
|
-
* Handle a request as an API call if its pathname matches a function under
|
|
66
|
-
* `apiDir`. Returns `true` when it owned the request (a route matched, whether
|
|
67
|
-
* the handler succeeded or threw), `false` when nothing matched so the caller
|
|
68
|
-
* should fall through to static serving.
|
|
69
|
-
*
|
|
70
|
-
* @param {object} io
|
|
71
|
-
* @param {string} io.apiDir Absolute path to the project's `api/` directory.
|
|
72
|
-
* @param {import("node:http").IncomingMessage} io.req
|
|
73
|
-
* @param {import("node:http").ServerResponse} io.res
|
|
74
|
-
* @returns {Promise<boolean>}
|
|
75
|
-
*/
|
|
76
|
-
export function handleApiRequest({ apiDir, req, res }: {
|
|
77
|
-
apiDir: string;
|
|
78
|
-
req: import("node:http").IncomingMessage;
|
|
79
|
-
res: import("node:http").ServerResponse;
|
|
80
|
-
}): Promise<boolean>;
|
|
81
|
-
/**
|
|
82
|
-
* A discovered API route.
|
|
83
|
-
*/
|
|
84
|
-
export type ApiRoute = {
|
|
85
|
-
/**
|
|
86
|
-
* Absolute path to the handler module.
|
|
87
|
-
*/
|
|
88
|
-
file: string;
|
|
89
|
-
/**
|
|
90
|
-
* Route segments after `/api`; a dynamic segment
|
|
91
|
-
* is stored as `[name]` (e.g. `["users", "[id]"]`).
|
|
92
|
-
*/
|
|
93
|
-
segments: string[];
|
|
94
|
-
};
|
package/types/src/builder.d.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
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
|
-
};
|
package/types/src/catalog.d.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
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;
|
|
@@ -1,11 +0,0 @@
|
|
|
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;
|
|
@@ -1,76 +0,0 @@
|
|
|
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
|
-
};
|