@heroiclands/package-build 20.3.1 → 20.5.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 +351 -0
- package/CONTENT.md +322 -110
- package/README.md +21 -10
- package/bin/content-build.mjs +204 -92
- package/bin/package-build.mjs +48 -15
- package/config.mjs +6 -8
- package/content-config.mjs +518 -151
- package/docs/api.md +1352 -0
- package/docs/commands.md +1609 -0
- package/docs/configuration.md +1432 -0
- package/docs/content-format.md +73 -74
- package/docs/diagnostics.md +356 -0
- package/docs/getting-started.md +813 -0
- package/docs/project-setup.md +469 -0
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +64 -61
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +57 -52
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +42 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +17 -8
- package/engine/code-fences.mjs +3 -3
- package/engine/compendiums.mjs +8 -8
- package/engine/compile-corpus.mjs +4 -5
- package/engine/content-address.mjs +24 -24
- package/engine/content-charset.mjs +1 -1
- package/engine/content-format-check.mjs +24 -25
- package/engine/content-format.mjs +8 -8
- package/engine/content-html.mjs +202 -0
- package/engine/content-icons.mjs +196 -165
- package/engine/content-index.mjs +61 -40
- package/engine/content-links.mjs +74 -41
- package/engine/content-lint.mjs +64 -34
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +38 -34
- package/engine/content-tree.mjs +1 -1
- package/engine/derived-fields.mjs +174 -0
- package/engine/diagnostics.mjs +3 -4
- package/engine/document-subtypes.mjs +6 -7
- package/engine/field-reference.mjs +8 -8
- package/engine/field-spec.mjs +29 -30
- package/engine/folder-notes.mjs +18 -16
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +95 -103
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +44 -39
- package/engine/helpers.mjs +147 -84
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +26 -10
- package/engine/item-compiler.mjs +54 -29
- package/engine/item-docs.mjs +11 -13
- package/engine/item-registry.mjs +13 -13
- package/engine/journals.mjs +24 -15
- package/engine/macros.mjs +3 -3
- package/engine/map-notes.mjs +6 -6
- package/engine/metadata-index.mjs +5 -5
- package/engine/note-claims.mjs +51 -41
- package/engine/note-ids.mjs +5 -5
- package/engine/note-package.mjs +4 -4
- package/engine/note-renames.mjs +3 -3
- package/engine/note-schemas.mjs +3 -8
- package/engine/note-vocabulary.mjs +56 -54
- package/engine/pack-config.mjs +39 -25
- package/engine/pack-router.mjs +0 -0
- package/engine/pdf-build.mjs +464 -0
- package/engine/pdf-fonts.mjs +420 -0
- package/engine/pdf-render.mjs +798 -0
- package/engine/pdf-toc.mjs +525 -0
- package/engine/prose-config.mjs +9 -9
- package/engine/prose-lint.mjs +12 -13
- package/engine/region-events.mjs +2 -2
- package/engine/retired-fields.mjs +24 -22
- package/engine/runtime-only-fields.mjs +1 -1
- package/engine/scene-levels.mjs +1 -1
- package/engine/scenes.mjs +33 -25
- package/engine/schema-check.mjs +21 -21
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +66 -50
- package/engine/site-index.mjs +17 -18
- package/engine/sql-tables.mjs +21 -13
- package/engine/subtype-registry.mjs +5 -4
- package/engine/system-block.mjs +18 -19
- package/engine/systems.mjs +2 -2
- package/engine/web-wikilinks.mjs +41 -38
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +40 -42
- package/hm3/actors.mjs +30 -22
- package/hm3/document-subtypes.mjs +5 -5
- package/hm3/index.mjs +2 -2
- package/hm3/item-builders.mjs +1 -1
- package/hm3/item-fields.mjs +3 -3
- package/hm3/items.mjs +28 -8
- package/hm3/template-priority.mjs +2 -2
- package/lang.mjs +3 -3
- package/manifest.mjs +17 -20
- package/package.json +1 -2
- package/release.mjs +66 -6
- package/sohl/actors.mjs +36 -28
- package/sohl/affiliation-standings.mjs +2 -2
- package/sohl/being-info.mjs +5 -5
- package/sohl/default-item-art.mjs +5 -5
- package/sohl/document-subtypes.mjs +5 -5
- package/sohl/index.mjs +3 -3
- package/sohl/item-builders.mjs +7 -7
- package/sohl/item-fields.mjs +8 -9
- package/sohl/items.mjs +28 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +12 -12
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +91 -39
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +45 -40
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +60 -6
- package/types/engine/base-compiler.d.mts +27 -21
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +10 -1
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/compendiums.d.mts +3 -3
- package/types/engine/compile-corpus.d.mts +1 -1
- package/types/engine/content-address.d.mts +20 -20
- package/types/engine/content-format-check.d.mts +6 -6
- package/types/engine/content-format.d.mts +2 -2
- package/types/engine/content-html.d.mts +78 -0
- package/types/engine/content-icons.d.mts +139 -92
- package/types/engine/content-index.d.mts +59 -15
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +8 -6
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/content-tables.d.mts +49 -18
- package/types/engine/derived-fields.d.mts +101 -0
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/document-subtypes.d.mts +3 -3
- package/types/engine/field-spec.d.mts +37 -39
- package/types/engine/folder-notes.d.mts +4 -5
- package/types/engine/foreign-catalog.d.mts +3 -3
- package/types/engine/foundry-entries.d.mts +6 -7
- package/types/engine/frontmatter-lint.d.mts +10 -9
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +128 -56
- package/types/engine/homepage.d.mts +16 -18
- package/types/engine/ids.d.mts +13 -13
- package/types/engine/index-records.d.mts +3 -3
- package/types/engine/index.d.mts +6 -0
- package/types/engine/item-compiler.d.mts +21 -5
- package/types/engine/item-docs.d.mts +2 -2
- package/types/engine/item-registry.d.mts +6 -6
- package/types/engine/journals.d.mts +12 -3
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/metadata-index.d.mts +4 -4
- package/types/engine/note-claims.d.mts +30 -22
- package/types/engine/note-ids.d.mts +4 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-renames.d.mts +3 -3
- package/types/engine/note-vocabulary.d.mts +31 -203
- package/types/engine/pack-config.d.mts +7 -7
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/pdf-build.d.mts +42 -0
- package/types/engine/pdf-fonts.d.mts +30 -0
- package/types/engine/pdf-render.d.mts +144 -0
- package/types/engine/pdf-toc.d.mts +114 -0
- package/types/engine/prose-config.d.mts +9 -9
- package/types/engine/prose-lint.d.mts +3 -4
- package/types/engine/region-events.d.mts +2 -2
- package/types/engine/retired-fields.d.mts +10 -9
- package/types/engine/scenes.d.mts +10 -1
- package/types/engine/schema-check.d.mts +13 -13
- package/types/engine/site-build.d.mts +52 -25
- package/types/engine/site-index.d.mts +3 -4
- package/types/engine/sql-tables.d.mts +11 -5
- package/types/engine/subtype-registry.d.mts +3 -3
- package/types/engine/system-block.d.mts +3 -3
- package/types/engine/web-wikilinks.d.mts +7 -7
- package/types/engine/wikilink-syntax.d.mts +17 -17
- package/types/engine/wikilinks.d.mts +14 -14
- package/types/hm3/actors.d.mts +9 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +9 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/release.d.mts +15 -4
- package/types/sohl/actors.d.mts +12 -4
- package/types/sohl/affiliation-standings.d.mts +2 -2
- package/types/sohl/being-info.d.mts +2 -2
- package/types/sohl/document-subtypes.d.mts +1 -1
- package/types/sohl/items.d.mts +9 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
package/sohl/item-fields.mjs
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* This is the authority for what an item note may write, and — because
|
|
18
18
|
* {@link buildFromFields} turns each list into the builder that runs — it is
|
|
19
19
|
* the same authority the compiler obeys. A field that is not here is not
|
|
20
|
-
* emitted; a description here is a description of the thing that executes
|
|
21
|
-
*
|
|
20
|
+
* emitted; a description here is a description of the thing that executes.
|
|
21
|
+
* The per-type authoring reference on the knowledgebase is generated
|
|
22
22
|
* from this file.
|
|
23
23
|
*
|
|
24
24
|
* **SoHL type vocabulary, so it lives in `sohl/`.** `engine/` holds the
|
|
@@ -197,7 +197,7 @@ const STRIKE_MODES = Object.freeze({
|
|
|
197
197
|
* depends on it.
|
|
198
198
|
*
|
|
199
199
|
* Authored `impact.die`, stored `impactBase.die` — the one re-reading field
|
|
200
|
-
* whose two positions are spelled differently, so both are named
|
|
200
|
+
* whose two positions are spelled differently, so both are named.
|
|
201
201
|
*
|
|
202
202
|
* @param {object} fm - The note's frontmatter.
|
|
203
203
|
* @returns {number} The die size, `0` when the projectile declares none.
|
|
@@ -340,8 +340,7 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
340
340
|
},
|
|
341
341
|
{
|
|
342
342
|
// Plural because the field holds a map of many standings, one per
|
|
343
|
-
// affiliation — the singular
|
|
344
|
-
// (SoHL#1781).
|
|
343
|
+
// affiliation — the singular reads as a misnomer.
|
|
345
344
|
name: "relations",
|
|
346
345
|
to: "relations",
|
|
347
346
|
...RELATION,
|
|
@@ -448,7 +447,7 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
448
447
|
describe:
|
|
449
448
|
"What running the course to the end does to the host: `death`, or the benign default `cured`.",
|
|
450
449
|
},
|
|
451
|
-
// The two **authored** thirds of each timed-phase triplet
|
|
450
|
+
// The two **authored** thirds of each timed-phase triplet. Every
|
|
452
451
|
// one omits its key when the note does not carry it, because the value
|
|
453
452
|
// that stands otherwise is the DataModel's `initial: null` — writing a
|
|
454
453
|
// compile-time `null` over it would say "this phase takes no time",
|
|
@@ -513,7 +512,7 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
513
512
|
"The resolution interval in seconds, standing in for a roll of the formula. Omitted when unset.",
|
|
514
513
|
},
|
|
515
514
|
// The `…Date` third of every timed-phase triplet, declared as **runtime
|
|
516
|
-
// state
|
|
515
|
+
// state**. A phase is authored as its `…DurationFormula`; the
|
|
517
516
|
// `…DurationBase` records what that rolled to; the date records *when
|
|
518
517
|
// it happened*, and only play can know that. All four are
|
|
519
518
|
// `worldTimeDateField()`s in SoHL's schema — nullable rather than
|
|
@@ -949,7 +948,7 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
949
948
|
default: null,
|
|
950
949
|
describe: "Shortcode of the body location injured. Unset on a descriptive condition.",
|
|
951
950
|
},
|
|
952
|
-
// A trauma's three timed phases
|
|
951
|
+
// A trauma's three timed phases. Its healing check and course
|
|
953
952
|
// both fall back to a **world setting** when the trauma sets neither
|
|
954
953
|
// half, which is the sharper reason these omit rather than default: a
|
|
955
954
|
// compile-time `null` written here is still a value, and the seeding in
|
|
@@ -1007,7 +1006,7 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
1007
1006
|
describe:
|
|
1008
1007
|
"The course-test interval in seconds, standing in for a roll of the formula. Omitted when unset.",
|
|
1009
1008
|
},
|
|
1010
|
-
// Runtime state, for the reason `affliction`'s four are
|
|
1009
|
+
// Runtime state, for the reason `affliction`'s four are: a
|
|
1011
1010
|
// trauma's dates are crystallized when the phase fires, and world time
|
|
1012
1011
|
// does not exist while content is compiled.
|
|
1013
1012
|
{
|
package/sohl/items.mjs
CHANGED
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
* note, looking its subtype up in the system's map, dispatching to the
|
|
20
20
|
* consumer's registry, merging the authored `sohl.system` block, checking what
|
|
21
21
|
* was emitted against the receiving schema, and writing the envelope. That was
|
|
22
|
-
* all here until a second system needed it
|
|
22
|
+
* all here until a second system needed it, and it reached its
|
|
23
23
|
* system-specific facts through one constant read off SoHL's own map — which is
|
|
24
24
|
* why lifting it cost a subclass rather than a rewrite.
|
|
25
25
|
*
|
|
26
26
|
* What stays:
|
|
27
27
|
*
|
|
28
28
|
* - **The map**, declared in `document-subtypes.mjs` and named here, which
|
|
29
|
-
* decides which notes this pass claims and what each one becomes
|
|
29
|
+
* decides which notes this pass claims and what each one becomes.
|
|
30
30
|
* - **`commonSystem`** — `shortcode`, `templatePriority`, `actionDefs`, `notes` and
|
|
31
31
|
* `docHtml`, which SoHL's compiler writes on every item of every type and no
|
|
32
32
|
* field declaration states.
|
|
@@ -41,16 +41,38 @@ import { systemTemplatePriority } from "../engine/helpers.mjs";
|
|
|
41
41
|
import { SystemItemCompiler } from "../engine/item-compiler.mjs";
|
|
42
42
|
import { SOHL_DOCUMENT_SUBTYPES } from "./document-subtypes.mjs";
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* SoHL's Item compile pass.
|
|
46
|
+
*
|
|
47
|
+
* Declares SoHL's note-type → document-subtype map, which decides the notes
|
|
48
|
+
* this pass claims and what each becomes, and the `system` keys SoHL writes on
|
|
49
|
+
* every item whatever its type. Everything else is
|
|
50
|
+
* {@link module:engine/item-compiler}'s.
|
|
51
|
+
*/
|
|
44
52
|
export class Items extends SystemItemCompiler {
|
|
45
53
|
/**
|
|
46
54
|
* SoHL's note-type → document-subtype map — the one declaration that says
|
|
47
|
-
* which block this pass reads, which notes it claims, and what each becomes
|
|
48
|
-
* (#58/#79).
|
|
55
|
+
* which block this pass reads, which notes it claims, and what each becomes.
|
|
49
56
|
*
|
|
50
57
|
* @type {import("../engine/document-subtypes.mjs").DocumentSubtypeMap}
|
|
51
58
|
*/
|
|
52
59
|
static documentSubtypes = SOHL_DOCUMENT_SUBTYPES;
|
|
53
60
|
|
|
61
|
+
/**
|
|
62
|
+
* The `system` keys this pass derives from the note.
|
|
63
|
+
*
|
|
64
|
+
* `docHtml` holds the `@UUID` of the JournalEntry the note's prose compiled
|
|
65
|
+
* into, so a note writing prose there ships a string where every reader
|
|
66
|
+
* expects a pointer. `notes` is a play-time scratchpad the compiler writes
|
|
67
|
+
* empty, so an authored one ships a note's content as a GM's jottings.
|
|
68
|
+
*
|
|
69
|
+
* @type {readonly {key: string, from: string}[]}
|
|
70
|
+
*/
|
|
71
|
+
static derivedSystemKeys = Object.freeze([
|
|
72
|
+
{ key: "docHtml", from: "the note's own body" },
|
|
73
|
+
{ key: "notes", from: "the note's own body" },
|
|
74
|
+
]);
|
|
75
|
+
|
|
54
76
|
/**
|
|
55
77
|
* The `system.*` fields SoHL writes on every item, whatever its type:
|
|
56
78
|
* shortcode, templatePriority, actionDefs, notes, docHtml.
|
|
@@ -65,8 +87,8 @@ export class Items extends SystemItemCompiler {
|
|
|
65
87
|
return {
|
|
66
88
|
shortcode: fm.shortcode,
|
|
67
89
|
// Required nullable number: a priority, or `null` for a document
|
|
68
|
-
// that is not a template (
|
|
69
|
-
//
|
|
90
|
+
// that is not a template (the archetype contract).
|
|
91
|
+
// `system.archetype` is the legacy spelling; the receiving
|
|
70
92
|
// schema declares only the new name, so the emitted key moves with
|
|
71
93
|
// it — an undeclared `system` key is discarded at construction
|
|
72
94
|
// without a warning.
|
package/sohl/kb-passes.mjs
CHANGED
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The `sohl` knowledgebase's own body passes
|
|
15
|
+
* The `sohl` knowledgebase's own body passes.
|
|
16
16
|
*
|
|
17
17
|
* `content-build site` publishes a content tree as a website, and almost all of
|
|
18
18
|
* that job is the same for every package. These two rewrites are not: they are
|
|
19
19
|
* driven by a TypeDoc symbol map and a repository layout only this package has,
|
|
20
|
-
* and
|
|
20
|
+
* and they are ruled explicitly per-consumer.
|
|
21
21
|
*
|
|
22
22
|
* They live here rather than in a script in the consuming repository for the
|
|
23
23
|
* same reason `sohl/item-builders.mjs` and `sohl/being-info.mjs` do: a
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* broken link or a failed build for a syntax example in prose would not be.
|
|
34
34
|
*
|
|
35
35
|
* Building the bundle is a different matter: a `symbolMap` that is configured
|
|
36
|
-
* and cannot be used fails, loudly, before a page is rendered
|
|
36
|
+
* and cannot be used fails, loudly, before a page is rendered. Degrading
|
|
37
37
|
* a tag the map does not know is a judgement about *prose*; degrading every tag
|
|
38
38
|
* on the site because the map was never read is a build that lied.
|
|
39
39
|
*
|
|
@@ -58,12 +58,12 @@ import log from "loglevel";
|
|
|
58
58
|
* with no symbols: a bare `catch` returned `{}` for all five. Nothing then
|
|
59
59
|
* compares an emitted page against what its source asked for, so the first
|
|
60
60
|
* observer of a broken map was a reader who clicked nothing, because every
|
|
61
|
-
* `{@link}` on the published site had quietly become a code span
|
|
61
|
+
* `{@link}` on the published site had quietly become a code span.
|
|
62
62
|
*
|
|
63
63
|
* The path is resolved against the **repository root**, never the process cwd.
|
|
64
64
|
* `site.passOptions.symbolMap` is authored repo-relative, so a cwd-relative
|
|
65
65
|
* read misses the moment `content-build site` is driven from anywhere but the
|
|
66
|
-
* repository root — which is exactly how
|
|
66
|
+
* repository root — which is exactly how the end-to-end verification, running
|
|
67
67
|
* through `PACKAGE_BUILD_CONFIG` from outside the tree, found this.
|
|
68
68
|
*
|
|
69
69
|
* @param {string|undefined} file - Path to the map, if configured.
|
package/sohl/note-schemas.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* What every SoHL content type may write under `sohl:` — the vocabulary the
|
|
16
|
-
* frontmatter linter checks a note against
|
|
16
|
+
* frontmatter linter checks a note against.
|
|
17
17
|
*
|
|
18
18
|
* **Item types need no declaration here.** {@link ITEM_FIELDS} already is one,
|
|
19
19
|
* and it is the same list the compiler obeys, so an item's schema and its
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* nothing here builds anything, and claiming an emitted path they do not
|
|
27
27
|
* produce would be a lie in the one place a reader would trust it. When one of
|
|
28
28
|
* those compilers becomes declarative, its entry here becomes the builder, the
|
|
29
|
-
* way `ITEM_FIELDS` did
|
|
29
|
+
* way `ITEM_FIELDS` did.
|
|
30
30
|
*
|
|
31
31
|
* **Every consumer loads all of it.** An adventure module authors the full
|
|
32
32
|
* vocabulary — a specific skill, a magic sword, an NPC, a custom beast is the
|
|
@@ -82,11 +82,6 @@ const MACRO_FIELDS = Object.freeze([
|
|
|
82
82
|
},
|
|
83
83
|
]);
|
|
84
84
|
|
|
85
|
-
/**
|
|
86
|
-
* A `being` note — an actor, with its body, movement and embedded items.
|
|
87
|
-
*
|
|
88
|
-
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
89
|
-
*/
|
|
90
85
|
/**
|
|
91
86
|
* A `vehicle` note — a conveyance that carries goods and people.
|
|
92
87
|
*
|
|
@@ -94,7 +89,7 @@ const MACRO_FIELDS = Object.freeze([
|
|
|
94
89
|
* vehicle two `data` properties and no `sohl:` field of its own, and the
|
|
95
90
|
* closed `data:` container is where `engine/note-vocabulary.mjs` holds them.
|
|
96
91
|
* Declaring the type with no fields distinguishes a type with no vocabulary
|
|
97
|
-
* from a type that is unknown, which are different findings
|
|
92
|
+
* from a type that is unknown, which are different findings.
|
|
98
93
|
*
|
|
99
94
|
* It is here rather than in the engine because a vehicle is a SoHL actor —
|
|
100
95
|
* the specification maps it to `sohl` and marks it NA for hm3.
|
|
@@ -103,6 +98,11 @@ const MACRO_FIELDS = Object.freeze([
|
|
|
103
98
|
*/
|
|
104
99
|
const VEHICLE_FIELDS = Object.freeze([]);
|
|
105
100
|
|
|
101
|
+
/**
|
|
102
|
+
* A `being` note — an actor, with its body, movement and embedded items.
|
|
103
|
+
*
|
|
104
|
+
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
105
|
+
*/
|
|
106
106
|
const BEING_FIELDS = Object.freeze([
|
|
107
107
|
{
|
|
108
108
|
name: "body",
|
|
@@ -139,7 +139,7 @@ const BEING_FIELDS = Object.freeze([
|
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* A map note — one type whose `battlemap` / `localmap` / `regionalmap`
|
|
142
|
-
* subType decides the derived canvas
|
|
142
|
+
* subType decides the derived canvas. Compiled into a
|
|
143
143
|
* Foundry Scene.
|
|
144
144
|
*
|
|
145
145
|
* The three differ only in derived canvas defaults, which is the map compiler's
|
|
@@ -148,8 +148,8 @@ const BEING_FIELDS = Object.freeze([
|
|
|
148
148
|
*
|
|
149
149
|
* `img` is the one required field — the compiler refuses a map note without it,
|
|
150
150
|
* since a scene with no background is not a map. It was spelled `image` and
|
|
151
|
-
* read from the `sohl:` block
|
|
152
|
-
* swept; that retirement has since completed and `image` is gone
|
|
151
|
+
* read from the `sohl:` block; both were read while the trees were
|
|
152
|
+
* swept; that retirement has since completed and `image` is gone.
|
|
153
153
|
*
|
|
154
154
|
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
155
155
|
*/
|
|
@@ -332,7 +332,7 @@ const PRESENTATION_FIELDS = Object.freeze({
|
|
|
332
332
|
* one vocabulary rather than two. They are declared there rather than here
|
|
333
333
|
* because they are note-format knowledge — a `homepage` carries no `system`
|
|
334
334
|
* block and would mean the same thing for a game system that is not SoHL — and
|
|
335
|
-
* because a package declaring no `itemBuilders` never reaches this file
|
|
335
|
+
* because a package declaring no `itemBuilders` never reaches this file.
|
|
336
336
|
*
|
|
337
337
|
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
338
338
|
*/
|
package/sohl/skill-base.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Build-time Skill Base evaluation — the small part of SoHL's `SafeExpression`
|
|
16
|
-
* needed to compile a skill's opening mastery level into the pack
|
|
16
|
+
* needed to compile a skill's opening mastery level into the pack.
|
|
17
17
|
*
|
|
18
18
|
* A skill's `skillBaseFormula` is a `SafeExpression` in the `skill.base` scope:
|
|
19
19
|
* an expression over one binding, `attr` (attribute scores by shortcode), with
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this package compiles Foundry documents at all.
|
|
3
|
+
*
|
|
4
|
+
* The one question every Foundry-side reader asks — the manifest writer, to
|
|
5
|
+
* decide whether there is a package for Foundry to install, and the pack
|
|
6
|
+
* compilers, to decide whether there is anything to compile.
|
|
7
|
+
*
|
|
8
|
+
* @param {{packageKind: string}} config - A resolved configuration.
|
|
9
|
+
* @returns {boolean} Whether the package compiles Foundry documents.
|
|
10
|
+
*/
|
|
11
|
+
export function compilesFoundryDocuments(config: {
|
|
12
|
+
packageKind: string;
|
|
13
|
+
}): boolean;
|
|
1
14
|
/**
|
|
2
15
|
* Whether this package publishes the pages its content tree compiles to.
|
|
3
16
|
*
|
|
@@ -30,13 +43,27 @@ export function publishesContentPages(config: {
|
|
|
30
43
|
*/
|
|
31
44
|
export function defineConfig(config: ContentBuildConfigInput): ContentBuildConfig;
|
|
32
45
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
46
|
+
* What kind of package this is.
|
|
47
|
+
*
|
|
48
|
+
* `systems` and `modules` are the two Foundry answers, and the value is also
|
|
49
|
+
* the directory Foundry installs the package under, which is why they are
|
|
50
|
+
* plural. `documentation` is the answer "not a Foundry package at all": it
|
|
51
|
+
* publishes a site and a book from its notes, installs into no Foundry data
|
|
52
|
+
* directory and compiles no compendium.
|
|
36
53
|
*
|
|
37
54
|
* @satisfies {readonly PackageKind[]}
|
|
38
55
|
*/
|
|
39
|
-
export const PACKAGE_KINDS: readonly ["systems", "modules"];
|
|
56
|
+
export const PACKAGE_KINDS: readonly ["systems", "modules", "documentation"];
|
|
57
|
+
/**
|
|
58
|
+
* The kind that compiles no Foundry documents.
|
|
59
|
+
*
|
|
60
|
+
* Spelled once and read wherever a pass asks whether it applies, so the
|
|
61
|
+
* validator, the CLI and the compile passes cannot come to disagree about what
|
|
62
|
+
* the value means.
|
|
63
|
+
*
|
|
64
|
+
* @type {string}
|
|
65
|
+
*/
|
|
66
|
+
export const DOCUMENTATION_KIND: string;
|
|
40
67
|
export namespace DEFAULT_PATHS {
|
|
41
68
|
let content: "assets/content";
|
|
42
69
|
let contentIndex: "build/content-index";
|
|
@@ -49,7 +76,7 @@ export namespace DEFAULT_PATHS {
|
|
|
49
76
|
/**
|
|
50
77
|
* The Foundry document types a compendium pack may hold. This is the set the
|
|
51
78
|
* toolchain is able to compile a pack of; a document type Foundry supports but
|
|
52
|
-
* this toolchain does not compile is deliberately absent (
|
|
79
|
+
* this toolchain does not compile is deliberately absent (playlists
|
|
53
80
|
* and roll tables are out of scope).
|
|
54
81
|
*
|
|
55
82
|
* @satisfies {readonly PackDocumentType[]}
|
|
@@ -68,15 +95,11 @@ export const PACK_DOCUMENT_TYPES: readonly ["Actor", "Adventure", "Item", "Journ
|
|
|
68
95
|
* key is **refused**, at the line it was written on, with a message that says
|
|
69
96
|
* the mechanism is gone rather than naming a value to correct.
|
|
70
97
|
*
|
|
71
|
-
*
|
|
98
|
+
* **`landing` is one such key.** It named which note addressed a whole section
|
|
72
99
|
* rather than a page within one — a *landing page*, which therefore had no slug
|
|
73
|
-
* of its own.
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* no note lands anything. The key outlived its mechanism by one release only
|
|
77
|
-
* because both publishing consumers still declared the then-true
|
|
78
|
-
* `landing: readme`, and neither breaking them over a correct statement nor
|
|
79
|
-
* accepting the key in silence was acceptable. Neither declares it now.
|
|
100
|
+
* of its own. There are no sections to address: a section is a Hugo content
|
|
101
|
+
* directory the note format does not carry, a page's address names no
|
|
102
|
+
* directory, and so no note lands anything.
|
|
80
103
|
*
|
|
81
104
|
* @type {Readonly<Record<string, string>>}
|
|
82
105
|
*/
|
|
@@ -89,7 +112,7 @@ export const RETIRED_ADDRESS_KEYS: Readonly<Record<string, string>>;
|
|
|
89
112
|
* `thalorna`, whose site is nothing but its content. It is not the package's
|
|
90
113
|
* own mount point: where the package itself is served is the consuming build's
|
|
91
114
|
* knowledge, held in `PACKAGE_BASE` (`engine/content-address.mjs`) and prefixed at
|
|
92
|
-
* resolve time, so it is never recorded here
|
|
115
|
+
* resolve time, so it is never recorded here.
|
|
93
116
|
*
|
|
94
117
|
* It is the whole scheme: `landing`, the key that named which note addressed a
|
|
95
118
|
* whole section, is retired with the sections themselves — see
|
|
@@ -103,7 +126,7 @@ export const DEFAULT_ADDRESS_SCHEME: Readonly<{
|
|
|
103
126
|
*
|
|
104
127
|
* Every HeroicLands package publishes something: a top-level, human-authored
|
|
105
128
|
* homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
|
|
106
|
-
* module is, which system it needs and how to install it
|
|
129
|
+
* module is, which system it needs and how to install it. So there is no
|
|
107
130
|
* value here meaning *no web presence at all* — homepage-only is the **floor**,
|
|
108
131
|
* and the default.
|
|
109
132
|
*
|
|
@@ -141,7 +164,7 @@ export const SITE_MODES: readonly ["homepage", "content"];
|
|
|
141
164
|
* How the loader hands {@link defineConfig} the system version it resolved.
|
|
142
165
|
*
|
|
143
166
|
* A **Symbol**, deliberately. `stats.systemVersion` is refused from an authored
|
|
144
|
-
* configuration
|
|
167
|
+
* configuration, but the value still has to reach here from the loader —
|
|
145
168
|
* which is the half that may do I/O, and which reads a system package's version
|
|
146
169
|
* out of the adjacent `package.json`. A string key would be a second spelling of
|
|
147
170
|
* the refused one, forgeable from YAML and reachable by `rejectUnknownKeys`; a
|
|
@@ -156,7 +179,7 @@ export const DERIVED_SYSTEM_VERSION: symbol;
|
|
|
156
179
|
*
|
|
157
180
|
* Every HeroicLands package publishes something: a top-level, human-authored
|
|
158
181
|
* homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
|
|
159
|
-
* module is, which system it needs and how to install it
|
|
182
|
+
* module is, which system it needs and how to install it. So there is no
|
|
160
183
|
* value here meaning *no web presence at all* — homepage-only is the **floor**,
|
|
161
184
|
* and the default.
|
|
162
185
|
*
|
|
@@ -183,7 +206,7 @@ export const DERIVED_SYSTEM_VERSION: symbol;
|
|
|
183
206
|
* means what it said.
|
|
184
207
|
*/
|
|
185
208
|
export type SiteMode = "homepage" | "content";
|
|
186
|
-
export type PackageKind = "systems" | "modules";
|
|
209
|
+
export type PackageKind = "systems" | "modules" | "documentation";
|
|
187
210
|
export type PackDocumentType = "Actor" | "Adventure" | "Item" | "JournalEntry" | "Macro" | "Scene";
|
|
188
211
|
/**
|
|
189
212
|
* One compendium pack the build compiles, named exactly as it is declared in
|
|
@@ -194,7 +217,7 @@ export type PackDocumentType = "Actor" | "Adventure" | "Item" | "JournalEntry" |
|
|
|
194
217
|
* type** receives its document. The two are orthogonal, and both are needed
|
|
195
218
|
* once a repository groups same-type documents editorially — which it may have
|
|
196
219
|
* to, since a compendium UUID carries its pack name and collapsing such a
|
|
197
|
-
* layout breaks every stored reference
|
|
220
|
+
* layout breaks every stored reference.
|
|
198
221
|
*/
|
|
199
222
|
export type PackSpec = {
|
|
200
223
|
/**
|
|
@@ -304,7 +327,7 @@ export type PathsInput = {
|
|
|
304
327
|
foreignCache?: string | undefined;
|
|
305
328
|
/**
|
|
306
329
|
* Where a dependency's published content
|
|
307
|
-
* index is fetched to
|
|
330
|
+
* index is fetched to. Inbound,
|
|
308
331
|
* for *every* declared dependency, not
|
|
309
332
|
* only those supplying a catalogue.
|
|
310
333
|
*/
|
|
@@ -503,7 +526,7 @@ export type AddressSchemeInput = {
|
|
|
503
526
|
* `fields` is what makes the type documentable: a builder function says
|
|
504
527
|
* nothing about the vocabulary it consumes, so a consumer that declares its
|
|
505
528
|
* fields can generate its own authoring reference and check its own notes,
|
|
506
|
-
* while one that does not is simply undocumented rather than broken
|
|
529
|
+
* while one that does not is simply undocumented rather than broken.
|
|
507
530
|
*/
|
|
508
531
|
export type ItemBuilderEntry = ((fm: object) => object) | {
|
|
509
532
|
system: (fm: object) => object;
|
|
@@ -511,7 +534,7 @@ export type ItemBuilderEntry = ((fm: object) => object) | {
|
|
|
511
534
|
fields?: readonly object[];
|
|
512
535
|
};
|
|
513
536
|
/**
|
|
514
|
-
* One **registry** of a declared set, and the system it belongs to
|
|
537
|
+
* One **registry** of a declared set, and the system it belongs to.
|
|
515
538
|
*
|
|
516
539
|
* A repository shipping content for two systems declares one of these per
|
|
517
540
|
* system: the accepted type vocabulary is their union, and a type both declare
|
|
@@ -546,17 +569,27 @@ export type ContentBuildConfigInput = {
|
|
|
546
569
|
contentPackage: string;
|
|
547
570
|
/**
|
|
548
571
|
* Foundry package id, as it appears in
|
|
549
|
-
*
|
|
572
|
+
* `system.json` / `module.json`.
|
|
573
|
+
* Refused by a `documentation`
|
|
574
|
+
* package, which ships no Foundry
|
|
575
|
+
* package.
|
|
550
576
|
*/
|
|
551
|
-
foundryPackage
|
|
577
|
+
foundryPackage?: string | undefined;
|
|
552
578
|
/**
|
|
553
|
-
* Whether the package is a system
|
|
579
|
+
* Whether the package is a system, a
|
|
580
|
+
* module, or documentation — the kind
|
|
581
|
+
* that publishes a site and a book
|
|
582
|
+
* while compiling nothing.
|
|
554
583
|
*/
|
|
555
584
|
packageKind: PackageKind;
|
|
556
585
|
/**
|
|
557
|
-
* Identity stamped into every
|
|
586
|
+
* Identity stamped into every
|
|
587
|
+
* document's `_stats`. Required of a
|
|
588
|
+
* package that compiles documents, and
|
|
589
|
+
* refused by a `documentation` one,
|
|
590
|
+
* which compiles none.
|
|
558
591
|
*/
|
|
559
|
-
stats
|
|
592
|
+
stats?: StatsSpec | undefined;
|
|
560
593
|
/**
|
|
561
594
|
* The consumer's
|
|
562
595
|
* item-type registry: each content `type`
|
|
@@ -570,7 +603,7 @@ export type ContentBuildConfigInput = {
|
|
|
570
603
|
* two systems declares a **list** of
|
|
571
604
|
* `{ system, builders }` registries
|
|
572
605
|
* instead, and the accepted type
|
|
573
|
-
* vocabulary is their union
|
|
606
|
+
* vocabulary is their union.
|
|
574
607
|
*/
|
|
575
608
|
itemBuilders?: Record<string, ItemBuilderEntry> | readonly ItemRegistrySpec[] | undefined;
|
|
576
609
|
/**
|
|
@@ -579,8 +612,7 @@ export type ContentBuildConfigInput = {
|
|
|
579
612
|
* the pack it belongs in with its
|
|
580
613
|
* `pack:` frontmatter, and one pack of
|
|
581
614
|
* the type is marked `default: true` to
|
|
582
|
-
* receive the notes that name none
|
|
583
|
-
* (#1566).
|
|
615
|
+
* receive the notes that name none.
|
|
584
616
|
*/
|
|
585
617
|
packs: PackSpec[];
|
|
586
618
|
/**
|
|
@@ -631,15 +663,29 @@ export type ContentBuildConfigInput = {
|
|
|
631
663
|
export type ContentBuildConfig = {
|
|
632
664
|
rootDir: string;
|
|
633
665
|
contentPackage: string;
|
|
634
|
-
|
|
666
|
+
/**
|
|
667
|
+
* `null` for a `documentation`
|
|
668
|
+
* package, which ships no Foundry package.
|
|
669
|
+
*/
|
|
670
|
+
foundryPackage: string | null;
|
|
635
671
|
packageKind: PackageKind;
|
|
636
672
|
/**
|
|
637
|
-
* Derived
|
|
638
|
-
*
|
|
673
|
+
* Derived, and **conditional**: the served
|
|
674
|
+
* Foundry asset root,
|
|
675
|
+
* `<packageKind>/<foundryPackage>/assets`,
|
|
676
|
+
* for a package Foundry installs — and
|
|
677
|
+
* `null` for a `documentation` package,
|
|
678
|
+
* which Foundry serves no files for. See
|
|
679
|
+
* {@link module :engine/helpers.resolveImg},
|
|
680
|
+
* the one reader of it.
|
|
639
681
|
*/
|
|
640
|
-
assetRoot: string;
|
|
682
|
+
assetRoot: string | null;
|
|
641
683
|
paths: Readonly<ResolvedPaths>;
|
|
642
|
-
|
|
684
|
+
/**
|
|
685
|
+
* `null` for a `documentation`
|
|
686
|
+
* package, which stamps no `_stats`.
|
|
687
|
+
*/
|
|
688
|
+
stats: Readonly<StatsSpec> | null;
|
|
643
689
|
/**
|
|
644
690
|
* Derived: the
|
|
645
691
|
* `system` builder of each entry, whichever
|
|
@@ -658,14 +704,13 @@ export type ContentBuildConfig = {
|
|
|
658
704
|
* the frontmatter fields each entry
|
|
659
705
|
* declared. Sparse, like `itemArt` — a type
|
|
660
706
|
* absent here compiles normally and is
|
|
661
|
-
* simply undocumented
|
|
707
|
+
* simply undocumented.
|
|
662
708
|
*/
|
|
663
709
|
itemFields: Readonly<Record<string, readonly object[]>>;
|
|
664
710
|
/**
|
|
665
711
|
* Derived: the same builders, kept per
|
|
666
712
|
* declaring system. `{}` for the single
|
|
667
|
-
* registry form, which names no system
|
|
668
|
-
* (#58).
|
|
713
|
+
* registry form, which names no system.
|
|
669
714
|
*/
|
|
670
715
|
itemBuildersBySystem: Readonly<Record<string, Readonly<Record<string, Function>>>>;
|
|
671
716
|
/**
|
|
@@ -688,7 +733,7 @@ export type ContentBuildConfig = {
|
|
|
688
733
|
* {@link ContentBuildConfigInput.itemBuilders},
|
|
689
734
|
* unioned across every declared registry, so
|
|
690
735
|
* the accepted item types and the builder
|
|
691
|
-
* tables are one list
|
|
736
|
+
* tables are one list.
|
|
692
737
|
*/
|
|
693
738
|
itemTypes: ReadonlySet<string>;
|
|
694
739
|
/**
|
|
@@ -700,6 +745,13 @@ export type ContentBuildConfig = {
|
|
|
700
745
|
*/
|
|
701
746
|
docEntryTypes: ReadonlySet<string>;
|
|
702
747
|
skipDirectories: readonly string[];
|
|
748
|
+
/**
|
|
749
|
+
* The
|
|
750
|
+
* fonts this package ships and the names it
|
|
751
|
+
* draws from them; empty when it declares
|
|
752
|
+
* none.
|
|
753
|
+
*/
|
|
754
|
+
icons: import("./engine/content-icons.mjs").IconRegistry;
|
|
703
755
|
packs: readonly Readonly<ResolvedPackSpec>[];
|
|
704
756
|
/**
|
|
705
757
|
* Derived: every pack directory
|
package/types/e2e.d.mts
CHANGED
|
@@ -220,7 +220,7 @@ export function findExecutable(name: string, { cwd, env }?: {
|
|
|
220
220
|
*
|
|
221
221
|
* Asked twice per run, and the second asking is the point: an install running
|
|
222
222
|
* alongside the suite can take the runner out from under it mid-flight, which
|
|
223
|
-
* is precisely the failure that reported itself as green
|
|
223
|
+
* is precisely the failure that reported itself as green.
|
|
224
224
|
*
|
|
225
225
|
* @param {object} opts
|
|
226
226
|
* @param {readonly string[]} opts.command - The program and its arguments.
|
|
@@ -268,7 +268,7 @@ export function freshResults({ paths, since, cwd }: {
|
|
|
268
268
|
* exit status on its own cannot call a run green, because every way of stopping
|
|
269
269
|
* a runner before it starts — a corrupt install, a missing browser, a killed
|
|
270
270
|
* process, the concurrent `npm ci` that surfaced this — produces a run that
|
|
271
|
-
* executed nothing, and nothing is not a pass
|
|
271
|
+
* executed nothing, and nothing is not a pass.
|
|
272
272
|
*
|
|
273
273
|
* This can only ever make a verdict worse. A suite that failed keeps its own
|
|
274
274
|
* status; a suite that passed on no evidence loses the claim. Never the other
|
|
@@ -297,7 +297,7 @@ export function suiteVerdict({ status, vanished, declared, fresh }: {
|
|
|
297
297
|
* `MODULE_NOT_FOUND` naming nothing relevant.
|
|
298
298
|
*
|
|
299
299
|
* The suite is bracketed by checks rather than trusted on its exit status,
|
|
300
|
-
* because a run that never started used to report as green
|
|
300
|
+
* because a run that never started used to report as green:
|
|
301
301
|
*
|
|
302
302
|
* - **Before.** Every executable the command needs is resolved, and a missing
|
|
303
303
|
* one is an error naming it — rather than a container stood up, a world
|