@heroiclands/package-build 25.6.3 → 25.7.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/CHANGELOG.md +17 -0
- package/README.md +19 -1
- package/bin/content-commands.mjs +14 -70
- package/bin/package-build.mjs +25 -10
- package/ci/wip-workflows.test.mjs +252 -0
- package/content-config.mjs +40 -12
- package/docs/api.md +237 -48
- package/docs/commands.md +73 -36
- package/docs/configuration.md +92 -48
- package/docs/guides/release-and-deploy.md +26 -14
- package/docs/guides/site.md +29 -6
- package/engine/cdn-publish.mjs +164 -6
- package/engine/content-index.mjs +71 -19
- package/engine/content-spans.mjs +18 -1
- package/engine/content-styles.mjs +85 -0
- package/engine/derived-sections.mjs +4 -3
- package/engine/event-views.mjs +6 -4
- package/engine/helpers.mjs +33 -9
- package/engine/index.mjs +1 -0
- package/engine/note-cache.mjs +1107 -0
- package/engine/note-page.mjs +424 -0
- package/engine/pack-config.mjs +47 -4
- package/engine/pathnames.mjs +22 -7
- package/engine/prepared-only.mjs +32 -0
- package/engine/preview-index.mjs +55 -13
- package/engine/site-build.mjs +34 -448
- package/engine/site-config.mjs +33 -4
- package/engine/site-maps.mjs +16 -24
- package/engine/site-origins.mjs +23 -0
- package/engine/site-page.mjs +648 -0
- package/engine/site-render.mjs +142 -10
- package/engine/site-serve.mjs +1 -1
- package/engine/sql-tables.mjs +12 -3
- package/package.json +6 -1
- package/site-theme/static/css/style.css +14 -0
- package/types/content-config.d.mts +24 -4
- package/types/engine/cdn-publish.d.mts +22 -0
- package/types/engine/content-index.d.mts +36 -2
- package/types/engine/content-styles.d.mts +20 -0
- package/types/engine/derived-sections.d.mts +3 -3
- package/types/engine/event-views.d.mts +4 -3
- package/types/engine/helpers.d.mts +18 -1
- package/types/engine/index.d.mts +1 -0
- package/types/engine/note-cache.d.mts +149 -0
- package/types/engine/note-page.d.mts +92 -0
- package/types/engine/pack-config.d.mts +30 -0
- package/types/engine/prepared-only.d.mts +14 -0
- package/types/engine/preview-index.d.mts +35 -0
- package/types/engine/site-build.d.mts +5 -100
- package/types/engine/site-config.d.mts +3 -2
- package/types/engine/site-maps.d.mts +7 -11
- package/types/engine/site-origins.d.mts +9 -0
- package/types/engine/site-page.d.mts +261 -0
- package/types/engine/site-render.d.mts +20 -1
- package/types/engine/sql-tables.d.mts +8 -4
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A note's frontmatter and body, from its source text.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} source - The note as authored.
|
|
5
|
+
* @param {string} file - Where it is, for a finding.
|
|
6
|
+
* @param {object} ctx - `{ config, contentPackage }`, which decode its
|
|
7
|
+
* addresses.
|
|
8
|
+
* @returns {{fm: object, body: string, bodyLine: number}|null} `null` for text
|
|
9
|
+
* that is not front-mattered markdown.
|
|
10
|
+
* @throws {Error} When an address in its frontmatter cannot be decoded; the
|
|
11
|
+
* error carries `file` and `position`.
|
|
12
|
+
*/
|
|
13
|
+
export function parseNote(source: string, file: string, ctx: object): {
|
|
14
|
+
fm: object;
|
|
15
|
+
body: string;
|
|
16
|
+
bodyLine: number;
|
|
17
|
+
} | null;
|
|
18
|
+
/**
|
|
19
|
+
* The page a note publishes as, or why it publishes none.
|
|
20
|
+
*
|
|
21
|
+
* @param {{fm: object, body: string, bodyLine: number}} note - From {@link parseNote}.
|
|
22
|
+
* @param {object} ctx - `{ file, fileBase, relPath, folder, base, packages,
|
|
23
|
+
* contentPackage, sectionPages, present, dates }`: the note's path, its
|
|
24
|
+
* file name, its path below the content root and its folder's name; the
|
|
25
|
+
* package's site address; the packages the site publishes and the one the
|
|
26
|
+
* note belongs to; the pages `site.sections` names; and the present and
|
|
27
|
+
* reckoning a being's age is computed in.
|
|
28
|
+
* @returns {{page?: object, fmLinks: object[], addressFinding?: object}|null}
|
|
29
|
+
* `null` for a note with no page: a homepage, a stub, a GM note, or one
|
|
30
|
+
* outside the published packages. Otherwise the page, or the finding that
|
|
31
|
+
* says why it has no address, with any wikilink authored in frontmatter.
|
|
32
|
+
*/
|
|
33
|
+
export function contentPage(note: {
|
|
34
|
+
fm: object;
|
|
35
|
+
body: string;
|
|
36
|
+
bodyLine: number;
|
|
37
|
+
}, ctx: object): {
|
|
38
|
+
page?: object;
|
|
39
|
+
fmLinks: object[];
|
|
40
|
+
addressFinding?: object;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* The figure the website sets a drawing in: the SVG inline, so its place names
|
|
44
|
+
* stay links, with no blank line inside it — a blank line would end the HTML
|
|
45
|
+
* block and hand the rest of the drawing to the Markdown renderer.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} svg - The drawing, as {@link module:engine/site-maps.inlineSvg} wrote it.
|
|
48
|
+
* @param {string} alt - What the drawing shows, for a screen reader.
|
|
49
|
+
* @returns {string} One HTML block.
|
|
50
|
+
*/
|
|
51
|
+
export function inlineDrawingFigure(svg: string, alt: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* The frontmatter a page publishes with.
|
|
54
|
+
*
|
|
55
|
+
* A content page carries the package the build **derived**. No note
|
|
56
|
+
* declares one, so the note's frontmatter alone would publish a page that does
|
|
57
|
+
* not say which package it belongs to. Writing the derived value keeps a page
|
|
58
|
+
* self-describing and makes sweeping the field out of a content tree
|
|
59
|
+
* output-preserving for a site as it already is for the packs.
|
|
60
|
+
*
|
|
61
|
+
* **`related` is derived, never authored.** What links to a page is a fact
|
|
62
|
+
* about every other page, known only once the whole tree has resolved — see
|
|
63
|
+
* {@link module:engine/related-pages} — so an authored value is dropped, and
|
|
64
|
+
* {@link module:engine/site-build.renderPages} sets the derived block once it holds the graph.
|
|
65
|
+
*
|
|
66
|
+
* @param {object} page - The page.
|
|
67
|
+
* @param {object} options
|
|
68
|
+
* @param {(data: object, page: object) => void} [options.decorate] - Called
|
|
69
|
+
* with each page's frontmatter, for whatever a consumer's own pass adds.
|
|
70
|
+
* @param {(value: unknown, type: string, accepts?: Iterable<string>) => string|null} [options.artSrc] -
|
|
71
|
+
* Translates an art address into the pathname the website resolver takes, or
|
|
72
|
+
* `null` where nothing answers it.
|
|
73
|
+
* @param {(src: string) => string} [options.webSrc] - Translates an authored
|
|
74
|
+
* pathname into the address the website serves. Every artwork field goes
|
|
75
|
+
* through it, so a page's `img:` and its body images name the same file the
|
|
76
|
+
* same way.
|
|
77
|
+
* @returns {object} The frontmatter.
|
|
78
|
+
*/
|
|
79
|
+
export function pageFrontmatter(page: object, { decorate, webSrc, artSrc }: {
|
|
80
|
+
decorate?: ((data: object, page: object) => void) | undefined;
|
|
81
|
+
artSrc?: ((value: unknown, type: string, accepts?: Iterable<string>) => string | null) | undefined;
|
|
82
|
+
webSrc?: ((src: string) => string) | undefined;
|
|
83
|
+
}): object;
|
|
84
|
+
/**
|
|
85
|
+
* The title a content page publishes under — the note's name.
|
|
86
|
+
*
|
|
87
|
+
* One rule, read by the page's own front matter and by every `related` entry
|
|
88
|
+
* that names the page, so a card lists a page by exactly the title its heading
|
|
89
|
+
* shows.
|
|
90
|
+
*
|
|
91
|
+
* @param {object} page - The page, from {@link module:engine/site-build.collectContentPages}.
|
|
92
|
+
* @returns {string} The title.
|
|
93
|
+
*/
|
|
94
|
+
export function pageTitle(page: object): string;
|
|
95
|
+
/**
|
|
96
|
+
* Rewrite a page's artwork addresses into the URLs the website serves.
|
|
97
|
+
*
|
|
98
|
+
* The slots are read from {@link module:engine/art-fields.ART_SLOTS}, so a slot
|
|
99
|
+
* added to the vocabulary reaches the page without anyone remembering this
|
|
100
|
+
* function exists. Only an authored **string** is touched: `null` is a note
|
|
101
|
+
* naming no art and `""` is one naming none on purpose, and neither is an
|
|
102
|
+
* address to resolve. A slot's declining word (`banner: none`) is emitted as
|
|
103
|
+
* a blank, the value a theme reads as "draw no image".
|
|
104
|
+
*
|
|
105
|
+
* **An address nothing answers is dropped**, not emitted as written. The theme
|
|
106
|
+
* renders nothing where a value is absent — its silent-disappear convention —
|
|
107
|
+
* and a raw address left in place would reach the reader as a broken image
|
|
108
|
+
* source with nothing saying why.
|
|
109
|
+
*
|
|
110
|
+
* @param {object} data - The frontmatter being emitted, rewritten in place.
|
|
111
|
+
* @param {(src: string) => string} webSrc - The website's pathname resolver.
|
|
112
|
+
* @param {(value: unknown, type: string, accepts?: Iterable<string>) => string|null} artSrc -
|
|
113
|
+
* The address resolver, yielding the pathname `webSrc` takes.
|
|
114
|
+
* @returns {void}
|
|
115
|
+
*/
|
|
116
|
+
export function resolveArtFields(data: object, webSrc: (src: string) => string, artSrc: (value: unknown, type: string, accepts?: Iterable<string>) => string | null): void;
|
|
117
|
+
/**
|
|
118
|
+
* @param {unknown} value - Anything.
|
|
119
|
+
* @returns {boolean} Whether it is a mapping a field may be read out of.
|
|
120
|
+
*/
|
|
121
|
+
export function isPlainObject(value: unknown): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Transform one content page.
|
|
124
|
+
*
|
|
125
|
+
* `page` is from {@link contentPage}; the options are what it resolves
|
|
126
|
+
* against: the site `index`, the `foreign` indexes, the consumer's `pass`, the
|
|
127
|
+
* frontmatter `decorate`, the prepared `sqlTables`, the `config`, the asset
|
|
128
|
+
* `artIndex`, other pages' `figuresByAddress`, the `events` index, `drawing`
|
|
129
|
+
* and the marked-text `runs`. The result holds the expanded `markdown`, its
|
|
130
|
+
* `figures`, the page's frontmatter as `data`, the links it `resolved`, and
|
|
131
|
+
* each kind of finding.
|
|
132
|
+
*
|
|
133
|
+
* Reads no file. A drawing a generated **From here** section names is asked
|
|
134
|
+
* of `drawing`, by its file name, for its SVG text, and set inline when it
|
|
135
|
+
* answers.
|
|
136
|
+
*/
|
|
137
|
+
export function renderSitePage(page: any, { index, foreign, pass, decorate, sqlTables, config, artIndex, figuresByAddress, events, drawing, runs, }: {
|
|
138
|
+
index: any;
|
|
139
|
+
foreign: any;
|
|
140
|
+
pass?: {} | undefined;
|
|
141
|
+
decorate: any;
|
|
142
|
+
sqlTables: any;
|
|
143
|
+
config: any;
|
|
144
|
+
artIndex: any;
|
|
145
|
+
figuresByAddress?: Map<any, any> | undefined;
|
|
146
|
+
events: any;
|
|
147
|
+
drawing?: (() => undefined) | undefined;
|
|
148
|
+
runs?: import("./content-scripts.mjs").RunContext | undefined;
|
|
149
|
+
}): {
|
|
150
|
+
page: any;
|
|
151
|
+
markdown: string;
|
|
152
|
+
figures: object[];
|
|
153
|
+
data: object;
|
|
154
|
+
resolved: object[];
|
|
155
|
+
tableErrors: object[];
|
|
156
|
+
expressionErrors: object[];
|
|
157
|
+
secretErrors: {
|
|
158
|
+
file: any;
|
|
159
|
+
line: number;
|
|
160
|
+
column: number;
|
|
161
|
+
message: string;
|
|
162
|
+
}[];
|
|
163
|
+
captionErrors: {
|
|
164
|
+
file: any;
|
|
165
|
+
line: any;
|
|
166
|
+
column: any;
|
|
167
|
+
message: any;
|
|
168
|
+
}[];
|
|
169
|
+
headingErrors: {
|
|
170
|
+
line: number;
|
|
171
|
+
column: number;
|
|
172
|
+
message: string;
|
|
173
|
+
file: any;
|
|
174
|
+
}[];
|
|
175
|
+
footnoteErrors: {
|
|
176
|
+
file: any;
|
|
177
|
+
line: number;
|
|
178
|
+
column: number;
|
|
179
|
+
message: string;
|
|
180
|
+
}[];
|
|
181
|
+
wikiErrors: object[];
|
|
182
|
+
imageErrors: any[];
|
|
183
|
+
embedErrors: {
|
|
184
|
+
file: string;
|
|
185
|
+
line: number;
|
|
186
|
+
column: number | undefined;
|
|
187
|
+
severity: "error";
|
|
188
|
+
message: string;
|
|
189
|
+
}[];
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Resolves `site.pass` to its bundle.
|
|
193
|
+
*
|
|
194
|
+
* @param {string|undefined} name - The configured name.
|
|
195
|
+
* @param {object} options - The configured options, plus `repoRoot`.
|
|
196
|
+
* @returns {{beforeLinks?: Function}} The bundle.
|
|
197
|
+
*/
|
|
198
|
+
export function resolveSitePass(name: string | undefined, options: object): {
|
|
199
|
+
beforeLinks?: Function;
|
|
200
|
+
};
|
|
201
|
+
/** The site frontmatter decoration shared by the site writer and page preview. */
|
|
202
|
+
export function sitePageDecorator(config: any, index: any): (data: any, page: any) => void;
|
|
203
|
+
/**
|
|
204
|
+
* How a site renders a page body from the markdown its build expanded.
|
|
205
|
+
*
|
|
206
|
+
* @param {object} config - The resolved configuration.
|
|
207
|
+
* @returns {(markdown: string, options?: {runs?: object, figures?: object[]}) => string}
|
|
208
|
+
* The body HTML as the site writer receives it.
|
|
209
|
+
*/
|
|
210
|
+
export function siteBodyRenderer(config: object): (markdown: string, options?: {
|
|
211
|
+
runs?: object;
|
|
212
|
+
figures?: object[];
|
|
213
|
+
}) => string;
|
|
214
|
+
/**
|
|
215
|
+
* Each finding of a page render as a diagnostic, kind by kind.
|
|
216
|
+
*
|
|
217
|
+
* @param {object} result - From {@link renderSitePage}, or the site build's
|
|
218
|
+
* gathered result, which carries the same lists.
|
|
219
|
+
* @param {(file: string) => string} rawOf - A note's source text, which
|
|
220
|
+
* locates a link or an image by the literal it was handed.
|
|
221
|
+
* @returns {Array<{file?: string, line?: number, column?: number,
|
|
222
|
+
* severity: string, message: string}>} The diagnostics.
|
|
223
|
+
*/
|
|
224
|
+
export function pageDiagnostics(result: object, rawOf: (file: string) => string): Array<{
|
|
225
|
+
file?: string;
|
|
226
|
+
line?: number;
|
|
227
|
+
column?: number;
|
|
228
|
+
severity: string;
|
|
229
|
+
message: string;
|
|
230
|
+
}>;
|
|
231
|
+
/**
|
|
232
|
+
* A wikilink authored in a note's frontmatter, as a diagnostic.
|
|
233
|
+
*
|
|
234
|
+
* @param {{file: string, link: string, path: string}} finding - From
|
|
235
|
+
* {@link contentPage}'s `fmLinks`.
|
|
236
|
+
* @returns {{file: string, severity: "error", message: string}} The diagnostic.
|
|
237
|
+
*/
|
|
238
|
+
export function frontmatterLinkDiagnostic(finding: {
|
|
239
|
+
file: string;
|
|
240
|
+
link: string;
|
|
241
|
+
path: string;
|
|
242
|
+
}): {
|
|
243
|
+
file: string;
|
|
244
|
+
severity: "error";
|
|
245
|
+
message: string;
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* A note whose page has no address, as a diagnostic.
|
|
249
|
+
*
|
|
250
|
+
* @param {{file: string, reason: string}} finding - From {@link contentPage}'s
|
|
251
|
+
* `addressFinding`.
|
|
252
|
+
* @returns {{file: string, severity: "error", message: string}} The diagnostic.
|
|
253
|
+
*/
|
|
254
|
+
export function addressDiagnostic(finding: {
|
|
255
|
+
file: string;
|
|
256
|
+
reason: string;
|
|
257
|
+
}): {
|
|
258
|
+
file: string;
|
|
259
|
+
severity: "error";
|
|
260
|
+
message: string;
|
|
261
|
+
};
|
|
@@ -155,7 +155,13 @@ export function deliverSiteFonts(config: object, out: string): {
|
|
|
155
155
|
* What the build found, and, when it found nothing that stops it, what was
|
|
156
156
|
* written, the pages it was written from and how a note rendered again
|
|
157
157
|
* becomes its page. `written` is `null` when a gate fired.
|
|
158
|
-
*
|
|
158
|
+
* With `site.inputs`, the local default-exported provider receives `{config}`
|
|
159
|
+
* and supplies the navigation plus text artifacts. All artifact paths are checked
|
|
160
|
+
* before replacing output; artifacts are then written after the renderer clears
|
|
161
|
+
* and writes the site, and included in `written.files`.
|
|
162
|
+
*
|
|
163
|
+
* @throws {Error} When the site's settings, cached menu or input provider fail,
|
|
164
|
+
* or a provider artifact is unsafe or collides with builder-owned output.
|
|
159
165
|
*/
|
|
160
166
|
export function buildPackageSite({ config, out, year, progress }: {
|
|
161
167
|
config: object;
|
|
@@ -175,3 +181,16 @@ export function buildPackageSite({ config, out, year, progress }: {
|
|
|
175
181
|
* icon stylesheets, the spoiler script, the icon font and the theme's images.
|
|
176
182
|
*/
|
|
177
183
|
export const SITE_STATIC_DIR: string;
|
|
184
|
+
export type SiteInputs = {
|
|
185
|
+
/**
|
|
186
|
+
* The selected menu.
|
|
187
|
+
*/
|
|
188
|
+
navigation: import("./site-config.mjs").NavigationEntry[];
|
|
189
|
+
/**
|
|
190
|
+
* Text artifacts relative to the site's output.
|
|
191
|
+
*/
|
|
192
|
+
files: Record<string, string>;
|
|
193
|
+
};
|
|
194
|
+
export type SiteInputsProvider = (options: {
|
|
195
|
+
config: import("../content-config.mjs").ContentBuildConfig;
|
|
196
|
+
}) => SiteInputs | Promise<SiteInputs>;
|
|
@@ -214,8 +214,8 @@ export function prepareInlineSqlExpressions(db: any, sources: any): Promise<Map<
|
|
|
214
214
|
* surface publishes to.
|
|
215
215
|
* @param {string} contentBase - Root of the content tree.
|
|
216
216
|
* @param {object} [opts]
|
|
217
|
-
* @param {string} [opts.only] -
|
|
218
|
-
* every note.
|
|
217
|
+
* @param {string|Set<string>} [opts.only] - The note file, or files, to give
|
|
218
|
+
* sections to; absent, every note.
|
|
219
219
|
* @param {Map<string, object>} [opts.foreignIndex] - The fetched indexes, whose
|
|
220
220
|
* places, affiliations and works the lists take in.
|
|
221
221
|
* @param {object} [opts.config] - The resolved configuration.
|
|
@@ -233,7 +233,7 @@ export function prepareInlineSqlExpressions(db: any, sources: any): Promise<Map<
|
|
|
233
233
|
* the derived lists alone.
|
|
234
234
|
*/
|
|
235
235
|
export function generatedSectionsFor(db: object | undefined, records: object[], contentBase: string, { only, foreignIndex, config, derived: given, all, parsed }?: {
|
|
236
|
-
only?: string | undefined;
|
|
236
|
+
only?: string | Set<string> | undefined;
|
|
237
237
|
foreignIndex?: Map<string, object> | undefined;
|
|
238
238
|
config?: object | undefined;
|
|
239
239
|
derived?: Map<string, Map<string, string>> | undefined;
|
|
@@ -351,11 +351,14 @@ export function cachedDependencies(config?: object): Promise<Array<{
|
|
|
351
351
|
* generated sections take in, where the caller holds them already; absent,
|
|
352
352
|
* they are read from the cache.
|
|
353
353
|
* @param {import("./content-session.mjs").ContentSyntax} [opts.syntax] - Exact-text scanner projections.
|
|
354
|
+
* @param {string|Iterable<string>} [opts.only] - One note's file, or several:
|
|
355
|
+
* answer their directives and give them their generated sections, and no
|
|
356
|
+
* other note's. The queries still read the whole corpus.
|
|
354
357
|
* @returns {Promise<Map<string, object[]>|undefined>} Results by note path,
|
|
355
358
|
* carrying `inline` and `pageLists` beside them, or nothing when the tree
|
|
356
359
|
* holds no such directive and no note is given a generated section.
|
|
357
360
|
*/
|
|
358
|
-
export function prepareTreeSqlTables(contentBase: string, { config, skipDirectories, records, parsed, database, audience, foreignIndex, syntax, }?: {
|
|
361
|
+
export function prepareTreeSqlTables(contentBase: string, { config, skipDirectories, records, parsed, database, audience, foreignIndex, syntax, only, }?: {
|
|
359
362
|
config?: object | undefined;
|
|
360
363
|
skipDirectories?: readonly string[] | undefined;
|
|
361
364
|
records?: object[] | undefined;
|
|
@@ -367,6 +370,7 @@ export function prepareTreeSqlTables(contentBase: string, { config, skipDirector
|
|
|
367
370
|
audience?: "all" | "public" | undefined;
|
|
368
371
|
foreignIndex?: Map<string, object> | undefined;
|
|
369
372
|
syntax?: import("./content-session.mjs").ContentSyntax | undefined;
|
|
373
|
+
only?: string | Iterable<string> | undefined;
|
|
370
374
|
}): Promise<Map<string, object[]> | undefined>;
|
|
371
375
|
/**
|
|
372
376
|
* Prepare authored link-check tables in each source note's audience. Public
|