@heroiclands/package-build 20.3.0 → 20.4.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.
Files changed (178) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/CONTENT.md +111 -92
  3. package/README.md +2 -9
  4. package/bin/content-build.mjs +70 -61
  5. package/bin/package-build.mjs +2 -2
  6. package/config.mjs +6 -8
  7. package/content-config.mjs +187 -64
  8. package/docs/content-format.md +57 -68
  9. package/e2e.mjs +4 -4
  10. package/engine/actor-compiler.mjs +36 -36
  11. package/engine/address-charset.mjs +6 -6
  12. package/engine/address-diff.mjs +12 -11
  13. package/engine/anchored-sections.mjs +1 -1
  14. package/engine/anchors.mjs +1 -1
  15. package/engine/base-compiler.mjs +36 -38
  16. package/engine/bundle-notes.mjs +4 -4
  17. package/engine/bundles.mjs +8 -8
  18. package/engine/code-fences.mjs +3 -3
  19. package/engine/compendiums.mjs +8 -8
  20. package/engine/compile-corpus.mjs +4 -5
  21. package/engine/content-address.mjs +15 -15
  22. package/engine/content-charset.mjs +1 -1
  23. package/engine/content-format-check.mjs +24 -25
  24. package/engine/content-format.mjs +8 -8
  25. package/engine/content-html.mjs +202 -0
  26. package/engine/content-icons.mjs +225 -98
  27. package/engine/content-index.mjs +17 -17
  28. package/engine/content-links.mjs +30 -30
  29. package/engine/content-lint.mjs +20 -24
  30. package/engine/content-package.mjs +7 -9
  31. package/engine/content-slug.mjs +2 -2
  32. package/engine/content-tables.mjs +7 -8
  33. package/engine/content-tree.mjs +1 -1
  34. package/engine/derived-fields.mjs +174 -0
  35. package/engine/diagnostics.mjs +3 -4
  36. package/engine/document-subtypes.mjs +6 -7
  37. package/engine/field-reference.mjs +8 -8
  38. package/engine/field-spec.mjs +29 -30
  39. package/engine/folder-notes.mjs +14 -14
  40. package/engine/foreign-catalog.mjs +8 -9
  41. package/engine/foundry-entries.mjs +19 -20
  42. package/engine/frontmatter-lint.mjs +64 -69
  43. package/engine/frontmatter.mjs +11 -11
  44. package/engine/generate.mjs +39 -39
  45. package/engine/helpers.mjs +63 -54
  46. package/engine/homepage.mjs +20 -22
  47. package/engine/ids.mjs +15 -15
  48. package/engine/index-records.mjs +4 -4
  49. package/engine/index.mjs +14 -8
  50. package/engine/item-compiler.mjs +54 -29
  51. package/engine/item-docs.mjs +11 -13
  52. package/engine/item-registry.mjs +13 -13
  53. package/engine/journals.mjs +15 -15
  54. package/engine/macros.mjs +3 -3
  55. package/engine/map-notes.mjs +6 -6
  56. package/engine/metadata-index.mjs +5 -5
  57. package/engine/note-claims.mjs +36 -34
  58. package/engine/note-ids.mjs +5 -5
  59. package/engine/note-package.mjs +4 -4
  60. package/engine/note-renames.mjs +3 -3
  61. package/engine/note-schemas.mjs +3 -3
  62. package/engine/note-vocabulary.mjs +27 -26
  63. package/engine/pack-config.mjs +13 -13
  64. package/engine/pack-router.mjs +0 -0
  65. package/engine/prose-config.mjs +9 -9
  66. package/engine/prose-lint.mjs +12 -13
  67. package/engine/region-events.mjs +2 -2
  68. package/engine/retired-fields.mjs +24 -22
  69. package/engine/runtime-only-fields.mjs +1 -1
  70. package/engine/scene-levels.mjs +1 -1
  71. package/engine/scenes.mjs +19 -20
  72. package/engine/schema-check.mjs +20 -20
  73. package/engine/schema-extract.mjs +1 -1
  74. package/engine/site-build.mjs +45 -47
  75. package/engine/site-index.mjs +17 -18
  76. package/engine/sql-tables.mjs +21 -13
  77. package/engine/subtype-registry.mjs +5 -4
  78. package/engine/system-block.mjs +18 -19
  79. package/engine/systems.mjs +2 -2
  80. package/engine/web-wikilinks.mjs +35 -35
  81. package/engine/wikilink-syntax.mjs +16 -16
  82. package/engine/wikilinks.mjs +39 -39
  83. package/hm3/actors.mjs +22 -22
  84. package/hm3/document-subtypes.mjs +5 -5
  85. package/hm3/index.mjs +2 -2
  86. package/hm3/item-builders.mjs +1 -1
  87. package/hm3/item-fields.mjs +3 -3
  88. package/hm3/items.mjs +20 -8
  89. package/hm3/template-priority.mjs +2 -2
  90. package/lang.mjs +3 -3
  91. package/manifest.mjs +17 -20
  92. package/package.json +1 -2
  93. package/release.mjs +3 -3
  94. package/sohl/actors.mjs +28 -28
  95. package/sohl/affiliation-standings.mjs +2 -2
  96. package/sohl/being-info.mjs +5 -5
  97. package/sohl/default-item-art.mjs +5 -5
  98. package/sohl/document-subtypes.mjs +5 -5
  99. package/sohl/index.mjs +3 -3
  100. package/sohl/item-builders.mjs +7 -7
  101. package/sohl/item-fields.mjs +8 -9
  102. package/sohl/items.mjs +20 -6
  103. package/sohl/kb-passes.mjs +5 -5
  104. package/sohl/note-schemas.mjs +7 -7
  105. package/sohl/skill-base.mjs +1 -1
  106. package/types/content-config.d.mts +25 -24
  107. package/types/e2e.d.mts +3 -3
  108. package/types/engine/actor-compiler.d.mts +14 -13
  109. package/types/engine/address-charset.d.mts +6 -6
  110. package/types/engine/address-diff.d.mts +3 -3
  111. package/types/engine/base-compiler.d.mts +17 -19
  112. package/types/engine/bundle-notes.d.mts +3 -3
  113. package/types/engine/bundles.d.mts +1 -1
  114. package/types/engine/code-fences.d.mts +3 -3
  115. package/types/engine/compendiums.d.mts +3 -3
  116. package/types/engine/compile-corpus.d.mts +1 -1
  117. package/types/engine/content-address.d.mts +11 -11
  118. package/types/engine/content-format-check.d.mts +6 -6
  119. package/types/engine/content-format.d.mts +2 -2
  120. package/types/engine/content-html.d.mts +78 -0
  121. package/types/engine/content-icons.d.mts +150 -62
  122. package/types/engine/content-index.d.mts +2 -2
  123. package/types/engine/content-links.d.mts +8 -8
  124. package/types/engine/content-lint.d.mts +2 -2
  125. package/types/engine/content-package.d.mts +6 -8
  126. package/types/engine/derived-fields.d.mts +101 -0
  127. package/types/engine/diagnostics.d.mts +2 -2
  128. package/types/engine/document-subtypes.d.mts +3 -3
  129. package/types/engine/field-spec.d.mts +37 -39
  130. package/types/engine/folder-notes.d.mts +4 -5
  131. package/types/engine/foreign-catalog.d.mts +3 -3
  132. package/types/engine/foundry-entries.d.mts +6 -7
  133. package/types/engine/frontmatter-lint.d.mts +7 -7
  134. package/types/engine/frontmatter.d.mts +7 -7
  135. package/types/engine/generate.d.mts +7 -7
  136. package/types/engine/helpers.d.mts +25 -27
  137. package/types/engine/homepage.d.mts +16 -18
  138. package/types/engine/ids.d.mts +13 -13
  139. package/types/engine/index-records.d.mts +3 -3
  140. package/types/engine/index.d.mts +2 -0
  141. package/types/engine/item-compiler.d.mts +21 -5
  142. package/types/engine/item-docs.d.mts +2 -2
  143. package/types/engine/item-registry.d.mts +6 -6
  144. package/types/engine/journals.d.mts +3 -3
  145. package/types/engine/map-notes.d.mts +2 -2
  146. package/types/engine/metadata-index.d.mts +4 -4
  147. package/types/engine/note-claims.d.mts +16 -15
  148. package/types/engine/note-ids.d.mts +4 -4
  149. package/types/engine/note-package.d.mts +1 -1
  150. package/types/engine/note-renames.d.mts +3 -3
  151. package/types/engine/note-vocabulary.d.mts +9 -8
  152. package/types/engine/pack-config.d.mts +3 -3
  153. package/types/engine/pack-router.d.mts +1 -1
  154. package/types/engine/prose-config.d.mts +9 -9
  155. package/types/engine/prose-lint.d.mts +3 -4
  156. package/types/engine/region-events.d.mts +2 -2
  157. package/types/engine/retired-fields.d.mts +10 -9
  158. package/types/engine/schema-check.d.mts +11 -11
  159. package/types/engine/site-build.d.mts +18 -19
  160. package/types/engine/site-index.d.mts +3 -4
  161. package/types/engine/sql-tables.d.mts +11 -5
  162. package/types/engine/subtype-registry.d.mts +3 -3
  163. package/types/engine/system-block.d.mts +3 -3
  164. package/types/engine/web-wikilinks.d.mts +7 -7
  165. package/types/engine/wikilink-syntax.d.mts +17 -17
  166. package/types/engine/wikilinks.d.mts +13 -12
  167. package/types/hm3/actors.d.mts +1 -1
  168. package/types/hm3/document-subtypes.d.mts +1 -1
  169. package/types/hm3/items.d.mts +1 -2
  170. package/types/hm3/template-priority.d.mts +1 -1
  171. package/types/manifest.d.mts +8 -8
  172. package/types/sohl/actors.d.mts +2 -2
  173. package/types/sohl/affiliation-standings.d.mts +2 -2
  174. package/types/sohl/being-info.d.mts +2 -2
  175. package/types/sohl/document-subtypes.d.mts +1 -1
  176. package/types/sohl/items.d.mts +1 -2
  177. package/types/sohl/note-schemas.d.mts +1 -1
  178. package/MIGRATING.md +0 -608
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 (#139), and it reached its
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 (#79).
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.
@@ -44,13 +44,27 @@ import { SOHL_DOCUMENT_SUBTYPES } from "./document-subtypes.mjs";
44
44
  export class Items extends SystemItemCompiler {
45
45
  /**
46
46
  * 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).
47
+ * which block this pass reads, which notes it claims, and what each becomes.
49
48
  *
50
49
  * @type {import("../engine/document-subtypes.mjs").DocumentSubtypeMap}
51
50
  */
52
51
  static documentSubtypes = SOHL_DOCUMENT_SUBTYPES;
53
52
 
53
+ /**
54
+ * The `system` keys this pass derives from the note.
55
+ *
56
+ * `docHtml` holds the `@UUID` of the JournalEntry the note's prose compiled
57
+ * into, so a note writing prose there ships a string where every reader
58
+ * expects a pointer. `notes` is a play-time scratchpad the compiler writes
59
+ * empty, so an authored one ships a note's content as a GM's jottings.
60
+ *
61
+ * @type {readonly {key: string, from: string}[]}
62
+ */
63
+ static derivedSystemKeys = Object.freeze([
64
+ { key: "docHtml", from: "the note's own body" },
65
+ { key: "notes", from: "the note's own body" },
66
+ ]);
67
+
54
68
  /**
55
69
  * The `system.*` fields SoHL writes on every item, whatever its type:
56
70
  * shortcode, templatePriority, actionDefs, notes, docHtml.
@@ -65,8 +79,8 @@ export class Items extends SystemItemCompiler {
65
79
  return {
66
80
  shortcode: fm.shortcode,
67
81
  // Required nullable number: a priority, or `null` for a document
68
- // that is not a template (#126 / archetype contract #604). The
69
- // field was `system.archetype` until #266 / sohl#1836; the receiving
82
+ // that is not a template (the archetype contract).
83
+ // `system.archetype` is the legacy spelling; the receiving
70
84
  // schema declares only the new name, so the emitted key moves with
71
85
  // it — an undeclared `system` key is discarded at construction
72
86
  // without a warning.
@@ -12,12 +12,12 @@
12
12
  */
13
13
 
14
14
  /**
15
- * The `sohl` knowledgebase's own body passes (#63).
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 #63 rules them explicitly per-consumer.
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 (#75). Degrading
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 (#75).
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 #51's end-to-end verification, running
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.
@@ -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 (#19).
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 (#22).
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
@@ -94,7 +94,7 @@ const MACRO_FIELDS = Object.freeze([
94
94
  * vehicle two `data` properties and no `sohl:` field of its own, and the
95
95
  * closed `data:` container is where `engine/note-vocabulary.mjs` holds them.
96
96
  * Declaring the type with no fields distinguishes a type with no vocabulary
97
- * from a type that is unknown, which are different findings (#231).
97
+ * from a type that is unknown, which are different findings.
98
98
  *
99
99
  * It is here rather than in the engine because a vehicle is a SoHL actor —
100
100
  * the specification maps it to `sohl` and marks it NA for hm3.
@@ -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 (#174). Compiled into a
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 until #142, which read both while the trees were
152
- * swept; that retirement has since completed and `image` is gone (#149).
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 (#51).
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
  */
@@ -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 (#46).
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
@@ -49,7 +49,7 @@ export namespace DEFAULT_PATHS {
49
49
  /**
50
50
  * The Foundry document types a compendium pack may hold. This is the set the
51
51
  * toolchain is able to compile a pack of; a document type Foundry supports but
52
- * this toolchain does not compile is deliberately absent (see #1501 — playlists
52
+ * this toolchain does not compile is deliberately absent (playlists
53
53
  * and roll tables are out of scope).
54
54
  *
55
55
  * @satisfies {readonly PackDocumentType[]}
@@ -68,15 +68,11 @@ export const PACK_DOCUMENT_TYPES: readonly ["Actor", "Adventure", "Item", "Journ
68
68
  * key is **refused**, at the line it was written on, with a message that says
69
69
  * the mechanism is gone rather than naming a value to correct.
70
70
  *
71
- * **What `landing` did (#204).** It named which note addressed a whole section
71
+ * **`landing` is one such key.** It named which note addressed a whole section
72
72
  * rather than a page within one — a *landing page*, which therefore had no slug
73
- * of its own. #203 retired the second of its two rules and #204 retired the
74
- * concept both rules chose between: a section is a Hugo content directory that
75
- * the note format does not carry, a page's address names no directory, and so
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.
73
+ * of its own. There are no sections to address: a section is a Hugo content
74
+ * directory the note format does not carry, a page's address names no
75
+ * directory, and so no note lands anything.
80
76
  *
81
77
  * @type {Readonly<Record<string, string>>}
82
78
  */
@@ -89,7 +85,7 @@ export const RETIRED_ADDRESS_KEYS: Readonly<Record<string, string>>;
89
85
  * `thalorna`, whose site is nothing but its content. It is not the package's
90
86
  * own mount point: where the package itself is served is the consuming build's
91
87
  * knowledge, held in `PACKAGE_BASE` (`engine/content-address.mjs`) and prefixed at
92
- * resolve time, so it is never recorded here (#1465).
88
+ * resolve time, so it is never recorded here.
93
89
  *
94
90
  * It is the whole scheme: `landing`, the key that named which note addressed a
95
91
  * whole section, is retired with the sections themselves — see
@@ -103,7 +99,7 @@ export const DEFAULT_ADDRESS_SCHEME: Readonly<{
103
99
  *
104
100
  * Every HeroicLands package publishes something: a top-level, human-authored
105
101
  * homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
106
- * module is, which system it needs and how to install it (#50). So there is no
102
+ * module is, which system it needs and how to install it. So there is no
107
103
  * value here meaning *no web presence at all* — homepage-only is the **floor**,
108
104
  * and the default.
109
105
  *
@@ -141,7 +137,7 @@ export const SITE_MODES: readonly ["homepage", "content"];
141
137
  * How the loader hands {@link defineConfig} the system version it resolved.
142
138
  *
143
139
  * A **Symbol**, deliberately. `stats.systemVersion` is refused from an authored
144
- * configuration (#48), but the value still has to reach here from the loader —
140
+ * configuration, but the value still has to reach here from the loader —
145
141
  * which is the half that may do I/O, and which reads a system package's version
146
142
  * out of the adjacent `package.json`. A string key would be a second spelling of
147
143
  * the refused one, forgeable from YAML and reachable by `rejectUnknownKeys`; a
@@ -156,7 +152,7 @@ export const DERIVED_SYSTEM_VERSION: symbol;
156
152
  *
157
153
  * Every HeroicLands package publishes something: a top-level, human-authored
158
154
  * homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
159
- * module is, which system it needs and how to install it (#50). So there is no
155
+ * module is, which system it needs and how to install it. So there is no
160
156
  * value here meaning *no web presence at all* — homepage-only is the **floor**,
161
157
  * and the default.
162
158
  *
@@ -194,7 +190,7 @@ export type PackDocumentType = "Actor" | "Adventure" | "Item" | "JournalEntry" |
194
190
  * type** receives its document. The two are orthogonal, and both are needed
195
191
  * once a repository groups same-type documents editorially — which it may have
196
192
  * to, since a compendium UUID carries its pack name and collapsing such a
197
- * layout breaks every stored reference (#1566).
193
+ * layout breaks every stored reference.
198
194
  */
199
195
  export type PackSpec = {
200
196
  /**
@@ -304,7 +300,7 @@ export type PathsInput = {
304
300
  foreignCache?: string | undefined;
305
301
  /**
306
302
  * Where a dependency's published content
307
- * index is fetched to (#239). Inbound,
303
+ * index is fetched to. Inbound,
308
304
  * for *every* declared dependency, not
309
305
  * only those supplying a catalogue.
310
306
  */
@@ -503,7 +499,7 @@ export type AddressSchemeInput = {
503
499
  * `fields` is what makes the type documentable: a builder function says
504
500
  * nothing about the vocabulary it consumes, so a consumer that declares its
505
501
  * fields can generate its own authoring reference and check its own notes,
506
- * while one that does not is simply undocumented rather than broken (#22).
502
+ * while one that does not is simply undocumented rather than broken.
507
503
  */
508
504
  export type ItemBuilderEntry = ((fm: object) => object) | {
509
505
  system: (fm: object) => object;
@@ -511,7 +507,7 @@ export type ItemBuilderEntry = ((fm: object) => object) | {
511
507
  fields?: readonly object[];
512
508
  };
513
509
  /**
514
- * One **registry** of a declared set, and the system it belongs to (#58).
510
+ * One **registry** of a declared set, and the system it belongs to.
515
511
  *
516
512
  * A repository shipping content for two systems declares one of these per
517
513
  * system: the accepted type vocabulary is their union, and a type both declare
@@ -570,7 +566,7 @@ export type ContentBuildConfigInput = {
570
566
  * two systems declares a **list** of
571
567
  * `{ system, builders }` registries
572
568
  * instead, and the accepted type
573
- * vocabulary is their union (#58).
569
+ * vocabulary is their union.
574
570
  */
575
571
  itemBuilders?: Record<string, ItemBuilderEntry> | readonly ItemRegistrySpec[] | undefined;
576
572
  /**
@@ -579,8 +575,7 @@ export type ContentBuildConfigInput = {
579
575
  * the pack it belongs in with its
580
576
  * `pack:` frontmatter, and one pack of
581
577
  * the type is marked `default: true` to
582
- * receive the notes that name none
583
- * (#1566).
578
+ * receive the notes that name none.
584
579
  */
585
580
  packs: PackSpec[];
586
581
  /**
@@ -658,14 +653,13 @@ export type ContentBuildConfig = {
658
653
  * the frontmatter fields each entry
659
654
  * declared. Sparse, like `itemArt` — a type
660
655
  * absent here compiles normally and is
661
- * simply undocumented (#22).
656
+ * simply undocumented.
662
657
  */
663
658
  itemFields: Readonly<Record<string, readonly object[]>>;
664
659
  /**
665
660
  * Derived: the same builders, kept per
666
661
  * declaring system. `{}` for the single
667
- * registry form, which names no system
668
- * (#58).
662
+ * registry form, which names no system.
669
663
  */
670
664
  itemBuildersBySystem: Readonly<Record<string, Readonly<Record<string, Function>>>>;
671
665
  /**
@@ -688,7 +682,7 @@ export type ContentBuildConfig = {
688
682
  * {@link ContentBuildConfigInput.itemBuilders},
689
683
  * unioned across every declared registry, so
690
684
  * the accepted item types and the builder
691
- * tables are one list (#1504).
685
+ * tables are one list.
692
686
  */
693
687
  itemTypes: ReadonlySet<string>;
694
688
  /**
@@ -700,6 +694,13 @@ export type ContentBuildConfig = {
700
694
  */
701
695
  docEntryTypes: ReadonlySet<string>;
702
696
  skipDirectories: readonly string[];
697
+ /**
698
+ * The
699
+ * fonts this package ships and the names it
700
+ * draws from them; empty when it declares
701
+ * none.
702
+ */
703
+ icons: import("./engine/content-icons.mjs").IconRegistry;
703
704
  packs: readonly Readonly<ResolvedPackSpec>[];
704
705
  /**
705
706
  * 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 (#153).
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 (#153).
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 (#153):
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
@@ -34,7 +34,7 @@ export function deepMerge(base: any, overlay: any): any;
34
34
  * vocabulary, so a reference is translated forward through the system's map
35
35
  * before it reaches this function; see
36
36
  * {@link SystemActorCompiler#embeddedSubtype} for why the translation goes that
37
- * way and not the other (#140).
37
+ * way and not the other.
38
38
  *
39
39
  * @param {string} subType - The Foundry Item subtype.
40
40
  * @param {string} shortcode - The item's `system.shortcode`.
@@ -43,7 +43,7 @@ export function deepMerge(base: any, overlay: any): any;
43
43
  export function itemAddress(subType: string, shortcode: string): string;
44
44
  /**
45
45
  * The key one predefined item is held under **for the package that publishes
46
- * it** — the address a `model:` naming that package resolves through (#334).
46
+ * it** — the address a `model:` naming that package resolves through.
47
47
  *
48
48
  * The unqualified {@link itemAddress} stays beside it, and the two answer
49
49
  * different questions. A `model` that names no package means *this* one and
@@ -70,11 +70,12 @@ export function packagedItemAddress(pkg: string, subType: string, shortcode: str
70
70
  * A shortcode is case-sensitive and routinely mixed — `Clb`, `LtShoe`,
71
71
  * `HsTunic` — while an **address** is not: `readQualifier` normalises what it
72
72
  * reads, and every canonical address is lowercase. So the moment a `model:` is
73
- * read as an address (#334), `weapongear-clb` has to find the document whose
74
- * `system.shortcode` is `Clb`, and an exact match cannot (#346).
73
+ * read as an address, `weapongear-clb` has to find the document whose
74
+ * `system.shortcode` is `Clb`, and an exact match cannot.
75
75
  *
76
76
  * Folding is safe because the fold is already the address: no two items in any
77
- * published tree differ only by the case of their shortcode, and #340 will make
77
+ * published tree differ only by the case of their shortcode, and the rule
78
+ * makes
78
79
  * that impossible rather than merely true.
79
80
  *
80
81
  * **This is not {@link itemAddress}, and must not become it.** That one seeds
@@ -116,13 +117,13 @@ export function embeddedIdentity(item: object): string;
116
117
  * four corpora holds 180 items, at which 64 bits collide with probability
117
118
  * around 10⁻¹⁵.
118
119
  *
119
- * **It takes no index** (#268). Keying on a position meant reordering a being's
120
+ * **It takes no index**. Keying on a position meant reordering a being's
120
121
  * item list renumbered every id after the change, so a re-import created new
121
122
  * documents beside the old ones — while nothing about those documents had
122
123
  * changed, only their neighbours. The identity always exists or must be stated;
123
124
  * see {@link embeddedIdentity}.
124
125
  *
125
- * Keyed by the **document subtype**, so renaming a note type (#78) leaves every
126
+ * Keyed by the **document subtype**, so renaming a note type leaves every
126
127
  * embedded id where it was.
127
128
  *
128
129
  * @param {string} actorId - The owning actor's id.
@@ -186,7 +187,7 @@ export class SystemActorCompiler extends BasePackCompiler {
186
187
  foreignSourceDirs: any;
187
188
  /**
188
189
  * Every package a `model:` may name besides this one — the dependencies
189
- * whose item catalogues were supplied (#334).
190
+ * whose item catalogues were supplied.
190
191
  *
191
192
  * @returns {Set<string>} The dependency package ids.
192
193
  */
@@ -210,7 +211,7 @@ export class SystemActorCompiler extends BasePackCompiler {
210
211
  * The Foundry Item subtype an embedded reference's `type` addresses.
211
212
  *
212
213
  * **The reference is in the note vocabulary; the address is in the
213
- * document's** (#140). An actor writes `(type, shortcode)` with the type an
214
+ * document's**. An actor writes `(type, shortcode)` with the type an
214
215
  * author authors, while {@link itemAddress} keys the predefined items by
215
216
  * the subtype each compiled document carries — so exactly one of the two
216
217
  * sides has to translate, and it is this one. The system's map is a
@@ -230,7 +231,7 @@ export class SystemActorCompiler extends BasePackCompiler {
230
231
  * descriptor must carry enough fields to stand alone. The embedded
231
232
  * item's `_id` is regenerated deterministically from
232
233
  * `(actorId, subType, shortcode, indexKey)` so re-exports are stable —
233
- * from the **document subtype**, so that renaming a note type (#78) leaves
234
+ * from the **document subtype**, so that renaming a note type leaves
234
235
  * every embedded id exactly where it was.
235
236
  * Returns null if the descriptor cannot be resolved.
236
237
  *
@@ -241,7 +242,7 @@ export class SystemActorCompiler extends BasePackCompiler {
241
242
  * `null` for a stand-alone entry.
242
243
  * @param {object} [overlay] - The entry's remaining properties.
243
244
  * @param {string} indexKey - Where the reference sits, for a diagnostic.
244
- * It no longer reaches the id (#268) — it names the entry in a message.
245
+ * It no longer reaches the id — it names the entry in a message.
245
246
  * @param {string} ctx - Diagnostic context (the actor's label).
246
247
  * @param {object} [at] - Where to locate a finding.
247
248
  * @param {string} [at.fmKey] - The frontmatter key the reference sits
@@ -253,7 +254,7 @@ export class SystemActorCompiler extends BasePackCompiler {
253
254
  /**
254
255
  * Read an entry's `model:` — the address of the item it is a copy of.
255
256
  *
256
- * The address grammar is the wikilink one (#336), so a `model` is written at
257
+ * The address grammar is the wikilink one, so a `model` is written at
257
258
  * whatever length says what it means: `skill-wpnc` within this package,
258
259
  * `sohl-sohl-skill-wpnc` to reach another. The system segment defaults from
259
260
  * the block the entry sits in — `<system>.items` — which is what makes the
@@ -262,7 +263,7 @@ export class SystemActorCompiler extends BasePackCompiler {
262
263
  *
263
264
  * It replaced a top-level `shortcode:` that meant something different from
264
265
  * the `system.shortcode` beside it and could not say which package a
265
- * template came from (#334).
266
+ * template came from.
266
267
  *
267
268
  * @param {unknown} model - The authored value.
268
269
  * @param {number} index - The entry's position, for the message.
@@ -11,7 +11,7 @@
11
11
  */
12
12
  export function isAddressSegment(value: unknown): boolean;
13
13
  /**
14
- * The one charset every segment of a canonical address is held to (#59).
14
+ * The one charset every segment of a canonical address is held to.
15
15
  *
16
16
  * An address is a hyphen-joined tuple — `package-system-type-shortcode`, so
17
17
  * `sohl-none-doc-gear` — and it is read back by **counting segments**, with a
@@ -41,7 +41,7 @@ export function isAddressSegment(value: unknown): boolean;
41
41
  * digits only.
42
42
  *
43
43
  * Case *was* deliberately unconstrained, on the reasoning that case has no
44
- * bearing on the separator — which is true, and beside the point (#340).
44
+ * bearing on the separator — which is true, and beside the point.
45
45
  *
46
46
  * **Two names that differ only in case are two names nobody can tell apart.** A
47
47
  * shortcode is how a person names a thing when writing a reference —
@@ -53,10 +53,10 @@ export function isAddressSegment(value: unknown): boolean;
53
53
  * `sohl-sohl-weapongear-clb` and its `_id` derived from that. The authored name
54
54
  * and its address disagreed, and everything downstream keys on the address —
55
55
  * which left two notes differing only in case sharing one address, one `_id` and
56
- * one URL, with nothing to report it. It also forced two exceptions elsewhere:
57
- * #336 had to exempt the shortcode from the lowercase rule it pinned on every
58
- * other segment, and #346 had to fold the shortcode's case in the item catalogue
59
- * because an address is lowercased when read.
56
+ * one URL, with nothing to report it. It also forces two exceptions elsewhere:
57
+ * the shortcode has to be exempted from the lowercase rule pinned on every
58
+ * other segment, and its case has to be folded in the item catalogue because
59
+ * an address is lowercased when read.
60
60
  *
61
61
  * One case, one spelling, no exceptions. Every tree already complies but two,
62
62
  * and nothing in any of them collides when folded.
@@ -57,7 +57,7 @@ export function declaredPredecessors(contentBase: any, { skipDirectories, maps,
57
57
  * @param {Map<string, {to: string, file: string}>} [opts.predecessors] - The
58
58
  * declared renames, from {@link declaredPredecessors}. Omitted, the diff
59
59
  * falls back to the id join alone and reports an unpinned rename as a
60
- * withdrawal, which is what it did before #278.
60
+ * withdrawal, which is what it did before.
61
61
  * @returns {Array<object>} One finding per departed address, in address order
62
62
  * so two runs read the same. `kind` is `"renamed"` (with `to`, and `declared`
63
63
  * when it was the note's word rather than an id match) or `"withdrawn"`.
@@ -105,7 +105,7 @@ export function noteFilesById(contentBase: string, { skipDirectories, config, re
105
105
  * A **declared** rename knows its note without any lookup — the declaration is
106
106
  * how it was found — and is reported at the `renamedFrom:` line rather than the
107
107
  * `shortcode:` line, because that is the line the finding is about and the one
108
- * the author deletes once the declaration has done its work (#278).
108
+ * the author deletes once the declaration has done its work.
109
109
  *
110
110
  * @param {object} finding - One finding from {@link diffItemAddresses}.
111
111
  * @param {Map<string, string>} noteFiles - From {@link noteFilesById}.
@@ -126,7 +126,7 @@ export function locateAddressFinding(finding: object, noteFiles: Map<string, str
126
126
  * known — and says so, rather than leaving the reader to wonder whether one was
127
127
  * looked for.
128
128
  *
129
- * **A declared rename says it is declared** (#278). The two claims are not
129
+ * **A declared rename says it is declared**. The two claims are not
130
130
  * equally checkable: an id match is a fact in the artefacts, while a
131
131
  * declaration is an author's word, and a reader deciding whether to trust the
132
132
  * successor needs to know which one they have. Saying "the same document" of a