@heroiclands/package-build 17.1.0 → 18.0.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 +1773 -0
- package/CONTENT.md +288 -72
- package/README.md +1 -1
- package/bin/content-build.mjs +218 -137
- package/bin/package-build.mjs +43 -0
- package/content-config.mjs +62 -67
- package/docs/content-format.md +768 -58
- package/engine/actor-compiler.mjs +586 -0
- package/engine/address-charset.mjs +11 -8
- package/engine/address-diff.mjs +266 -22
- package/engine/anchored-sections.mjs +83 -0
- package/engine/anchors.mjs +83 -0
- package/engine/base-compiler.mjs +148 -18
- package/engine/bundle-notes.mjs +276 -0
- package/engine/bundles.mjs +307 -0
- package/engine/code-fences.mjs +103 -0
- package/engine/compile-corpus.mjs +89 -0
- package/engine/content-address.mjs +267 -5
- package/engine/content-format-check.mjs +54 -11
- package/engine/content-format.mjs +37 -5
- package/engine/content-index.mjs +394 -111
- package/engine/content-links.mjs +185 -77
- package/engine/content-lint.mjs +232 -14
- package/engine/content-package.mjs +2 -1
- package/engine/content-tables.mjs +99 -3
- package/engine/document-subtypes.mjs +49 -6
- package/engine/field-reference.mjs +1 -1
- package/engine/field-spec.mjs +56 -6
- package/engine/folder-notes.mjs +470 -0
- package/engine/foreign-catalog.mjs +195 -4
- package/engine/{manifest-emit.mjs → foundry-entries.mjs} +78 -81
- package/engine/frontmatter-lint.mjs +245 -19
- package/engine/frontmatter.mjs +88 -8
- package/engine/generate.mjs +304 -13
- package/engine/helpers.mjs +293 -64
- package/engine/ids.mjs +137 -2
- package/engine/index-records.mjs +126 -0
- package/engine/index.mjs +23 -5
- package/engine/item-compiler.mjs +349 -0
- package/engine/item-docs.mjs +7 -1
- package/engine/item-registry.mjs +6 -0
- package/engine/journals.mjs +93 -27
- package/engine/macros.mjs +4 -2
- package/engine/metadata-index.mjs +495 -0
- package/engine/note-claims.mjs +146 -25
- package/engine/note-ids.mjs +112 -0
- package/engine/note-renames.mjs +134 -0
- package/engine/note-schemas.mjs +25 -0
- package/engine/note-vocabulary.mjs +110 -27
- package/engine/pack-config.mjs +4 -0
- package/engine/pack-router.mjs +23 -0
- package/engine/retired-fields.mjs +137 -3
- package/engine/scenes.mjs +66 -34
- package/engine/schema-check.mjs +58 -17
- package/engine/site-build.mjs +71 -12
- package/engine/site-index.mjs +20 -7
- package/engine/sql-tables.mjs +485 -0
- package/engine/subtype-registry.mjs +102 -0
- package/engine/system-block.mjs +96 -12
- package/engine/systems.mjs +201 -0
- package/engine/web-wikilinks.mjs +50 -20
- package/engine/wikilink-syntax.mjs +17 -8
- package/engine/wikilinks.mjs +124 -51
- package/engine/yaml-lint.mjs +282 -0
- package/hm3/actors.mjs +352 -0
- package/hm3/default-item-art.mjs +75 -0
- package/hm3/document-subtypes.mjs +134 -0
- package/hm3/index.mjs +56 -0
- package/hm3/item-builders.mjs +84 -0
- package/hm3/item-fields.mjs +180 -0
- package/hm3/items.mjs +96 -0
- package/hm3/template-priority.mjs +85 -0
- package/labels.mjs +191 -0
- package/manifest.mjs +43 -2
- package/package.json +19 -4
- package/release.mjs +62 -7
- package/sohl/actors.mjs +33 -487
- package/sohl/being-info.mjs +16 -7
- package/sohl/default-item-art.mjs +14 -3
- package/sohl/document-subtypes.mjs +16 -10
- package/sohl/item-builders.mjs +14 -5
- package/sohl/item-fields.mjs +68 -7
- package/sohl/items.mjs +44 -258
- package/sohl/note-schemas.mjs +2 -2
- package/types/content-config.d.mts +21 -42
- package/types/engine/actor-compiler.d.mts +204 -0
- package/types/engine/address-charset.d.mts +11 -8
- package/types/engine/address-diff.d.mts +53 -5
- package/types/engine/anchored-sections.d.mts +21 -0
- package/types/engine/anchors.d.mts +20 -0
- package/types/engine/base-compiler.d.mts +17 -17
- package/types/engine/bundle-notes.d.mts +173 -0
- package/types/engine/bundles.d.mts +60 -0
- package/types/engine/code-fences.d.mts +43 -0
- package/types/engine/compile-corpus.d.mts +32 -0
- package/types/engine/content-address.d.mts +205 -5
- package/types/engine/content-format-check.d.mts +6 -2
- package/types/engine/content-format.d.mts +57 -1
- package/types/engine/content-index.d.mts +64 -80
- package/types/engine/content-links.d.mts +52 -7
- package/types/engine/content-lint.d.mts +10 -1
- package/types/engine/content-package.d.mts +2 -1
- package/types/engine/content-tables.d.mts +21 -39
- package/types/engine/document-subtypes.d.mts +37 -3
- package/types/engine/field-spec.d.mts +76 -5
- package/types/engine/folder-notes.d.mts +159 -0
- package/types/engine/foreign-catalog.d.mts +53 -0
- package/types/engine/{manifest-emit.d.mts → foundry-entries.d.mts} +16 -38
- package/types/engine/frontmatter-lint.d.mts +10 -2
- package/types/engine/frontmatter.d.mts +64 -0
- package/types/engine/generate.d.mts +38 -0
- package/types/engine/helpers.d.mts +94 -30
- package/types/engine/ids.d.mts +96 -0
- package/types/engine/index-records.d.mts +68 -0
- package/types/engine/index.d.mts +9 -3
- package/types/engine/item-compiler.d.mts +131 -0
- package/types/engine/journals.d.mts +47 -9
- package/types/engine/metadata-index.d.mts +226 -0
- package/types/engine/note-claims.d.mts +57 -11
- package/types/engine/note-ids.d.mts +38 -0
- package/types/engine/note-renames.d.mts +102 -0
- package/types/engine/note-vocabulary.d.mts +44 -8
- package/types/engine/retired-fields.d.mts +75 -0
- package/types/engine/scenes.d.mts +3 -2
- package/types/engine/schema-check.d.mts +25 -4
- package/types/engine/site-build.d.mts +4 -4
- package/types/engine/site-index.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +185 -0
- package/types/engine/subtype-registry.d.mts +49 -0
- package/types/engine/system-block.d.mts +40 -1
- package/types/engine/systems.d.mts +106 -0
- package/types/engine/web-wikilinks.d.mts +4 -2
- package/types/engine/wikilink-syntax.d.mts +10 -3
- package/types/engine/wikilinks.d.mts +41 -13
- package/types/engine/yaml-lint.d.mts +107 -0
- package/types/hm3/actors.d.mts +48 -0
- package/types/hm3/default-item-art.d.mts +42 -0
- package/types/hm3/document-subtypes.d.mts +24 -0
- package/types/hm3/index.d.mts +7 -0
- package/types/hm3/item-builders.d.mts +11 -0
- package/types/hm3/item-fields.d.mts +12 -0
- package/types/hm3/items.d.mts +23 -0
- package/types/hm3/template-priority.d.mts +21 -0
- package/types/manifest.d.mts +22 -1
- package/types/release.d.mts +9 -4
- package/types/sohl/actors.d.mts +7 -74
- package/types/sohl/being-info.d.mts +8 -27
- package/types/sohl/default-item-art.d.mts +5 -3
- package/types/sohl/items.d.mts +17 -32
- package/engine/foreign-manifests.mjs +0 -126
- package/engine/kb-manifest.mjs +0 -490
- package/types/engine/foreign-manifests.d.mts +0 -43
- package/types/engine/kb-manifest.d.mts +0 -241
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
* pack from appearing to answer for any note.
|
|
8
8
|
*
|
|
9
9
|
* @param {string} docType - The Foundry document type a pack holds.
|
|
10
|
-
* @param {ClaimSources} [sources] - What to answer from.
|
|
10
|
+
* @param {ClaimSources} [sources] - What to answer from.
|
|
11
|
+
* @param {object} [opts] - Options.
|
|
12
|
+
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
13
|
+
* compile and handed in — required, for the reason above (#243). Defaults to the
|
|
11
14
|
* configured registries and the systems this toolchain ships.
|
|
12
15
|
* @returns {ReadonlySet<string>} The note types such a pass would claim.
|
|
13
16
|
*/
|
|
@@ -19,9 +22,21 @@ export function noteTypesClaimedBy(docType: string, sources?: ClaimSources): Rea
|
|
|
19
22
|
* is claimed — which is what keeps a type deliberately unmapped for one system,
|
|
20
23
|
* and claimed for another, silent (#79).
|
|
21
24
|
*
|
|
25
|
+
* **A prebuilt pack claims nothing.** Its per-document JSON is checked in
|
|
26
|
+
* rather than compiled, so it has no pass and no note is routed into one —
|
|
27
|
+
* which `content-config.mjs` already states by refusing `default: true`
|
|
28
|
+
* alongside `prebuilt`. Counting it would tell an author their note is claimed
|
|
29
|
+
* by a pack that will never look at it. Before #259 the point could not arise:
|
|
30
|
+
* the only prebuilt pack in the wild is `harn-adventures`'s Adventure pack, and
|
|
31
|
+
* no compiler was registered for that document type, so the row answered for
|
|
32
|
+
* nothing whatever it was asked. Now one is.
|
|
33
|
+
*
|
|
22
34
|
* @param {object} [config] - The resolved build configuration. Defaults to this
|
|
23
35
|
* repository's.
|
|
24
36
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
37
|
+
* @param {object} [opts] - Options.
|
|
38
|
+
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
39
|
+
* compile and handed in — required, for the reason above (#243).
|
|
25
40
|
* @returns {ReadonlySet<string>} The claimed note types.
|
|
26
41
|
*/
|
|
27
42
|
export function claimedNoteTypes(config?: object, sources?: ClaimSources): ReadonlySet<string>;
|
|
@@ -35,6 +50,9 @@ export function claimedNoteTypes(config?: object, sources?: ClaimSources): Reado
|
|
|
35
50
|
* declare on top.
|
|
36
51
|
*
|
|
37
52
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
53
|
+
* @param {object} [opts] - Options.
|
|
54
|
+
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
55
|
+
* compile and handed in — required, for the reason above (#243).
|
|
38
56
|
* @returns {ReadonlySet<string>} The vocabulary.
|
|
39
57
|
*/
|
|
40
58
|
export function noteTypeVocabulary(sources?: ClaimSources): ReadonlySet<string>;
|
|
@@ -51,10 +69,15 @@ export function noteTypeVocabulary(sources?: ClaimSources): ReadonlySet<string>;
|
|
|
51
69
|
* @param {object} [config] - The resolved build configuration. Defaults to this
|
|
52
70
|
* repository's.
|
|
53
71
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
72
|
+
* @param {object} [opts] - Options.
|
|
73
|
+
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
74
|
+
* compile and handed in — required, for the reason above (#243).
|
|
54
75
|
* @returns {Array<{file: string, line?: number, column?: number,
|
|
55
76
|
* severity: "error", message: string, type: string}>} One finding per note.
|
|
56
77
|
*/
|
|
57
|
-
export function unclaimedNoteFindings(config?: object, sources?: ClaimSources
|
|
78
|
+
export function unclaimedNoteFindings(config?: object, sources?: ClaimSources, { records }?: {
|
|
79
|
+
records?: readonly object[] | undefined;
|
|
80
|
+
}): Array<{
|
|
58
81
|
file: string;
|
|
59
82
|
line?: number;
|
|
60
83
|
column?: number;
|
|
@@ -74,19 +97,42 @@ export function unclaimedNoteFindings(config?: object, sources?: ClaimSources):
|
|
|
74
97
|
*/
|
|
75
98
|
export const NEVER_PACKED_TYPES: ReadonlySet<string>;
|
|
76
99
|
/**
|
|
77
|
-
*
|
|
100
|
+
* Content types the specification states and this toolchain does not yet
|
|
101
|
+
* compile.
|
|
102
|
+
*
|
|
103
|
+
* **Stated, never inferred, and that distinction is the whole point.** An
|
|
104
|
+
* unimplemented type and a type somebody forgot to route look identical from
|
|
105
|
+
* the outside: both are documented, both validate, and neither reaches a pass.
|
|
106
|
+
* The only thing separating them is intent, so intent is written down here.
|
|
78
107
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
108
|
+
* Inferring it — "declared, but absent from the configured vocabulary" — reads
|
|
109
|
+
* correctly and is worthless, because the configured vocabulary is *derived
|
|
110
|
+
* from the routing*. Take a type's route away and it leaves the vocabulary too,
|
|
111
|
+
* so the inference excuses precisely the mistake it was meant to catch. That is
|
|
112
|
+
* not hypothetical: it is #241, where `place`, `lore` and `scenario` were
|
|
113
|
+
* declared, validated and unrouted, and every gate reported success until a
|
|
114
|
+
* downstream repository failed on 450 notes.
|
|
81
115
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* same reason: the engine owns the *mechanism* that asks each system what it
|
|
85
|
-
* compiles, and the systems own the answers.
|
|
116
|
+
* A type leaves this set when it is implemented, the way `bundle` did in #259.
|
|
117
|
+
* The membership is asserted, so it cannot be forgotten in either direction.
|
|
86
118
|
*
|
|
87
|
-
* @type {
|
|
119
|
+
* @type {ReadonlySet<string>}
|
|
120
|
+
*/
|
|
121
|
+
export const UNIMPLEMENTED_TYPES: ReadonlySet<string>;
|
|
122
|
+
/**
|
|
123
|
+
* Note types that reach a pack by a route **other than the pack router**.
|
|
124
|
+
*
|
|
125
|
+
* A folder is the only one, and it is not unclaimed: it compiles to a real
|
|
126
|
+
* `Folder` document. What it has no answer to is *which* pack claims it, because
|
|
127
|
+
* that is not a property of the note — a folder materialises in every pack
|
|
128
|
+
* holding a document that references it, and its ancestors with it (#257). So
|
|
129
|
+
* it is exempt from the claim check for the opposite reason a homepage is:
|
|
130
|
+
* a homepage is in no pack, and a folder may be in several.
|
|
131
|
+
*
|
|
132
|
+
* @type {ReadonlySet<string>}
|
|
88
133
|
*/
|
|
89
|
-
export const
|
|
134
|
+
export const DERIVED_PACKED_TYPES: ReadonlySet<string>;
|
|
135
|
+
export { KNOWN_DOCUMENT_SUBTYPE_MAPS } from "./subtype-registry.mjs";
|
|
90
136
|
/**
|
|
91
137
|
* What a claim question is asked against.
|
|
92
138
|
*
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The document id a note compiles under: its pin, or its address.
|
|
3
|
+
*
|
|
4
|
+
* Returns `undefined` for a file with **no address** — no `type`, or no
|
|
5
|
+
* `shortcode`. Such a file is not an addressable note, so it has no document
|
|
6
|
+
* and inventing an id for one would file it under nothing. Every caller already
|
|
7
|
+
* had to handle an absent id (that is what the authored field's absence meant),
|
|
8
|
+
* so this reports the same thing rather than throwing where a walk used to
|
|
9
|
+
* skip; whether an id is *required* stays each pass's own decision
|
|
10
|
+
* (`BasePackCompiler.requiresId`).
|
|
11
|
+
*
|
|
12
|
+
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
13
|
+
* @param {object} [opts]
|
|
14
|
+
* @param {string} [opts.pkg] - The owning content package. Defaults to the
|
|
15
|
+
* configured one, which is the only package a tree's notes belong to (#56).
|
|
16
|
+
* @param {readonly object[]} [opts.maps] - The document-subtype maps, which
|
|
17
|
+
* decide the address's `<system>` segment.
|
|
18
|
+
* @returns {string|undefined} The document's `_id`, or `undefined` when the
|
|
19
|
+
* note has no address to derive one from.
|
|
20
|
+
*/
|
|
21
|
+
export function noteDocId(fm: object | null | undefined, { pkg, maps }?: {
|
|
22
|
+
pkg?: string | undefined;
|
|
23
|
+
maps?: readonly object[] | undefined;
|
|
24
|
+
}): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Fill a note's `id` in place, so everything downstream reads one value.
|
|
27
|
+
*
|
|
28
|
+
* The corpus readers each hold their own parsed frontmatter and each ask for
|
|
29
|
+
* `fm.id` in several places; normalising the field once, where the note is
|
|
30
|
+
* read, is what makes "the id is derived" true for all of them rather than for
|
|
31
|
+
* whichever ones remembered to derive it. Idempotent, and a no-op for a note
|
|
32
|
+
* that authored an id or has no address.
|
|
33
|
+
*
|
|
34
|
+
* @param {object|null|undefined} fm - Parsed frontmatter, mutated in place.
|
|
35
|
+
* @param {object} [opts] - As {@link noteDocId}.
|
|
36
|
+
* @returns {object|null|undefined} `fm`, for chaining.
|
|
37
|
+
*/
|
|
38
|
+
export function resolveNoteId(fm: object | null | undefined, opts?: object): object | null | undefined;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shortcodes a note declares it used to be published under (#278).
|
|
3
|
+
*
|
|
4
|
+
* A package's `(type, shortcode)` addresses are a published interface, and
|
|
5
|
+
* `addresses diff` reports what a build stopped publishing — telling a
|
|
6
|
+
* **rename** from a **withdrawal** by matching document ids across two
|
|
7
|
+
* releases. #270 removed the property that rested on. An id is now derived from
|
|
8
|
+
* the canonical address, which carries the shortcode, so renaming a shortcode
|
|
9
|
+
* moves the id too: both sides of the join move together, the match finds
|
|
10
|
+
* nothing, and a rename is reported as a withdrawal with no successor named.
|
|
11
|
+
*
|
|
12
|
+
* **The remaining lever needed foresight, which is the wrong thing to ask for.**
|
|
13
|
+
* An authored `id:` still wins, and pinning one does keep a document's identity
|
|
14
|
+
* across a rename — but it has to be written *before* the rename, by an author
|
|
15
|
+
* who does not yet know they will make one. An author who has just renamed a
|
|
16
|
+
* shortcode knows exactly what the old one was, and that is the only moment
|
|
17
|
+
* anyone does.
|
|
18
|
+
*
|
|
19
|
+
* So a note states it:
|
|
20
|
+
*
|
|
21
|
+
* ```yaml
|
|
22
|
+
* type: weapongear
|
|
23
|
+
* shortcode: Taburi
|
|
24
|
+
* renamedFrom: Tabri
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* **A declaration is an assertion, not a match, and the diagnostic says which
|
|
28
|
+
* it had.** That distinction is the whole ethos of `address-diff.mjs`: it
|
|
29
|
+
* refuses to guess a successor from a similar-looking string, because a wrong
|
|
30
|
+
* one sends the reader to the wrong fix. An author's declaration is neither a
|
|
31
|
+
* guess nor an identity match — it is testimony from the one party that knows —
|
|
32
|
+
* so it is used, attributed, and never silently blended with an id match.
|
|
33
|
+
*
|
|
34
|
+
* **It is a list, because renames chain.** The diff is release-to-release and a
|
|
35
|
+
* shortcode may be renamed more than once between two releases; a baseline
|
|
36
|
+
* several releases back published a name two renames ago. A single value would
|
|
37
|
+
* report that as a withdrawal again, which is the bug this closes.
|
|
38
|
+
*
|
|
39
|
+
* **It is transient.** Once every baseline a build is compared against post-dates
|
|
40
|
+
* the rename, the declaration has nothing left to say and may be deleted. That
|
|
41
|
+
* is the difference from an `id:` pin, which is permanent, opaque, and a second
|
|
42
|
+
* identity for a thing that already has one (#270).
|
|
43
|
+
*
|
|
44
|
+
* **It is one key per note, at the top level, however many systems the note
|
|
45
|
+
* compiles into.** A shortcode is the note's, not a system block's: a note
|
|
46
|
+
* carrying `sohl:` and `hm3:` blocks compiles into two documents that share one
|
|
47
|
+
* shortcode, so a rename moves both and one declaration covers both.
|
|
48
|
+
*
|
|
49
|
+
* This module reads the key and says nothing about whether the values are
|
|
50
|
+
* *sound* — that a value is a well-formed shortcode, is not the note's own, and
|
|
51
|
+
* does not name an address some live note still publishes are cross-note
|
|
52
|
+
* questions, and `engine/content-lint.mjs` owns them. Composing a value into an
|
|
53
|
+
* address key is likewise not here: the diff defines that space and spells the
|
|
54
|
+
* key once, in `engine/address-diff.mjs`.
|
|
55
|
+
*
|
|
56
|
+
* @module
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* The `renamedFrom:` entries a note authors, exactly as authored.
|
|
60
|
+
*
|
|
61
|
+
* Scalar or list, because one predecessor is the overwhelmingly common case and
|
|
62
|
+
* requiring `- ` on it would be friction with nothing behind it; both normalize
|
|
63
|
+
* here so no reader has to ask which form it got.
|
|
64
|
+
*
|
|
65
|
+
* Entries are returned **unvalidated** — a number, a nested list, a blank
|
|
66
|
+
* string all come back as they were written. The lint needs to see them to
|
|
67
|
+
* report them, and a reader that quietly dropped them would report a correct
|
|
68
|
+
* tree clean while a typo silently did nothing.
|
|
69
|
+
*
|
|
70
|
+
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
71
|
+
* @returns {readonly unknown[]} The authored entries, in authored order; empty
|
|
72
|
+
* when the note declares none.
|
|
73
|
+
*/
|
|
74
|
+
export function renamedFromEntries(fm: object | null | undefined): readonly unknown[];
|
|
75
|
+
/**
|
|
76
|
+
* The well-formed shortcodes among a note's `renamedFrom:` entries.
|
|
77
|
+
*
|
|
78
|
+
* Trimmed, de-duplicated, and in authored order. Anything that is not a
|
|
79
|
+
* non-blank string is skipped rather than coerced: it is reported by the lint,
|
|
80
|
+
* and a diff that guessed at what a number meant would claim a rename nobody
|
|
81
|
+
* declared.
|
|
82
|
+
*
|
|
83
|
+
* De-duplicating here rather than leaving it to callers is not tidiness — the
|
|
84
|
+
* predecessor index is a map, so a repeated entry would otherwise be indexed
|
|
85
|
+
* twice and the second write would look like a conflicting claim.
|
|
86
|
+
*
|
|
87
|
+
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
88
|
+
* @returns {string[]} The declared predecessor shortcodes.
|
|
89
|
+
*/
|
|
90
|
+
export function renamedFrom(fm: object | null | undefined): string[];
|
|
91
|
+
/**
|
|
92
|
+
* Whether a note declares the key at all, however malformed its value.
|
|
93
|
+
*
|
|
94
|
+
* Separate from {@link renamedFrom} returning nothing, because the two mean
|
|
95
|
+
* opposite things to a lint: a note declaring no key is silent and correct,
|
|
96
|
+
* while one declaring `renamedFrom: []` — or a single blank string — has said
|
|
97
|
+
* something that does nothing, which is worth a word.
|
|
98
|
+
*
|
|
99
|
+
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
100
|
+
* @returns {boolean} `true` when the key is present and not null.
|
|
101
|
+
*/
|
|
102
|
+
export function declaresRenamedFrom(fm: object | null | undefined): boolean;
|
|
@@ -199,7 +199,7 @@ export const NOTE_VOCABULARY: Readonly<{
|
|
|
199
199
|
subTypes: readonly string[];
|
|
200
200
|
data: readonly DataFieldSpec[];
|
|
201
201
|
}>;
|
|
202
|
-
|
|
202
|
+
armor: Readonly<{
|
|
203
203
|
data: readonly DataFieldSpec[];
|
|
204
204
|
}>;
|
|
205
205
|
armorlocation: Readonly<{
|
|
@@ -209,7 +209,7 @@ export const NOTE_VOCABULARY: Readonly<{
|
|
|
209
209
|
attribute: Readonly<{
|
|
210
210
|
data: readonly DataFieldSpec[];
|
|
211
211
|
}>;
|
|
212
|
-
|
|
212
|
+
concoction: Readonly<{
|
|
213
213
|
subTypes: readonly string[];
|
|
214
214
|
data: readonly (DataFieldSpec | Readonly<{
|
|
215
215
|
describe: "How many of the thing there are; one when unstated.";
|
|
@@ -237,7 +237,7 @@ export const NOTE_VOCABULARY: Readonly<{
|
|
|
237
237
|
subTypes: readonly string[];
|
|
238
238
|
data: readonly DataFieldSpec[];
|
|
239
239
|
}>;
|
|
240
|
-
|
|
240
|
+
projectile: Readonly<{
|
|
241
241
|
subTypes: readonly string[];
|
|
242
242
|
data: readonly (DataFieldSpec | Readonly<{
|
|
243
243
|
describe: "How many of the thing there are; one when unstated.";
|
|
@@ -264,6 +264,29 @@ export const NOTE_VOCABULARY: Readonly<{
|
|
|
264
264
|
macro: Readonly<{
|
|
265
265
|
data: readonly never[];
|
|
266
266
|
}>;
|
|
267
|
+
folder: Readonly<{
|
|
268
|
+
data: readonly ({
|
|
269
|
+
describe: string;
|
|
270
|
+
shape: "a wikilink, or a map of wikilinks keyed by pack";
|
|
271
|
+
kind: "scalar-or-map";
|
|
272
|
+
entryShape: "a wikilink";
|
|
273
|
+
keys: "pack";
|
|
274
|
+
name: string;
|
|
275
|
+
} | {
|
|
276
|
+
describe: string;
|
|
277
|
+
shape: "string";
|
|
278
|
+
kind: "string";
|
|
279
|
+
name: string;
|
|
280
|
+
})[];
|
|
281
|
+
}>;
|
|
282
|
+
bundle: Readonly<{
|
|
283
|
+
data: readonly {
|
|
284
|
+
describe: string;
|
|
285
|
+
shape: "list of wikilinks";
|
|
286
|
+
kind: "list";
|
|
287
|
+
name: string;
|
|
288
|
+
}[];
|
|
289
|
+
}>;
|
|
267
290
|
lore: Readonly<{
|
|
268
291
|
subTypes: readonly string[];
|
|
269
292
|
data: readonly never[];
|
|
@@ -349,17 +372,30 @@ export type DataFieldSpec = {
|
|
|
349
372
|
*/
|
|
350
373
|
name: string;
|
|
351
374
|
/**
|
|
352
|
-
* -
|
|
353
|
-
* shape, for the lint. Absent means no claim is made about the
|
|
354
|
-
* is the honest answer wherever the specification's stated
|
|
355
|
-
* shape notes are authored in today disagree.
|
|
375
|
+
* -
|
|
376
|
+
* The value's shape, for the lint. Absent means no claim is made about the
|
|
377
|
+
* value — which is the honest answer wherever the specification's stated
|
|
378
|
+
* shape and the shape notes are authored in today disagree.
|
|
356
379
|
*/
|
|
357
|
-
kind?: "string" | "number" | "boolean" | "map" | "list" | undefined;
|
|
380
|
+
kind?: "string" | "number" | "boolean" | "map" | "list" | "scalar-or-map" | undefined;
|
|
358
381
|
/**
|
|
359
382
|
* - Human-readable shape, for a finding and for
|
|
360
383
|
* documentation.
|
|
361
384
|
*/
|
|
362
385
|
shape?: string | undefined;
|
|
386
|
+
/**
|
|
387
|
+
* - For a `scalar-or-map` field, what one
|
|
388
|
+
* entry of the map is. A finding names the entry at fault rather than
|
|
389
|
+
* quoting the whole map back, so the string an author has to correct is the
|
|
390
|
+
* one the message holds.
|
|
391
|
+
*/
|
|
392
|
+
entryShape?: string | undefined;
|
|
393
|
+
/**
|
|
394
|
+
* - For a `scalar-or-map` field, what its keys name.
|
|
395
|
+
* `"pack"` means each is a pack this package declares, so a key naming none
|
|
396
|
+
* is a finding of its own: it addresses a hierarchy nothing will ever read.
|
|
397
|
+
*/
|
|
398
|
+
keys?: "pack" | undefined;
|
|
363
399
|
/**
|
|
364
400
|
* - One line, for the author-facing reference.
|
|
365
401
|
*/
|
|
@@ -153,6 +153,43 @@ export function assertNoSectionField(fm: object | null | undefined, { file, absP
|
|
|
153
153
|
file?: string | undefined;
|
|
154
154
|
absPath?: string | undefined;
|
|
155
155
|
}): void;
|
|
156
|
+
/**
|
|
157
|
+
* What a note writing a top-level `traits:` block is told.
|
|
158
|
+
*
|
|
159
|
+
* The message states the **mapping**, not just the destination, because three
|
|
160
|
+
* of the keys reshaped as well as moved: the block nested its measurements
|
|
161
|
+
* where the format flattens them. A bare "write `data:` instead" would send an
|
|
162
|
+
* author to author `data.height: {m: 1.78}`, which is a declared key holding an
|
|
163
|
+
* undeclared shape.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} [file] - The note's path, named in the message. Omit it where
|
|
166
|
+
* the caller emits through a diagnostic, whose locator already starts the
|
|
167
|
+
* line — repeating it prints the path twice.
|
|
168
|
+
* @returns {string} The message, unpunctuated at the end as a finding is.
|
|
169
|
+
*/
|
|
170
|
+
export function traitsRetiredMessage(file?: string): string;
|
|
171
|
+
/**
|
|
172
|
+
* Refuse a note that declares a top-level `traits:` block at all.
|
|
173
|
+
*
|
|
174
|
+
* Presence is the whole test, as it is for `draft:` and `aliases:`: an empty
|
|
175
|
+
* `traits:` is still a note claiming a block that no longer exists.
|
|
176
|
+
*
|
|
177
|
+
* @param {object|null|undefined} fm - Parsed frontmatter, or nothing when it
|
|
178
|
+
* could not be parsed.
|
|
179
|
+
* @param {object} [options] - Options.
|
|
180
|
+
* @param {string} [options.file] - The note's path, named in the message. Omit
|
|
181
|
+
* it where the caller emits through a diagnostic, which puts the locator at
|
|
182
|
+
* the start of the line already.
|
|
183
|
+
* @param {string} [options.absPath] - The note's file on disk, read only on the
|
|
184
|
+
* failing path to locate the offending line and column. The position rides on
|
|
185
|
+
* the thrown error as `position`, for a caller that emits a diagnostic.
|
|
186
|
+
* @returns {void}
|
|
187
|
+
* @throws {Error} When the note declares the block.
|
|
188
|
+
*/
|
|
189
|
+
export function assertNoTraitsField(fm: object | null | undefined, { file, absPath }?: {
|
|
190
|
+
file?: string | undefined;
|
|
191
|
+
absPath?: string | undefined;
|
|
192
|
+
}): void;
|
|
156
193
|
/**
|
|
157
194
|
* A frontmatter key's position in a note's file, or nothing.
|
|
158
195
|
*
|
|
@@ -196,6 +233,31 @@ export function locateFrontmatterKey(absPath: string | undefined, key: string, v
|
|
|
196
233
|
* @returns {string} The message, unpunctuated at the end as a finding is.
|
|
197
234
|
*/
|
|
198
235
|
export function retiredAliasMessage(retired: string, current: string, file?: string): string;
|
|
236
|
+
/**
|
|
237
|
+
* What a note writing a field at its **legacy in-block position** is told.
|
|
238
|
+
*
|
|
239
|
+
* The same three-step retirement `retiredAliasMessage` announces, applied to a
|
|
240
|
+
* *position* rather than a spelling (#305). A field whose shared source moved
|
|
241
|
+
* under `data:` keeps reading the key its block still carries, that read wins,
|
|
242
|
+
* and it is reported here so a sweep has something to count down — without it,
|
|
243
|
+
* moving a field into `data:` would be a flag day across every repository that
|
|
244
|
+
* authors it.
|
|
245
|
+
*
|
|
246
|
+
* It names the block, because the key is `hm3.species` and not `species`: an
|
|
247
|
+
* author told to move "`species`" has two regions to guess between.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} block - The system block the key was written in.
|
|
250
|
+
* @param {{name?: string, legacyKey?: string}} field - The declaration, which
|
|
251
|
+
* names both positions.
|
|
252
|
+
* @param {string} [file] - The note's path, named in the message. Omit it where
|
|
253
|
+
* the caller emits through a diagnostic, whose locator already starts the
|
|
254
|
+
* line — repeating it prints the path twice.
|
|
255
|
+
* @returns {string} The message, unpunctuated at the end as a finding is.
|
|
256
|
+
*/
|
|
257
|
+
export function legacyKeyMessage(block: string, field: {
|
|
258
|
+
name?: string;
|
|
259
|
+
legacyKey?: string;
|
|
260
|
+
}, file?: string): string;
|
|
199
261
|
/**
|
|
200
262
|
* Whether a note writes the retired spelling of a field, wherever it put it.
|
|
201
263
|
*
|
|
@@ -236,6 +298,19 @@ export function readAliasedField(fm: object | null | undefined, current: string)
|
|
|
236
298
|
* `image` is retired on a map — which declares `img` — and remains an unknown
|
|
237
299
|
* key anywhere else.
|
|
238
300
|
*
|
|
301
|
+
* **`templatePriority` (#266).** The number that decides which of several
|
|
302
|
+
* competing templates the Create dialog offers was called `archetype`, and
|
|
303
|
+
* `archetypes` — one letter apart — is a list of what *sort* a character is.
|
|
304
|
+
* A priority and a taxonomy cannot be told apart by a plural `s`, so the
|
|
305
|
+
* priority takes the name that says what it is. The specification already
|
|
306
|
+
* called it `templatePriority` on two of its three sides.
|
|
307
|
+
*
|
|
308
|
+
* **`relations` (SoHL#1781).** The field holds a *map* of standings, one per
|
|
309
|
+
* affiliation — its own description says so, and `resolveRelation` has always
|
|
310
|
+
* read it that way. `relation` named the many as one, which every author had to
|
|
311
|
+
* read past. Only `affiliation` declares the field, so the alias is reported
|
|
312
|
+
* there and the old spelling stays an ordinary unknown key everywhere else.
|
|
313
|
+
*
|
|
239
314
|
* **`img` (#142).** Every note type names its artwork `img`, at the note's top
|
|
240
315
|
* level, and resolves it the same way. A map alone named its background art
|
|
241
316
|
* `image` and read it out of the `sohl:` block — two spellings for one idea,
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export function collectKnownActionNames(repoRoot: string): Set<string>;
|
|
16
16
|
export class Scenes extends BasePackCompiler {
|
|
17
|
-
constructor({ contentBase, dest, companionDests, folderResolver, repoRoot, }: {
|
|
17
|
+
constructor({ contentBase, dest, skipDirectories, companionDests, folderResolver, repoRoot, }: {
|
|
18
18
|
contentBase: any;
|
|
19
19
|
dest: any;
|
|
20
|
+
skipDirectories: any;
|
|
20
21
|
companionDests?: {} | undefined;
|
|
21
22
|
folderResolver?: (() => null) | undefined;
|
|
22
23
|
repoRoot?: string | undefined;
|
|
@@ -30,7 +31,7 @@ export class Scenes extends BasePackCompiler {
|
|
|
30
31
|
*/
|
|
31
32
|
adventureCount: number;
|
|
32
33
|
index: Map<string, object> | undefined;
|
|
33
|
-
effectsByAddress: Map<
|
|
34
|
+
effectsByAddress: Map<any, any> | undefined;
|
|
34
35
|
knownActions: Set<string> | undefined;
|
|
35
36
|
/** place key → `{name, img, scenes: [], journal: []}` */
|
|
36
37
|
places: Map<any, any> | undefined;
|
|
@@ -93,7 +93,7 @@ export function compareFields({ builders, artifact, documentType, subtypeOf, }:
|
|
|
93
93
|
* *observed*. {@link compareFields} reads the `itemBuilders` declarations and
|
|
94
94
|
* {@link checkAuthoredSystemData} reads a note's `<system>.system`; between them
|
|
95
95
|
* they miss every key a compiler writes on its own initiative, which is not a
|
|
96
|
-
* residue — it is `shortcode`, `actionDefs`, `notes`, `docHtml` and `
|
|
96
|
+
* residue — it is `shortcode`, `actionDefs`, `notes`, `docHtml` and `templatePriority`.
|
|
97
97
|
*
|
|
98
98
|
* **The keys come from the object the compiler built, after a JSON round trip.**
|
|
99
99
|
* That is exactly what the pack file receives, so a key whose value is
|
|
@@ -159,11 +159,24 @@ export function compareEmittedSystem({ system, artifact, documentType, subtype,
|
|
|
159
159
|
* stamps no system at all, and a system that has not adopted the artifact yet
|
|
160
160
|
* is simply unchecked. Neither is an error, and the caller says which it was.
|
|
161
161
|
*
|
|
162
|
+
* **A build may have more than one system, and then the caller names it (#139).**
|
|
163
|
+
* `stats.systemId` is the package-wide answer, and a repository shipping content
|
|
164
|
+
* for two systems has no package-wide answer — it is deliberately `null` there,
|
|
165
|
+
* because a module feeding both `sohl` and `hm3` targets neither. Left at that,
|
|
166
|
+
* every schema check in such a build would be skipped in silence, which is the
|
|
167
|
+
* state #60 exists to remove: the five type names the two systems *share* are
|
|
168
|
+
* exactly the ones a wrong-system emission hides in. So a pass supplies the
|
|
169
|
+
* system its pack declares, and the version comes from that system's own
|
|
170
|
+
* `systems:` entry rather than from a package-wide stamp.
|
|
171
|
+
*
|
|
162
172
|
* @param {object} config - The resolved build configuration.
|
|
173
|
+
* @param {string|null} [system] - The system whose schema is wanted. Defaults
|
|
174
|
+
* to the package-wide `stats.systemId`, which is every single-system build
|
|
175
|
+
* and the behaviour this always had.
|
|
163
176
|
* @returns {{artifact: SchemaArtifact, source: string}|null} The schema and
|
|
164
177
|
* where it was read from.
|
|
165
178
|
*/
|
|
166
|
-
export function resolveSchemaArtifact(config: object): {
|
|
179
|
+
export function resolveSchemaArtifact(config: object, system?: string | null): {
|
|
167
180
|
artifact: SchemaArtifact;
|
|
168
181
|
source: string;
|
|
169
182
|
} | null;
|
|
@@ -238,14 +251,18 @@ export function emittedUndeclaredMessage(finding: EmissionFinding): string;
|
|
|
238
251
|
* @param {string} opts.block - The system block to read, e.g. `"sohl"`.
|
|
239
252
|
* @param {string} opts.documentType - `Item`, `Actor`, …
|
|
240
253
|
* @param {string} opts.subType - The document subtype the note compiles into.
|
|
254
|
+
* @param {string} [opts.system] - The system whose published schema to read,
|
|
255
|
+
* where a build has more than one (#139). Defaults to the package-wide
|
|
256
|
+
* `stats.systemId`.
|
|
241
257
|
* @param {object} [opts.config] - The resolved build configuration.
|
|
242
258
|
* @returns {{path: string, message: string}[]} One finding per undeclared path,
|
|
243
259
|
* shallowest-first.
|
|
244
260
|
*/
|
|
245
|
-
export function checkAuthoredSystemData(fm: object, { block, documentType, subType, config }: {
|
|
261
|
+
export function checkAuthoredSystemData(fm: object, { block, documentType, subType, system, config }: {
|
|
246
262
|
block: string;
|
|
247
263
|
documentType: string;
|
|
248
264
|
subType: string;
|
|
265
|
+
system?: string | undefined;
|
|
249
266
|
config?: object | undefined;
|
|
250
267
|
}): {
|
|
251
268
|
path: string;
|
|
@@ -275,10 +292,13 @@ export function checkAuthoredSystemData(fm: object, { block, documentType, subTy
|
|
|
275
292
|
* @param {string} opts.type - The note's content type, for the message.
|
|
276
293
|
* @param {readonly {to?: string}[]} [opts.fields] - The type's field
|
|
277
294
|
* declaration, which decides each finding's origin.
|
|
295
|
+
* @param {string} [opts.system] - The system whose published schema to read,
|
|
296
|
+
* where a build has more than one (#139). Defaults to the package-wide
|
|
297
|
+
* `stats.systemId`.
|
|
278
298
|
* @param {object} [opts.config] - The resolved build configuration.
|
|
279
299
|
* @returns {(EmissionFinding & {message: string})[]} One per undeclared path.
|
|
280
300
|
*/
|
|
281
|
-
export function checkEmittedSystemData(
|
|
301
|
+
export function checkEmittedSystemData(emitted: any, { fm, block, documentType, subType, type, fields, system, config, }: {
|
|
282
302
|
fm: object;
|
|
283
303
|
block: string;
|
|
284
304
|
documentType: string;
|
|
@@ -287,6 +307,7 @@ export function checkEmittedSystemData(system: object, { fm, block, documentType
|
|
|
287
307
|
fields?: readonly {
|
|
288
308
|
to?: string;
|
|
289
309
|
}[] | undefined;
|
|
310
|
+
system?: string | undefined;
|
|
290
311
|
config?: object | undefined;
|
|
291
312
|
}): (EmissionFinding & {
|
|
292
313
|
message: string;
|
|
@@ -127,10 +127,10 @@ export function writeHomepages(outRoot: string, pages: readonly object[], config
|
|
|
127
127
|
* @param {object[]} pages - Every page, from both walks.
|
|
128
128
|
* @param {object} findings - `{ addressFindings, fmLinkFindings }` from
|
|
129
129
|
* collection.
|
|
130
|
-
* @param {object} options - `{
|
|
130
|
+
* @param {object} options - `{ config }`.
|
|
131
131
|
* @returns {object} The gate results and, when they pass, the built index.
|
|
132
132
|
*/
|
|
133
|
-
export function siteGates(pages: object[], findings: object, {
|
|
133
|
+
export function siteGates(pages: object[], findings: object, { config }: object): object;
|
|
134
134
|
/**
|
|
135
135
|
* The gate result of a build that ran none of them.
|
|
136
136
|
*
|
|
@@ -374,7 +374,7 @@ export function resolveOutputRoot(rootDir: string, out: string): string;
|
|
|
374
374
|
* @returns {{gates: object, stats: object|null, tableErrors: object[],
|
|
375
375
|
* wikiErrors: object[], manifests: object|null}}
|
|
376
376
|
*/
|
|
377
|
-
export function buildSite({ config, outRoot }?: {
|
|
377
|
+
export function buildSite({ config, outRoot, sqlTables }?: {
|
|
378
378
|
config?: object | undefined;
|
|
379
379
|
outRoot?: string | undefined;
|
|
380
380
|
}): {
|
|
@@ -385,4 +385,4 @@ export function buildSite({ config, outRoot }?: {
|
|
|
385
385
|
manifests: object | null;
|
|
386
386
|
};
|
|
387
387
|
export { formatUnaddressableFinding };
|
|
388
|
-
import { formatUnaddressableFinding } from "./
|
|
388
|
+
import { formatUnaddressableFinding } from "./metadata-index.mjs";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* each already knowing its own `url`.
|
|
6
6
|
* @param {object} [options] - Cross-package inputs.
|
|
7
7
|
* @param {Map<string, {package: string, type?: string}>} [options.foreignIndex]
|
|
8
|
-
* The merged index from `
|
|
8
|
+
* The merged index from `loadForeignIndexes`. Omit when the build publishes
|
|
9
9
|
* no cross-package links.
|
|
10
10
|
* @returns {SiteIndex} The index, and what could not be addressed unambiguously.
|
|
11
11
|
*/
|