@zvndev/darkmown 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +21 -10
- package/CHANGELOG.md +17 -0
- package/README.md +117 -16
- package/docs/spec-alignment.md +10 -0
- package/grammar/wd-directives.gbnf +1 -1
- package/package.json +11 -3
- package/site/pages/benchmarks/index.skin +67 -0
- package/site/pages/benchmarks/index.wd +126 -0
- package/site/pages/docs/index.wd +48 -3
- package/site/pages/index.wd +1 -0
- package/src/builder.js +140 -20
- package/src/catalog.js +13 -4
- package/src/cli.js +11 -1
- package/src/compiler/body.js +30 -1
- package/src/compiler/context.js +19 -1
- package/src/compiler/includes.js +44 -1
- package/src/compiler/markdown.js +35 -12
- package/src/compiler/media.js +25 -0
- package/src/compiler/page.js +25 -4
- package/src/compiler/structure.js +272 -4
- package/src/compiler.js +13 -3
- package/src/errors.js +24 -0
- package/src/font-subset-worker.js +131 -0
- package/src/font-subset.js +457 -0
- package/src/grammar.js +3 -2
- package/src/headers.js +28 -1
- package/src/image-variant-resize.js +71 -0
- package/src/image-variants.js +294 -0
- package/src/statics.js +22 -14
- package/types/builder.d.ts +34 -1
- package/types/catalog.d.ts +3 -2
- package/types/compiler/context.d.ts +41 -0
- package/types/compiler/includes.d.ts +23 -0
- package/types/compiler/page.d.ts +9 -3
- package/types/compiler/structure.d.ts +53 -1
- package/types/compiler.d.ts +5 -2
- package/types/font-subset.d.ts +140 -0
- package/types/headers.d.ts +14 -0
- package/types/image-variants.d.ts +131 -0
|
@@ -24,12 +24,64 @@ export function takeA11yAttrs(rest: string, ctx: Ctx, index: number, what: strin
|
|
|
24
24
|
*/
|
|
25
25
|
export function a11yAttrHtml(attrs: [string, string][]): string;
|
|
26
26
|
/**
|
|
27
|
+
* Compile an `@include` line — inline form (`@include /nav.wd`) or block form
|
|
28
|
+
* (`@include /card.wd … @endinclude`, with `childrenLines` holding the lines
|
|
29
|
+
* between opener and closer, captured by {@link scanIncludeBlock}).
|
|
30
|
+
*
|
|
31
|
+
* Block form is compile-time macro expansion and nothing more: the children
|
|
32
|
+
* lines compile in the CALLER's context (its scope, its `:state`, its loop
|
|
33
|
+
* item when the call sits in a `@loop` body) BEFORE the target compiles, and
|
|
34
|
+
* the resulting HTML rides into the include's scope under
|
|
35
|
+
* {@link INCLUDE_CHILDREN}, where the body parser splices it at each
|
|
36
|
+
* `{ children }` slot line. No runtime marker, no reactivity of its own.
|
|
37
|
+
* Children compile ONCE even when the include places the slot twice, so state
|
|
38
|
+
* a child line declares is declared once in the caller.
|
|
39
|
+
*
|
|
40
|
+
* The include file's own frontmatter may declare `defaults: [name="value" …]`
|
|
41
|
+
* fallback values for `with` arguments (see {@link parseIncludeDefaults}); a
|
|
42
|
+
* caller-provided argument always wins over a default, and an argument with
|
|
43
|
+
* neither keeps the literal-braces behavior.
|
|
27
44
|
* @param {string} line
|
|
28
45
|
* @param {Ctx} ctx
|
|
29
46
|
* @param {number} index 0-based line index for `file:line` errors.
|
|
47
|
+
* @param {string[]} [childrenLines] Lines between `@include` and `@endinclude`
|
|
48
|
+
* for the block form; undefined for the inline form.
|
|
30
49
|
* @returns {string}
|
|
31
50
|
*/
|
|
32
|
-
export function handleInclude(line: string, ctx: Ctx, index: number): string;
|
|
51
|
+
export function handleInclude(line: string, ctx: Ctx, index: number, childrenLines?: string[]): string;
|
|
52
|
+
/**
|
|
53
|
+
* Scan ahead from an `@include` opener for the `@endinclude` that pairs with
|
|
54
|
+
* it. Pairing is nearest-opener-first: a nested `@include` line pushes, an
|
|
55
|
+
* `@endinclude` line pops the most recent unclosed opener, and the first
|
|
56
|
+
* `@endinclude` found with nothing on the stack belongs to THIS opener — so
|
|
57
|
+
* nested blocks pair correctly, and an inline `@include` earlier in the file
|
|
58
|
+
* than a block (the common nav-include-then-card-block page) is unaffected.
|
|
59
|
+
* Fenced code is skipped, exactly as in the other block scanners.
|
|
60
|
+
*
|
|
61
|
+
* Returns null when no closer pairs — the include is the INLINE form, which
|
|
62
|
+
* stays legal (backward compatible): an opener that never pairs is an inline
|
|
63
|
+
* include followed by ordinary prose, and the two are indistinguishable, so
|
|
64
|
+
* there is deliberately no "unclosed block" error.
|
|
65
|
+
* @param {string[]} lines The current body slice.
|
|
66
|
+
* @param {number} start 0-based index of the `@include` opener line.
|
|
67
|
+
* @returns {{ body: string[], end: number } | null} The children lines and the
|
|
68
|
+
* closer's 0-based index, or null for the inline form.
|
|
69
|
+
*/
|
|
70
|
+
export function scanIncludeBlock(lines: string[], start: number): {
|
|
71
|
+
body: string[];
|
|
72
|
+
end: number;
|
|
73
|
+
} | null;
|
|
74
|
+
/**
|
|
75
|
+
* `@endinclude` reached the body dispatcher, meaning no `@include` opener
|
|
76
|
+
* claimed it — the one-closer-too-many case (a typo'd closer, or a nested
|
|
77
|
+
* block attempted inside a children block, where the inner opener already
|
|
78
|
+
* took the closer the author meant for the outer one). Always throws.
|
|
79
|
+
* @param {string} line The offending line, for the message.
|
|
80
|
+
* @param {Ctx} ctx
|
|
81
|
+
* @param {number} index 0-based line index for `file:line`.
|
|
82
|
+
* @returns {never}
|
|
83
|
+
*/
|
|
84
|
+
export function strayEndinclude(line: string, ctx: Ctx, index: number): never;
|
|
33
85
|
/**
|
|
34
86
|
* @param {string} header
|
|
35
87
|
* @param {string[]} bodyLines
|
package/types/compiler.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* a different source (see `compileFromMemory`).
|
|
5
5
|
* @param {string} file Absolute path to the source `.md`/`.wd` file.
|
|
6
6
|
* @param {import("./config.js").Paths} context Resolved project paths.
|
|
7
|
-
* @param {{ feed?: { href: string, title: string }, site?: import("./compiler/page.js").SiteContext, collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>, vars?: Record<string, unknown>, reader?: import("./compiler/reader.js").Reader }} [options]
|
|
7
|
+
* @param {{ feed?: { href: string, title: string }, site?: import("./compiler/page.js").SiteContext, collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>, vars?: Record<string, unknown>, reader?: import("./compiler/reader.js").Reader, imageVariants?: Map<string, number[]> | null }} [options]
|
|
8
8
|
* @returns {CompiledPage}
|
|
9
9
|
*/
|
|
10
10
|
export function compilePage(file: string, context: import("./config.js").Paths, options?: {
|
|
@@ -16,6 +16,7 @@ export function compilePage(file: string, context: import("./config.js").Paths,
|
|
|
16
16
|
collections?: Map<string, import("./compiler/collections.js").CollectionRow[]>;
|
|
17
17
|
vars?: Record<string, unknown>;
|
|
18
18
|
reader?: import("./compiler/reader.js").Reader;
|
|
19
|
+
imageVariants?: Map<string, number[]> | null;
|
|
19
20
|
}): CompiledPage;
|
|
20
21
|
/**
|
|
21
22
|
* Compile a source file into its body HTML, frontmatter, and assets (no page
|
|
@@ -26,9 +27,11 @@ export function compilePage(file: string, context: import("./config.js").Paths,
|
|
|
26
27
|
* @param {Record<string, unknown>} [vars] Initial static scope variables.
|
|
27
28
|
* @param {Map<string, import("./compiler/collections.js").CollectionRow[]>} [collections]
|
|
28
29
|
* @param {import("./compiler/reader.js").Reader} [reader] Source reader.
|
|
30
|
+
* @param {Map<string, number[]> | null} [imageVariants] Builder-generated
|
|
31
|
+
* responsive variants (original's absolute source path → widths).
|
|
29
32
|
* @returns {CompiledDocument}
|
|
30
33
|
*/
|
|
31
|
-
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;
|
|
34
|
+
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, imageVariants?: Map<string, number[]> | null): CompiledDocument;
|
|
32
35
|
/**
|
|
33
36
|
* Harden every `<img>` in an assembled page body, reading intrinsic dimensions
|
|
34
37
|
* from the real filesystem by default.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subset every project-local font referenced by the emitted stylesheets and
|
|
3
|
+
* rewrite the dist CSS to lead with the subset woff2.
|
|
4
|
+
*
|
|
5
|
+
* Skips, none of them errors: remote/protocol-relative/data/relative URLs
|
|
6
|
+
* (silently), already-woff2 sources (silently), URLs that escape or miss the
|
|
7
|
+
* project (silently — a broken link is an authoring bug, not a subsetting one).
|
|
8
|
+
* An unreadable font file, and one the toolchain fails on, get a hint naming
|
|
9
|
+
* the file and ship as-is. With no `@font-face` in any emitted stylesheet the
|
|
10
|
+
* pass is a no-op and never even scans the HTML.
|
|
11
|
+
* @param {Paths} paths
|
|
12
|
+
* @param {{ cacheDir?: string, quiet?: boolean,
|
|
13
|
+
* runJobs?: (payload: { charset: number[], jobs: SubsetJob[] }) => SubsetResult }} [options]
|
|
14
|
+
* `quiet` suppresses the hints (dev-server rebuilds). `runJobs` is the subset
|
|
15
|
+
* seam — the default spawns the worker process; tests inject fakes for the
|
|
16
|
+
* unavailable/failure paths.
|
|
17
|
+
* @returns {FontSubsetPlan}
|
|
18
|
+
*/
|
|
19
|
+
export function subsetFonts(paths: Paths, options?: {
|
|
20
|
+
cacheDir?: string;
|
|
21
|
+
quiet?: boolean;
|
|
22
|
+
runJobs?: (payload: {
|
|
23
|
+
charset: number[];
|
|
24
|
+
jobs: SubsetJob[];
|
|
25
|
+
}) => SubsetResult;
|
|
26
|
+
}): FontSubsetPlan;
|
|
27
|
+
/**
|
|
28
|
+
* The default subset seam: run every pending job in ONE child process (the
|
|
29
|
+
* build is synchronous; the wasm API is not), communicating through temp JSON
|
|
30
|
+
* files rather than stdio so a large payload never hits a pipe buffer. The
|
|
31
|
+
* worker always writes a results file — a missing or unparsable one means the
|
|
32
|
+
* child itself died, which is reported as `unavailable` (the build then behaves
|
|
33
|
+
* as if the toolchain were absent: a hint, no subsets, no failure).
|
|
34
|
+
* @param {{ charset: number[], jobs: SubsetJob[] }} payload
|
|
35
|
+
* @param {(cmd: string, args: string[], opts: object) => unknown} [spawn]
|
|
36
|
+
* Injectable for tests; the real one is `spawnSync`.
|
|
37
|
+
* @returns {SubsetResult}
|
|
38
|
+
*/
|
|
39
|
+
export function runSubsetJobs(payload: {
|
|
40
|
+
charset: number[];
|
|
41
|
+
jobs: SubsetJob[];
|
|
42
|
+
}, spawn?: (cmd: string, args: string[], opts: object) => unknown): SubsetResult;
|
|
43
|
+
/**
|
|
44
|
+
* The subset charset for a build: the base set plus every code point appearing
|
|
45
|
+
* in the given texts (the emitted pages' HTML). Numeric character references
|
|
46
|
+
* (`★`, `★`) are decoded first so a character the compiler emitted
|
|
47
|
+
* as an entity still lands in the union. Tags and attribute syntax contribute
|
|
48
|
+
* only ASCII, which the base set already carries, so the whole-file scan can
|
|
49
|
+
* only ever over-include by a handful of glyphs.
|
|
50
|
+
* @param {string[]} texts
|
|
51
|
+
* @returns {number[]} Sorted ascending, deduped.
|
|
52
|
+
*/
|
|
53
|
+
export function charsetFromTexts(texts: string[]): number[];
|
|
54
|
+
/**
|
|
55
|
+
* Rewrite the `@font-face` blocks of an emitted stylesheet so each subsetted
|
|
56
|
+
* font's `src` leads with the subset woff2, the original kept as fallback:
|
|
57
|
+
* src: url("/f/a-subset.woff2") format("woff2"), url("/f/a.ttf") format("truetype");
|
|
58
|
+
* Only the `src` declaration changes — font-display and every other descriptor
|
|
59
|
+
* pass through byte-identically. Idempotent: a block already carrying the
|
|
60
|
+
* subset reference (a previous build's rewrite of a since-unedited skin) is
|
|
61
|
+
* left alone.
|
|
62
|
+
* @param {string} css Emitted stylesheet contents.
|
|
63
|
+
* @param {Map<string, string>} subsetByUrl url() target as written → subset URL.
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
66
|
+
export function rewriteFontFaceCss(css: string, subsetByUrl: Map<string, string>): string;
|
|
67
|
+
/** The base charset, sorted ascending. */
|
|
68
|
+
export const BASE_CODEPOINTS: number[];
|
|
69
|
+
export type Paths = import("./config.js").Paths;
|
|
70
|
+
/**
|
|
71
|
+
* One subset handed to the worker: reduce `source` to the shared charset and
|
|
72
|
+
* write the woff2 result to `out`, the cache path.
|
|
73
|
+
*/
|
|
74
|
+
export type SubsetJob = {
|
|
75
|
+
/**
|
|
76
|
+
* Absolute path of the original font file.
|
|
77
|
+
*/
|
|
78
|
+
source: string;
|
|
79
|
+
/**
|
|
80
|
+
* Absolute cache path the subset woff2 is written to.
|
|
81
|
+
*/
|
|
82
|
+
out: string;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* What the worker reports back. `unavailable` means the toolchain could not be
|
|
86
|
+
* loaded at all (harfbuzzjs/wawoff2 not installed) — every pending font then
|
|
87
|
+
* ships unsubsetted. `failed` carries one entry per font the toolchain itself
|
|
88
|
+
* rejected (corrupt payload, unsupported format).
|
|
89
|
+
*/
|
|
90
|
+
export type SubsetResult = {
|
|
91
|
+
unavailable: boolean;
|
|
92
|
+
failed: {
|
|
93
|
+
file: string;
|
|
94
|
+
error: string;
|
|
95
|
+
}[];
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The post-pass result, feeding the build summary. `unavailable` marks the
|
|
99
|
+
* toolchain-absent build (which is otherwise identical to not having the
|
|
100
|
+
* feature).
|
|
101
|
+
*/
|
|
102
|
+
export type FontSubsetPlan = {
|
|
103
|
+
/**
|
|
104
|
+
* Fonts freshly subsetted this build.
|
|
105
|
+
*/
|
|
106
|
+
subsetted: number;
|
|
107
|
+
/**
|
|
108
|
+
* Fonts served from the on-disk cache.
|
|
109
|
+
*/
|
|
110
|
+
cached: number;
|
|
111
|
+
/**
|
|
112
|
+
* harfbuzzjs/wawoff2 could not be loaded.
|
|
113
|
+
*/
|
|
114
|
+
unavailable: boolean;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* A project-local font referenced by an emitted `@font-face` rule.
|
|
118
|
+
*/
|
|
119
|
+
export type FontRef = {
|
|
120
|
+
/**
|
|
121
|
+
* The url() target exactly as written in the CSS.
|
|
122
|
+
*/
|
|
123
|
+
url: string;
|
|
124
|
+
/**
|
|
125
|
+
* Absolute path of the font file it resolves to.
|
|
126
|
+
*/
|
|
127
|
+
source: string;
|
|
128
|
+
/**
|
|
129
|
+
* Served URL of the subset (`<stem>-subset.woff2`).
|
|
130
|
+
*/
|
|
131
|
+
subsetUrl: string;
|
|
132
|
+
/**
|
|
133
|
+
* Absolute dist path the subset is written to.
|
|
134
|
+
*/
|
|
135
|
+
subsetDist: string;
|
|
136
|
+
/**
|
|
137
|
+
* Absolute cache path, set once the hashes are known.
|
|
138
|
+
*/
|
|
139
|
+
cacheFile?: string | undefined;
|
|
140
|
+
};
|
package/types/headers.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CSP for one route: its base policy (`REACTIVE_CSP`/`STATIC_CSP`) with the
|
|
3
|
+
* page's `:embed` frame hosts unioned into `frame-src`. The compiler records the
|
|
4
|
+
* FINAL iframe src of every `:embed` (after the YouTube/Vimeo rewrite), so a
|
|
5
|
+
* generic embed — a booking widget, a map — is authorized on exactly the pages
|
|
6
|
+
* that carry it instead of being blocked by the shipped policy. YouTube/Vimeo
|
|
7
|
+
* embeds dedupe against the base list, so a page whose embeds are all covered
|
|
8
|
+
* already produces a byte-identical policy, as does a page with no embeds.
|
|
9
|
+
* @param {boolean} reactive Whether the route ships the reactive runtime.
|
|
10
|
+
* @param {Iterable<string>} [embedHosts] Origins (`https://app.example.com`) or
|
|
11
|
+
* `'self'` for a same-origin embed, collected at compile time.
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
export function routeCsp(reactive: boolean, embedHosts?: Iterable<string>): string;
|
|
1
15
|
/**
|
|
2
16
|
* The full security-header set for one response, including the CSP variant.
|
|
3
17
|
* @param {boolean} reactive Whether the route ships the reactive runtime.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan `site/pages` for raster images and generate `@<width>` variants into
|
|
3
|
+
* `dist`, returning the variant map the compiler wires into srcsets.
|
|
4
|
+
*
|
|
5
|
+
* Skips, none of them errors: `@<width>` variant files themselves (they are
|
|
6
|
+
* output, not sources), hidden-path and symlinked files (mirroring
|
|
7
|
+
* `emitPageAssets`, which would never publish them), images at or under 700px
|
|
8
|
+
* wide (already small), widths at or above the intrinsic size (never
|
|
9
|
+
* upscale), and widths the author already provided (their file wins). An image
|
|
10
|
+
* whose dimensions cannot be read, and one sharp fails on, get a hint naming
|
|
11
|
+
* the file and ship without variants.
|
|
12
|
+
* @param {Paths} paths
|
|
13
|
+
* @param {{ widths?: number[], cacheDir?: string, quiet?: boolean,
|
|
14
|
+
* runJobs?: (jobs: ResizeJob[]) => ResizeResult }} [options]
|
|
15
|
+
* `widths` overrides {@link DEFAULT_VARIANT_WIDTHS}. `quiet` suppresses the
|
|
16
|
+
* hints (dev-server rebuilds, which already printed them at the initial
|
|
17
|
+
* build). `runJobs` is the resize seam — the default spawns the worker
|
|
18
|
+
* process; tests inject fakes for the unavailable/crash paths.
|
|
19
|
+
* @returns {ImageVariantPlan}
|
|
20
|
+
*/
|
|
21
|
+
export function generateImageVariants(paths: Paths, options?: {
|
|
22
|
+
widths?: number[];
|
|
23
|
+
cacheDir?: string;
|
|
24
|
+
quiet?: boolean;
|
|
25
|
+
runJobs?: (jobs: ResizeJob[]) => ResizeResult;
|
|
26
|
+
}): ImageVariantPlan;
|
|
27
|
+
/**
|
|
28
|
+
* The default resize seam: run every pending job in ONE child process (the
|
|
29
|
+
* build is synchronous; sharp is not), communicating through temp JSON files
|
|
30
|
+
* rather than stdio so a large job list never hits a pipe buffer. The worker
|
|
31
|
+
* always writes a results file — a missing or unparsable one means the child
|
|
32
|
+
* itself died, which is reported as `unavailable` (the build then behaves as
|
|
33
|
+
* if sharp were absent: a hint, no variants, no failure).
|
|
34
|
+
* @param {ResizeJob[]} jobs
|
|
35
|
+
* @param {(cmd: string, args: string[], opts: object) => unknown} [spawn]
|
|
36
|
+
* Injectable for tests; the real one is `spawnSync`.
|
|
37
|
+
* @returns {ResizeResult}
|
|
38
|
+
*/
|
|
39
|
+
export function runResizeJobs(jobs: ResizeJob[], spawn?: (cmd: string, args: string[], opts: object) => unknown): ResizeResult;
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {import("./config.js").Paths} Paths
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* One resize handed to the worker: shrink `source` to `width` pixels wide and
|
|
45
|
+
* write it (in its own format) to `out`, the cache path.
|
|
46
|
+
* @typedef {object} ResizeJob
|
|
47
|
+
* @property {string} source Absolute path of the original image.
|
|
48
|
+
* @property {string} out Absolute cache path the resized variant is written to.
|
|
49
|
+
* @property {number} width Target width in pixels (always below the intrinsic).
|
|
50
|
+
* @property {"jpeg" | "png" | "webp"} format Output encoder, from the source extension.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* What the worker reports back. `unavailable` means sharp could not be loaded
|
|
54
|
+
* at all (not installed, or a broken native binding) — every pending image
|
|
55
|
+
* then ships without variants. `failed` carries one entry per image that
|
|
56
|
+
* sharp itself rejected (corrupt payload, unsupported encoding).
|
|
57
|
+
* @typedef {object} ResizeResult
|
|
58
|
+
* @property {boolean} unavailable
|
|
59
|
+
* @property {{ file: string, width: number, error: string }[]} failed
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* The pre-pass result: `variants` is the map the compiler's srcset wiring
|
|
63
|
+
* consults (original's ABSOLUTE source path → sorted widths generated into
|
|
64
|
+
* dist), and the counts feed the build summary. `unavailable` marks the
|
|
65
|
+
* sharp-absent build (which is otherwise identical to not having the feature).
|
|
66
|
+
* @typedef {object} ImageVariantPlan
|
|
67
|
+
* @property {Map<string, number[]>} variants
|
|
68
|
+
* @property {number} generated Variants resized this build.
|
|
69
|
+
* @property {number} cached Variants served from the on-disk cache.
|
|
70
|
+
* @property {boolean} unavailable sharp could not be loaded.
|
|
71
|
+
*/
|
|
72
|
+
/** The widths generated by default, both comfortably under a typical source. */
|
|
73
|
+
export const DEFAULT_VARIANT_WIDTHS: number[];
|
|
74
|
+
export type Paths = import("./config.js").Paths;
|
|
75
|
+
/**
|
|
76
|
+
* One resize handed to the worker: shrink `source` to `width` pixels wide and
|
|
77
|
+
* write it (in its own format) to `out`, the cache path.
|
|
78
|
+
*/
|
|
79
|
+
export type ResizeJob = {
|
|
80
|
+
/**
|
|
81
|
+
* Absolute path of the original image.
|
|
82
|
+
*/
|
|
83
|
+
source: string;
|
|
84
|
+
/**
|
|
85
|
+
* Absolute cache path the resized variant is written to.
|
|
86
|
+
*/
|
|
87
|
+
out: string;
|
|
88
|
+
/**
|
|
89
|
+
* Target width in pixels (always below the intrinsic).
|
|
90
|
+
*/
|
|
91
|
+
width: number;
|
|
92
|
+
/**
|
|
93
|
+
* Output encoder, from the source extension.
|
|
94
|
+
*/
|
|
95
|
+
format: "jpeg" | "png" | "webp";
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* What the worker reports back. `unavailable` means sharp could not be loaded
|
|
99
|
+
* at all (not installed, or a broken native binding) — every pending image
|
|
100
|
+
* then ships without variants. `failed` carries one entry per image that
|
|
101
|
+
* sharp itself rejected (corrupt payload, unsupported encoding).
|
|
102
|
+
*/
|
|
103
|
+
export type ResizeResult = {
|
|
104
|
+
unavailable: boolean;
|
|
105
|
+
failed: {
|
|
106
|
+
file: string;
|
|
107
|
+
width: number;
|
|
108
|
+
error: string;
|
|
109
|
+
}[];
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* The pre-pass result: `variants` is the map the compiler's srcset wiring
|
|
113
|
+
* consults (original's ABSOLUTE source path → sorted widths generated into
|
|
114
|
+
* dist), and the counts feed the build summary. `unavailable` marks the
|
|
115
|
+
* sharp-absent build (which is otherwise identical to not having the feature).
|
|
116
|
+
*/
|
|
117
|
+
export type ImageVariantPlan = {
|
|
118
|
+
variants: Map<string, number[]>;
|
|
119
|
+
/**
|
|
120
|
+
* Variants resized this build.
|
|
121
|
+
*/
|
|
122
|
+
generated: number;
|
|
123
|
+
/**
|
|
124
|
+
* Variants served from the on-disk cache.
|
|
125
|
+
*/
|
|
126
|
+
cached: number;
|
|
127
|
+
/**
|
|
128
|
+
* sharp could not be loaded.
|
|
129
|
+
*/
|
|
130
|
+
unavailable: boolean;
|
|
131
|
+
};
|