@heroiclands/package-build 20.3.1 → 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 +75 -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 +196 -165
  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 +139 -92
  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
@@ -22,7 +22,7 @@ export function metadataFileName(pkg: string): string;
22
22
  * `itemCatalog: true` says a dependency supplies *items*; citing its
23
23
  * *addresses* is a separate edge, and a package may have either without the
24
24
  * other. `harn-ensemble` cites no foreign address and carries 324,016 embedded
25
- * item references (`HeroicLands/harn-ensemble#42`); a package citing addresses
25
+ * item references; a package citing addresses
26
26
  * and needing no items is the mirror of it. Gating the index on the catalogue
27
27
  * flag would serve neither.
28
28
  *
@@ -84,7 +84,7 @@ export function cachedMetadataFiles(config: object): string[];
84
84
  * The same fetched indexes, each paired with the package that published it.
85
85
  *
86
86
  * The id is what a SQL content table addresses a dependency's notes by
87
- * (`FROM sohl.notes`, #246), so the pairing has to survive the lookup —
87
+ * (`FROM sohl.notes`), so the pairing has to survive the lookup —
88
88
  * {@link cachedMetadataFiles} drops it, and a caller reconstructing the id from
89
89
  * the file name would be parsing a path to recover something the declaration
90
90
  * already stated.
@@ -113,7 +113,7 @@ export function cachedMetadataIndexes(config: object): Array<{
113
113
  * rather than being written once per cache. Two copies would be two chances to
114
114
  * get it wrong, and the wrong answer is invisible: every cached version is a
115
115
  * complete, stamped, perfectly valid artifact, so picking the older one reports
116
- * nothing and simply resolves against stale data (#272).
116
+ * nothing and simply resolves against stale data.
117
117
  *
118
118
  * @param {string[]} dirs - Complete cache directories, named `<id>@<version>`.
119
119
  * @returns {string} The newest one.
@@ -179,7 +179,7 @@ export function cachedIndexPath(config: object, pkg: string): string;
179
179
  * therefore reported against the index, once, instead of once per citing note.
180
180
  *
181
181
  * The realistic cause is a version skew: a dependency released before the
182
- * address grammar gained its `<system>` segment (#59) ships three-segment keys.
182
+ * address grammar gained its `<system>` segment ships three-segment keys.
183
183
  * Re-fetching after that dependency releases is the fix.
184
184
  *
185
185
  * @param {Map<string, object>} foreignIndex - The resolved foreign index.
@@ -10,19 +10,19 @@
10
10
  * @param {ClaimSources} [sources] - What to answer from.
11
11
  * @param {object} [opts] - Options.
12
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
13
+ * compile and handed in — required, for the reason above. Defaults to the
14
14
  * configured registries and the systems this toolchain ships.
15
15
  * @returns {ReadonlySet<string>} The note types such a pass would claim.
16
16
  */
17
17
  export function noteTypesClaimedBy(docType: string, sources?: ClaimSources): ReadonlySet<string>;
18
18
  /**
19
- * Every document class a note of one type compiles into (#152).
19
+ * Every document class a note of one type compiles into.
20
20
  *
21
21
  * **A note produces more than one document, and that is the ordinary case.** An
22
22
  * item note compiles an Item *and* the JournalEntry its prose becomes; a map
23
- * note a Scene and a JournalEntry; since #337 an actor note an Actor and a
23
+ * note a Scene and a JournalEntry; an actor note an Actor and a
24
24
  * JournalEntry too. {@link claimedNoteTypes} unions over the configured packs
25
- * and so answers "is this note compiled *at all*", which is #146's question and
25
+ * and so answers "is this note compiled *at all*", and
26
26
  * cannot see a note that compiles one of its two documents and loses the other.
27
27
  *
28
28
  * Asked of the **claim table** rather than of a list of its own, so the set of
@@ -33,7 +33,7 @@ export function noteTypesClaimedBy(docType: string, sources?: ClaimSources): Rea
33
33
  * **Union across systems, never per system.** A type one system maps and
34
34
  * another does not appears once, because the `Item` and `Actor` rows already
35
35
  * fold the maps together — so this cannot report a document class a system
36
- * deliberately declines to produce, which is the silence #79 requires.
36
+ * deliberately declines to produce, which is the silence the rule requires.
37
37
  *
38
38
  * ## The JournalEntry row is the one that is per *note*
39
39
  *
@@ -73,13 +73,14 @@ export function documentClassesFor(type: string, sources?: ClaimSources, { hasPr
73
73
  *
74
74
  * The union across the configured pack list, so a type claimed by any one pack
75
75
  * is claimed — which is what keeps a type deliberately unmapped for one system,
76
- * and claimed for another, silent (#79).
76
+ * and claimed for another, silent.
77
77
  *
78
78
  * **A prebuilt pack claims nothing.** Its per-document JSON is checked in
79
79
  * rather than compiled, so it has no pass and no note is routed into one —
80
80
  * which `content-config.mjs` already states by refusing `default: true`
81
81
  * alongside `prebuilt`. Counting it would tell an author their note is claimed
82
- * by a pack that will never look at it. Before #259 the point could not arise:
82
+ * by a pack that will never look at it. With no unimplemented type declared,
83
+ * the point cannot arise:
83
84
  * the only prebuilt pack in the wild is `harn-adventures`'s Adventure pack, and
84
85
  * no compiler was registered for that document type, so the row answered for
85
86
  * nothing whatever it was asked. Now one is.
@@ -89,7 +90,7 @@ export function documentClassesFor(type: string, sources?: ClaimSources, { hasPr
89
90
  * @param {ClaimSources} [sources] - What to answer from.
90
91
  * @param {object} [opts] - Options.
91
92
  * @param {readonly object[]} [opts.records] - The corpus, derived once by the
92
- * compile and handed in — required, for the reason above (#243).
93
+ * compile and handed in — required, for the reason above.
93
94
  * @returns {ReadonlySet<string>} The claimed note types.
94
95
  */
95
96
  export function claimedNoteTypes(config?: object, sources?: ClaimSources): ReadonlySet<string>;
@@ -105,7 +106,7 @@ export function claimedNoteTypes(config?: object, sources?: ClaimSources): Reado
105
106
  * @param {ClaimSources} [sources] - What to answer from.
106
107
  * @param {object} [opts] - Options.
107
108
  * @param {readonly object[]} [opts.records] - The corpus, derived once by the
108
- * compile and handed in — required, for the reason above (#243).
109
+ * compile and handed in — required, for the reason above.
109
110
  * @returns {ReadonlySet<string>} The vocabulary.
110
111
  */
111
112
  export function noteTypeVocabulary(sources?: ClaimSources): ReadonlySet<string>;
@@ -124,7 +125,7 @@ export function noteTypeVocabulary(sources?: ClaimSources): ReadonlySet<string>;
124
125
  * @param {ClaimSources} [sources] - What to answer from.
125
126
  * @param {object} [opts] - Options.
126
127
  * @param {readonly object[]} [opts.records] - The corpus, derived once by the
127
- * compile and handed in — required, for the reason above (#243).
128
+ * compile and handed in — required, for the reason above.
128
129
  * @returns {Array<{file: string, line?: number, column?: number,
129
130
  * severity: "error", message: string, type: string}>} One finding per note.
130
131
  */
@@ -162,11 +163,11 @@ export const NEVER_PACKED_TYPES: ReadonlySet<string>;
162
163
  * correctly and is worthless, because the configured vocabulary is *derived
163
164
  * from the routing*. Take a type's route away and it leaves the vocabulary too,
164
165
  * so the inference excuses precisely the mistake it was meant to catch. That is
165
- * not hypothetical: it is #241, where `place`, `lore` and `scenario` were
166
- * declared, validated and unrouted, and every gate reported success until a
167
- * downstream repository failed on 450 notes.
166
+ * not hypothetical: `place`, `lore` and `scenario` were declared, validated
167
+ * and unrouted, and every gate reported success until a downstream repository
168
+ * failed on the notes carrying them.
168
169
  *
169
- * A type leaves this set when it is implemented, the way `bundle` did in #259.
170
+ * A type leaves this set when it is implemented.
170
171
  * The membership is asserted, so it cannot be forgotten in either direction.
171
172
  *
172
173
  * @type {ReadonlySet<string>}
@@ -178,7 +179,7 @@ export const UNIMPLEMENTED_TYPES: ReadonlySet<string>;
178
179
  * A folder is the only one, and it is not unclaimed: it compiles to a real
179
180
  * `Folder` document. What it has no answer to is *which* pack claims it, because
180
181
  * that is not a property of the note — a folder materialises in every pack
181
- * holding a document that references it, and its ancestors with it (#257). So
182
+ * holding a document that references it, and its ancestors with it. So
182
183
  * it is exempt from the claim check for the opposite reason a homepage is:
183
184
  * a homepage is in no pack, and a folder may be in several.
184
185
  *
@@ -5,15 +5,15 @@
5
5
  * the rule but an application of it.** A `Folder` is a document of its own
6
6
  * class, and its id is hashed under the `folder` namespace so that a folder and
7
7
  * an item sharing a shortcode cannot derive one id — a collision Foundry would
8
- * not report, since it keys folders and documents in separate collections
9
- * (#258). So the answer for a folder comes from
8
+ * not report, since it keys folders and documents in separate collections.
9
+ * So the answer for a folder comes from
10
10
  * {@link module:engine/folder-notes.folderDocId}, the pass that emits those
11
11
  * documents, rather than from a second derivation here.
12
12
  *
13
13
  * That this function ever answered differently was invisible from inside a
14
14
  * build — no pass reads a folder's id from here — and surfaced only in the
15
15
  * content index, which is read from outside and had no way to be checked
16
- * against what shipped (#310).
16
+ * against what shipped.
17
17
  *
18
18
  * Returns `undefined` for a file with **no address** — no `type`, or no
19
19
  * `shortcode`. Such a file is not an addressable note, so it has no document
@@ -26,7 +26,7 @@
26
26
  * @param {object|null|undefined} fm - Parsed frontmatter.
27
27
  * @param {object} [opts]
28
28
  * @param {string} [opts.pkg] - The owning content package. Defaults to the
29
- * configured one, which is the only package a tree's notes belong to (#56).
29
+ * configured one, which is the only package a tree's notes belong to.
30
30
  * @param {readonly object[]} [opts.maps] - The document-subtype maps, which
31
31
  * decide the address's `<system>` segment.
32
32
  * @returns {string|undefined} The document's `_id`, or `undefined` when the
@@ -6,7 +6,7 @@
6
6
  * field, so a collection note that scopes itself with `WHERE … and package =
7
7
  * "sohl"` would match nothing now that the field is gone, and would render an
8
8
  * **empty table** in silence. Supplying the derived value here is what kept the
9
- * sweep mechanical rather than a trap (#56) — and a query that never mentions
9
+ * sweep mechanical rather than a trap — and a query that never mentions
10
10
  * `package` is unaffected either way.
11
11
  *
12
12
  * The frontmatter is copied rather than written into: it is the note's own
@@ -1,10 +1,10 @@
1
1
  /**
2
- * The shortcodes a note declares it used to be published under (#278).
2
+ * The shortcodes a note declares it used to be published under.
3
3
  *
4
4
  * A package's `(type, shortcode)` addresses are a published interface, and
5
5
  * `addresses diff` reports what a build stopped publishing — telling a
6
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
7
+ * releases. The property that rested on is gone: an id is derived from
8
8
  * the canonical address, which carries the shortcode, so renaming a shortcode
9
9
  * moves the id too: both sides of the join move together, the match finds
10
10
  * nothing, and a rename is reported as a withdrawal with no successor named.
@@ -39,7 +39,7 @@
39
39
  * **It is transient.** Once every baseline a build is compared against post-dates
40
40
  * the rename, the declaration has nothing left to say and may be deleted. That
41
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).
42
+ * identity for a thing that already has one.
43
43
  *
44
44
  * **It is one key per note, at the top level, however many systems the note
45
45
  * compiles into.** A shortcode is the note's, not a system block's: a note
@@ -24,7 +24,7 @@ export function declaredTags(type: string, groups?: object): readonly string[];
24
24
  */
25
25
  export function hasTag(fm: object | null | undefined, tag: string): boolean;
26
26
  /**
27
- * Whether a note is tagged as an unfinished **draft** (#183).
27
+ * Whether a note is tagged as an unfinished **draft**.
28
28
  *
29
29
  * The one reader of {@link DRAFT_TAG}, so both builds ask the same question of
30
30
  * the same field. Presentation only: a draft note is in the packs, in the
@@ -38,10 +38,11 @@ export function isDraftNote(fm: object | null | undefined): boolean;
38
38
  /**
39
39
  * What a note carrying a subType outside the address charset is told.
40
40
  *
41
- * **Why the charset holds for a subType, which reaches no address.** #206 said
41
+ * **Why the charset holds for a subType, which reaches no address.** The rule
42
+ * said
42
43
  * "the hyphen separates the segments of an address", and that was true of a
43
44
  * subType when it shipped: `sectionOf` returned a `doc`'s subType, so the value
44
- * was a URL path segment. #204 retired sections and it is not one now. The rule
45
+ * was a URL path segment. Sections are retired and it is not one. The rule
45
46
  * stays, on its own footing: a subType is a vocabulary term the whole toolchain
46
47
  * keys on, and it is one closed set away from being an address segment again —
47
48
  * so the reason to spell it in the address charset is that a charset holding
@@ -72,8 +73,8 @@ export function typeCharsetMessage(type: string): string;
72
73
  *
73
74
  * The message states the reason **per key**, as {@link typeCharsetMessage} and
74
75
  * {@link subTypeCharsetMessage} do: a type is an address segment, and a subType
75
- * has not been one since #204 retired sections, so a single claim covering both
76
- * would be half wrong (#210).
76
+ * is not one, since sections are retired, so a single claim covering both
77
+ * would be half wrong.
77
78
  *
78
79
  * @param {Readonly<Record<string, TypeVocabulary>>} vocabulary - The registry.
79
80
  * @param {string} [where] - What declares it, for the message.
@@ -116,7 +117,7 @@ export function subTypes(type: string, vocabulary?: Readonly<Record<string, Type
116
117
  * @type {Readonly<Record<string, TypeVocabulary>>}
117
118
  */
118
119
  /**
119
- * The tags that **classify** a note, grouped by what they classify (#172).
120
+ * The tags that **classify** a note, grouped by what they classify.
120
121
  *
121
122
  * `tags:` lives at the open top level and most tags belong there: a theme, a
122
123
  * region, a working state is the author's own and this build has no opinion
@@ -142,7 +143,7 @@ export function subTypes(type: string, vocabulary?: Readonly<Record<string, Type
142
143
  * this replaced had to spell it `Fishing Village` as a value of its own.
143
144
  */
144
145
  /**
145
- * The declared tag that marks a note as **unfinished** (#183).
146
+ * The declared tag that marks a note as **unfinished**.
146
147
  *
147
148
  * Named once and referenced from the declaration below, because a second
148
149
  * spelling is how the two come apart: rename the tag in `DECLARED_TAGS` and a
@@ -361,7 +362,7 @@ export const NOTE_VOCABULARY: Readonly<{
361
362
  *
362
363
  * A deliberate subset of {@link import ("./field-spec.mjs").FieldSpec}: no `to`,
363
364
  * because nothing here builds anything yet. Reading `data.*` through into a
364
- * document's `system` block is the passthrough slice (#126), and claiming an
365
+ * document's `system` block is the passthrough slice, and claiming an
365
366
  * emitted path this does not produce would be a lie in the one place a reader
366
367
  * would trust it.
367
368
  */
@@ -20,7 +20,7 @@ export function findConfigFile(from: string): string | undefined;
20
20
  *
21
21
  * Kept separate from {@link loadPackConfig} because the *choice* is worth being
22
22
  * able to ask about without loading anything: the two walks disagreeing is the
23
- * observable form of #364, and a caller that wants to report it — or a test
23
+ * observable form of that, and a caller that wants to report it — or a test
24
24
  * that wants to describe it — should not have to reproduce the resolution and
25
25
  * risk disagreeing with the loader about it. It performs I/O, and is named for
26
26
  * it, like the {@link findConfigFile} it calls twice.
@@ -58,7 +58,7 @@ export function resolveConfigFile({ cwd, moduleDir }?: {
58
58
  * worse than locating none — a reader would learn that some configuration
59
59
  * errors carry a position and could not predict which — so the path rides on
60
60
  * the error and every one of them is located here, at the boundary that knows
61
- * which file was read (#95).
61
+ * which file was read.
62
62
  *
63
63
  * The message keeps its body and gains the `file:line:column: error: ` prefix
64
64
  * every other finding in this build already uses, so nothing a reader has today
@@ -82,7 +82,7 @@ export function locateConfigError(err: unknown, configPath?: string): unknown;
82
82
  * cannot write `import.meta.dirname`, and any absolute path it wrote instead
83
83
  * would be one machine's — so authoring it is rejected rather than honoured.
84
84
  * - **`itemBuilders`** is a *name* (`sohl`) — or a list of names, for a tree
85
- * feeding more than one system (#58) — resolved against the built-in
85
+ * feeding more than one system — resolved against the built-in
86
86
  * registries. A registry's name is the system it belongs to. A registry of a
87
87
  * consumer's own is code, and code goes in an `.mjs` configuration.
88
88
  * - **`stats.systemVersion`** is derived from the adjacent `package.json` when
@@ -48,7 +48,7 @@ export class PackRoutingError extends Error {
48
48
  *
49
49
  * Deliberately close to the retired `package:` and deliberately not the same
50
50
  * word: `package:` said which *distribution* owned a note — now the
51
- * repository's `contentPackage`, and no longer authorable (#56) — while `pack:`
51
+ * repository's `contentPackage`, and no longer authorable — while `pack:`
52
52
  * says which *compendium* receives its document.
53
53
  */
54
54
  export const PACK_FIELD: "pack";
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @param {string} file - Path of the file about to be formatted.
8
8
  * @returns {object} Options to hand Prettier directly. Never carries
9
- * `overrides`: passing that inline is what silently did nothing (#76).
9
+ * `overrides`: passing that inline is what silently did nothing.
10
10
  */
11
11
  export function sharedPrettierOptionsFor(file: string): object;
12
12
  /**
@@ -15,11 +15,11 @@ export function sharedPrettierOptionsFor(file: string): object;
15
15
  * The runner resolves each file's options as *either* the consumer's own config
16
16
  * or {@link sharedPrettierOptionsFor}, never a merge. That is what bare Prettier
17
17
  * does and it is the contract — but it means the conventions this package exists
18
- * to publish hold by convention alone, and they lapse in two opposite directions
19
- * (#133). A consumer that declares any config of its own gets whatever that
18
+ * to publish hold by convention alone, and they lapse in two opposite directions.
19
+ * A consumer that declares any config of its own gets whatever that
20
20
  * config says: spread {@link PRETTIER_BASE} without the markdown override and
21
- * every note reindents at 4, the reindentation the override was added to prevent
22
- * (#76); write a partial `.prettierrc` such as `{"tabWidth": 2}` and
21
+ * every note reindents at 4, the reindentation the override was added to prevent;
22
+ * write a partial `.prettierrc` such as `{"tabWidth": 2}` and
23
23
  * `printWidth`, `trailingComma`, `experimentalTernaries` and the rest fall back
24
24
  * to Prettier's own defaults. A consumer that declares *nothing* formats one way
25
25
  * under this command and another under a bare `npx prettier`.
@@ -53,14 +53,14 @@ export function sharedPrettierDivergence(resolved: object | null | undefined, fi
53
53
  /**
54
54
  * The prose conventions every content repository writes to — one Prettier
55
55
  * configuration and one markdownlint rule set, declared here so a note
56
- * formatted in one repository is formatted the same way in the next (#69).
56
+ * formatted in one repository is formatted the same way in the next.
57
57
  *
58
- * These used to exist in exactly one consumer. The SoHL repository carried
58
+ * These belong in no single consumer. The SoHL repository carried
59
59
  * both; `sohl-thalorna` had Prettier but never ran it from `lint`; and
60
60
  * `sohl-kethira-basic` had neither, so the package least likely to have been
61
61
  * proofread was checked for addresses and nothing else. A rule set copied into
62
62
  * three repositories is one rule with three implementations, which is the drift
63
- * #20 exists to remove — so it is declared once, here, and every consumer
63
+ * this exists to remove — so it is declared once, here, and every consumer
64
64
  * invokes it.
65
65
  *
66
66
  * **Neither of these is an override.** A consumer that declares its own
@@ -95,7 +95,7 @@ export const PRETTIER_BASE: Readonly<object>;
95
95
  * **Declared apart from the `overrides` block, not derived from it.** Prettier
96
96
  * applies `overrides` only while resolving a config *file*; options handed to
97
97
  * it directly keep the global values, so a consumer with no config of its own
98
- * silently got markdown at 4 (#76). The runner needs the adjustment as data it
98
+ * silently got markdown at 4. The runner needs the adjustment as data it
99
99
  * can apply itself, and {@link PRETTIER_CONFIG} composes the same values into
100
100
  * the shape a config file wants — one source, two presentations.
101
101
  *
@@ -14,8 +14,7 @@
14
14
  * @param {boolean} [opts.write=false] - Rewrite unformatted files in place
15
15
  * rather than reporting them. Each file is formatted to a fixpoint (up to
16
16
  * {@link MAX_FORMAT_PASSES} passes), so a written tree is one a second run
17
- * leaves alone; a file that will not converge is reported and left unchanged
18
- * (#125).
17
+ * leaves alone; a file that will not converge is reported and left unchanged.
19
18
  * @param {object} [opts.prettier] - The Prettier module, for tests.
20
19
  * @returns {Promise<{findings: Array<{file: string, severity: string,
21
20
  * message: string}>, checked: number, written: string[]}>} The findings, how
@@ -37,7 +36,7 @@ export function checkFormatting(root: string, opts?: {
37
36
  }>;
38
37
  /**
39
38
  * Report where a repository's own Prettier configuration parts from the shared
40
- * one — or that it has none at all (#133).
39
+ * one — or that it has none at all.
41
40
  *
42
41
  * **Warnings, every one of them.** A consumer's config wins by design and this
43
42
  * does not change that; it only refuses to let the divergence be silent, which
@@ -58,7 +57,7 @@ export function checkFormatting(root: string, opts?: {
58
57
  * @returns {Promise<{findings: Array<{file?: string, severity: string,
59
58
  * message: string}>, configFile: string|null}>} The findings and the config
60
59
  * file they are about, which is `null` when the repository declares none. A
61
- * finding about a missing file carries no `file`: #17's rule is to drop a
60
+ * finding about a missing file carries no `file`: the rule is to drop a
62
61
  * field rather than invent one.
63
62
  */
64
63
  export function checkPrettierConventions(root: string, opts?: {
@@ -9,10 +9,10 @@
9
9
  * runtime bridge from drifting apart.
10
10
  *
11
11
  * It sits in this package rather than in the system's `src/` tree because the
12
- * map-note compiler that reads it is installed as a dependency (#1501), and a
12
+ * map-note compiler that reads it is installed as a dependency, and a
13
13
  * relative path out of the package would resolve to garbage from
14
14
  * `node_modules`. The runtime reaches it back through the package's
15
- * `./engine/region-events` entry point (#1510). It is engine-side, not
15
+ * `./engine/region-events` entry point. It is engine-side, not
16
16
  * SoHL-side, because any content module that authors a scene region — an
17
17
  * adventure module included — needs this vocabulary.
18
18
  *
@@ -43,11 +43,11 @@ export function assertNoDraftField(fm: object | null | undefined, { file, absPat
43
43
  * It says what the field fed and what to write instead, rather than which value
44
44
  * to correct: no value makes declaring it right.
45
45
  *
46
- * **What it did (#180).** It was the authored half of the alias index — the
46
+ * **What it did.** It was the authored half of the alias index — the
47
47
  * namespace a bare `[[Alias]]` was looked up in. Across the three content trees
48
48
  * not one bare link resolved through it, while the collision rule that kept it
49
49
  * unambiguous folded in every note's `name.full` and so dictated what a note
50
- * could be named (#179). The form is retired, so the list has no reader.
50
+ * could be named. The form is retired, so the list has no reader.
51
51
  *
52
52
  * **`name.aliases` is a different field and is not retired.** It fed the same
53
53
  * index, but unlike the top-level list it is being kept — reserved, unread,
@@ -114,10 +114,10 @@ export function declaresRetiredAliasesField(fm: object | null | undefined): bool
114
114
  * It names what lands a section now rather than a value to correct: no value
115
115
  * makes declaring the field right.
116
116
  *
117
- * **What it did (#202).** It named the section a `collection` note headed,
117
+ * **What it did.** It named the section a `collection` note headed,
118
118
  * under the `collection` landing rule — the only reader it ever had, in the
119
119
  * second branch of `landingOf` (`engine/content-address.mjs`). That rule went
120
- * first, and the whole mechanism went with it (#204): a section is a Hugo
120
+ * first, and the whole mechanism went with it: a section is a Hugo
121
121
  * directory the note format does not carry, so no note lands one and a page
122
122
  * that introduces a type is an ordinary note addressed `doc-<type>`. Nothing
123
123
  * else read the field, and no schema or vocabulary declared it, so left in
@@ -237,7 +237,7 @@ export function retiredAliasMessage(retired: string, current: string, file?: str
237
237
  * What a note writing a field at its **legacy in-block position** is told.
238
238
  *
239
239
  * The same three-step retirement `retiredAliasMessage` announces, applied to a
240
- * *position* rather than a spelling (#305). A field whose shared source moved
240
+ * *position* rather than a spelling. A field whose shared source moved
241
241
  * under `data:` keeps reading the key its block still carries, that read wins,
242
242
  * and it is reported here so a sweep has something to count down — without it,
243
243
  * moving a field into `data:` would be a flag day across every repository that
@@ -260,9 +260,10 @@ export function legacyKeyMessage(block: string, field: {
260
260
  }, file?: string): string;
261
261
  /**
262
262
  * What a note writing a field at the **top-level key `data:` gathered it off**
263
- * is told (#332).
263
+ * is told.
264
264
  *
265
- * {@link legacyKeyMessage}'s counterpart for the other retiring position. #128
265
+ * {@link legacyKeyMessage}'s counterpart for the other retiring position. The
266
+ * sweep
266
267
  * did not invent the facts `data:` holds — it collected them out of the note's
267
268
  * open top level — so `portrait:` beside `img:` is the *pre-`data:`* spelling
268
269
  * of `data.portrait`, and both are read for the same reason both in-block
@@ -322,14 +323,14 @@ export function readAliasedField(fm: object | null | undefined, current: string)
322
323
  * `relation` is retired on an affiliation — which declares `relations` — and
323
324
  * remains an unknown key anywhere else.
324
325
  *
325
- * **`templatePriority` (#266).** The number that decides which of several
326
+ * **`templatePriority`.** The number that decides which of several
326
327
  * competing templates the Create dialog offers was called `archetype`, and
327
328
  * `archetypes` — one letter apart — is a list of what *sort* a character is.
328
329
  * A priority and a taxonomy cannot be told apart by a plural `s`, so the
329
330
  * priority takes the name that says what it is. The specification already
330
331
  * called it `templatePriority` on two of its three sides.
331
332
  *
332
- * **`relations` (SoHL#1781).** The field holds a *map* of standings, one per
333
+ * **`relations`.** The field holds a *map* of standings, one per
333
334
  * affiliation — its own description says so, and `resolveRelation` has always
334
335
  * read it that way. `relation` named the many as one, which every author had to
335
336
  * read past. Only `affiliation` declares the field, so the alias is reported
@@ -46,7 +46,7 @@ export function declaredFields(artifact: SchemaArtifact, documentType: string, s
46
46
  * the path beneath it separately, so a comparison that knew only the leaf would
47
47
  * report the container as unemitted and the leaf as undeclared.
48
48
  *
49
- * **A runtime-only field is not in it** (#330). It declares a `to` in order to
49
+ * **A runtime-only field is not in it**. It declares a `to` in order to
50
50
  * *claim* the path — so the verbatim passthrough leaves it alone and the
51
51
  * refusal has something to name — and `buildFromFields` deliberately skips it,
52
52
  * because the document writes that field in play. Counting it here would make
@@ -76,7 +76,7 @@ export function emittedFields(fields: readonly {
76
76
  * compile into.
77
77
  * @param {(type: string) => string} [opts.subtypeOf] - Maps a builder's type to
78
78
  * the document subtype it emits. Defaults to identity, which is what the
79
- * coincidence of names amounts to today (#79) — stated as a seam so that the
79
+ * coincidence of names amounts to today — stated as a seam so that the
80
80
  * explicit map replaces a default rather than a hard-coded assumption.
81
81
  * @returns {{undeclared: object[], unemitted: object[], skipped: string[]}}
82
82
  * `undeclared` fails a build; `unemitted` is reported; `skipped` names the
@@ -96,7 +96,7 @@ export function compareFields({ builders, artifact, documentType, subtypeOf, }:
96
96
  };
97
97
  /**
98
98
  * What a **compiled document** carries in `system`, against what the receiving
99
- * subtype declares (#155).
99
+ * subtype declares.
100
100
  *
101
101
  * The third of the three checks, and the only one whose emitted set is
102
102
  * *observed*. {@link compareFields} reads the `itemBuilders` declarations and
@@ -148,7 +148,7 @@ export function compareEmittedSystem({ system, artifact, documentType, subtype,
148
148
  * The published schema this build should check itself against, or `null`.
149
149
  *
150
150
  * **Which system, and which version, are already settled.** `stats.systemId`
151
- * and `stats.systemVersion` are derived rather than authored (#48) — a system
151
+ * and `stats.systemVersion` are derived rather than authored — a system
152
152
  * package is its own system, and a module takes the one it requires — and the
153
153
  * version is the `compatibility.verified` it pins. So the question "whose
154
154
  * schema, at what version" has one answer here rather than a second set of
@@ -168,12 +168,12 @@ export function compareEmittedSystem({ system, artifact, documentType, subtype,
168
168
  * stamps no system at all, and a system that has not adopted the artifact yet
169
169
  * is simply unchecked. Neither is an error, and the caller says which it was.
170
170
  *
171
- * **A build may have more than one system, and then the caller names it (#139).**
171
+ * **A build may have more than one system, and then the caller names it.**
172
172
  * `stats.systemId` is the package-wide answer, and a repository shipping content
173
173
  * for two systems has no package-wide answer — it is deliberately `null` there,
174
174
  * because a module feeding both `sohl` and `hm3` targets neither. Left at that,
175
175
  * every schema check in such a build would be skipped in silence, which is the
176
- * state #60 exists to remove: the five type names the two systems *share* are
176
+ * state this exists to remove: the five type names the two systems *share* are
177
177
  * exactly the ones a wrong-system emission hides in. So a pass supplies the
178
178
  * system its pack declares, and the version comes from that system's own
179
179
  * `systems:` entry rather than from a package-wide stamp.
@@ -236,7 +236,7 @@ export function unemittedMessage(finding: object): string;
236
236
  export function emittedUndeclaredMessage(finding: EmissionFinding): string;
237
237
  /**
238
238
  * What a note authors under `<system>.system`, against what the receiving
239
- * subtype declares (#58).
239
+ * subtype declares.
240
240
  *
241
241
  * The **note-side** half of the check `compareFields` performs on the
242
242
  * declarations. A field list is checked once for the whole build because it is
@@ -261,7 +261,7 @@ export function emittedUndeclaredMessage(finding: EmissionFinding): string;
261
261
  * @param {string} opts.documentType - `Item`, `Actor`, …
262
262
  * @param {string} opts.subType - The document subtype the note compiles into.
263
263
  * @param {string} [opts.system] - The system whose published schema to read,
264
- * where a build has more than one (#139). Defaults to the package-wide
264
+ * where a build has more than one. Defaults to the package-wide
265
265
  * `stats.systemId`.
266
266
  * @param {object} [opts.config] - The resolved build configuration.
267
267
  * @returns {{path: string, message: string}[]} One finding per undeclared path,
@@ -279,7 +279,7 @@ export function checkAuthoredSystemData(fm: object, { block, documentType, subTy
279
279
  }[];
280
280
  /**
281
281
  * The `system` block a compiler just assembled, against what the receiving
282
- * subtype declares (#155).
282
+ * subtype declares.
283
283
  *
284
284
  * The build-time face of {@link compareEmittedSystem}: it resolves the schema
285
285
  * the way every other check here does — the system's own committed artifact, or
@@ -302,7 +302,7 @@ export function checkAuthoredSystemData(fm: object, { block, documentType, subTy
302
302
  * @param {readonly {to?: string}[]} [opts.fields] - The type's field
303
303
  * declaration, which decides each finding's origin.
304
304
  * @param {string} [opts.system] - The system whose published schema to read,
305
- * where a build has more than one (#139). Defaults to the package-wide
305
+ * where a build has more than one. Defaults to the package-wide
306
306
  * `stats.systemId`.
307
307
  * @param {object} [opts.config] - The resolved build configuration.
308
308
  * @returns {(EmissionFinding & {message: string})[]} One per undeclared path.
@@ -326,7 +326,7 @@ export function checkEmittedSystemData(emitted: any, { fm, block, documentType,
326
326
  *
327
327
  * A mismatch stops the check rather than resolving anyway: a schema read under
328
328
  * the wrong shape would report confident nonsense in both directions, and a
329
- * silently skipped check is the state #60 exists to leave.
329
+ * silently skipped check is the state this exists to leave.
330
330
  *
331
331
  * @type {number}
332
332
  */