@heroiclands/package-build 22.5.0 → 22.6.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.
@@ -82,13 +82,16 @@ export class BasePackCompiler {
82
82
  static readsPackOutputOf: readonly string[];
83
83
  /**
84
84
  * Whether this pass's document **is** a system's data, and therefore takes
85
- * only notes that carry that system's block.
85
+ * only notes that carry the block this pass reads.
86
86
  *
87
- * A pack may declare a `system:` — `harn-ensemble` ships an `actors-hm3`
88
- * and an `actors-sohl` from one tree — and the note-side half of that is
89
- * the block named after the system. A note carrying no such block has
90
- * nothing to say about it, so compiling it there would emit a **hollow
91
- * document**: a subtype, and none of the fields the subtype exists for.
87
+ * The question is asked of {@link BasePackCompiler#system} — the pass's own
88
+ * system, which an Actor or Item pass always has — rather than of the
89
+ * pack's `system:`, which a pack need not declare. A note carrying no such
90
+ * block has nothing to say about that system, so compiling it would emit a
91
+ * **hollow document**: a subtype, and none of the fields the subtype exists
92
+ * for. `harn-ensemble` ships an `actors-hm3` and an `actors-sohl` from one
93
+ * tree, and `sohl-thalorna` ships one `actors` declaring nothing; the rule
94
+ * is the same in both, because it is the pass that reads a block.
92
95
  *
93
96
  * False by default, because most passes write documents that are not
94
97
  * system data at all. A JournalEntry of prose is the same document under
@@ -265,22 +268,49 @@ export class BasePackCompiler {
265
268
  * routes to no pack at all — a build failure, never a silent drop.
266
269
  */
267
270
  routesHere(fm: object): boolean;
271
+ /**
272
+ * The system block this pass reads, where it reads one.
273
+ *
274
+ * `undefined` on the base class, because most passes read none: a
275
+ * JournalEntry, a Macro, a Scene and an Adventure are Foundry's documents
276
+ * rather than any system's. The Actor and Item passes answer with the
277
+ * block their {@link SystemActorCompiler.documentSubtypes} names, which is
278
+ * the same declaration that says which notes they claim and what each
279
+ * becomes.
280
+ *
281
+ * Stated here so {@link BasePackCompiler#eligibleFor} is total: a pass
282
+ * declaring `requiresSystemBlock` without a system reads no block, and a
283
+ * note can carry nothing for it.
284
+ *
285
+ * @returns {string|undefined} The block key, or `undefined`.
286
+ */
287
+ get system(): string | undefined;
268
288
  /**
269
289
  * Whether a claimed, routed note may become this pack's document at all.
270
290
  *
271
- * The pack-eligibility gate, and it fails rather than skipping: a note that
272
- * routed *here* and carries nothing for this pack's system is an authoring
273
- * mistake with a hollow document at the end of it, not a note that belongs
274
- * to another pass. Skipping it quietly is how a whole tree compiles to
275
- * documents nobody can use.
291
+ * **A system block is what makes a game document.** A pass whose document
292
+ * *is* a system's data compiles a note only where the note carries the
293
+ * block that pass reads, so a note saying nothing about any system becomes
294
+ * no Actor and no Item anywhere — its prose still compiles into a page, a
295
+ * PDF leaf and a JournalEntry, which are documents no system defines.
296
+ *
297
+ * Asked of this pass's own {@link BasePackCompiler#system}, never of the
298
+ * pack's `system:`. A pack declaring none is a single-system convenience
299
+ * compiled by the fallback pass for its document type, and that pass still
300
+ * reads exactly one block — so the note-side question is the same one
301
+ * whether or not the pack answered it.
302
+ *
303
+ * A note this pass has nothing to compile is **skipped**, counted like any
304
+ * other note the pack does not own. A deliberately unstatted person is the
305
+ * ordinary case, and a block deleted by accident shows in the diff that
306
+ * deleted it; what would otherwise be discarded in silence is the block
307
+ * written for a system no pack of the class serves, and that is reported by
308
+ * {@link module:engine/note-claims.unclaimedNoteFindings} rather than here,
309
+ * where a pass can see only its own half of the configuration.
276
310
  *
277
311
  * @param {object} fm - The note's frontmatter.
278
312
  * @returns {boolean} True when the note may be compiled here; `false` when
279
- * it belongs to another system's pass of the same document type, which is
280
- * skipped as quietly as any other note this pack does not own.
281
- * @throws {Error} When this pack's system is absent from the note and no
282
- * other configured system claims it. The error carries a `position` where
283
- * the note's own file can be read.
313
+ * it carries nothing for this pass's system.
284
314
  */
285
315
  eligibleFor(fm: object): boolean;
286
316
  /**
@@ -104,9 +104,10 @@ export function asciiAliases(aliases: unknown): Array<string>;
104
104
  * @returns {Record<string, any>} The record, keys sorted at every depth. A
105
105
  * **stub** — a note with an empty body, on a type an empty body suppresses —
106
106
  * carries `address` and `anchors` as `null`: it publishes no page, so it
107
- * holds no address and offers no anchor. It keeps everything else, its `id`
108
- * and its `foundry` block included, because the document it compiles is
109
- * derived from `data:` rather than from prose.
107
+ * holds no address and offers no anchor. It keeps its `id`, and a `foundry`
108
+ * block naming every document that was made — which is every document
109
+ * derived from `data:`, and no journal, because a journal of an empty body
110
+ * would be empty and is not created.
110
111
  * @throws {Error} When the note carries a key this module derives, which would
111
112
  * otherwise be overwritten without a word. `file` and, where the file was
112
113
  * read, `position` ride on the error.
@@ -1,11 +1,40 @@
1
+ /**
2
+ * The system-specific compilers, derived from the passes themselves.
3
+ *
4
+ * A repository feeding two systems declares one Item pack and one Actor pack
5
+ * per system — `harn-ensemble` has `actors-hm3` and `actors-sohl` — and each
6
+ * pack's `system:` is what says whose data model its documents are shaped for.
7
+ * That is the same field the `_stats` stamp, the item-catalogue scope and the
8
+ * `itemBuilders` lookup already read, so nothing new is declared to make the
9
+ * compiler follow it.
10
+ *
11
+ * @param {readonly Function[]} passes - The system passes to table.
12
+ * @returns {Readonly<Record<string, Readonly<Record<string, Function>>>>}
13
+ * System id → document class → pass.
14
+ * @throws {Error} When a pass declares no system or no document class, which is
15
+ * a pass that cannot be addressed by either question this table answers.
16
+ */
17
+ export function systemCompilers(passes: readonly Function[]): Readonly<Record<string, Readonly<Record<string, Function>>>>;
1
18
  /**
2
19
  * The compiler class a pack of one document type and one system gets.
3
20
  *
21
+ * A pack declaring **no** system takes the fallback pass for its document
22
+ * class, which reads
23
+ * {@link module:engine/subtype-registry.DEFAULT_DOCUMENT_SUBTYPES} — the
24
+ * single-system convenience every tree shipping for one system is built on.
25
+ *
26
+ * A pack declaring a system this toolchain has no pass for is **refused by
27
+ * name**. Falling through to the fallback would compile that pack out of
28
+ * another system's blocks and ship it stamped with the system it asked for,
29
+ * which is the quiet failure the refusal exists to replace.
30
+ *
4
31
  * @param {string} docType - The Foundry document type the pack holds.
5
32
  * @param {string|null} [system] - The system the pack declares, if any.
6
33
  * @returns {Function|undefined} The compiler class, or `undefined` for a
7
34
  * document type nothing here compiles — which {@link generatePack} reports
8
35
  * rather than defaulting past.
36
+ * @throws {Error} When a system-bearing document class is asked for a system
37
+ * this toolchain ships no pass for.
9
38
  */
10
39
  export function compilerFor(docType: string, system?: string | null): Function | undefined;
11
40
  /**
@@ -10,24 +10,23 @@ export function infoboxFor(system: string | undefined): object | undefined;
10
10
  * Whether one system compiles a document for one note.
11
11
  *
12
12
  * This is what a system box's _available_ asserts, and it is the compile's own
13
- * question rather than a reading of the frontmatter. A note carrying no block
14
- * is not a note a system has nothing for: where the pack compiling its document
15
- * declares no `system:`, the document is built from `data:` and the field
16
- * defaults and ships exactly like any other.
13
+ * question rather than a reading of the frontmatter.
17
14
  *
18
15
  * Three statements answer it, and they are the three the compile itself
19
16
  * follows:
20
17
  *
21
- * 1. **The map** says which document class this system makes of the note's
18
+ * 1. **The note's block.** A system block is what makes a game document, so a
19
+ * note carrying nothing for this system compiles into no document of it
20
+ * anywhere — the rule
21
+ * {@link module:engine/base-compiler.BasePackCompiler#eligibleFor} applies,
22
+ * asked here from outside.
23
+ * 2. **The map** says which document class this system makes of the note's
22
24
  * type. No row, no document — and no box either, which is why a caller
23
25
  * reaching here already has one.
24
- * 2. **The router** says which pack that document goes to, read from the pack
25
- * list this build is driven by.
26
- * 3. **That pack's `system:`** decides the rest. Declaring one, it writes that
27
- * system's data and takes only notes that say something about it — the rule
28
- * {@link module:engine/base-compiler.BasePackCompiler#eligibleFor} applies,
29
- * asked here from outside. Declaring none, it is compiled by the fallback
30
- * pass, which needs no block and answers for
26
+ * 3. **The router** says which pack that document goes to, read from the pack
27
+ * list this build is driven by, and **that pack's `system:`** decides whose
28
+ * it is. Declaring one, it writes that system's data. Declaring none, it is
29
+ * compiled by the fallback pass, which reads
31
30
  * {@link module:engine/subtype-registry.DEFAULT_DOCUMENT_SUBTYPES} alone —
32
31
  * so a tree with no HM3 pack ships no HM3 document however a note is
33
32
  * written.
@@ -29,6 +29,17 @@ export function itemDescription(markdown: string, fm: object, name: string): str
29
29
  * a configuration one.
30
30
  */
31
31
  export class SystemItemCompiler extends BasePackCompiler {
32
+ /**
33
+ * The Foundry document class this pass writes.
34
+ *
35
+ * Declared by the class that does the writing, so the table pairing a
36
+ * system with its passes is derived from the passes themselves rather than
37
+ * written out a second time — see
38
+ * {@link module:engine/generate.systemCompilers}.
39
+ *
40
+ * @type {string}
41
+ */
42
+ static documentClass: string;
32
43
  /**
33
44
  * The note-type → document-subtype map this pass compiles against.
34
45
  *
@@ -102,7 +102,12 @@ export function claimedNoteTypes(config?: object, sources?: ClaimSources): Reado
102
102
  */
103
103
  export function noteTypeVocabulary(sources?: ClaimSources): ReadonlySet<string>;
104
104
  /**
105
- * Every note in the content tree that no configured pack would compile.
105
+ * Every note in the content tree that no configured pack would compile, and
106
+ * every system block no configured pack would read.
107
+ *
108
+ * Two questions of one walk, because they are the same question asked of a
109
+ * note's type and of a note's systems, and a note can fail either while passing
110
+ * the other — see {@link discardedSystemBlockFindings}.
106
111
  *
107
112
  * Read-only: it walks the tree and reports, and writes nothing. Three kinds of
108
113
  * note are passed over, each for a stated reason rather than by omission — a
@@ -59,6 +59,32 @@ export function isStubbableType(type: string | null | undefined, vocabulary?: Re
59
59
  export function isStubNote(frontmatter: Record<string, any> | null | undefined, body: string | null | undefined, vocabulary?: Readonly<Record<string, {
60
60
  stubbable?: boolean;
61
61
  }>>): boolean;
62
+ /**
63
+ * Whether a note's body compiles into a JournalEntry that holds anything.
64
+ *
65
+ * > **A document that would be empty is not created.** Nothing names one
66
+ * > either: the index records the note with every field that names an artefact
67
+ * > set to `null`.
68
+ *
69
+ * The question is about the **output**, not the input, and that is what makes
70
+ * one rule serve every caller: a note's own journal, and the documentation
71
+ * journal an item's prose compiles into beside it, are the same document asked
72
+ * the same question.
73
+ *
74
+ * A JournalEntry's content is its pages, and a page comes from
75
+ * {@link module:engine/journals.splitPages} — a lead page of the prose before
76
+ * the first heading, and one page per heading after it. A body of whitespace
77
+ * yields neither, so an empty body is exactly an empty journal.
78
+ *
79
+ * **An infobox does not count.** The panel is a rendering of `data:`, which the
80
+ * index already publishes; an entry holding nothing else gives a consumer
81
+ * nothing it cannot read from the record.
82
+ *
83
+ * @param {string|null|undefined} body - The note body, frontmatter stripped.
84
+ * @returns {boolean} Whether a JournalEntry compiled from this body holds
85
+ * anything.
86
+ */
87
+ export function journalHasContent(body: string | null | undefined): boolean;
62
88
  /**
63
89
  * The placeholder phrases a body reduces to, or an empty list.
64
90
  *
@@ -50,12 +50,15 @@ export const KNOWN_DOCUMENT_SUBTYPE_MAPS: readonly import("./document-subtypes.m
50
50
  /**
51
51
  * The map a pack declaring no `system:` compiles its documents against.
52
52
  *
53
- * A pack names the system its documents are shaped for, and one declaring none
54
- * is compiled by the fallback pass for its document type — a single-system
53
+ * **The single-system fallback, and not a default any system inherits.** A pack
54
+ * names the system its documents are shaped for, and one declaring none is
55
+ * compiled by the fallback pass for its document type — a single-system
55
56
  * package's ordinary arrangement, and the one `sohl-thalorna` ships. That pass
56
- * follows one map whatever a note carries, which makes this the answer to "a
57
- * document compiled here belongs to *which* system?" wherever a pack has not
58
- * said.
57
+ * reads this map's block and no other, so a note carrying nothing for this
58
+ * system compiles into no document there; a note carrying another system's
59
+ * block reaches that system's pass or nothing at all, never this one. This is
60
+ * the answer to "a document compiled here belongs to *which* system?" wherever
61
+ * a pack has not said, and it answers nothing about a system that has said.
59
62
  *
60
63
  * Stated here rather than read off the compiler classes because those are not
61
64
  * reachable from a leaf: `engine/item-compiler.mjs` imports the journals pass,
@@ -67,6 +70,30 @@ export const KNOWN_DOCUMENT_SUBTYPE_MAPS: readonly import("./document-subtypes.m
67
70
  * @type {import("./document-subtypes.mjs").DocumentSubtypeMap}
68
71
  */
69
72
  export const DEFAULT_DOCUMENT_SUBTYPES: import("./document-subtypes.mjs").DocumentSubtypeMap;
73
+ /**
74
+ * Every system this toolchain ships a map for, by id.
75
+ *
76
+ * Derived from {@link KNOWN_DOCUMENT_SUBTYPE_MAPS}, so registering a map is the
77
+ * whole of adding a system to every reader that asks "which systems are there?"
78
+ * — the per-system findings among them.
79
+ *
80
+ * @type {readonly string[]}
81
+ */
82
+ export const SHIPPED_SYSTEMS: readonly string[];
83
+ /**
84
+ * The Foundry document classes a system compiles its own data into.
85
+ *
86
+ * Derived from the shipped maps' rows, so it is the set of classes for which
87
+ * "which system?" is a question with consequences: a pack of one of these
88
+ * classes is compiled by one system's pass reading one system's block, and a
89
+ * note carrying no such block produces nothing there. Every other class — a
90
+ * JournalEntry, a Macro, a Scene, an Adventure — has one implementation
91
+ * whatever a pack declares, because it is Foundry's document rather than any
92
+ * system's.
93
+ *
94
+ * @type {ReadonlySet<string>}
95
+ */
96
+ export const SYSTEM_DOCUMENT_CLASSES: ReadonlySet<string>;
70
97
  /**
71
98
  * Every note type any shipped map compiles into an **Actor**.
72
99
  *