@heroiclands/package-build 23.1.1 → 23.2.1
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 +69 -0
- package/bin/content-commands.mjs +68 -149
- package/bin/package-build.mjs +56 -10
- package/ci/check-banners.mjs +42 -6
- package/ci/confirm-npm-version.mjs +135 -0
- package/ci/content-format-reference.mjs +14 -5
- package/config.mjs +1 -0
- package/container.mjs +185 -4
- package/content-config.mjs +333 -210
- package/deploy.mjs +116 -10
- package/docs/api.md +238 -246
- package/docs/authoring/assets.md +11 -5
- package/docs/authoring/frontmatter.md +1 -1
- package/docs/authoring/links-and-markup.md +87 -0
- package/docs/commands.md +138 -99
- package/docs/configuration.md +277 -125
- package/docs/content-format.md +2 -0
- package/docs/diagnostics.md +48 -13
- package/docs/guides/book.md +341 -21
- package/docs/guides/e2e.md +13 -2
- package/docs/guides/icons.md +14 -4
- package/docs/guides/module-project.md +18 -8
- package/docs/guides/release-and-deploy.md +32 -0
- package/docs/guides/site.md +5 -2
- package/docs/project-setup.md +30 -10
- package/docs/reference/format-details.md +373 -170
- package/docs/reference/note-types.md +128 -109
- package/docs/reference/theme-pages.md +31 -6
- package/e2e.mjs +140 -28
- package/engine/actor-compiler.mjs +22 -31
- package/engine/address-charset.mjs +4 -17
- package/engine/address-fields.mjs +1 -1
- package/engine/address-render.mjs +12 -1
- package/engine/address-values.mjs +6 -0
- package/engine/address.mjs +46 -33
- package/engine/art-fields.mjs +30 -5
- package/engine/art-slots.mjs +10 -1
- package/engine/asset-bindings.mjs +12 -1
- package/engine/base-compiler.mjs +34 -65
- package/engine/being-age.mjs +2 -7
- package/engine/being-measurements.mjs +12 -1
- package/engine/calendar-artifacts.mjs +6 -0
- package/engine/calendar-choice.mjs +12 -1
- package/engine/calendar-format.mjs +12 -1
- package/engine/calendar-human.mjs +12 -1
- package/engine/compile-corpus.mjs +3 -1
- package/engine/content-address.mjs +9 -12
- package/engine/content-alerts.mjs +13 -1
- package/engine/content-blocks.mjs +14 -3
- package/engine/content-embeds.mjs +11 -3
- package/engine/content-figures.mjs +9 -0
- package/engine/content-footnotes.mjs +12 -1
- package/engine/content-format-check.mjs +11 -262
- package/engine/content-format.yaml +5 -2
- package/engine/content-images.mjs +3 -0
- package/engine/content-index.mjs +443 -20
- package/engine/content-links.mjs +29 -35
- package/engine/content-lint.mjs +2 -3
- package/engine/content-poetry.mjs +12 -1
- package/engine/content-slug.mjs +2 -14
- package/engine/content-spans.mjs +13 -1
- package/engine/content-tables.mjs +12 -1
- package/engine/culture-choice.mjs +210 -13
- package/engine/data-keys.mjs +19 -16
- package/engine/date-conversion.mjs +12 -1
- package/engine/declaration-check.mjs +9 -0
- package/engine/derived-fields.mjs +6 -7
- package/engine/diagnostics.mjs +34 -4
- package/engine/docs-checks.mjs +9 -0
- package/engine/document-subtypes.mjs +47 -34
- package/engine/event-views.mjs +139 -14
- package/engine/exported-scene.mjs +92 -28
- package/engine/extension-attributes.mjs +12 -1
- package/engine/field-spec.mjs +11 -102
- package/engine/folder-notes.mjs +0 -64
- package/engine/foreign-catalog.mjs +2 -1
- package/engine/format-generated.mjs +9 -0
- package/engine/foundry-entries.mjs +10 -28
- package/engine/frontmatter-lint.mjs +83 -392
- package/engine/frontmatter.mjs +20 -70
- package/engine/generate.mjs +10 -15
- package/engine/heading-attributes.mjs +12 -1
- package/engine/helpers.mjs +41 -102
- package/engine/holdings.mjs +1 -1
- package/engine/homepage.mjs +3 -10
- package/engine/ids.mjs +1 -167
- package/engine/index-records.mjs +6 -4
- package/engine/index.mjs +0 -3
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +13 -14
- package/engine/item-compiler.mjs +4 -10
- package/engine/item-docs.mjs +3 -5
- package/engine/item-registry.mjs +2 -10
- package/engine/journals.mjs +1 -5
- package/engine/literature-notes.mjs +4 -12
- package/engine/macros.mjs +1 -2
- package/engine/map-graphviz.mjs +12 -1
- package/engine/markdown-expressions.mjs +12 -1
- package/engine/markdownlint-run.mjs +567 -0
- package/engine/metadata-index.mjs +42 -12
- package/engine/note-addresses.mjs +143 -35
- package/engine/note-claims.mjs +14 -28
- package/engine/note-dates.mjs +3 -3
- package/engine/note-frontmatter.mjs +6 -0
- package/engine/note-ids.mjs +8 -14
- package/engine/note-package.mjs +8 -25
- package/engine/note-state.mjs +1 -3
- package/engine/note-vocabulary.mjs +148 -84
- package/engine/number-words.mjs +12 -1
- package/engine/pack-config.mjs +15 -25
- package/engine/pack-router.mjs +10 -16
- package/engine/pathnames.mjs +8 -22
- package/engine/pdf-build.mjs +773 -121
- package/engine/pdf-coverage.mjs +188 -0
- package/engine/pdf-index.mjs +54 -7
- package/engine/pdf-pages.mjs +247 -0
- package/engine/pdf-render.mjs +114 -4
- package/engine/pdf-toc.mjs +29 -32
- package/engine/project-init.mjs +46 -6
- package/engine/prose-config.mjs +1 -1
- package/engine/prose-lint.mjs +52 -88
- package/engine/readability-lint.mjs +9 -0
- package/engine/reckoning-markers.mjs +12 -1
- package/engine/reference-targets.mjs +7 -0
- package/engine/runtime-only-fields.mjs +5 -8
- package/engine/scene-levels.mjs +2 -2
- package/engine/scenes.mjs +1 -1
- package/engine/shortcode-references.mjs +7 -0
- package/engine/site-build.mjs +30 -16
- package/engine/site-index.mjs +10 -16
- package/engine/site-preview.mjs +6 -0
- package/engine/site-root.mjs +8 -1
- package/engine/social-tie-terms.mjs +12 -1
- package/engine/social-ties.mjs +3 -0
- package/engine/sql-tables.mjs +56 -20
- package/engine/standing-terms.mjs +11 -1
- package/engine/standings.mjs +11 -27
- package/engine/system-block.mjs +39 -141
- package/engine/system-vocabulary.mjs +6 -0
- package/engine/walk-files.mjs +69 -0
- package/engine/web-wikilinks.mjs +23 -3
- package/engine/wikilink-syntax.mjs +32 -21
- package/engine/wikilinks.mjs +27 -16
- package/githooks/attribution.mjs +8 -0
- package/githooks/commit-message.mjs +9 -0
- package/hm3/actors.mjs +9 -48
- package/hm3/default-item-art.mjs +9 -9
- package/hm3/item-fields.mjs +2 -9
- package/hm3/template-priority.mjs +6 -7
- package/hugo-theme/data/banner-kinds.yaml +78 -0
- package/hugo-theme/data/banners.yaml +2 -3
- package/hugo-theme/layouts/404.html +3 -3
- package/hugo-theme/layouts/partials/banner-url.html +31 -7
- package/hugo-theme/layouts/partials/hero-banner.html +13 -14
- package/hugo-theme/layouts/partials/related.html +1 -1
- package/hugo-theme/layouts/partials/warn-missing-banner.html +1 -1
- package/hugo-theme/static/css/style.css +1 -1
- package/labels.mjs +2 -2
- package/manifest.mjs +11 -4
- package/markdownlint-config.mjs +1 -1
- package/package.json +6 -3
- package/release.mjs +21 -14
- package/sohl/actors.mjs +16 -27
- package/sohl/default-item-art.mjs +3 -3
- package/sohl/document-subtypes.mjs +1 -16
- package/sohl/infobox.mjs +2 -3
- package/sohl/item-builders.mjs +5 -8
- package/sohl/item-fields.mjs +5 -35
- package/sohl/items.mjs +0 -4
- package/sohl/kb-passes.mjs +3 -3
- package/types/container.d.mts +116 -5
- package/types/content-config.d.mts +83 -35
- package/types/deploy.d.mts +42 -6
- package/types/e2e.d.mts +35 -3
- package/types/engine/address-charset.d.mts +4 -17
- package/types/engine/address.d.mts +17 -8
- package/types/engine/art-fields.d.mts +7 -4
- package/types/engine/art-slots.d.mts +6 -0
- package/types/engine/base-compiler.d.mts +15 -17
- package/types/engine/content-address.d.mts +9 -12
- package/types/engine/content-embeds.d.mts +4 -2
- package/types/engine/content-format-check.d.mts +0 -64
- package/types/engine/content-index.d.mts +82 -3
- package/types/engine/content-links.d.mts +2 -4
- package/types/engine/culture-choice.d.mts +51 -8
- package/types/engine/data-keys.d.mts +2 -2
- package/types/engine/derived-fields.d.mts +1 -2
- package/types/engine/diagnostics.d.mts +27 -4
- package/types/engine/document-subtypes.d.mts +12 -31
- package/types/engine/event-views.d.mts +14 -2
- package/types/engine/exported-scene.d.mts +3 -2
- package/types/engine/field-spec.d.mts +13 -122
- package/types/engine/folder-notes.d.mts +0 -39
- package/types/engine/foreign-catalog.d.mts +2 -1
- package/types/engine/foundry-entries.d.mts +4 -5
- package/types/engine/frontmatter-lint.d.mts +2 -2
- package/types/engine/frontmatter.d.mts +19 -45
- package/types/engine/generate.d.mts +1 -1
- package/types/engine/helpers.d.mts +25 -42
- package/types/engine/homepage.d.mts +3 -10
- package/types/engine/ids.d.mts +0 -114
- package/types/engine/index-records.d.mts +6 -4
- package/types/engine/index.d.mts +0 -1
- package/types/engine/infobox-render.d.mts +7 -1
- package/types/engine/infobox.d.mts +3 -2
- package/types/engine/item-docs.d.mts +1 -1
- package/types/engine/item-registry.d.mts +2 -4
- package/types/engine/literature-notes.d.mts +1 -1
- package/types/engine/markdownlint-run.d.mts +40 -0
- package/types/engine/metadata-index.d.mts +9 -1
- package/types/engine/note-addresses.d.mts +27 -2
- package/types/engine/note-claims.d.mts +3 -5
- package/types/engine/note-ids.d.mts +2 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-state.d.mts +1 -3
- package/types/engine/note-vocabulary.d.mts +28 -21
- package/types/engine/pack-config.d.mts +2 -6
- package/types/engine/pack-router.d.mts +4 -4
- package/types/engine/pathnames.d.mts +3 -3
- package/types/engine/pdf-build.d.mts +98 -12
- package/types/engine/pdf-coverage.d.mts +60 -0
- package/types/engine/pdf-index.d.mts +34 -5
- package/types/engine/pdf-pages.d.mts +143 -0
- package/types/engine/pdf-render.d.mts +45 -1
- package/types/engine/pdf-toc.d.mts +12 -14
- package/types/engine/prose-config.d.mts +1 -1
- package/types/engine/prose-lint.d.mts +11 -10
- package/types/engine/runtime-only-fields.d.mts +2 -2
- package/types/engine/site-build.d.mts +9 -5
- package/types/engine/site-index.d.mts +4 -5
- package/types/engine/site-root.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -2
- package/types/engine/standing-terms.d.mts +2 -1
- package/types/engine/standings.d.mts +7 -9
- package/types/engine/system-block.d.mts +10 -44
- package/types/engine/walk-files.d.mts +15 -0
- package/types/engine/wikilink-syntax.d.mts +18 -19
- package/types/hm3/actors.d.mts +1 -2
- package/types/hm3/item-fields.d.mts +2 -4
- package/types/hm3/template-priority.d.mts +6 -7
- package/types/manifest.d.mts +3 -2
- package/types/release.d.mts +8 -7
- package/types/sohl/actors.d.mts +2 -1
- package/types/sohl/document-subtypes.d.mts +1 -2
- package/types/sohl/item-fields.d.mts +3 -7
- package/engine/retired-fields.mjs +0 -631
- package/types/engine/retired-fields.d.mts +0 -354
|
@@ -74,10 +74,16 @@ export function collectHomepages(contentBase: string, ctx: object): {
|
|
|
74
74
|
* @param {import("./related-pages.mjs").Related} [options.related] - The
|
|
75
75
|
* homepage's backlinks and mentions. Absent where nothing connects to it,
|
|
76
76
|
* and when the tree contains only a homepage, where no content link resolves.
|
|
77
|
+
* @param {readonly object[]} [options.records] - The corpus, so a `data.banner`
|
|
78
|
+
* address resolves against the images this package ships.
|
|
79
|
+
* @param {object} [options.foreign] - The dependencies' vendored indexes, so a
|
|
80
|
+
* `data.banner` may name an image a dependency ships.
|
|
77
81
|
* @returns {number} How many pages were written.
|
|
78
82
|
*/
|
|
79
|
-
export function writeHomepages(outRoot: string, pages: readonly object[], config: object, { related }?: {
|
|
83
|
+
export function writeHomepages(outRoot: string, pages: readonly object[], config: object, { related, records, foreign }?: {
|
|
80
84
|
related?: import("./related-pages.mjs").Related | undefined;
|
|
85
|
+
records?: readonly object[] | undefined;
|
|
86
|
+
foreign?: object | undefined;
|
|
81
87
|
}): number;
|
|
82
88
|
/**
|
|
83
89
|
* The integrity gates a site build runs before it writes anything.
|
|
@@ -147,9 +153,7 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
|
|
|
147
153
|
/**
|
|
148
154
|
* The frontmatter a page publishes with.
|
|
149
155
|
*
|
|
150
|
-
* An authored `aliases` is
|
|
151
|
-
* here, which makes this a guard rather than a working path. It is a list of
|
|
152
|
-
* names a reader might call the note. Hugo reads
|
|
156
|
+
* An authored `aliases` is a list of names a reader might call the note. Hugo reads
|
|
153
157
|
* `aliases` as **URL redirects**, so passing them through would publish a
|
|
154
158
|
* redirect stub at each name. They are dropped, and this build emits no
|
|
155
159
|
* redirects of its own.
|
|
@@ -171,7 +175,7 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
|
|
|
171
175
|
* `<base><slug>/`.
|
|
172
176
|
*
|
|
173
177
|
* A content page carries the package the build **derived**. No note
|
|
174
|
-
* declares one
|
|
178
|
+
* declares one, so the note's frontmatter alone
|
|
175
179
|
* would publish a page that does not say which package it belongs to. The
|
|
176
180
|
* emitted page is what a theme reads: `breadcrumbs.html` reads
|
|
177
181
|
* `.Params.package`. Writing the derived value keeps a page
|
|
@@ -104,11 +104,10 @@ export function resolveCrossNoteFigures(target: string, { contentTypes, packages
|
|
|
104
104
|
* the one pass that resolves them.
|
|
105
105
|
* @returns {object} The resolver context.
|
|
106
106
|
*
|
|
107
|
-
* There is deliberately **no `manifestsComplete
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* caller still passing it is ignored rather than obeyed.
|
|
107
|
+
* There is deliberately **no `manifestsComplete`**: an unresolved cross-package
|
|
108
|
+
* address is never softened while a manifest is missing, since the pack
|
|
109
|
+
* compilers and the link checker do not soften it and one authored link must
|
|
110
|
+
* not get two verdicts.
|
|
112
111
|
*/
|
|
113
112
|
export function wikiContext(built: SiteIndex, { src, file, type, errors, foreignIndex, assets, resolved }: {
|
|
114
113
|
src: string;
|
|
@@ -42,7 +42,7 @@ export function indexSite(where: {
|
|
|
42
42
|
* sits there. Left in place it would redirect the prefix root — the homepage —
|
|
43
43
|
* to an address nothing publishes. The same holds for a `pagefind/` left by an
|
|
44
44
|
* earlier build when `search` is off: deployed, it is a working search over
|
|
45
|
-
* pages that may
|
|
45
|
+
* pages that may not exist, so it goes too.
|
|
46
46
|
*
|
|
47
47
|
* `_headers` is written before the index is built, so a failed index leaves
|
|
48
48
|
* the root files as they would be — the failure is the indexer's, reported as
|
|
@@ -98,7 +98,7 @@ export function runSqlQuery(db: object, sql: string): Promise<{
|
|
|
98
98
|
* ships a link that does not resolve. A `_section` alias splits the result into
|
|
99
99
|
* a headed table per distinct value, in the order the rows arrive — so the
|
|
100
100
|
* authored `ORDER BY` decides the section order too, and one query replaces the
|
|
101
|
-
* forty near-identical blocks
|
|
101
|
+
* forty near-identical blocks it would otherwise take.
|
|
102
102
|
*
|
|
103
103
|
* **A result selecting nothing still renders its header and rule.** The finding
|
|
104
104
|
* is the point, not withholding the output: an authored heading with an empty
|
|
@@ -212,6 +212,8 @@ export function generatedSectionsFor(db: object | undefined, records: object[],
|
|
|
212
212
|
* From {@link generatedSectionsFor}.
|
|
213
213
|
* @param {Array<{source: string, markdown: string, frontmatter?: object}>} sources -
|
|
214
214
|
* The bodies to answer, extended in place.
|
|
215
|
+
* @param {Map<string, {body: string, frontmatter: object|null}>} [parsed] -
|
|
216
|
+
* Notes already parsed, keyed by file; a note absent from it is read.
|
|
215
217
|
* @returns {void}
|
|
216
218
|
*/
|
|
217
219
|
export function joinGeneratedSections(generated: {
|
|
@@ -221,6 +223,9 @@ export function joinGeneratedSections(generated: {
|
|
|
221
223
|
source: string;
|
|
222
224
|
markdown: string;
|
|
223
225
|
frontmatter?: object;
|
|
226
|
+
}>, parsed?: Map<string, {
|
|
227
|
+
body: string;
|
|
228
|
+
frontmatter: object | null;
|
|
224
229
|
}>): void;
|
|
225
230
|
/**
|
|
226
231
|
* Record each note's generated sections on its prepared results, where the
|
|
@@ -235,6 +240,17 @@ export function joinGeneratedSections(generated: {
|
|
|
235
240
|
export function attachGeneratedSections(prepared: Map<string, object[]>, generated: {
|
|
236
241
|
sections: Map<string, string>;
|
|
237
242
|
}): void;
|
|
243
|
+
/**
|
|
244
|
+
* Each declared dependency's cached index, as {@link openNotesDatabase} attaches
|
|
245
|
+
* them. Empty where none has been fetched.
|
|
246
|
+
*
|
|
247
|
+
* @param {object} [config] - Resolved configuration, defaulting to ambient.
|
|
248
|
+
* @returns {Promise<Array<{id: string, file: string}>>} The dependencies.
|
|
249
|
+
*/
|
|
250
|
+
export function cachedDependencies(config?: object): Promise<Array<{
|
|
251
|
+
id: string;
|
|
252
|
+
file: string;
|
|
253
|
+
}>>;
|
|
238
254
|
/**
|
|
239
255
|
* Answer every `sql` directive in a content tree.
|
|
240
256
|
*
|
|
@@ -259,6 +275,14 @@ export function attachGeneratedSections(prepared: Map<string, object[]>, generat
|
|
|
259
275
|
* @param {object[]} [opts.records] - Index records the caller already derived.
|
|
260
276
|
* A command that also builds a link index holds them already, and deriving
|
|
261
277
|
* them twice is the duplicated-corpus failure this closes.
|
|
278
|
+
* @param {Map<string, {body: string, frontmatter: object|null}>} [opts.parsed] -
|
|
279
|
+
* The notes {@link module:engine/content-index.indexRecordsFor} parsed for
|
|
280
|
+
* `records`, keyed by file, so no note is parsed twice. A note absent from it
|
|
281
|
+
* is read.
|
|
282
|
+
* @param {object} [opts.database] - An open notes database over `records`, from
|
|
283
|
+
* {@link openNotesDatabase} with this call's `audience` and the declared
|
|
284
|
+
* dependencies from {@link cachedDependencies}. It is queried and left open;
|
|
285
|
+
* absent, one is opened and closed here.
|
|
262
286
|
* @param {"all"|"public"} [opts.audience] - Whether to exclude GM notes.
|
|
263
287
|
* @param {Map<string, object>} [opts.foreignIndex] - The fetched indexes the
|
|
264
288
|
* generated sections take in, where the caller holds them already; absent,
|
|
@@ -267,10 +291,15 @@ export function attachGeneratedSections(prepared: Map<string, object[]>, generat
|
|
|
267
291
|
* carrying `inline` and `pageLists` beside them, or nothing when the tree
|
|
268
292
|
* holds no such directive and no note is given a generated section.
|
|
269
293
|
*/
|
|
270
|
-
export function prepareTreeSqlTables(contentBase: string, { config, skipDirectories, records, audience, foreignIndex }?: {
|
|
294
|
+
export function prepareTreeSqlTables(contentBase: string, { config, skipDirectories, records, parsed, database, audience, foreignIndex }?: {
|
|
271
295
|
config?: object | undefined;
|
|
272
296
|
skipDirectories?: readonly string[] | undefined;
|
|
273
297
|
records?: object[] | undefined;
|
|
298
|
+
parsed?: Map<string, {
|
|
299
|
+
body: string;
|
|
300
|
+
frontmatter: object | null;
|
|
301
|
+
}> | undefined;
|
|
302
|
+
database?: object | undefined;
|
|
274
303
|
audience?: "all" | "public" | undefined;
|
|
275
304
|
foreignIndex?: Map<string, object> | undefined;
|
|
276
305
|
}): Promise<Map<string, object[]> | undefined>;
|
|
@@ -21,7 +21,8 @@ export const STANDING_BODY_TYPES: readonly string[];
|
|
|
21
21
|
*
|
|
22
22
|
* `rank` is the level on the body's own `governance.ranks` ladder, and every
|
|
23
23
|
* membership states one. `office` is a key of its `governance.offices` map, and
|
|
24
|
-
* is stated only where the being holds a post.
|
|
24
|
+
* is stated only where the being holds a post. `societies` names the societies
|
|
25
|
+
* the membership is held in, as a list because a membership can span several.
|
|
25
26
|
*
|
|
26
27
|
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
27
28
|
*/
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The standings a being authored, in one shape whichever shape it wrote.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* none of them asks which it was handed:
|
|
4
|
+
* Two spellings reach here and every reader downstream takes the same entries,
|
|
5
|
+
* so none of them asks which it was handed:
|
|
7
6
|
*
|
|
8
7
|
* - an **{@link AddressEntries}** — the map after the note boundary decoded its
|
|
9
8
|
* keys into typed Addresses, which is the shape every compile sees;
|
|
10
|
-
* - a **plain map**, which is the shape a checker reading raw YAML sees
|
|
11
|
-
* - a **list**, which names bodies and says nothing about standing in them.
|
|
9
|
+
* - a **plain map**, which is the shape a checker reading raw YAML sees.
|
|
12
10
|
*
|
|
13
11
|
* An emptied map arrives from the property editor as `[]` and means what `{}`
|
|
14
12
|
* means — this being authors no membership — so both read as no entries.
|
|
@@ -18,12 +16,12 @@
|
|
|
18
16
|
* Address is what a finding should name.
|
|
19
17
|
*
|
|
20
18
|
* @param {unknown} value - The authored `data.affiliations`.
|
|
21
|
-
* @returns {{form: "absent"|"
|
|
19
|
+
* @returns {{form: "absent"|"map"|"malformed",
|
|
22
20
|
* entries: Array<{body: unknown, sourceKey: string|number, standing: unknown}>}}
|
|
23
21
|
* The form it was written in, and its entries.
|
|
24
22
|
*/
|
|
25
23
|
export function readStandings(value: unknown): {
|
|
26
|
-
form: "absent" | "
|
|
24
|
+
form: "absent" | "map" | "malformed";
|
|
27
25
|
entries: Array<{
|
|
28
26
|
body: unknown;
|
|
29
27
|
sourceKey: string | number;
|
|
@@ -128,7 +126,7 @@ export function standingLead(standing: object, digest?: {
|
|
|
128
126
|
* Five questions, and the last three are what keying the entry by its body
|
|
129
127
|
* buys:
|
|
130
128
|
*
|
|
131
|
-
* 1. the value is a map keyed by Address
|
|
129
|
+
* 1. the value is a map keyed by Address;
|
|
132
130
|
* 2. every key names an affiliation that resolves, once;
|
|
133
131
|
* 3. the entry states a standing at all — what a stated standing holds is the
|
|
134
132
|
* inner-key check's, read from {@link STANDING_FIELDS};
|
|
@@ -136,7 +134,7 @@ export function standingLead(standing: object, digest?: {
|
|
|
136
134
|
* 5. an `office` is a key of that body's `governance.offices`.
|
|
137
135
|
*
|
|
138
136
|
* Both of the last two are read from the named body's own frontmatter as the
|
|
139
|
-
* lint runs, so a
|
|
137
|
+
* lint runs, so a rung or a post that does not exist fails on every being pointing
|
|
140
138
|
* at it rather than on a list somebody has to remember to edit.
|
|
141
139
|
*
|
|
142
140
|
* @param {object} note - The note.
|
|
@@ -95,17 +95,14 @@ export function sharedProperty(fm: object, source: string, defaultValue?: any):
|
|
|
95
95
|
*/
|
|
96
96
|
export function blockProperty(fm: object, block: string, key: string, defaultValue?: any): any;
|
|
97
97
|
/**
|
|
98
|
-
* A system override followed by a shared `data:` value
|
|
99
|
-
* retiring top-level spelling `data:` gathered it off, reporting which one
|
|
98
|
+
* A system override followed by a shared `data:` value, reporting which one
|
|
100
99
|
* answered.
|
|
101
100
|
*
|
|
102
101
|
* {@link module:engine/field-spec.resolveFieldValue}'s counterpart for a
|
|
103
102
|
* universal `data:` key — `pack` and `packFolder`, declared for every note
|
|
104
103
|
* type rather than per type, so neither is a `FieldSpec` that resolver takes.
|
|
105
104
|
* The order is the same shape: a system's own override, then the shared
|
|
106
|
-
* `data:` position
|
|
107
|
-
* `data:` existed. The top-level value stays readable while a tree still on
|
|
108
|
-
* it moves its authored fields.
|
|
105
|
+
* `data:` position.
|
|
109
106
|
*
|
|
110
107
|
* @param {object} fm - The note's frontmatter.
|
|
111
108
|
* @param {string} block - The system block key.
|
|
@@ -132,46 +129,15 @@ export function blockDataProperty(fm: object, block: string, key: string, defaul
|
|
|
132
129
|
/**
|
|
133
130
|
* The key a field is authored at **inside** a system block — step 2.
|
|
134
131
|
*
|
|
135
|
-
* `
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* as it always did.
|
|
139
|
-
*
|
|
140
|
-
* Named and exported rather than spelled inline because three readers ask the
|
|
141
|
-
* question and must agree — the resolver here, the frontmatter lint building
|
|
142
|
-
* the set of keys a block may carry, and the author-facing surfaces naming
|
|
143
|
-
* where a value was written.
|
|
144
|
-
*
|
|
145
|
-
* @param {{name?: string, legacyKey?: string}} field - The declaration.
|
|
146
|
-
* @returns {string|undefined} The in-block key, or `undefined` for a field that
|
|
147
|
-
* is not authored at all.
|
|
148
|
-
*/
|
|
149
|
-
export function legacyKeyOf(field: {
|
|
150
|
-
name?: string;
|
|
151
|
-
legacyKey?: string;
|
|
152
|
-
}): string | undefined;
|
|
153
|
-
/**
|
|
154
|
-
* The bare top-level key a `data:`-sourced field is being swept off — step 3b.
|
|
155
|
-
*
|
|
156
|
-
* The retiring spelling of `data.portrait` is not a second declaration anyone
|
|
157
|
-
* has to write — it is `portrait`, mechanically, and the same holds for every
|
|
158
|
-
* other key the container gathered. Deriving it is what keeps the two spellings
|
|
159
|
-
* of one field from disagreeing the way two declarations would.
|
|
160
|
-
*
|
|
161
|
-
* **Only a `data.` source has one.** `protection.blunt` and `impact.die` are
|
|
162
|
-
* paths into containers a note has always written at the top level; they were
|
|
163
|
-
* never `blunt:` or `die:`, and reading those would invent a position rather
|
|
164
|
-
* than remember one.
|
|
165
|
-
*
|
|
166
|
-
* A field declaring {@link module:engine/field-spec.FieldSpec `topLevelMeans`}
|
|
167
|
-
* has no shared position at all, retiring or otherwise — the resolver checks
|
|
168
|
-
* that before asking.
|
|
132
|
+
* The field's `name`, except that a name which is a path into `data:` has no
|
|
133
|
+
* in-block position. Named and exported because the resolver and the
|
|
134
|
+
* frontmatter lint, which builds the set of keys a block may carry, must agree.
|
|
169
135
|
*
|
|
170
136
|
* @param {{name?: string}} field - The declaration.
|
|
171
|
-
* @returns {string|undefined} The
|
|
172
|
-
*
|
|
137
|
+
* @returns {string|undefined} The in-block key, or `undefined` for a field that
|
|
138
|
+
* is not authored in the block.
|
|
173
139
|
*/
|
|
174
|
-
export function
|
|
140
|
+
export function inBlockKey(field: {
|
|
175
141
|
name?: string;
|
|
176
142
|
}): string | undefined;
|
|
177
143
|
/**
|
|
@@ -198,7 +164,7 @@ export function authoredKey(name: string | undefined): string;
|
|
|
198
164
|
* can distinguish a value an author wrote from one a default supplied, which
|
|
199
165
|
* the value alone never says.
|
|
200
166
|
*
|
|
201
|
-
* @typedef {"system"|"block"|"shared"|"
|
|
167
|
+
* @typedef {"system"|"block"|"shared"|"default"|"value"} FieldSource
|
|
202
168
|
*/
|
|
203
169
|
/**
|
|
204
170
|
* Resolve one declared field against a note, in the declared order.
|
|
@@ -394,4 +360,4 @@ export const SYSTEM_BLOCK_KEYS: ReadonlySet<string>;
|
|
|
394
360
|
* can distinguish a value an author wrote from one a default supplied, which
|
|
395
361
|
* the value alone never says.
|
|
396
362
|
*/
|
|
397
|
-
export type FieldSource = "system" | "block" | "shared" | "
|
|
363
|
+
export type FieldSource = "system" | "block" | "shared" | "default" | "value";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every file under a root, minus the directories nothing should walk.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} root - Absolute path to walk.
|
|
5
|
+
* @param {object} [hooks]
|
|
6
|
+
* @param {(dir: string) => void} [hooks.enter] - Called with each directory
|
|
7
|
+
* before its entries are read.
|
|
8
|
+
* @param {(abs: string, isDirectory: boolean) => boolean} [hooks.skip] -
|
|
9
|
+
* Whether to leave a path out; a skipped directory is not entered.
|
|
10
|
+
* @returns {string[]} Absolute file paths, in directory order.
|
|
11
|
+
*/
|
|
12
|
+
export function walkFiles(root: string, hooks?: {
|
|
13
|
+
enter?: ((dir: string) => void) | undefined;
|
|
14
|
+
skip?: ((abs: string, isDirectory: boolean) => boolean) | undefined;
|
|
15
|
+
}): string[];
|
|
@@ -56,15 +56,10 @@ export function authoredLabel({ display }: {
|
|
|
56
56
|
* the form to write rather than a value to correct: there is no value that
|
|
57
57
|
* makes an unlabelled link resolve.
|
|
58
58
|
*
|
|
59
|
-
* **
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* was fold every note's `name.full` into itself, which forbade two notes of a
|
|
64
|
-
* type from sharing a display name. So the namespace is gone, every
|
|
65
|
-
* link is an address, and an address needs the pipe that says so.
|
|
66
|
-
*
|
|
67
|
-
* The **link part may still be an anchor**: `[[#slug|Text]]` addresses a
|
|
59
|
+
* **A bare link has nothing to mean.** Every link is an address, and an
|
|
60
|
+
* address needs the pipe that says so.
|
|
61
|
+
*
|
|
62
|
+
* The **link part may be an anchor**: `[[#slug|Text]]` addresses a
|
|
68
63
|
* section of the page it is written on. It is the label that is required, not
|
|
69
64
|
* a target.
|
|
70
65
|
*
|
|
@@ -100,13 +95,9 @@ export function isEventAnchor(hit: {
|
|
|
100
95
|
* package publishing it is not a declared dependency — or is one whose index
|
|
101
96
|
* has not been fetched — and the link itself looks identical in every case.
|
|
102
97
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* written yet. That reasoning was a property of the bare form, which is retired;
|
|
107
|
-
* the intent behind it now has a real spelling, a `draft`-tagged note
|
|
108
|
-
* that exists and resolves and renders marked. So an address naming no
|
|
109
|
-
* note is a typo or an omission, both want fixing, and all three builds say so.
|
|
98
|
+
* An address naming no note is a typo or an omission: the intent of a
|
|
99
|
+
* placeholder for a note nobody has written yet is spelled as a `draft`-tagged
|
|
100
|
+
* note that exists, resolves and renders marked. Both want fixing, and all three builds say so.
|
|
110
101
|
*
|
|
111
102
|
* @param {string} target - The address as authored, named in the message.
|
|
112
103
|
* @returns {string} The message, unpunctuated at the end as a finding is.
|
|
@@ -165,17 +156,23 @@ export function ambiguousAddressMessage(target: string, packages?: Iterable<stri
|
|
|
165
156
|
* @param {string} [finding.type] - For `not-an-asset`, the type the address
|
|
166
157
|
* named.
|
|
167
158
|
* @param {string} [finding.stub] - For `stub`, where the stub is.
|
|
159
|
+
* @param {string} [finding.shortcode] - For `shortcode-not-lowercase`, the
|
|
160
|
+
* shortcode as written.
|
|
161
|
+
* @param {string} [finding.declared] - For `shortcode-not-lowercase`, the
|
|
162
|
+
* lowercase spelling, when it is a declared shortcode.
|
|
168
163
|
* @returns {string} The message.
|
|
169
164
|
* @throws {Error} On a reason outside the closed set — a resolver inventing one
|
|
170
165
|
* would otherwise report a link with no explanation at all.
|
|
171
166
|
*/
|
|
172
|
-
export function linkFindingMessage({ reason, target, packages, anchor, type, stub }: {
|
|
167
|
+
export function linkFindingMessage({ reason, target, packages, anchor, type, stub, shortcode, declared, }: {
|
|
173
168
|
reason: string;
|
|
174
169
|
target: string;
|
|
175
170
|
packages?: Iterable<string> | undefined;
|
|
176
171
|
anchor?: string | undefined;
|
|
177
172
|
type?: string | undefined;
|
|
178
173
|
stub?: string | undefined;
|
|
174
|
+
shortcode?: string | undefined;
|
|
175
|
+
declared?: string | undefined;
|
|
179
176
|
}): string;
|
|
180
177
|
/**
|
|
181
178
|
* Whether a parsed link addresses a section of the page it is written on.
|
|
@@ -221,8 +218,8 @@ export function readWikilink(inner: string, context: object): object;
|
|
|
221
218
|
*
|
|
222
219
|
* The one rule about a link's *shape* that both resolvers share also lives here
|
|
223
220
|
* — **a link carries a label** ({@link unlabelledLinkMessage}) — because the
|
|
224
|
-
* two
|
|
225
|
-
* first.
|
|
221
|
+
* two state it through one message and the author reads the same words
|
|
222
|
+
* whichever ran first.
|
|
226
223
|
*
|
|
227
224
|
* For the same reason, so does the **vocabulary of link findings**
|
|
228
225
|
* ({@link LINK_FINDING_REASONS}) and the message each one reports through
|
|
@@ -261,6 +258,8 @@ export const WIKILINK: RegExp;
|
|
|
261
258
|
* - `unlabelled` — no `|`, so the link addresses nothing.
|
|
262
259
|
* - `not-an-address` — labelled, but the target does not parse as an address.
|
|
263
260
|
* - `not-lowercase` — a package, system or type segment carries a capital.
|
|
261
|
+
* - `shortcode-not-lowercase` — the shortcode segment carries a capital. A
|
|
262
|
+
* shortcode is lowercase, and the link is refused rather than lowercased.
|
|
264
263
|
* - `unknown-type` — definitely qualified, but names no type this build knows.
|
|
265
264
|
* - `not-an-asset` — a real address, embedded where only a file can be drawn.
|
|
266
265
|
* - `unresolved` — parses as an address, and nothing publishes it.
|
package/types/hm3/actors.d.mts
CHANGED
|
@@ -10,8 +10,7 @@ export const ACTOR_FIELDS: readonly import("../engine/field-spec.mjs").FieldSpec
|
|
|
10
10
|
/**
|
|
11
11
|
* The two `data:` facts HM3 declares on a `character` and not on a `creature`.
|
|
12
12
|
*
|
|
13
|
-
* Both name
|
|
14
|
-
* {@link ACTOR_FIELDS} does.
|
|
13
|
+
* Both name a shared source in `data:`, which is the only place they are authored.
|
|
15
14
|
*
|
|
16
15
|
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
17
16
|
*/
|
|
@@ -7,10 +7,8 @@
|
|
|
7
7
|
* a registry is addressed by what a note calls itself. What the document is
|
|
8
8
|
* called is the map's answer, and only the map's.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* source the content format's mapping tables state, and `legacyKey` is the key
|
|
13
|
-
* the `hm3:` block still carries.
|
|
10
|
+
* A field whose `name` is a path into `data:` is authored there and nowhere
|
|
11
|
+
* else: `name` is the shared source the content format's mapping tables state.
|
|
14
12
|
*
|
|
15
13
|
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
16
14
|
*/
|
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
* than a `null` nothing reads.
|
|
7
7
|
*
|
|
8
8
|
* **Read through the shared resolver, not a field declaration**. A
|
|
9
|
-
* `FieldSpec`'s shared source is a single position, and this value has
|
|
10
|
-
* `data:`, this block, the top level
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* HM3 flag until it sweeps to `data:`.
|
|
9
|
+
* `FieldSpec`'s shared source is a single position, and this value has three:
|
|
10
|
+
* `data:`, this block, and the top level. The resolver is the single
|
|
11
|
+
* implementation of what a note said, so the two systems cannot disagree about
|
|
12
|
+
* it. It is read against **this** block: the `sohl:` block is not a source for
|
|
13
|
+
* an HM3 document, so a note that states the priority only there writes no HM3
|
|
14
|
+
* flag.
|
|
16
15
|
*
|
|
17
16
|
* @param {object} fm - The note's frontmatter.
|
|
18
17
|
* @param {string} block - This pass's system block.
|
package/types/manifest.d.mts
CHANGED
|
@@ -190,8 +190,9 @@ export function publishedRelationships(relationships: Record<string, unknown>):
|
|
|
190
190
|
* a key Foundry adds later needs no release of this package. The one
|
|
191
191
|
* exception is `descriptionHtml`, folded into the description below rather
|
|
192
192
|
* than surviving under its own name.
|
|
193
|
-
* - **Derived** — the identity, the description, the
|
|
194
|
-
*
|
|
193
|
+
* - **Derived** — the identity, the description, the authors (the top-level
|
|
194
|
+
* `authors` list without its roles), the release addresses, the version, the
|
|
195
|
+
* Foundry and system compatibility ranges, and the pack list.
|
|
195
196
|
* These are refused if also declared (`description` directly; `descriptionHtml`
|
|
196
197
|
* is how it is authored) and the two would disagree with nothing to say so.
|
|
197
198
|
* - **Computed** — namespaced `flags` a repository works out for itself, merged
|
package/types/release.d.mts
CHANGED
|
@@ -19,17 +19,18 @@
|
|
|
19
19
|
* Determines both asset names.
|
|
20
20
|
* @param {string} [opts.metadataDir] - Where the build writes its content
|
|
21
21
|
* index, consulted when the advertised file was not staged.
|
|
22
|
-
* @param {boolean} [opts.pdf] - Whether to build the
|
|
22
|
+
* @param {boolean} [opts.pdf] - Whether to build the books that ship beside the
|
|
23
23
|
* archive. `true` by default; `false` skips the build and reports the skip.
|
|
24
24
|
* @returns {Promise<{zip: string, manifest: string, metadata?: string,
|
|
25
|
-
* schema?: string,
|
|
25
|
+
* schema?: string, pdfs: string[], pdfFindings: object[], pdfSkipped: string|null,
|
|
26
26
|
* bytes: number, version: string}>} The paths written, what the book build
|
|
27
27
|
* found, the archive's size, and the version the manifest declares.
|
|
28
28
|
* `metadata` is absent when the manifest advertises no content index,
|
|
29
|
-
* `schema` is absent when the stage carries no `schema.json`, and `
|
|
30
|
-
*
|
|
31
|
-
* built, and otherwise the reason none was — itself
|
|
32
|
-
* builder could not be loaded
|
|
29
|
+
* `schema` is absent when the stage carries no `schema.json`, and `pdfs` is
|
|
30
|
+
* every book's PDF that was written, in declared order. `pdfSkipped` is
|
|
31
|
+
* `null` when a book was built, and otherwise the reason none was — itself
|
|
32
|
+
* `null` when the book builder could not be loaded or a book failed, which
|
|
33
|
+
* is reported through `pdfFindings`.
|
|
33
34
|
* @throws {Error} When the stage has no manifest — there is nothing to release,
|
|
34
35
|
* and an archive without one installs as nothing.
|
|
35
36
|
*/
|
|
@@ -44,7 +45,7 @@ export function packRelease({ stageDir, outDir, artifact, metadataDir, pdf, }?:
|
|
|
44
45
|
manifest: string;
|
|
45
46
|
metadata?: string;
|
|
46
47
|
schema?: string;
|
|
47
|
-
|
|
48
|
+
pdfs: string[];
|
|
48
49
|
pdfFindings: object[];
|
|
49
50
|
pdfSkipped: string | null;
|
|
50
51
|
bytes: number;
|
package/types/sohl/actors.d.mts
CHANGED
|
@@ -26,7 +26,8 @@ export class Actors extends SystemActorCompiler {
|
|
|
26
26
|
* The body's own compiled item is the model, so a membership carries
|
|
27
27
|
* whatever that body declares — its subtype, its common skills, its
|
|
28
28
|
* standings toward others — and the being adds only what is true of *this*
|
|
29
|
-
* membership: the rung it stands on
|
|
29
|
+
* membership: the rung it stands on, the post it holds, and the society it
|
|
30
|
+
* is held in.
|
|
30
31
|
*
|
|
31
32
|
* A being naming a body that compiles to no item is a finding rather than a
|
|
32
33
|
* silently dropped membership: the note says the being belongs somewhere,
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* becomes.
|
|
4
4
|
*
|
|
5
5
|
* The Item rows are the thirteen types the item registry declares; the one
|
|
6
|
-
* Actor row is `being
|
|
7
|
-
* compiling to the same actor before they were retired. Types this
|
|
6
|
+
* Actor row is `being`. Types this
|
|
8
7
|
* map does not name — `doc`, `macro`, the three map types — compile into
|
|
9
8
|
* documents that carry no system subtype at all, so they have no row and never
|
|
10
9
|
* needed one.
|
|
@@ -6,13 +6,9 @@ export const COMBAT_TECHNIQUE_STRIKE_MODE: import("../engine/field-spec.mjs").Fi
|
|
|
6
6
|
* Every item type's frontmatter vocabulary, in the order the `system` block
|
|
7
7
|
* emits it.
|
|
8
8
|
*
|
|
9
|
-
* **A field whose shared source is a path into `data:`
|
|
10
|
-
* `name` is the source the content format's mapping tables
|
|
11
|
-
* `data.
|
|
12
|
-
* wins while a tree writes it. Naming only the source would move the in-block
|
|
13
|
-
* read to a key spelled `data.seat`, which nothing authors; naming only the key
|
|
14
|
-
* leaves the container the specification points at unread, and the field then
|
|
15
|
-
* compiles its default over an authored value with nothing said.
|
|
9
|
+
* **A field whose shared source is a path into `data:` is authored there and
|
|
10
|
+
* nowhere else.** `name` is the source the content format's mapping tables
|
|
11
|
+
* state — `data.seat`, `data.weight`.
|
|
16
12
|
*
|
|
17
13
|
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
18
14
|
*/
|