@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.
- package/CHANGELOG.md +75 -0
- package/CONTENT.md +111 -92
- package/README.md +2 -9
- package/bin/content-build.mjs +70 -61
- package/bin/package-build.mjs +2 -2
- package/config.mjs +6 -8
- package/content-config.mjs +187 -64
- package/docs/content-format.md +57 -68
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +36 -36
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +12 -11
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +36 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +8 -8
- package/engine/code-fences.mjs +3 -3
- package/engine/compendiums.mjs +8 -8
- package/engine/compile-corpus.mjs +4 -5
- package/engine/content-address.mjs +15 -15
- package/engine/content-charset.mjs +1 -1
- package/engine/content-format-check.mjs +24 -25
- package/engine/content-format.mjs +8 -8
- package/engine/content-html.mjs +202 -0
- package/engine/content-icons.mjs +196 -165
- package/engine/content-index.mjs +17 -17
- package/engine/content-links.mjs +30 -30
- package/engine/content-lint.mjs +20 -24
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +7 -8
- package/engine/content-tree.mjs +1 -1
- package/engine/derived-fields.mjs +174 -0
- package/engine/diagnostics.mjs +3 -4
- package/engine/document-subtypes.mjs +6 -7
- package/engine/field-reference.mjs +8 -8
- package/engine/field-spec.mjs +29 -30
- package/engine/folder-notes.mjs +14 -14
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +64 -69
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +39 -39
- package/engine/helpers.mjs +63 -54
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +14 -8
- package/engine/item-compiler.mjs +54 -29
- package/engine/item-docs.mjs +11 -13
- package/engine/item-registry.mjs +13 -13
- package/engine/journals.mjs +15 -15
- package/engine/macros.mjs +3 -3
- package/engine/map-notes.mjs +6 -6
- package/engine/metadata-index.mjs +5 -5
- package/engine/note-claims.mjs +36 -34
- package/engine/note-ids.mjs +5 -5
- package/engine/note-package.mjs +4 -4
- package/engine/note-renames.mjs +3 -3
- package/engine/note-schemas.mjs +3 -3
- package/engine/note-vocabulary.mjs +27 -26
- package/engine/pack-config.mjs +13 -13
- package/engine/pack-router.mjs +0 -0
- package/engine/prose-config.mjs +9 -9
- package/engine/prose-lint.mjs +12 -13
- package/engine/region-events.mjs +2 -2
- package/engine/retired-fields.mjs +24 -22
- package/engine/runtime-only-fields.mjs +1 -1
- package/engine/scene-levels.mjs +1 -1
- package/engine/scenes.mjs +19 -20
- package/engine/schema-check.mjs +20 -20
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +45 -47
- package/engine/site-index.mjs +17 -18
- package/engine/sql-tables.mjs +21 -13
- package/engine/subtype-registry.mjs +5 -4
- package/engine/system-block.mjs +18 -19
- package/engine/systems.mjs +2 -2
- package/engine/web-wikilinks.mjs +35 -35
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +39 -39
- package/hm3/actors.mjs +22 -22
- package/hm3/document-subtypes.mjs +5 -5
- package/hm3/index.mjs +2 -2
- package/hm3/item-builders.mjs +1 -1
- package/hm3/item-fields.mjs +3 -3
- package/hm3/items.mjs +20 -8
- package/hm3/template-priority.mjs +2 -2
- package/lang.mjs +3 -3
- package/manifest.mjs +17 -20
- package/package.json +1 -2
- package/release.mjs +3 -3
- package/sohl/actors.mjs +28 -28
- package/sohl/affiliation-standings.mjs +2 -2
- package/sohl/being-info.mjs +5 -5
- package/sohl/default-item-art.mjs +5 -5
- package/sohl/document-subtypes.mjs +5 -5
- package/sohl/index.mjs +3 -3
- package/sohl/item-builders.mjs +7 -7
- package/sohl/item-fields.mjs +8 -9
- package/sohl/items.mjs +20 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +7 -7
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +25 -24
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +14 -13
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +3 -3
- package/types/engine/base-compiler.d.mts +17 -19
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +1 -1
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/compendiums.d.mts +3 -3
- package/types/engine/compile-corpus.d.mts +1 -1
- package/types/engine/content-address.d.mts +11 -11
- package/types/engine/content-format-check.d.mts +6 -6
- package/types/engine/content-format.d.mts +2 -2
- package/types/engine/content-html.d.mts +78 -0
- package/types/engine/content-icons.d.mts +139 -92
- package/types/engine/content-index.d.mts +2 -2
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +2 -2
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/derived-fields.d.mts +101 -0
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/document-subtypes.d.mts +3 -3
- package/types/engine/field-spec.d.mts +37 -39
- package/types/engine/folder-notes.d.mts +4 -5
- package/types/engine/foreign-catalog.d.mts +3 -3
- package/types/engine/foundry-entries.d.mts +6 -7
- package/types/engine/frontmatter-lint.d.mts +7 -7
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +25 -27
- package/types/engine/homepage.d.mts +16 -18
- package/types/engine/ids.d.mts +13 -13
- package/types/engine/index-records.d.mts +3 -3
- package/types/engine/index.d.mts +2 -0
- package/types/engine/item-compiler.d.mts +21 -5
- package/types/engine/item-docs.d.mts +2 -2
- package/types/engine/item-registry.d.mts +6 -6
- package/types/engine/journals.d.mts +3 -3
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/metadata-index.d.mts +4 -4
- package/types/engine/note-claims.d.mts +16 -15
- package/types/engine/note-ids.d.mts +4 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-renames.d.mts +3 -3
- package/types/engine/note-vocabulary.d.mts +9 -8
- package/types/engine/pack-config.d.mts +3 -3
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/prose-config.d.mts +9 -9
- package/types/engine/prose-lint.d.mts +3 -4
- package/types/engine/region-events.d.mts +2 -2
- package/types/engine/retired-fields.d.mts +10 -9
- package/types/engine/schema-check.d.mts +11 -11
- package/types/engine/site-build.d.mts +18 -19
- package/types/engine/site-index.d.mts +3 -4
- package/types/engine/sql-tables.d.mts +11 -5
- package/types/engine/subtype-registry.d.mts +3 -3
- package/types/engine/system-block.d.mts +3 -3
- package/types/engine/web-wikilinks.d.mts +7 -7
- package/types/engine/wikilink-syntax.d.mts +17 -17
- package/types/engine/wikilinks.d.mts +13 -12
- package/types/hm3/actors.d.mts +1 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +1 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/sohl/actors.d.mts +2 -2
- package/types/sohl/affiliation-standings.d.mts +2 -2
- package/types/sohl/being-info.d.mts +2 -2
- package/types/sohl/document-subtypes.d.mts +1 -1
- package/types/sohl/items.d.mts +1 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
package/engine/item-registry.mjs
CHANGED
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
*
|
|
18
18
|
* Both are read from the one resolved configuration, so they are literally the
|
|
19
19
|
* same object's keys and values: a type cannot be whitelisted for compilation
|
|
20
|
-
* without the builder that compiles it, which is the guarantee
|
|
21
|
-
* for. Where a consumer declares **several** registries, one per system
|
|
20
|
+
* without the builder that compiles it, which is the guarantee this exists
|
|
21
|
+
* for. Where a consumer declares **several** registries, one per system,
|
|
22
22
|
* the vocabulary is their union and every lookup below takes the system that is
|
|
23
23
|
* asking — a type both systems declare has two builders, and answering with one
|
|
24
24
|
* of them because it was declared first is the silent-wrong-output failure this
|
|
25
25
|
* package spends its time removing. The Item compiler dispatches through {@link itemBuilder}, so the table a
|
|
26
26
|
* consumer configured is the table its notes compile with — the whitelist and
|
|
27
|
-
* the dispatch
|
|
28
|
-
* own registry got the types it asked for and the builders it did not
|
|
27
|
+
* the dispatch would otherwise come from different places, and a consumer supplying its
|
|
28
|
+
* own registry got the types it asked for and the builders it did not.
|
|
29
29
|
*
|
|
30
30
|
* **The registry itself is a consumer's, and stays a leaf.** SoHL's lives in
|
|
31
31
|
* `@heroiclands/package-build/sohl/item-builders`; the consumer names it in
|
|
@@ -52,9 +52,9 @@ import { resolveImg } from "./helpers.mjs";
|
|
|
52
52
|
* **Derived, never authored.** These are the keys of the consuming
|
|
53
53
|
* repository's `itemBuilders` registry, so the whitelist and the builder table
|
|
54
54
|
* are the same list and cannot drift apart. They already had: `trait` was
|
|
55
|
-
* whitelisted long after the item type was retired
|
|
55
|
+
* whitelisted long after the item type was retired, with no builder
|
|
56
56
|
* behind it, so every `type: trait` note passed the gate and then failed to
|
|
57
|
-
* compile
|
|
57
|
+
* compile.
|
|
58
58
|
*
|
|
59
59
|
* An accessor rather than a hoisted constant, so that importing this module
|
|
60
60
|
* needs no configuration (#2).
|
|
@@ -73,7 +73,7 @@ export function itemTypes() {
|
|
|
73
73
|
* two systems declare the type. So a contested type without a system **throws**
|
|
74
74
|
* rather than resolving: the alternative is a document built by one system's
|
|
75
75
|
* builder and stamped with another's, which is exactly the shape of defect the
|
|
76
|
-
* document-subtype map exists to stop
|
|
76
|
+
* document-subtype map exists to stop.
|
|
77
77
|
*
|
|
78
78
|
* @param {string} what - What is being looked up, for the message.
|
|
79
79
|
* @param {"itemBuilders"|"itemArt"|"itemFields"} table - Which table.
|
|
@@ -87,7 +87,7 @@ function lookup(what, table, type, system) {
|
|
|
87
87
|
// The registry is keyed by the current spelling of a note type, and a note
|
|
88
88
|
// still on a renamed one resolves through it unchanged. One place, because
|
|
89
89
|
// every type-keyed table this module reaches — builders, art, fields — is
|
|
90
|
-
// indexed here
|
|
90
|
+
// indexed here.
|
|
91
91
|
type = currentType(type);
|
|
92
92
|
if (system !== undefined) {
|
|
93
93
|
const perSystem = /** @type {Record<string, Record<string, unknown>>} */ (
|
|
@@ -112,7 +112,7 @@ function lookup(what, table, type, system) {
|
|
|
112
112
|
*
|
|
113
113
|
* Unreachable through the compiler — its whitelist *is* this registry's keys —
|
|
114
114
|
* so a throw here means a caller invented a type. It names the type rather than
|
|
115
|
-
* failing as an anonymous `is not a function
|
|
115
|
+
* failing as an anonymous `is not a function`.
|
|
116
116
|
*
|
|
117
117
|
* @param {string} type - The note's `type` frontmatter.
|
|
118
118
|
* @param {string} [system] - The system compiling it, where a build declares
|
|
@@ -139,9 +139,9 @@ export function itemBuilder(type, system) {
|
|
|
139
139
|
* The frontmatter fields a type's registry entry declares, if any.
|
|
140
140
|
*
|
|
141
141
|
* Sparse by design: a type whose entry declares none compiles normally and is
|
|
142
|
-
* simply undocumented
|
|
142
|
+
* simply undocumented. What reads it is the `system`-block passthrough,
|
|
143
143
|
* which has to know which paths a declared field already writes before it
|
|
144
|
-
* writes the rest
|
|
144
|
+
* writes the rest.
|
|
145
145
|
*
|
|
146
146
|
* @param {string} type - The item type.
|
|
147
147
|
* @param {string} [system] - The system compiling it, where a build declares
|
|
@@ -160,7 +160,7 @@ export function itemFields(type, system) {
|
|
|
160
160
|
*
|
|
161
161
|
* Read from the consuming repository's `itemBuilders` registry, the same place
|
|
162
162
|
* the type itself is declared, so a consumer's own type can bring art a
|
|
163
|
-
* SoHL-owned table could never hold. Art
|
|
163
|
+
* SoHL-owned table could never hold. Art is not looked up in
|
|
164
164
|
* `sohl/default-item-art.mjs` instead: a type was configurable while its
|
|
165
165
|
* default art was not, so a second consumer's items compiled only if every one
|
|
166
166
|
* of its notes set `img:` (#7).
|
|
@@ -195,7 +195,7 @@ export function itemArt(type, system) {
|
|
|
195
195
|
);
|
|
196
196
|
}
|
|
197
197
|
// `art` is non-empty by the guard above, so the translation never returns
|
|
198
|
-
// the `null` a note's unset `img:` would
|
|
198
|
+
// the `null` a note's unset `img:` would; the coalesce states that
|
|
199
199
|
// rather than leaving the declared `string` return a half-truth.
|
|
200
200
|
return resolveImg(art) ?? "";
|
|
201
201
|
}
|
package/engine/journals.mjs
CHANGED
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
* keeps only a pointer to it. See `item-docs.mjs` for why, and for the ids the
|
|
29
29
|
* two passes agree on. A macro note's `{#script}` page is compiled here like
|
|
30
30
|
* any other: the macro pass reads the same page independently, and withholds
|
|
31
|
-
* nothing from the journal
|
|
31
|
+
* nothing from the journal.
|
|
32
32
|
*
|
|
33
33
|
* Folder placement is identical to the items pack: `sohl.packFolder` in
|
|
34
34
|
* frontmatter is a folder **note's address**, resolved through the shared
|
|
35
|
-
* address index by the constructor's `folderResolver
|
|
35
|
+
* address index by the constructor's `folderResolver`. A folder
|
|
36
36
|
* materialises in every pack holding a document that names it, so a journals
|
|
37
|
-
* pack needs to declare nothing
|
|
37
|
+
* pack needs to declare nothing — which is what stopped this pass
|
|
38
38
|
* filing documentation into folders its own pack had never heard of. A
|
|
39
39
|
* documentation entry reuses its document's folder verbatim.
|
|
40
40
|
*
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
*
|
|
44
44
|
* The walk itself — filtering by type, expanding tables, converting
|
|
45
45
|
* wikilinks, writing the JSON and counting errors — belongs to {@link sohl.utils.packs.BasePackCompiler}; this module
|
|
46
|
-
* states only what makes this pass its own
|
|
46
|
+
* states only what makes this pass its own.
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
import log from "loglevel";
|
|
@@ -141,7 +141,7 @@ export function splitPages(body, leadName = "Introduction") {
|
|
|
141
141
|
* on an identity alone:
|
|
142
142
|
*
|
|
143
143
|
* - **An anchor**, declared twice, has always collided.
|
|
144
|
-
* - **A name**, repeated among the unanchored pages, collides
|
|
144
|
+
* - **A name**, repeated among the unanchored pages, collides once
|
|
145
145
|
* the index out of the key. `MD024` with `siblings_only` already makes two
|
|
146
146
|
* sibling headings with the same text a lint error, so this is the same rule
|
|
147
147
|
* restated where the build can enforce it — a lint is a separate command, and
|
|
@@ -199,7 +199,7 @@ export function assertUniqueAnchors(rawPages, noteName) {
|
|
|
199
199
|
* doc's first page without having compiled it (see
|
|
200
200
|
* {@link sohl.utils.packs.itemDocPointer}).
|
|
201
201
|
*
|
|
202
|
-
* **It takes no index
|
|
202
|
+
* **It takes no index**. Keying a page by position *and* name,
|
|
203
203
|
* so inserting a heading renumbered every page after it and a re-import created
|
|
204
204
|
* new pages beside the old ones — while nothing about those pages had changed.
|
|
205
205
|
* The anchored case above never took one, and is the shape this now shares.
|
|
@@ -275,7 +275,7 @@ export function buildPages(rawPages, entryId, noteName) {
|
|
|
275
275
|
* @param {object} [params.stats] - The `_stats` block to stamp. Passed by the
|
|
276
276
|
* caller because it is a property of the *pack* being written, not of the
|
|
277
277
|
* entry: a module may ship the same content for two systems, and each pack's
|
|
278
|
-
* documents record the system version they were built against
|
|
278
|
+
* documents record the system version they were built against. A
|
|
279
279
|
* caller with no pack in hand gets the package-wide block.
|
|
280
280
|
* @returns {object} The JournalEntry document, keyed for the pack.
|
|
281
281
|
*/
|
|
@@ -317,7 +317,7 @@ export class Journals extends BasePackCompiler {
|
|
|
317
317
|
/**
|
|
318
318
|
* **None.** A JournalEntry has no artwork — no `img` property, and no
|
|
319
319
|
* nested place for one — so a note whose whole document is prose has
|
|
320
|
-
* nowhere to put an authored path
|
|
320
|
+
* nowhere to put an authored path.
|
|
321
321
|
*
|
|
322
322
|
* The emptiness is the declaration, in the sense `JOURNAL_ONLY_FIELDS` is:
|
|
323
323
|
* it is what separates a pass that emits no art from one that has simply
|
|
@@ -338,13 +338,13 @@ export class Journals extends BasePackCompiler {
|
|
|
338
338
|
|
|
339
339
|
/**
|
|
340
340
|
* Journal notes, plus every doc-carrying note — an item's prose is its
|
|
341
|
-
* documentation, so it compiles here and the item keeps a pointer to it
|
|
342
|
-
*
|
|
343
|
-
* whose prose is the place description its pins point at
|
|
341
|
+
* documentation, so it compiles here and the item keeps a pointer to it;
|
|
342
|
+
* a macro's is the same arrangement, and so is a map's,
|
|
343
|
+
* whose prose is the place description its pins point at.
|
|
344
344
|
*
|
|
345
345
|
* Two memberships, and they mean different things.
|
|
346
346
|
* {@link module:engine/ids.JOURNAL_TYPES} is the types whose whole document
|
|
347
|
-
* *is* a journal — `doc`,
|
|
347
|
+
* *is* a journal — `doc`, `place`, `lore` and `scenario`,
|
|
348
348
|
* which the content format has always described and nothing compiled.
|
|
349
349
|
* {@link sohl.utils.packs.docEntryTypes}, read through
|
|
350
350
|
* {@link sohl.utils.packs.hasDocEntry}, is the types whose prose becomes a
|
|
@@ -383,7 +383,7 @@ export class Journals extends BasePackCompiler {
|
|
|
383
383
|
* the items pass wrote resolves to it (see
|
|
384
384
|
* {@link sohl.utils.packs.itemDocPointer}). A macro's `{#script}` page is
|
|
385
385
|
* compiled here like any other; nothing is withheld from the journal
|
|
386
|
-
* because the macro pass also reads it
|
|
386
|
+
* because the macro pass also reads it.
|
|
387
387
|
*
|
|
388
388
|
* @param {object} fm - The note's frontmatter.
|
|
389
389
|
* @param {string} markdown - The body, tables expanded and wikilinks
|
|
@@ -404,12 +404,12 @@ export class Journals extends BasePackCompiler {
|
|
|
404
404
|
// resolving it *here* is what cures the defect this comment used to
|
|
405
405
|
// describe. A folder note has one definition and one address, so the
|
|
406
406
|
// journals pack materialises the very folder the items pack does, by
|
|
407
|
-
// the same id
|
|
407
|
+
// the same id. There is no second folder file left to disagree
|
|
408
408
|
// with the first, and so no arrangement to assume: the mirroring
|
|
409
409
|
// failure is unrepresentable rather than merely reported.
|
|
410
410
|
//
|
|
411
411
|
// The id spelling used to cross packs verbatim here, on the assumption
|
|
412
|
-
// both declared it — the arrangement
|
|
412
|
+
// both declared it — the arrangement retired with the YAML.
|
|
413
413
|
const { value: authoredFolder } = folderField(fm);
|
|
414
414
|
const folder = this.folderResolver(authoredFolder, { isAddress: true });
|
|
415
415
|
|
package/engine/macros.mjs
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
*
|
|
47
47
|
* The walk itself — filtering by type, expanding tables, converting
|
|
48
48
|
* wikilinks, writing the JSON and counting errors — belongs to {@link sohl.utils.packs.BasePackCompiler}; this module
|
|
49
|
-
* states only what makes this pass its own
|
|
49
|
+
* states only what makes this pass its own.
|
|
50
50
|
*/
|
|
51
51
|
|
|
52
52
|
import log from "loglevel";
|
|
@@ -261,7 +261,7 @@ export function buildMacroEntry(fm, { command, folder = null, stats = defaultSta
|
|
|
261
261
|
// into chat instead of running.
|
|
262
262
|
type: resolveMacroType(fm, name),
|
|
263
263
|
author: null,
|
|
264
|
-
// Nullish, not
|
|
264
|
+
// Nullish, not `||`: a macro note that names no art gets the
|
|
265
265
|
// shared default, one that writes `img: ""` ships blank on purpose.
|
|
266
266
|
img: resolveImg(fm.img) ?? DEFAULT_MACRO_IMG,
|
|
267
267
|
scope: resolveMacroScope(fm, name),
|
|
@@ -326,7 +326,7 @@ export class Macros extends BasePackCompiler {
|
|
|
326
326
|
folder: this.folderResolver(folderField(fm).value, {
|
|
327
327
|
isAddress: folderField(fm).isAddress,
|
|
328
328
|
}),
|
|
329
|
-
// This pack's system, not the package-wide one
|
|
329
|
+
// This pack's system, not the package-wide one.
|
|
330
330
|
stats: this.stats,
|
|
331
331
|
});
|
|
332
332
|
}
|
package/engine/map-notes.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* **Map notes** — the markdown → Foundry `Scene` translation
|
|
15
|
+
* **Map notes** — the markdown → Foundry `Scene` translation.
|
|
16
16
|
*
|
|
17
17
|
* A map note carries an *essence*: a curated, hand-owned subset of what a Scene
|
|
18
18
|
* record holds, exactly as a weapon note carries a weapon's essence rather than
|
|
@@ -57,7 +57,7 @@ import { compendiumUuid, makeId, MAP_SUBTYPES, MAP_TYPES } from "./ids.mjs";
|
|
|
57
57
|
// exactly one the bridge forwards.
|
|
58
58
|
import { CURATED_REGION_EVENTS, EXCLUDED_REGION_EVENTS } from "./region-events.mjs";
|
|
59
59
|
// A map's background art is `img`, as every other note type's art is. `image`,
|
|
60
|
-
// the spelling a map alone once used, is retired and gone
|
|
60
|
+
// the spelling a map alone once used, is retired and gone.
|
|
61
61
|
import { sohlField } from "./frontmatter.mjs";
|
|
62
62
|
|
|
63
63
|
/* -------------------------------------------------------------------- */
|
|
@@ -113,7 +113,7 @@ export const MAP_SUBTYPE_PROFILES = Object.freeze({
|
|
|
113
113
|
/**
|
|
114
114
|
* The canvas profile for a map subType.
|
|
115
115
|
*
|
|
116
|
-
* Keyed on the subType rather than the type
|
|
116
|
+
* Keyed on the subType rather than the type: every map note is
|
|
117
117
|
* `type: map`, and which canvas it derives is the one thing the three
|
|
118
118
|
* spellings ever decided.
|
|
119
119
|
*
|
|
@@ -556,7 +556,7 @@ const SCROLLING_TEXT_EVENTS = Object.freeze([
|
|
|
556
556
|
* @type {Readonly<Record<string, {fields: string[], events?: readonly string[]}>>}
|
|
557
557
|
*/
|
|
558
558
|
const BEHAVIOR_SPECS = Object.freeze({
|
|
559
|
-
// The SoHL bridge
|
|
559
|
+
// The SoHL bridge.
|
|
560
560
|
trigger: { fields: ["events", "action"], events: CURATED_REGION_EVENTS },
|
|
561
561
|
adjustDarknessLevel: { fields: ["mode", "modifier"] },
|
|
562
562
|
applyActiveEffect: { fields: ["effects"] },
|
|
@@ -590,7 +590,7 @@ const BEHAVIOR_SPECS = Object.freeze({
|
|
|
590
590
|
});
|
|
591
591
|
|
|
592
592
|
/**
|
|
593
|
-
* The behaviour types a map note may carry (
|
|
593
|
+
* The behaviour types a map note may carry (v1).
|
|
594
594
|
*
|
|
595
595
|
* @type {ReadonlySet<string>}
|
|
596
596
|
*/
|
|
@@ -619,7 +619,7 @@ export const BANNED_REGION_BEHAVIOR_TYPES = Object.freeze(
|
|
|
619
619
|
[
|
|
620
620
|
"executeMacro",
|
|
621
621
|
"its target Macro must ship in the same Adventure to resolve, and " +
|
|
622
|
-
"Adventure-bundled macros are not built yet
|
|
622
|
+
"Adventure-bundled macros are not built yet.",
|
|
623
623
|
],
|
|
624
624
|
]),
|
|
625
625
|
);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The published content index — the artifact packages exchange addresses
|
|
16
|
-
* through
|
|
16
|
+
* through.
|
|
17
17
|
*
|
|
18
18
|
* **A package publishes its own index; a consumer fetches the ones it depends
|
|
19
19
|
* on.** That is the whole mechanism, and it replaces a vendored link manifest
|
|
@@ -94,7 +94,7 @@ export function metadataFileName(pkg) {
|
|
|
94
94
|
* `itemCatalog: true` says a dependency supplies *items*; citing its
|
|
95
95
|
* *addresses* is a separate edge, and a package may have either without the
|
|
96
96
|
* other. `harn-ensemble` cites no foreign address and carries 324,016 embedded
|
|
97
|
-
* item references
|
|
97
|
+
* item references; a package citing addresses
|
|
98
98
|
* and needing no items is the mirror of it. Gating the index on the catalogue
|
|
99
99
|
* flag would serve neither.
|
|
100
100
|
*
|
|
@@ -182,7 +182,7 @@ export function cachedMetadataFiles(config) {
|
|
|
182
182
|
* The same fetched indexes, each paired with the package that published it.
|
|
183
183
|
*
|
|
184
184
|
* The id is what a SQL content table addresses a dependency's notes by
|
|
185
|
-
* (`FROM sohl.notes
|
|
185
|
+
* (`FROM sohl.notes`), so the pairing has to survive the lookup —
|
|
186
186
|
* {@link cachedMetadataFiles} drops it, and a caller reconstructing the id from
|
|
187
187
|
* the file name would be parsing a path to recover something the declaration
|
|
188
188
|
* already stated.
|
|
@@ -230,7 +230,7 @@ export function cachedMetadataIndexes(config) {
|
|
|
230
230
|
* rather than being written once per cache. Two copies would be two chances to
|
|
231
231
|
* get it wrong, and the wrong answer is invisible: every cached version is a
|
|
232
232
|
* complete, stamped, perfectly valid artifact, so picking the older one reports
|
|
233
|
-
* nothing and simply resolves against stale data
|
|
233
|
+
* nothing and simply resolves against stale data.
|
|
234
234
|
*
|
|
235
235
|
* @param {string[]} dirs - Complete cache directories, named `<id>@<version>`.
|
|
236
236
|
* @returns {string} The newest one.
|
|
@@ -426,7 +426,7 @@ export function cachedIndexPath(config, pkg) {
|
|
|
426
426
|
* therefore reported against the index, once, instead of once per citing note.
|
|
427
427
|
*
|
|
428
428
|
* The realistic cause is a version skew: a dependency released before the
|
|
429
|
-
* address grammar gained its `<system>` segment
|
|
429
|
+
* address grammar gained its `<system>` segment ships three-segment keys.
|
|
430
430
|
* Re-fetching after that dependency releases is the fix.
|
|
431
431
|
*
|
|
432
432
|
* @param {Map<string, object>} foreignIndex - The resolved foreign index.
|
package/engine/note-claims.mjs
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* **Which note types a configuration compiles at all** — the finding for a note
|
|
16
|
-
* whose type nothing claims
|
|
17
|
-
* document while the rest of it compiles
|
|
16
|
+
* whose type nothing claims, and the one for a note that loses a
|
|
17
|
+
* document while the rest of it compiles.
|
|
18
18
|
*
|
|
19
19
|
* Every compile pass answers one question about a note: _is this mine?_ A note
|
|
20
20
|
* every pass answers "no" to is skipped as quietly as the thousands that
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*
|
|
30
30
|
* This module supplies the missing complaint, and it is asked **once per
|
|
31
31
|
* build** rather than once per pass. That is not an optimisation: it is the
|
|
32
|
-
* only place the question can be answered correctly.
|
|
32
|
+
* only place the question can be answered correctly. The rule is that a
|
|
33
33
|
* markdown type with no mapping in a given system produces no document *for
|
|
34
34
|
* that system*, silently and correctly — so a per-pass check would report
|
|
35
35
|
* `armorlocation` against every system that does not map it, which is precisely
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
* who invented a word. Collapsing the two would send `harn-ensemble` to correct
|
|
52
52
|
* five perfectly good notes.
|
|
53
53
|
*
|
|
54
|
-
* ## The partial case is a third condition, and it was invisible
|
|
54
|
+
* ## The partial case is a third condition, and it was invisible
|
|
55
55
|
*
|
|
56
56
|
* The table above asks whether a note is compiled *at all*, and a note that
|
|
57
57
|
* compiles one of its two documents answers yes. But a note produces more than
|
|
58
58
|
* one document as a matter of course — an item note an Item and the
|
|
59
59
|
* JournalEntry its prose becomes, a map note a Scene and a JournalEntry, an
|
|
60
|
-
* actor note an Actor and a JournalEntry
|
|
60
|
+
* actor note an Actor and a JournalEntry — so a configuration
|
|
61
61
|
* missing a pack for *one* of them dropped that document while the rest of the
|
|
62
62
|
* note compiled into a pack that does exist. The build succeeded and shipped
|
|
63
63
|
* half of what was written.
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
|
|
86
86
|
import { assertSuppliedCorpus, parseMarkdownFile } from "./helpers.mjs";
|
|
87
87
|
// The record accessors only: this module is imported by the content index, so
|
|
88
|
-
// importing the index back would close a cycle
|
|
88
|
+
// importing the index back would close a cycle.
|
|
89
89
|
import { authoredFrontmatter, isNoteRecord, noteFile } from "./index-records.mjs";
|
|
90
90
|
import { JOURNAL_TYPES, MAP_TYPES, PACK_BY_TYPE, RETIRED_TYPES, currentType } from "./ids.mjs";
|
|
91
91
|
import { itemTypes } from "./item-registry.mjs";
|
|
@@ -124,11 +124,11 @@ export const NEVER_PACKED_TYPES = Object.freeze(new Set([HOMEPAGE_TYPE]));
|
|
|
124
124
|
* correctly and is worthless, because the configured vocabulary is *derived
|
|
125
125
|
* from the routing*. Take a type's route away and it leaves the vocabulary too,
|
|
126
126
|
* so the inference excuses precisely the mistake it was meant to catch. That is
|
|
127
|
-
* not hypothetical:
|
|
128
|
-
*
|
|
129
|
-
*
|
|
127
|
+
* not hypothetical: `place`, `lore` and `scenario` were declared, validated
|
|
128
|
+
* and unrouted, and every gate reported success until a downstream repository
|
|
129
|
+
* failed on the notes carrying them.
|
|
130
130
|
*
|
|
131
|
-
* A type leaves this set when it is implemented
|
|
131
|
+
* A type leaves this set when it is implemented.
|
|
132
132
|
* The membership is asserted, so it cannot be forgotten in either direction.
|
|
133
133
|
*
|
|
134
134
|
* @type {ReadonlySet<string>}
|
|
@@ -141,7 +141,7 @@ export const UNIMPLEMENTED_TYPES = Object.freeze(new Set(["vehicle"]));
|
|
|
141
141
|
* A folder is the only one, and it is not unclaimed: it compiles to a real
|
|
142
142
|
* `Folder` document. What it has no answer to is *which* pack claims it, because
|
|
143
143
|
* that is not a property of the note — a folder materialises in every pack
|
|
144
|
-
* holding a document that references it, and its ancestors with it
|
|
144
|
+
* holding a document that references it, and its ancestors with it. So
|
|
145
145
|
* it is exempt from the claim check for the opposite reason a homepage is:
|
|
146
146
|
* a homepage is in no pack, and a folder may be in several.
|
|
147
147
|
*
|
|
@@ -153,7 +153,7 @@ export const DERIVED_PACKED_TYPES = Object.freeze(new Set([FOLDER_TYPE]));
|
|
|
153
153
|
* The note-type → document-subtype maps this toolchain ships.
|
|
154
154
|
*
|
|
155
155
|
* Declared in {@link module:engine/subtype-registry} and re-exported here,
|
|
156
|
-
* where it
|
|
156
|
+
* where it is read from. It sits on a leaf so that
|
|
157
157
|
* `helpers.mjs` could reach it: this module imports `walkMarkdownTree` from
|
|
158
158
|
* there, so a dependency the other way would have closed a cycle.
|
|
159
159
|
*
|
|
@@ -232,7 +232,7 @@ function mappingSystems(maps, type) {
|
|
|
232
232
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
233
233
|
* @param {object} [opts] - Options.
|
|
234
234
|
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
235
|
-
* compile and handed in — required, for the reason above
|
|
235
|
+
* compile and handed in — required, for the reason above. Defaults to the
|
|
236
236
|
* configured registries and the systems this toolchain ships.
|
|
237
237
|
* @returns {ReadonlySet<string>} The note types such a pass would claim.
|
|
238
238
|
*/
|
|
@@ -263,8 +263,8 @@ export function noteTypesClaimedBy(docType, sources) {
|
|
|
263
263
|
return Object.freeze(new Set(["macro"]));
|
|
264
264
|
case "Scene":
|
|
265
265
|
return Object.freeze(new Set(MAP_TYPES));
|
|
266
|
-
// The bundles pass: an Adventure is what a `bundle` note compiles into
|
|
267
|
-
//
|
|
266
|
+
// The bundles pass: an Adventure is what a `bundle` note compiles into.
|
|
267
|
+
// A **prebuilt** Adventure pack still claims nothing —
|
|
268
268
|
// {@link claimedNoteTypes} passes over it, because no note is routed
|
|
269
269
|
// into a pack whose JSON is checked in rather than compiled.
|
|
270
270
|
case "Adventure":
|
|
@@ -297,13 +297,13 @@ export const CLAIMABLE_DOCUMENT_TYPES = Object.freeze([
|
|
|
297
297
|
]);
|
|
298
298
|
|
|
299
299
|
/**
|
|
300
|
-
* Every document class a note of one type compiles into
|
|
300
|
+
* Every document class a note of one type compiles into.
|
|
301
301
|
*
|
|
302
302
|
* **A note produces more than one document, and that is the ordinary case.** An
|
|
303
303
|
* item note compiles an Item *and* the JournalEntry its prose becomes; a map
|
|
304
|
-
* note a Scene and a JournalEntry;
|
|
304
|
+
* note a Scene and a JournalEntry; an actor note an Actor and a
|
|
305
305
|
* JournalEntry too. {@link claimedNoteTypes} unions over the configured packs
|
|
306
|
-
* and so answers "is this note compiled *at all*",
|
|
306
|
+
* and so answers "is this note compiled *at all*", and
|
|
307
307
|
* cannot see a note that compiles one of its two documents and loses the other.
|
|
308
308
|
*
|
|
309
309
|
* Asked of the **claim table** rather than of a list of its own, so the set of
|
|
@@ -314,7 +314,7 @@ export const CLAIMABLE_DOCUMENT_TYPES = Object.freeze([
|
|
|
314
314
|
* **Union across systems, never per system.** A type one system maps and
|
|
315
315
|
* another does not appears once, because the `Item` and `Actor` rows already
|
|
316
316
|
* fold the maps together — so this cannot report a document class a system
|
|
317
|
-
* deliberately declines to produce, which is the silence
|
|
317
|
+
* deliberately declines to produce, which is the silence the rule requires.
|
|
318
318
|
*
|
|
319
319
|
* ## The JournalEntry row is the one that is per *note*
|
|
320
320
|
*
|
|
@@ -361,7 +361,7 @@ export function documentClassesFor(type, sources, { hasProse } = {}) {
|
|
|
361
361
|
|
|
362
362
|
/**
|
|
363
363
|
* Whether a note carries a body at all — the condition `Journals.skipNote`
|
|
364
|
-
* applies, asked from the outside
|
|
364
|
+
* applies, asked from the outside.
|
|
365
365
|
*
|
|
366
366
|
* Read from the file rather than from the index record, because a record
|
|
367
367
|
* carries a note's frontmatter and its derived address and not its prose. The
|
|
@@ -388,13 +388,14 @@ function noteHasProse(absPath) {
|
|
|
388
388
|
*
|
|
389
389
|
* The union across the configured pack list, so a type claimed by any one pack
|
|
390
390
|
* is claimed — which is what keeps a type deliberately unmapped for one system,
|
|
391
|
-
* and claimed for another, silent
|
|
391
|
+
* and claimed for another, silent.
|
|
392
392
|
*
|
|
393
393
|
* **A prebuilt pack claims nothing.** Its per-document JSON is checked in
|
|
394
394
|
* rather than compiled, so it has no pass and no note is routed into one —
|
|
395
395
|
* which `content-config.mjs` already states by refusing `default: true`
|
|
396
396
|
* alongside `prebuilt`. Counting it would tell an author their note is claimed
|
|
397
|
-
* by a pack that will never look at it.
|
|
397
|
+
* by a pack that will never look at it. With no unimplemented type declared,
|
|
398
|
+
* the point cannot arise:
|
|
398
399
|
* the only prebuilt pack in the wild is `harn-adventures`'s Adventure pack, and
|
|
399
400
|
* no compiler was registered for that document type, so the row answered for
|
|
400
401
|
* nothing whatever it was asked. Now one is.
|
|
@@ -404,7 +405,7 @@ function noteHasProse(absPath) {
|
|
|
404
405
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
405
406
|
* @param {object} [opts] - Options.
|
|
406
407
|
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
407
|
-
* compile and handed in — required, for the reason above
|
|
408
|
+
* compile and handed in — required, for the reason above.
|
|
408
409
|
* @returns {ReadonlySet<string>} The claimed note types.
|
|
409
410
|
*/
|
|
410
411
|
export function claimedNoteTypes(config = loadPackConfig(), sources) {
|
|
@@ -428,7 +429,7 @@ export function claimedNoteTypes(config = loadPackConfig(), sources) {
|
|
|
428
429
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
429
430
|
* @param {object} [opts] - Options.
|
|
430
431
|
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
431
|
-
* compile and handed in — required, for the reason above
|
|
432
|
+
* compile and handed in — required, for the reason above.
|
|
432
433
|
* @returns {ReadonlySet<string>} The vocabulary.
|
|
433
434
|
*/
|
|
434
435
|
export function noteTypeVocabulary(sources) {
|
|
@@ -483,7 +484,7 @@ function article(word) {
|
|
|
483
484
|
function configurationMessage(type, config, sources) {
|
|
484
485
|
// Every table below is keyed by the current spelling of a note type; the
|
|
485
486
|
// message quotes the authored one, which is what the reader has in front of
|
|
486
|
-
// them
|
|
487
|
+
// them.
|
|
487
488
|
const current = currentType(type);
|
|
488
489
|
const documents = mappedDocuments(sources.maps, type);
|
|
489
490
|
if (!documents.length && sources.itemTypes.has(current)) documents.push("Item");
|
|
@@ -550,10 +551,10 @@ function specifiedMessage(type) {
|
|
|
550
551
|
}
|
|
551
552
|
|
|
552
553
|
/**
|
|
553
|
-
* The **partial** finding: the note compiles, and one of its documents does not
|
|
554
|
-
* (#152).
|
|
554
|
+
* The **partial** finding: the note compiles, and one of its documents does not.
|
|
555
555
|
*
|
|
556
|
-
*
|
|
556
|
+
* The unclaimed check asks "does anything claim this note", and the answer is
|
|
557
|
+
* yes —
|
|
557
558
|
* which is exactly why this went unreported. A note produces more than one
|
|
558
559
|
* document, and a configuration missing a pack for one of them drops that
|
|
559
560
|
* document while the rest of the note compiles into a pack that does exist. The
|
|
@@ -562,7 +563,8 @@ function specifiedMessage(type) {
|
|
|
562
563
|
*
|
|
563
564
|
* The message names the note, the document class with no pack, and the class
|
|
564
565
|
* that *did* compile — the last because it is what distinguishes this from
|
|
565
|
-
*
|
|
566
|
+
* the unclaimed finding at a glance: the note is not unclaimed, it is
|
|
567
|
+
* half-claimed, and
|
|
566
568
|
* the fix is a pack rather than a `type:`.
|
|
567
569
|
*
|
|
568
570
|
* @param {string} type - The note's declared `type`.
|
|
@@ -618,7 +620,7 @@ function authoringMessage(type) {
|
|
|
618
620
|
* @param {ClaimSources} [sources] - What to answer from.
|
|
619
621
|
* @param {object} [opts] - Options.
|
|
620
622
|
* @param {readonly object[]} [opts.records] - The corpus, derived once by the
|
|
621
|
-
* compile and handed in — required, for the reason above
|
|
623
|
+
* compile and handed in — required, for the reason above.
|
|
622
624
|
* @returns {Array<{file: string, line?: number, column?: number,
|
|
623
625
|
* severity: "error", message: string, type: string}>} One finding per note.
|
|
624
626
|
*/
|
|
@@ -632,7 +634,7 @@ export function unclaimedNoteFindings(config = loadPackConfig(), sources, { reco
|
|
|
632
634
|
// and no note is routed into it.
|
|
633
635
|
const configured = new Set((config.packs ?? []).filter((p) => !p.prebuilt).map((p) => p.type));
|
|
634
636
|
|
|
635
|
-
// The corpus this compile derived once
|
|
637
|
+
// The corpus this compile derived once, required rather than
|
|
636
638
|
// derived here: this module is imported *by* the content index, so it
|
|
637
639
|
// could not derive one without closing a cycle — and the caller that wants
|
|
638
640
|
// this answer is running a compile and already holds it.
|
|
@@ -651,13 +653,13 @@ export function unclaimedNoteFindings(config = loadPackConfig(), sources, { reco
|
|
|
651
653
|
// A **renamed** spelling is a live type, not an unknown one: it resolves
|
|
652
654
|
// to the same row, the same registry entry and the same pack. So the
|
|
653
655
|
// claim is asked of the current spelling while the finding quotes the
|
|
654
|
-
// authored one
|
|
656
|
+
// authored one. The rename itself is reported by the frontmatter
|
|
655
657
|
// lint, which can say what to write instead.
|
|
656
658
|
const current = currentType(type);
|
|
657
659
|
|
|
658
660
|
// Every document this note produces, against the classes this
|
|
659
661
|
// configuration has a pack for. Three outcomes, and the middle one is
|
|
660
|
-
//
|
|
662
|
+
// the half-claimed one — invisible while the question is only "is anything
|
|
661
663
|
// claiming this note", because the answer there is yes.
|
|
662
664
|
const produces = documentClassesFor(current, resolved, {
|
|
663
665
|
// Lazy: only a doc-carrying type whose JournalEntry has nowhere to
|
|
@@ -673,7 +675,7 @@ export function unclaimedNoteFindings(config = loadPackConfig(), sources, { reco
|
|
|
673
675
|
|
|
674
676
|
// Some do and some do not: the note compiles, and one of its documents
|
|
675
677
|
// is dropped in silence. A type nothing produces at all falls past this
|
|
676
|
-
// to the
|
|
678
|
+
// to the unclaimed messages below, where `produces` being empty is itself
|
|
677
679
|
// part of the answer.
|
|
678
680
|
if (compiled.length) {
|
|
679
681
|
findings.push({
|
package/engine/note-ids.mjs
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* says everything the id said, is readable, and is the identity `content-lint`
|
|
21
21
|
* already guards: a duplicate address is a build error, while a duplicate `id`
|
|
22
22
|
* was checked nowhere. So the derived id inherits a guarantee, where the
|
|
23
|
-
* authored one had none
|
|
23
|
+
* authored one had none.
|
|
24
24
|
*
|
|
25
25
|
* **An authored `id` always wins.** That is the pattern the map compiler
|
|
26
26
|
* already uses and documents — `regionDocId(sceneId, key, pinned)` returns
|
|
@@ -73,15 +73,15 @@ function text(value) {
|
|
|
73
73
|
* the rule but an application of it.** A `Folder` is a document of its own
|
|
74
74
|
* class, and its id is hashed under the `folder` namespace so that a folder and
|
|
75
75
|
* an item sharing a shortcode cannot derive one id — a collision Foundry would
|
|
76
|
-
* not report, since it keys folders and documents in separate collections
|
|
77
|
-
*
|
|
76
|
+
* not report, since it keys folders and documents in separate collections.
|
|
77
|
+
* So the answer for a folder comes from
|
|
78
78
|
* {@link module:engine/folder-notes.folderDocId}, the pass that emits those
|
|
79
79
|
* documents, rather than from a second derivation here.
|
|
80
80
|
*
|
|
81
81
|
* That this function ever answered differently was invisible from inside a
|
|
82
82
|
* build — no pass reads a folder's id from here — and surfaced only in the
|
|
83
83
|
* content index, which is read from outside and had no way to be checked
|
|
84
|
-
* against what shipped
|
|
84
|
+
* against what shipped.
|
|
85
85
|
*
|
|
86
86
|
* Returns `undefined` for a file with **no address** — no `type`, or no
|
|
87
87
|
* `shortcode`. Such a file is not an addressable note, so it has no document
|
|
@@ -94,7 +94,7 @@ function text(value) {
|
|
|
94
94
|
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
95
95
|
* @param {object} [opts]
|
|
96
96
|
* @param {string} [opts.pkg] - The owning content package. Defaults to the
|
|
97
|
-
* configured one, which is the only package a tree's notes belong to
|
|
97
|
+
* configured one, which is the only package a tree's notes belong to.
|
|
98
98
|
* @param {readonly object[]} [opts.maps] - The document-subtype maps, which
|
|
99
99
|
* decide the address's `<system>` segment.
|
|
100
100
|
* @returns {string|undefined} The document's `_id`, or `undefined` when the
|
package/engine/note-package.mjs
CHANGED
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
* single-sourced in the repository that ships it — so the package is a property
|
|
20
20
|
* of the *repository*, not of the note, and no note declares it.
|
|
21
21
|
*
|
|
22
|
-
* It
|
|
22
|
+
* It is not a property of the note, and not a **selector**: as one, the compile loop
|
|
23
23
|
* read `package:` out of frontmatter and skipped anything that did not match
|
|
24
|
-
* the configured value. That is the defect this module exists to remove
|
|
25
|
-
*
|
|
24
|
+
* the configured value. That is the defect this module exists to remove.
|
|
25
|
+
* The skip was silent and it was bucketed as "belongs to another pass",
|
|
26
26
|
* so a tree whose notes named a package no configuration answered to compiled
|
|
27
27
|
* **zero notes and exited 0** — which is exactly the state the un-migrated
|
|
28
28
|
* `hm-loc-*` / `hm-adv-*` repositories are in today.
|
|
@@ -64,7 +64,7 @@ import { locateFrontmatterKey } from "./retired-fields.mjs";
|
|
|
64
64
|
* field, so a collection note that scopes itself with `WHERE … and package =
|
|
65
65
|
* "sohl"` would match nothing now that the field is gone, and would render an
|
|
66
66
|
* **empty table** in silence. Supplying the derived value here is what kept the
|
|
67
|
-
* sweep mechanical rather than a trap
|
|
67
|
+
* sweep mechanical rather than a trap — and a query that never mentions
|
|
68
68
|
* `package` is unaffected either way.
|
|
69
69
|
*
|
|
70
70
|
* The frontmatter is copied rather than written into: it is the note's own
|
package/engine/note-renames.mjs
CHANGED
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The shortcodes a note declares it used to be published under
|
|
15
|
+
* The shortcodes a note declares it used to be published under.
|
|
16
16
|
*
|
|
17
17
|
* A package's `(type, shortcode)` addresses are a published interface, and
|
|
18
18
|
* `addresses diff` reports what a build stopped publishing — telling a
|
|
19
19
|
* **rename** from a **withdrawal** by matching document ids across two
|
|
20
|
-
* releases.
|
|
20
|
+
* releases. The property that rested on is gone: an id is derived from
|
|
21
21
|
* the canonical address, which carries the shortcode, so renaming a shortcode
|
|
22
22
|
* moves the id too: both sides of the join move together, the match finds
|
|
23
23
|
* nothing, and a rename is reported as a withdrawal with no successor named.
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
* **It is transient.** Once every baseline a build is compared against post-dates
|
|
53
53
|
* the rename, the declaration has nothing left to say and may be deleted. That
|
|
54
54
|
* is the difference from an `id:` pin, which is permanent, opaque, and a second
|
|
55
|
-
* identity for a thing that already has one
|
|
55
|
+
* identity for a thing that already has one.
|
|
56
56
|
*
|
|
57
57
|
* **It is one key per note, at the top level, however many systems the note
|
|
58
58
|
* compiles into.** A shortcode is the note's, not a system block's: a note
|