@heroiclands/package-build 20.3.1 → 20.5.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 +351 -0
- package/CONTENT.md +322 -110
- package/README.md +21 -10
- package/bin/content-build.mjs +204 -92
- package/bin/package-build.mjs +48 -15
- package/config.mjs +6 -8
- package/content-config.mjs +518 -151
- package/docs/api.md +1352 -0
- package/docs/commands.md +1609 -0
- package/docs/configuration.md +1432 -0
- package/docs/content-format.md +73 -74
- package/docs/diagnostics.md +356 -0
- package/docs/getting-started.md +813 -0
- package/docs/project-setup.md +469 -0
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +64 -61
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +57 -52
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +42 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +17 -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 +24 -24
- 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 +61 -40
- package/engine/content-links.mjs +74 -41
- package/engine/content-lint.mjs +64 -34
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +38 -34
- 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 +18 -16
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +95 -103
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +44 -39
- package/engine/helpers.mjs +147 -84
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +26 -10
- 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 +24 -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 +51 -41
- 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 -8
- package/engine/note-vocabulary.mjs +56 -54
- package/engine/pack-config.mjs +39 -25
- package/engine/pack-router.mjs +0 -0
- package/engine/pdf-build.mjs +464 -0
- package/engine/pdf-fonts.mjs +420 -0
- package/engine/pdf-render.mjs +798 -0
- package/engine/pdf-toc.mjs +525 -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 +33 -25
- package/engine/schema-check.mjs +21 -21
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +66 -50
- 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 +41 -38
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +40 -42
- package/hm3/actors.mjs +30 -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 +28 -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 +66 -6
- package/sohl/actors.mjs +36 -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 +28 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +12 -12
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +91 -39
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +45 -40
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +60 -6
- package/types/engine/base-compiler.d.mts +27 -21
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +10 -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 +20 -20
- 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 +59 -15
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +8 -6
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/content-tables.d.mts +49 -18
- 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 +10 -9
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +128 -56
- 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 +6 -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 +12 -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 +30 -22
- 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 +31 -203
- package/types/engine/pack-config.d.mts +7 -7
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/pdf-build.d.mts +42 -0
- package/types/engine/pdf-fonts.d.mts +30 -0
- package/types/engine/pdf-render.d.mts +144 -0
- package/types/engine/pdf-toc.d.mts +114 -0
- 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/scenes.d.mts +10 -1
- package/types/engine/schema-check.d.mts +13 -13
- package/types/engine/site-build.d.mts +52 -25
- 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 +14 -14
- package/types/hm3/actors.d.mts +9 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +9 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/release.d.mts +15 -4
- package/types/sohl/actors.d.mts +12 -4
- 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 +9 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
package/engine/base-compiler.mjs
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* failed are the same in every pass. They were written out
|
|
20
20
|
* once per pass — three times when this was filed, five by the time it landed —
|
|
21
21
|
* so a fix to any of them had to be made everywhere, and the passes drifted
|
|
22
|
-
* apart in exactly the places nobody was comparing
|
|
22
|
+
* apart in exactly the places nobody was comparing.
|
|
23
23
|
*
|
|
24
24
|
* A pass now states only what makes it that pass:
|
|
25
25
|
*
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* `selects` answers *which document type* a pass claims, and it is the same
|
|
44
44
|
* answer for every pack of that type. Which **pack of that type** a claimed
|
|
45
45
|
* note lands in is a second question, answered by the pack router from the
|
|
46
|
-
* note's own `pack:` declaration
|
|
46
|
+
* note's own `pack:` declaration — so a subclass never has to know that
|
|
47
47
|
* its type ships in more than one pack.
|
|
48
48
|
*
|
|
49
49
|
* **This is the extension point.** The pack list is data
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
statsForPack,
|
|
75
75
|
} from "./helpers.mjs";
|
|
76
76
|
// The record accessors only — see `engine/index-records.mjs` for why they live
|
|
77
|
-
// apart from the index that builds them
|
|
77
|
+
// apart from the index that builds them.
|
|
78
78
|
import { isNoteRecord, noteFile } from "./index-records.mjs";
|
|
79
79
|
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
80
80
|
import { assertNoDeclaredPackage } from "./note-package.mjs";
|
|
@@ -98,7 +98,7 @@ import { locateFrontmatterKey } from "./retired-fields.mjs";
|
|
|
98
98
|
* note is one this build **refused** — it declares a retired frontmatter field
|
|
99
99
|
* — and it is an error; a skipped one legitimately belongs to another pass, and
|
|
100
100
|
* there are thousands of those. Folding the first into the second is what let a
|
|
101
|
-
* whole tree be filtered out in silence
|
|
101
|
+
* whole tree be filtered out in silence.
|
|
102
102
|
*
|
|
103
103
|
* @typedef {object} PassStats
|
|
104
104
|
* @property {number} compiled - Notes that became a document.
|
|
@@ -106,7 +106,7 @@ import { locateFrontmatterKey } from "./retired-fields.mjs";
|
|
|
106
106
|
* @property {number} skippedOther - Notes this pass does not claim.
|
|
107
107
|
* @property {number} declined - Notes this pack **refused** — one declaring a
|
|
108
108
|
* retired frontmatter field, or one routed to a system pack whose system it
|
|
109
|
-
* says nothing about
|
|
109
|
+
* says nothing about. Counted as errors, never as skips.
|
|
110
110
|
*/
|
|
111
111
|
|
|
112
112
|
/**
|
|
@@ -148,7 +148,7 @@ export class BasePackCompiler {
|
|
|
148
148
|
* its generated tables expanded and its wikilinks converted.
|
|
149
149
|
*
|
|
150
150
|
* False for a pass whose output must be exactly what the author typed —
|
|
151
|
-
* the macros pass, whose `command` is executable source
|
|
151
|
+
* the macros pass, whose `command` is executable source. A pass
|
|
152
152
|
* that says so also skips building the content-wide link index it would
|
|
153
153
|
* never read.
|
|
154
154
|
*
|
|
@@ -165,7 +165,7 @@ export class BasePackCompiler {
|
|
|
165
165
|
* passes wrote — so an Actor pass must run after every Item pass, and it
|
|
166
166
|
* says so here.
|
|
167
167
|
*
|
|
168
|
-
* The generator derives the compile order from this
|
|
168
|
+
* The generator derives the compile order from this, so the order
|
|
169
169
|
* `packs:` declares is presentation only — it is the manifest's `packs`
|
|
170
170
|
* array as well, and a consumer orders that for a reader. A pass that
|
|
171
171
|
* reads another's output states the dependency once, in the class that
|
|
@@ -181,7 +181,7 @@ export class BasePackCompiler {
|
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
183
|
* Whether this pass's document **is** a system's data, and therefore takes
|
|
184
|
-
* only notes that carry that system's block
|
|
184
|
+
* only notes that carry that system's block.
|
|
185
185
|
*
|
|
186
186
|
* A pack may declare a `system:` — `harn-ensemble` ships an `actors-hm3`
|
|
187
187
|
* and an `actors-sohl` from one tree — and the note-side half of that is
|
|
@@ -212,7 +212,7 @@ export class BasePackCompiler {
|
|
|
212
212
|
* legal on every note whatever its type, because
|
|
213
213
|
* `BLOCK_DOCUMENT_PROPERTIES` maps it onto `document.img` — so a note whose
|
|
214
214
|
* document has no such property authors it, validates, compiles, and loses
|
|
215
|
-
* the value with nothing said
|
|
215
|
+
* the value with nothing said: `Parrot` in `sohl-thalorna`
|
|
216
216
|
* had declared `img:` since long before the art rule existed and compiled
|
|
217
217
|
* `img: null` exactly as a note declaring nothing does. Naming the fields
|
|
218
218
|
* here is what lets the lint tell an inert key from a live one.
|
|
@@ -237,7 +237,7 @@ export class BasePackCompiler {
|
|
|
237
237
|
errorCount = 0;
|
|
238
238
|
|
|
239
239
|
/**
|
|
240
|
-
* Emitted-`system` findings, one per `documentType|subtype|field
|
|
240
|
+
* Emitted-`system` findings, one per `documentType|subtype|field`.
|
|
241
241
|
*
|
|
242
242
|
* A key the compiler writes is on **every** document of a subtype, so
|
|
243
243
|
* reporting it where it is found would print the same sentence 3,126 times
|
|
@@ -301,13 +301,19 @@ export class BasePackCompiler {
|
|
|
301
301
|
* never descends into. Required: see {@link assertStatedScope}.
|
|
302
302
|
* @param {(address: string|null) => string|null} [options.folderResolver] -
|
|
303
303
|
* Resolves a `packFolder` — a folder note's address — to the Foundry
|
|
304
|
-
* folder id it materialises as in this pack
|
|
304
|
+
* folder id it materialises as in this pack.
|
|
305
305
|
* @param {string} [options.packName] - The pack this pass writes.
|
|
306
|
+
* @param {string|null} [options.packSystem] - The system that pack declares,
|
|
307
|
+
* which decides the `_stats` it stamps and the system block a note must
|
|
308
|
+
* carry to reach it. `null` for a pack that declares none.
|
|
306
309
|
* @param {string} [options.docType] - The Foundry document type it holds.
|
|
307
310
|
* @param {{resolve: Function}} [options.router] - The pack router. Omit it
|
|
308
311
|
* — as the unit suite does — and every claimed note is compiled here.
|
|
309
312
|
* @param {boolean} [options.routingReporter] - Whether this pass reports a
|
|
310
313
|
* note of its type that routes nowhere.
|
|
314
|
+
* @param {object} [options.corpus] - The corpus this compile is running
|
|
315
|
+
* over, derived once and shared by every pass. A pass handed none derives
|
|
316
|
+
* its own in `prepare`, and reports that corpus's problems itself.
|
|
311
317
|
*/
|
|
312
318
|
constructor({
|
|
313
319
|
contentBase,
|
|
@@ -347,7 +353,7 @@ export class BasePackCompiler {
|
|
|
347
353
|
writable: false,
|
|
348
354
|
});
|
|
349
355
|
// The walk's scope, stated by whoever built this pass rather than
|
|
350
|
-
// resolved from the working directory
|
|
356
|
+
// resolved from the working directory. Every walk this compiler
|
|
351
357
|
// makes — its own, the table corpus, the link index, the SQL tables —
|
|
352
358
|
// uses this one answer.
|
|
353
359
|
Object.defineProperty(this, "skipDirectories", {
|
|
@@ -360,14 +366,14 @@ export class BasePackCompiler {
|
|
|
360
366
|
this.router = router;
|
|
361
367
|
this.routingReporter = routingReporter;
|
|
362
368
|
// The corpus this compile is running over, derived once by
|
|
363
|
-
// `generatePacksJson` and shared by every pass
|
|
369
|
+
// `generatePacksJson` and shared by every pass. A pass that is
|
|
364
370
|
// handed none derives its own in `prepare`, which is what a consumer
|
|
365
371
|
// constructing one compiler directly does.
|
|
366
372
|
this.corpus = corpus;
|
|
367
373
|
}
|
|
368
374
|
|
|
369
375
|
/**
|
|
370
|
-
* The `_stats` block every entry this pass emits is stamped with
|
|
376
|
+
* The `_stats` block every entry this pass emits is stamped with.
|
|
371
377
|
*
|
|
372
378
|
* Per pack rather than per package, because a module may ship the same
|
|
373
379
|
* content for two systems — `harn-ensemble` has an `actors-hm3` pack and an
|
|
@@ -410,8 +416,7 @@ export class BasePackCompiler {
|
|
|
410
416
|
* routed *here* and carries nothing for this pack's system is an authoring
|
|
411
417
|
* mistake with a hollow document at the end of it, not a note that belongs
|
|
412
418
|
* to another pass. Skipping it quietly is how a whole tree compiles to
|
|
413
|
-
* documents nobody can use
|
|
414
|
-
* instances of.
|
|
419
|
+
* documents nobody can use.
|
|
415
420
|
*
|
|
416
421
|
* @param {object} fm - The note's frontmatter.
|
|
417
422
|
* @returns {boolean} True when the note may be compiled here; `false` when
|
|
@@ -424,7 +429,7 @@ export class BasePackCompiler {
|
|
|
424
429
|
eligibleFor(fm) {
|
|
425
430
|
if (!this.constructor.requiresSystemBlock || !this.packSystem) return true;
|
|
426
431
|
if (carriesSystemBlock(fm, this.packSystem)) return true;
|
|
427
|
-
// Another system's pack of this document type will claim it
|
|
432
|
+
// Another system's pack of this document type will claim it. A
|
|
428
433
|
// note carrying only `hm3:` routes here because this pack is the
|
|
429
434
|
// *default* of its document type, and defaults are declared per type
|
|
430
435
|
// rather than per system — but it is not an incomplete note, it is
|
|
@@ -446,7 +451,7 @@ export class BasePackCompiler {
|
|
|
446
451
|
|
|
447
452
|
/**
|
|
448
453
|
* A refusal only this pass can make, because its subject is the note's
|
|
449
|
-
* **type
|
|
454
|
+
* **type**.
|
|
450
455
|
*
|
|
451
456
|
* The `assertNo*Field` family above it in the walk is type-agnostic by
|
|
452
457
|
* construction: it runs before `selects`, so that a note declaring a
|
|
@@ -473,7 +478,7 @@ export class BasePackCompiler {
|
|
|
473
478
|
* Whether this pass claims a note. **Required.**
|
|
474
479
|
*
|
|
475
480
|
* Called only for a note this build compiles — every note in the tree
|
|
476
|
-
* belongs to the configured content package
|
|
481
|
+
* belongs to the configured content package — so a subclass decides
|
|
477
482
|
* on `type` alone.
|
|
478
483
|
*
|
|
479
484
|
* @param {object} fm - The note's frontmatter.
|
|
@@ -524,7 +529,7 @@ export class BasePackCompiler {
|
|
|
524
529
|
// The corpus, and the three whole-tree derivations built over it. Every
|
|
525
530
|
// one of them is a pure function of (tree, scope, router), which do not
|
|
526
531
|
// vary between the passes of a single compile — so `generatePacksJson`
|
|
527
|
-
// derives them once and hands them to each pass
|
|
532
|
+
// derives them once and hands them to each pass.
|
|
528
533
|
//
|
|
529
534
|
// The measurement that motivated it: compiling `sohl` read every note
|
|
530
535
|
// **20 times**, four per pass — this link index, the table corpus, the
|
|
@@ -580,14 +585,14 @@ export class BasePackCompiler {
|
|
|
580
585
|
type: fm.type,
|
|
581
586
|
id: fm.id,
|
|
582
587
|
// Where this note is, so a link that resolves nowhere is reported
|
|
583
|
-
// at a position an author can open rather than by note name
|
|
588
|
+
// at a position an author can open rather than by note name.
|
|
584
589
|
file: absPath,
|
|
585
590
|
bodyLine,
|
|
586
591
|
bodyColumn,
|
|
587
592
|
lineMap,
|
|
588
593
|
// A `[[#slug]]` self-link addresses the source note, which has no
|
|
589
594
|
// entry in the index — so where its own documents landed has to
|
|
590
|
-
// travel with it
|
|
595
|
+
// travel with it.
|
|
591
596
|
pack: this.router?.resolveOrNull(fm, packForType(fm.type).docType),
|
|
592
597
|
docPack: this.router?.resolveOrNull(fm, "JournalEntry"),
|
|
593
598
|
index: this.linkIndex,
|
|
@@ -636,8 +641,7 @@ export class BasePackCompiler {
|
|
|
636
641
|
}
|
|
637
642
|
|
|
638
643
|
/**
|
|
639
|
-
* Report every `<system>.system` key the receiving subtype does not declare
|
|
640
|
-
* (#58).
|
|
644
|
+
* Report every `<system>.system` key the receiving subtype does not declare.
|
|
641
645
|
*
|
|
642
646
|
* An **error**, not a warning: Foundry drops an unknown `system` key at
|
|
643
647
|
* construction without a word, so the alternative is a document shipped
|
|
@@ -657,8 +661,8 @@ export class BasePackCompiler {
|
|
|
657
661
|
*/
|
|
658
662
|
reportUndeclaredSystemData(fm, block, documentType, subType) {
|
|
659
663
|
const absPath = this.currentNote?.absPath;
|
|
660
|
-
// Whose schema, where a build has more than one system: this pack's
|
|
661
|
-
//
|
|
664
|
+
// Whose schema, where a build has more than one system: this pack's.
|
|
665
|
+
// `undefined` — a pack that declares no system — keeps the
|
|
662
666
|
// package-wide answer this always used.
|
|
663
667
|
const findings = checkAuthoredSystemData(fm, {
|
|
664
668
|
block,
|
|
@@ -676,7 +680,7 @@ export class BasePackCompiler {
|
|
|
676
680
|
|
|
677
681
|
/**
|
|
678
682
|
* Record every `system` key the *compiled document* carries that the
|
|
679
|
-
* receiving subtype does not declare
|
|
683
|
+
* receiving subtype does not declare.
|
|
680
684
|
*
|
|
681
685
|
* The sibling of {@link BasePackCompiler#reportUndeclaredSystemData}, and
|
|
682
686
|
* the half that sees what no declaration states. A compiler writes keys of
|
|
@@ -734,7 +738,7 @@ export class BasePackCompiler {
|
|
|
734
738
|
/**
|
|
735
739
|
* Emit the collected emitted-`system` findings, once each.
|
|
736
740
|
*
|
|
737
|
-
* An **error**, for the reason
|
|
741
|
+
* An **error**, for the reason its sibling is one: the value is gone
|
|
738
742
|
* at load and the build says nothing, and severity that varied by *which
|
|
739
743
|
* part of the build wrote the key* would make the less fixable half the
|
|
740
744
|
* quieter one. What varies is the message, which says whose fix it is —
|
|
@@ -859,7 +863,7 @@ export class BasePackCompiler {
|
|
|
859
863
|
}
|
|
860
864
|
if (stats.declined) {
|
|
861
865
|
// Its own line, at error level: these are not skips, and burying
|
|
862
|
-
// them in the skipped tally is the defect
|
|
866
|
+
// them in the skipped tally is the defect. Each one has
|
|
863
867
|
// already been named individually as a diagnostic.
|
|
864
868
|
log.error(
|
|
865
869
|
`Declined ${stats.declined} note(s) — each named above, with ` +
|
|
@@ -892,7 +896,7 @@ export class BasePackCompiler {
|
|
|
892
896
|
// refusal, because it *is* the same refusal: the index defers to
|
|
893
897
|
// `assertNoDeclaredPackage` for a retired `package:`, which is the
|
|
894
898
|
// check this loop makes a few lines further down. All that changed is
|
|
895
|
-
// which pass sees the note first
|
|
899
|
+
// which pass sees the note first.
|
|
896
900
|
if (this.reportsCorpusProblems) {
|
|
897
901
|
for (const problem of this.corpus.problems ?? []) {
|
|
898
902
|
stats.declined++;
|
|
@@ -911,7 +915,7 @@ export class BasePackCompiler {
|
|
|
911
915
|
}
|
|
912
916
|
|
|
913
917
|
// The corpus, from the index this compile derived once — not a walk of
|
|
914
|
-
// this pass's own
|
|
918
|
+
// this pass's own. Each note is then read for its **prose**: the
|
|
915
919
|
// index carries what is *about* a note and deliberately not its text,
|
|
916
920
|
// nor the `bodyLine`/`bodyColumn` a diagnostic needs, and this pass has
|
|
917
921
|
// to have the body anyway. So the read is one this pass was already
|
|
@@ -922,7 +926,7 @@ export class BasePackCompiler {
|
|
|
922
926
|
const absPath = noteFile(this.contentBase, record);
|
|
923
927
|
const { frontmatter: fm, body, bodyLine, bodyColumn } = parseMarkdownFile(absPath);
|
|
924
928
|
// Which note this pass is on, so anything it calls can report a
|
|
925
|
-
// position without every method having to be handed one
|
|
929
|
+
// position without every method having to be handed one.
|
|
926
930
|
this.currentNote = { absPath, bodyLine, bodyColumn };
|
|
927
931
|
// A file carrying no frontmatter at all is not a note.
|
|
928
932
|
if (!fm) {
|
|
@@ -933,12 +937,12 @@ export class BasePackCompiler {
|
|
|
933
937
|
// note is answered whichever pass would have claimed it — and
|
|
934
938
|
// whatever the declared value says.
|
|
935
939
|
//
|
|
936
|
-
// - `package
|
|
940
|
+
// - `package:`: a note's package is the repository's
|
|
937
941
|
// configured one, so declaring it restates a constant.
|
|
938
|
-
// - `draft
|
|
942
|
+
// - `draft:`: it excluded the note from the packs, the
|
|
939
943
|
// manifest and the site, and no checker reported the links that
|
|
940
944
|
// left dangling.
|
|
941
|
-
// - `aliases
|
|
945
|
+
// - `aliases:`: it fed the alias index, which the bare
|
|
942
946
|
// `[[Alias]]` form was looked up in; the form is retired, so the
|
|
943
947
|
// list has no reader left. The nested `name.aliases` is a
|
|
944
948
|
// different field and is **not** refused — it is reserved, and
|
|
@@ -973,7 +977,7 @@ export class BasePackCompiler {
|
|
|
973
977
|
}
|
|
974
978
|
// The id this note's document is filed under: its authored `id`
|
|
975
979
|
// if it pins one, otherwise the id derived from its canonical
|
|
976
|
-
// address
|
|
980
|
+
// address. Resolved for every note this pass claims, and
|
|
977
981
|
// through the one function every other corpus reader calls — the
|
|
978
982
|
// wikilink index, the content index and the Foundry-address pass
|
|
979
983
|
// must all compute the id this pass compiles under, and none of
|
|
@@ -1021,7 +1025,7 @@ export class BasePackCompiler {
|
|
|
1021
1025
|
stats.skippedOther++;
|
|
1022
1026
|
continue;
|
|
1023
1027
|
}
|
|
1024
|
-
// The type-specific half of the retired-field family
|
|
1028
|
+
// The type-specific half of the retired-field family:
|
|
1025
1029
|
// what a note of *this* type may not write, which needs the
|
|
1026
1030
|
// type's own field declaration and so cannot be asked before
|
|
1027
1031
|
// `selects`. Counted as a declined note for the same reason
|
|
@@ -1048,7 +1052,7 @@ export class BasePackCompiler {
|
|
|
1048
1052
|
this.errorCount++;
|
|
1049
1053
|
// `position` is set by whatever failed if it knew where — an
|
|
1050
1054
|
// unresolved address, a bad table directive — so the report
|
|
1051
|
-
// points at the line rather than at the note
|
|
1055
|
+
// points at the line rather than at the note.
|
|
1052
1056
|
this.noteError(
|
|
1053
1057
|
`${this.noteLabel(fm)} failed to compile: ${err.message}`,
|
|
1054
1058
|
err.position,
|
package/engine/bundle-notes.mjs
CHANGED
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
* world's collection already holds that `_id`, then creates or updates each.
|
|
22
22
|
* Afterwards the documents live independently and the Adventure has no further
|
|
23
23
|
* role. **It is an installer** — a set of document *copies* packaged for
|
|
24
|
-
* one-shot import
|
|
24
|
+
* one-shot import.
|
|
25
25
|
*
|
|
26
|
-
* That is the whole difference from a folder
|
|
26
|
+
* That is the whole difference from a folder, which is a live grouping
|
|
27
27
|
* **by reference** that persists in the pack. A bundle carries copies and
|
|
28
28
|
* exists to be imported once, so the two are not variations on one idea.
|
|
29
29
|
*
|
|
@@ -140,7 +140,7 @@ export function bareAddress(value) {
|
|
|
140
140
|
* `### type: bundle` table puts it — the closed container, so a misspelled
|
|
141
141
|
* `content` is a finding rather than a silently empty Adventure. It is accepted
|
|
142
142
|
* at the top level too, exactly as a folder note's `parent` is: an author
|
|
143
|
-
* following
|
|
143
|
+
* following the shipped example rather than the specification should get a
|
|
144
144
|
* bundle, not a silent default.
|
|
145
145
|
*
|
|
146
146
|
* **Order is the author's**, and it is kept: an Adventure's `SetField` attaches
|
|
@@ -269,7 +269,7 @@ export function buildAdventure({
|
|
|
269
269
|
_id: id,
|
|
270
270
|
_stats: stats,
|
|
271
271
|
// The Foundry *collection* name, not the pack's: a pack directory may
|
|
272
|
-
// be called anything
|
|
272
|
+
// be called anything, and the key names the collection the
|
|
273
273
|
// record belongs to inside it.
|
|
274
274
|
_key: `!adventures!${id}`,
|
|
275
275
|
};
|
package/engine/bundles.mjs
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Adventure pack compiler — `type: bundle` notes → Foundry `Adventure`
|
|
16
|
-
* documents
|
|
16
|
+
* documents.
|
|
17
17
|
*
|
|
18
|
-
* The specification and the vocabulary
|
|
18
|
+
* The specification and the vocabulary leave the type
|
|
19
19
|
* declared and uncompiled: authoring one said so, in as many words. This is the
|
|
20
|
-
* pass, and the two decisions
|
|
20
|
+
* pass, and the two decisions it records are settled here.
|
|
21
21
|
*
|
|
22
22
|
* **Which pack.** Not the `adventures` **companion**. The scenes pass already
|
|
23
23
|
* writes one Adventure per pinned place into that pack, and a companion is
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* the router's rule for `pack:`, so there is one answer and not two. One note
|
|
33
33
|
* can compile into two documents — an item and the JournalEntry its prose
|
|
34
34
|
* became — and the second is bundled only when the note names it by its own
|
|
35
|
-
* `doc…` address, which is the address that already exists for it
|
|
35
|
+
* `doc…` address, which is the address that already exists for it.
|
|
36
36
|
* Nothing is inferred: naming `miscgear-bowlcer` puts the *item* in the bundle
|
|
37
37
|
* and not its description page.
|
|
38
38
|
*
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* a reader of every other one, which it states in
|
|
42
42
|
* {@link Bundles.readsPackOutputOf} rather than leaving to the order a
|
|
43
43
|
* consumer happened to write its pack list in — the generator derives the
|
|
44
|
-
* compile order from that declaration
|
|
44
|
+
* compile order from that declaration.
|
|
45
45
|
*
|
|
46
46
|
* **A pack's `system:` constrains what its Adventures may hold.** An
|
|
47
47
|
* `Adventure` has no `system` field, so a bundle spanning two systems cannot be
|
|
@@ -83,7 +83,7 @@ import { readQualifier } from "./wikilinks.mjs";
|
|
|
83
83
|
* the first.
|
|
84
84
|
*
|
|
85
85
|
* A **folder** document is skipped. It is emitted into every pack that holds
|
|
86
|
-
* something filed in it
|
|
86
|
+
* something filed in it, so it is not one pack's document and has no
|
|
87
87
|
* single note behind it; a bundle that wants folders is a question this pass
|
|
88
88
|
* refuses rather than guesses at — see {@link Bundles#resolveAddress}.
|
|
89
89
|
*
|
|
@@ -119,6 +119,15 @@ export function loadBundleSources(sourceDirs) {
|
|
|
119
119
|
return documents;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Adventure pack compiler.
|
|
124
|
+
*
|
|
125
|
+
* Walks the content tree and compiles every `type: bundle` note into one
|
|
126
|
+
* Adventure per system, holding **copies** of the compiled documents its
|
|
127
|
+
* `contents` addresses name. Reading other passes' output is what
|
|
128
|
+
* {@link Bundles.readsPackOutputOf} declares, and what the generator orders the
|
|
129
|
+
* compile by.
|
|
130
|
+
*/
|
|
122
131
|
export class Bundles extends BasePackCompiler {
|
|
123
132
|
static id = "bundles";
|
|
124
133
|
static label = "bundle";
|
|
@@ -126,7 +135,7 @@ export class Bundles extends BasePackCompiler {
|
|
|
126
135
|
/**
|
|
127
136
|
* Every document type a bundle can hold a copy of.
|
|
128
137
|
*
|
|
129
|
-
* The declaration the generator orders passes by
|
|
138
|
+
* The declaration the generator orders passes by: an Adventure holds
|
|
130
139
|
* *compiled* documents, so every pass that produces one runs first. Stated
|
|
131
140
|
* here, in the class that does the reading, rather than in each consuming
|
|
132
141
|
* repository's pack list.
|
|
@@ -225,7 +234,7 @@ export class Bundles extends BasePackCompiler {
|
|
|
225
234
|
throw new Error(
|
|
226
235
|
`bundle "${bundleName}" lists the folder "${address}". A ` +
|
|
227
236
|
`folder is not a member: it materialises in every pack ` +
|
|
228
|
-
`holding something filed in it
|
|
237
|
+
`holding something filed in it, so it belongs to no ` +
|
|
229
238
|
`one pack and there is no single copy to bundle. List the ` +
|
|
230
239
|
`documents instead`,
|
|
231
240
|
);
|
package/engine/code-fences.mjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* written. Every build-time rewriter that pattern-matches a body therefore has
|
|
19
19
|
* to know where code is — otherwise a source listing that happens to contain
|
|
20
20
|
* the rewriter's syntax is silently corrupted. Wikilink conversion met this as
|
|
21
|
-
* `[[0]]` inside a fence being turned into a link
|
|
21
|
+
* `[[0]]` inside a fence being turned into a link, and it depended on
|
|
22
22
|
* the surrounding literal's shape (`[[1,2],[3,4]]` survived), so the corruption
|
|
23
23
|
* looked arbitrary.
|
|
24
24
|
*
|
|
@@ -378,12 +378,12 @@ export function matchAllOutsideCode(markdown, pattern, options) {
|
|
|
378
378
|
* **Which runs count as code is {@link codeRegions}' rule, not a second copy of
|
|
379
379
|
* it.** The knowledgebase build carried its own regex once, and it was weaker in
|
|
380
380
|
* two ways that both corrupted the one page whose subject *is* link syntax — so
|
|
381
|
-
* its examples
|
|
381
|
+
* its examples are exactly the input a looser rule mangles. A
|
|
382
382
|
* single-backtick span was allowed to cross newlines, so one odd backtick paired
|
|
383
383
|
* with another paragraphs away and every span after it paired wrongly: prose was
|
|
384
384
|
* masked as code while real spans were left exposed. And only three-backtick
|
|
385
385
|
* fences were recognised, so a four-backtick example holding a three-backtick
|
|
386
|
-
* block — the documented "fences of any length" case
|
|
386
|
+
* block — the documented "fences of any length" case — leaked its
|
|
387
387
|
* contents.
|
|
388
388
|
*
|
|
389
389
|
* @param {string} body - The markdown body.
|
package/engine/compendiums.mjs
CHANGED
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
*
|
|
26
26
|
* **This module has no import-time side effects.** It creates no directories,
|
|
27
27
|
* reads no manifest, configures no logger, and parses no argv — every path and
|
|
28
|
-
* pack list is a parameter, defaulted from the resolved build configuration
|
|
29
|
-
*
|
|
28
|
+
* pack list is a parameter, defaulted from the resolved build configuration,
|
|
29
|
+
* which a caller may replace wholesale to compile another package's
|
|
30
30
|
* tree. Those side effects belong to the command
|
|
31
31
|
* line that drives it (`bin/build-compendiums.mjs`), so the library can be
|
|
32
32
|
* imported by another repository's build, or by a test, without a stray
|
|
33
33
|
* `build/` tree appearing or the shared `loglevel` singleton being
|
|
34
|
-
* reconfigured
|
|
34
|
+
* reconfigured. In particular, a *module* repository ships
|
|
35
35
|
* `module.json` rather than `system.template.json`, so importing must not
|
|
36
36
|
* depend on the latter existing.
|
|
37
37
|
*
|
|
@@ -64,7 +64,7 @@ import { loadPackConfig } from "./pack-config.mjs";
|
|
|
64
64
|
* @param {object} opts
|
|
65
65
|
* @param {object} [opts.config] The resolved build configuration, which
|
|
66
66
|
* the two path arguments below default from. Supplying one is how a caller
|
|
67
|
-
* compiles a package other than this repository's
|
|
67
|
+
* compiles a package other than this repository's.
|
|
68
68
|
* @param {string[]} [opts.sourcePacks] Every pack compiled from the content
|
|
69
69
|
* tree, in compile order. Defaults to the configured pack directories.
|
|
70
70
|
* @param {string} [opts.stageDest] Directory the LevelDB packs are built
|
|
@@ -73,10 +73,10 @@ import { loadPackConfig } from "./pack-config.mjs";
|
|
|
73
73
|
* @throws {Error} If pack JSON generation reported any error. Packs compiled
|
|
74
74
|
* from incomplete or empty JSON ship blank or short compendiums, and the
|
|
75
75
|
* omission is invisible until a player looks for content that is not there
|
|
76
|
-
*
|
|
76
|
+
* — so this is fatal, not a warning, and the caller is expected to
|
|
77
77
|
* turn it into a failing exit code.
|
|
78
78
|
* @throws {Error} If a compiled pack ships a Scene that has lost its embedded
|
|
79
|
-
* Level
|
|
79
|
+
* Level. Fatal for the same reason: Foundry reads a missing Level
|
|
80
80
|
* record as "no levels" and persists that on the next world launch, so the
|
|
81
81
|
* map image is gone before anyone notices it was ever at risk. See
|
|
82
82
|
* {@link verifyPackSceneLevels}.
|
|
@@ -137,7 +137,7 @@ export async function compilePacks({
|
|
|
137
137
|
// LevelDB key. Nothing in Foundry ties the two together on read: a
|
|
138
138
|
// missing Level record only warns, and the next world launch persists
|
|
139
139
|
// the emptied `levels` array — so the map is lost for good and the
|
|
140
|
-
// only symptom is a blank battlemap
|
|
140
|
+
// only symptom is a blank battlemap. Assert it on the bytes
|
|
141
141
|
// just written, which is the one place the compendium CLI's write path
|
|
142
142
|
// is observable.
|
|
143
143
|
const problems = await verifyPackSceneLevels(stage);
|
|
@@ -164,7 +164,7 @@ export async function compilePacks({
|
|
|
164
164
|
* @param {number} [options.ownership=0] Value to reset default ownership to.
|
|
165
165
|
* @param {string} [options.lastModifiedBy] The stamped author id. Defaults to
|
|
166
166
|
* the configured one — the same value `buildStats` stamps, so a compiled
|
|
167
|
-
* entry and a re-cleaned one never disagree
|
|
167
|
+
* entry and a re-cleaned one never disagree.
|
|
168
168
|
*/
|
|
169
169
|
function cleanPackEntry(
|
|
170
170
|
data,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The corpus one compile runs over, and everything derived from it
|
|
15
|
+
* The corpus one compile runs over, and everything derived from it.
|
|
16
16
|
*
|
|
17
17
|
* **A compile read every note twenty times.** Measured over `sohl`'s 1,685
|
|
18
18
|
* notes: 33,700 reads, exactly twenty per note. Four per pass — the
|
|
@@ -24,10 +24,9 @@
|
|
|
24
24
|
* to all of them.
|
|
25
25
|
*
|
|
26
26
|
* So they are derived **once**, here, and every pass is handed the result. That
|
|
27
|
-
* is
|
|
27
|
+
* is the claim stated at the point where it costs the most: not that
|
|
28
28
|
* re-deriving is wasteful, but that N passes each answering "which files are
|
|
29
|
-
* the corpus?" is N answers that can differ
|
|
30
|
-
* the twenty reads were paying for.
|
|
29
|
+
* the corpus?" is N answers that can differ.
|
|
31
30
|
*
|
|
32
31
|
* **This module exists apart from the compilers for an import reason.**
|
|
33
32
|
* Deriving the index reaches the pack router and the manifest emitter, and
|
|
@@ -50,7 +49,7 @@ import { prepareTreeSqlTables } from "./sql-tables.mjs";
|
|
|
50
49
|
* @param {object} opts - Options.
|
|
51
50
|
* @param {string} opts.contentBase - Root of the content tree.
|
|
52
51
|
* @param {readonly string[]} opts.skipDirectories - The scope, stated by the
|
|
53
|
-
* caller as every corpus read requires
|
|
52
|
+
* caller as every corpus read requires.
|
|
54
53
|
* @param {object} opts.router - The pack router this compile resolved. Shared
|
|
55
54
|
* by every pass, which is what makes one link index correct for all of them.
|
|
56
55
|
* @param {object} [opts.config] - The resolved configuration.
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
* address other packages link to. Stating it twice is how a manifest comes to
|
|
20
20
|
* assert a URL that resolves at build time and 404s for the reader.
|
|
21
21
|
*
|
|
22
|
-
* **A page's URL is its address** — `<package>/<type>-<shortcode
|
|
23
|
-
* it carries **no `<system>` segment** even though the canonical address does
|
|
24
|
-
*
|
|
22
|
+
* **A page's URL is its address** — `<package>/<type>-<shortcode>/`, and
|
|
23
|
+
* it carries **no `<system>` segment** even though the canonical address does.
|
|
24
|
+
* That is not an omission: a note publishes one page however many
|
|
25
25
|
* systems' documents it compiles into, so there is nothing for the segment to
|
|
26
26
|
* distinguish, and adding it would split one page's URL in two. The canonical
|
|
27
27
|
* address names a *document*; this names a *page*. It
|
|
28
|
-
*
|
|
28
|
+
* is not derived from `name.full`, which would make a display string load-bearing
|
|
29
29
|
* in three separate ways: a rename moved the URL and nothing redirected, two
|
|
30
30
|
* notes in one section could derive the same URL so a uniqueness check had to
|
|
31
31
|
* run, and a long name had to be abbreviated through a word table to keep the
|
|
@@ -62,7 +62,7 @@ export { DEFAULT_ADDRESS_SCHEME };
|
|
|
62
62
|
*/
|
|
63
63
|
export { NO_SYSTEM };
|
|
64
64
|
|
|
65
|
-
/** The knowledgebase's mount within this package's site
|
|
65
|
+
/** The knowledgebase's mount within this package's site. */
|
|
66
66
|
export const KB_PREFIX = "kb/";
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -73,7 +73,7 @@ export const KB_PREFIX = "kb/";
|
|
|
73
73
|
* key's **last two segments** — which is what makes a manifest entry's `path`
|
|
74
74
|
* derivable from the key it is filed under rather than transported beside it.
|
|
75
75
|
*
|
|
76
|
-
* It
|
|
76
|
+
* It is not the key's whole tail: the key carries a
|
|
77
77
|
* `<system>` segment, so its tail is now `system-type-shortcode` and a slug is
|
|
78
78
|
* the tail with that segment dropped. The behaviour here is unchanged, and
|
|
79
79
|
* deliberately — a page has no system to name (see the module note above), so
|
|
@@ -81,11 +81,11 @@ export const KB_PREFIX = "kb/";
|
|
|
81
81
|
* consumer deriving a `path` from a key drops the *package and the system*, not
|
|
82
82
|
* the package alone.
|
|
83
83
|
*
|
|
84
|
-
* The hyphen is a separator and never occurs inside a segment: a shortcode
|
|
85
|
-
*
|
|
86
|
-
* and a type is a bare word. That is the same charset
|
|
87
|
-
* parsing rests on, so the address and the key
|
|
88
|
-
* ends and the other begins.
|
|
84
|
+
* The hyphen is a separator and never occurs inside a segment: a shortcode
|
|
85
|
+
* matches `ADDRESS_SEGMENT_PATTERN` (`engine/address-charset.mjs`, enforced by
|
|
86
|
+
* `content-lint.mjs`) and a type is a bare word. That is the same charset
|
|
87
|
+
* guarantee positional key parsing rests on, so the address and the key
|
|
88
|
+
* cannot disagree about where one ends and the other begins.
|
|
89
89
|
*
|
|
90
90
|
* @param {object} fm - Parsed frontmatter.
|
|
91
91
|
* @returns {string} The address segment, e.g. `weapongear-dagger`.
|
|
@@ -131,9 +131,9 @@ export function addressSlug(fm) {
|
|
|
131
131
|
*
|
|
132
132
|
* **It is a pure function of the frontmatter**, and takes no options. Nothing
|
|
133
133
|
* about the file the note was read from reaches it: the `README.md` convention
|
|
134
|
-
* that made one note address a whole section is retired with the section itself
|
|
135
|
-
*
|
|
136
|
-
* It
|
|
134
|
+
* that made one note address a whole section is retired with the section itself,
|
|
135
|
+
* so every note is addressed alike and there is one rule and no branch.
|
|
136
|
+
* It takes no address scheme; the `landing` rule it once validated is
|
|
137
137
|
* discarded; with that key retired, `prefix` was the only thing left in the
|
|
138
138
|
* scheme and the paragraph above is the reason it never applied.
|
|
139
139
|
*
|
|
@@ -169,9 +169,9 @@ export function packageAddress(fm) {
|
|
|
169
169
|
* merge is a real conflict rather than an artefact of two packages sharing a
|
|
170
170
|
* namespace. `(type, shortcode)` alone is unique only *within* a package, and
|
|
171
171
|
* two independently authored packages reaching for the same short string is a
|
|
172
|
-
* matter of time
|
|
172
|
+
* matter of time.
|
|
173
173
|
*
|
|
174
|
-
* **The system segment
|
|
174
|
+
* **The system segment.** A package may ship content for more than one
|
|
175
175
|
* system, and one note then compiles into a document per system — an actor in
|
|
176
176
|
* `actors-sohl` *and* an actor in `actors-hm3`. Without a system segment both
|
|
177
177
|
* land on one key, so the address cannot name either of them. `harn-ensemble`
|
|
@@ -234,7 +234,7 @@ export function blockSystem(keyPath) {
|
|
|
234
234
|
/**
|
|
235
235
|
* Expand a written address to the one canonical address it names.
|
|
236
236
|
*
|
|
237
|
-
* **An omitted segment defaults from where the link is written**
|
|
237
|
+
* **An omitted segment defaults from where the link is written** — it is
|
|
238
238
|
* not a wildcard, and resolution is not a search. Package omitted means the
|
|
239
239
|
* citing note's own; system omitted means {@link blockSystem} of the key path it
|
|
240
240
|
* was written under. So every short form has exactly one expansion, computed
|
|
@@ -311,12 +311,12 @@ export const CANONICAL_KEY_SEGMENTS = 4;
|
|
|
311
311
|
*
|
|
312
312
|
* Parsing is plain positional counting: split on the separator, require
|
|
313
313
|
* {@link CANONICAL_KEY_SEGMENTS} of them, and assign each position its field.
|
|
314
|
-
* **The charset rule is what makes that sound** — every segment
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* the data: shortcodes by `content-lint.mjs
|
|
319
|
-
* `defineConfig
|
|
314
|
+
* **The charset rule is what makes that sound** — every segment matches
|
|
315
|
+
* `ADDRESS_SEGMENT_PATTERN` (`engine/address-charset.mjs`), so the hyphen is
|
|
316
|
+
* purely a separator and the count alone determines every field. That is
|
|
317
|
+
* enforced at each of the three sources rather than assumed of
|
|
318
|
+
* the data: shortcodes by `content-lint.mjs`, `contentPackage` by
|
|
319
|
+
* `defineConfig`, and types are bare words. Were any of them free to
|
|
320
320
|
* carry a hyphen, no amount of counting would recover the fields and the reader
|
|
321
321
|
* would need a vocabulary to match against instead.
|
|
322
322
|
*
|
|
@@ -440,7 +440,7 @@ export const DOCUMENT_ID_NAMESPACE = "document";
|
|
|
440
440
|
|
|
441
441
|
/**
|
|
442
442
|
* The Foundry `_id` of the document a note compiles into, derived from its
|
|
443
|
-
* canonical address
|
|
443
|
+
* canonical address.
|
|
444
444
|
*
|
|
445
445
|
* A note used to author this — an opaque 16-character string, one per note,
|
|
446
446
|
* that said nothing its address did not and that no check guaranteed. The
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* The charset authored content is held to, so a book can choose its face
|
|
15
|
+
* The charset authored content is held to, so a book can choose its face.
|
|
16
16
|
*
|
|
17
17
|
* The packs and the website render in whatever font the reader's browser or
|
|
18
18
|
* Foundry supplies, and a glyph nobody has is somebody else's problem. **A book
|