@heroiclands/package-build 22.28.0 → 23.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +1 -1
  3. package/bin/content-commands.mjs +1 -1
  4. package/ci/content-format-reference.mjs +46 -0
  5. package/docs/api.md +125 -142
  6. package/docs/authoring/assets.md +1 -1
  7. package/docs/authoring/dates-and-calendars.md +12 -6
  8. package/docs/authoring/first-note.md +1 -1
  9. package/docs/authoring/frontmatter.md +2 -2
  10. package/docs/authoring/links-and-markup.md +145 -29
  11. package/docs/commands.md +8 -10
  12. package/docs/configuration.md +13 -11
  13. package/docs/content-format.md +3 -3
  14. package/docs/guides/book.md +59 -4
  15. package/docs/guides/icons.md +4 -5
  16. package/docs/guides/packs.md +6 -0
  17. package/docs/guides/reference-pages.md +21 -1
  18. package/docs/guides/release-and-deploy.md +17 -1
  19. package/docs/guides/site.md +17 -18
  20. package/docs/reference/format-details.md +904 -275
  21. package/docs/reference/note-types.md +282 -91
  22. package/docs/reference/theme-pages.md +58 -66
  23. package/engine/address-values.mjs +124 -4
  24. package/engine/address.mjs +44 -3
  25. package/engine/anchors.mjs +103 -3
  26. package/engine/art-slots.mjs +2 -9
  27. package/engine/base-compiler.mjs +25 -6
  28. package/engine/calendar-artifacts.mjs +4 -1
  29. package/engine/calendar-notes.mjs +166 -102
  30. package/engine/content-format-check.mjs +2 -3
  31. package/engine/content-format.mjs +44 -1
  32. package/engine/content-format.yaml +84 -16
  33. package/engine/content-images.mjs +10 -1
  34. package/engine/content-index.mjs +37 -9
  35. package/engine/content-links.mjs +24 -5
  36. package/engine/content-tables.mjs +24 -3
  37. package/engine/data-keys.mjs +347 -0
  38. package/engine/derived-sections.mjs +322 -0
  39. package/engine/diagnostics.mjs +28 -0
  40. package/engine/event-fields.mjs +187 -0
  41. package/engine/event-rows.mjs +126 -0
  42. package/engine/event-views.mjs +305 -0
  43. package/engine/exported-scene.mjs +29 -53
  44. package/engine/frontmatter-lint.mjs +103 -77
  45. package/engine/frontmatter.mjs +7 -2
  46. package/engine/generate.mjs +53 -0
  47. package/engine/generated-sections.mjs +223 -0
  48. package/engine/heading-attributes.mjs +4 -2
  49. package/engine/helpers.mjs +12 -1
  50. package/engine/holdings.mjs +12 -33
  51. package/engine/ids.mjs +17 -11
  52. package/engine/index.mjs +4 -4
  53. package/engine/infobox-render.mjs +21 -6
  54. package/engine/infobox.mjs +217 -99
  55. package/engine/journals.mjs +104 -47
  56. package/engine/literature-notes.mjs +136 -0
  57. package/engine/literature-works.mjs +161 -0
  58. package/engine/map-graphviz.mjs +4 -18
  59. package/engine/markdown-expressions.mjs +116 -11
  60. package/engine/metadata-index.mjs +34 -0
  61. package/engine/near-miss.mjs +90 -0
  62. package/engine/note-addresses.mjs +75 -19
  63. package/engine/note-dates.mjs +5 -3
  64. package/engine/note-event-terms.mjs +364 -0
  65. package/engine/note-events.mjs +823 -0
  66. package/engine/note-vocabulary.mjs +195 -92
  67. package/engine/office-holders.mjs +20 -54
  68. package/engine/packagebuild-index.mjs +16 -1
  69. package/engine/pdf-build.mjs +97 -60
  70. package/engine/pdf-index.mjs +263 -0
  71. package/engine/pdf-render.mjs +47 -5
  72. package/engine/place-relation-terms.mjs +174 -0
  73. package/engine/place-relations.mjs +72 -160
  74. package/engine/rank-ladder.mjs +14 -41
  75. package/engine/reckoning-markers.mjs +2 -0
  76. package/engine/region-events.mjs +6 -12
  77. package/engine/scenes.mjs +73 -468
  78. package/engine/site-build.mjs +74 -85
  79. package/engine/site-index.mjs +3 -1
  80. package/engine/site-maps.mjs +43 -29
  81. package/engine/site-preview.mjs +40 -31
  82. package/engine/social-ties.mjs +2 -1
  83. package/engine/sql-tables.mjs +212 -9
  84. package/engine/standing-terms.mjs +145 -6
  85. package/engine/standings.mjs +37 -49
  86. package/engine/stub-lint.mjs +6 -0
  87. package/engine/web-wikilinks.mjs +21 -1
  88. package/engine/wikilink-syntax.mjs +34 -4
  89. package/engine/wikilinks.mjs +27 -2
  90. package/hugo-theme/layouts/partials/infobox/entry.html +4 -1
  91. package/hugo-theme/layouts/partials/page-body.html +0 -2
  92. package/hugo-theme/static/css/style.css +25 -55
  93. package/package.json +1 -2
  94. package/packagebuild-metadata.jsonl +13 -13
  95. package/sohl/default-item-art.mjs +6 -6
  96. package/sohl/note-schemas.mjs +8 -73
  97. package/types/engine/address-values.d.mts +50 -3
  98. package/types/engine/address.d.mts +21 -0
  99. package/types/engine/anchors.d.mts +49 -2
  100. package/types/engine/art-slots.d.mts +1 -1
  101. package/types/engine/base-compiler.d.mts +13 -4
  102. package/types/engine/calendar-notes.d.mts +7 -0
  103. package/types/engine/content-format.d.mts +52 -0
  104. package/types/engine/content-images.d.mts +5 -1
  105. package/types/engine/content-tables.d.mts +9 -1
  106. package/types/engine/data-keys.d.mts +145 -0
  107. package/types/engine/derived-sections.d.mts +73 -0
  108. package/types/engine/diagnostics.d.mts +15 -0
  109. package/types/engine/event-fields.d.mts +99 -0
  110. package/types/engine/event-rows.d.mts +12 -0
  111. package/types/engine/event-views.d.mts +67 -0
  112. package/types/engine/exported-scene.d.mts +5 -2
  113. package/types/engine/frontmatter-lint.d.mts +3 -3
  114. package/types/engine/generated-sections.d.mts +143 -0
  115. package/types/engine/holdings.d.mts +6 -20
  116. package/types/engine/ids.d.mts +15 -12
  117. package/types/engine/index.d.mts +1 -1
  118. package/types/engine/infobox.d.mts +13 -3
  119. package/types/engine/journals.d.mts +24 -11
  120. package/types/engine/literature-notes.d.mts +29 -0
  121. package/types/engine/literature-works.d.mts +67 -0
  122. package/types/engine/map-graphviz.d.mts +2 -10
  123. package/types/engine/markdown-expressions.d.mts +12 -3
  124. package/types/engine/near-miss.d.mts +42 -0
  125. package/types/engine/note-addresses.d.mts +7 -1
  126. package/types/engine/note-event-terms.d.mts +68 -0
  127. package/types/engine/note-events.d.mts +71 -0
  128. package/types/engine/note-vocabulary.d.mts +37 -8
  129. package/types/engine/office-holders.d.mts +3 -0
  130. package/types/engine/pdf-index.d.mts +35 -0
  131. package/types/engine/pdf-render.d.mts +8 -2
  132. package/types/engine/place-relation-terms.d.mts +83 -0
  133. package/types/engine/place-relations.d.mts +11 -66
  134. package/types/engine/rank-ladder.d.mts +2 -0
  135. package/types/engine/region-events.d.mts +6 -12
  136. package/types/engine/scenes.d.mts +6 -32
  137. package/types/engine/site-build.d.mts +8 -22
  138. package/types/engine/site-maps.d.mts +15 -7
  139. package/types/engine/sql-tables.d.mts +77 -2
  140. package/types/engine/standing-terms.d.mts +37 -4
  141. package/types/engine/standings.d.mts +14 -9
  142. package/types/engine/wikilink-syntax.d.mts +20 -0
  143. package/types/engine/wikilinks.d.mts +3 -2
  144. package/docs/guides/government-migration.md +0 -52
  145. package/engine/itinerary-scenes.mjs +0 -166
  146. package/engine/lore-events.mjs +0 -197
  147. package/engine/map-notes.mjs +0 -1309
  148. package/engine/map-raster.mjs +0 -51
  149. package/hugo-theme/layouts/partials/holdings/entry.html +0 -21
  150. package/hugo-theme/layouts/partials/holdings/kind-groups.html +0 -71
  151. package/hugo-theme/layouts/partials/holdings.html +0 -61
  152. package/hugo-theme/layouts/partials/place-map.html +0 -9
  153. package/types/engine/itinerary-scenes.d.mts +0 -29
  154. package/types/engine/lore-events.d.mts +0 -14
  155. package/types/engine/map-notes.d.mts +0 -297
  156. package/types/engine/map-raster.d.mts +0 -8
@@ -1,13 +1,16 @@
1
1
  /**
2
2
  * Compile a Foundry Scene export into a pack document.
3
3
  *
4
- * Only the note-derived Scene ID, compendium metadata, and pins marked
5
- * `#anchor` change. Every other authored Scene field passes through.
4
+ * The Scene passes through as exported. Only the note-derived Scene ID,
5
+ * compendium metadata, `data.fixup` and pins marked `#anchor` change; nothing
6
+ * else inside the Scene is read or checked.
6
7
  *
7
8
  * @param {object} fm - The map note's frontmatter.
8
9
  * @param {string} markdown - Its converted Markdown body.
9
10
  * @param {{journalEntryId?: string, stats?: object, resolveAddress?: Function}} [opts] - Pack metadata, derived JournalEntry ID, and asset resolver.
10
11
  * @returns {object} The keyed Scene document.
12
+ * @throws {Error} When `data.scene` is not an object, or a fixup or pin anchor
13
+ * names something the Scene or the note does not have.
11
14
  */
12
15
  export function buildExportedScene(fm: object, markdown: string, { journalEntryId, stats, resolveAddress }?: {
13
16
  journalEntryId?: string;
@@ -166,10 +166,10 @@ export const DEFAULT_SYSTEM_BLOCKS: Readonly<Record<string, SystemBlockSpec>>;
166
166
  *
167
167
  * {@link module:engine/art-fields.ART_SLOTS} is the declaration; this is that
168
168
  * list in the shape the checks below read, so the linter states no art key of
169
- * its own and a slot added there is checked here with no second edit. All four
170
- * are authored under `data:`, which is what `inData` records.
169
+ * its own and a slot added there is checked here with no second edit. Every
170
+ * slot is authored under `data:`, which is what `inData` records.
171
171
  *
172
- * `document` separates the three that reach a compiled document from `banner`,
172
+ * `document` separates the slots that reach a compiled document from `banner`,
173
173
  * which reaches none by design. The inert-art check reads it: a key that is
174
174
  * *meant* to reach no document is not an inert key, and reporting every note
175
175
  * that names a hero image would bury the finding that matters.
@@ -0,0 +1,143 @@
1
+ /**
2
+ * The pathname a generated section names the map from a place by.
3
+ *
4
+ * @param {string} shortcode - The place.
5
+ * @returns {string} `generated/from-<shortcode>.svg`.
6
+ */
7
+ export function fromHereSource(shortcode: string): string;
8
+ /**
9
+ * The file the map from a place is drawn into, wherever a surface draws it.
10
+ *
11
+ * @param {string} shortcode - The place.
12
+ * @returns {string} `from-<shortcode>.svg`.
13
+ */
14
+ export function fromHereFile(shortcode: string): string;
15
+ /**
16
+ * The drawing an image pathname names, when it names one the build makes.
17
+ *
18
+ * @param {string} src - An image's address, as the Markdown carries it.
19
+ * @returns {string|null} The drawn file's name, or `null` for any other image.
20
+ */
21
+ export function generatedDrawing(src: string): string | null;
22
+ /**
23
+ * Whether an authored image addresses the directory the build's drawings use.
24
+ *
25
+ * @param {string} src - The address, exactly as authored.
26
+ * @returns {string} The problem, as a finding's sentence, or `""`.
27
+ */
28
+ export function generatedDirectoryProblem(src: string): string;
29
+ /**
30
+ * Whether a note's own body declares a prose anchor with this slug.
31
+ *
32
+ * @param {object} record - The note's index record, whose `anchors` were read
33
+ * from the authored body.
34
+ * @param {string} slug - The section's anchor.
35
+ * @returns {boolean} Whether the author has written the section.
36
+ */
37
+ export function authoredSection(record: object, slug: string): boolean;
38
+ /**
39
+ * The heading line of one generated section, with its anchor.
40
+ *
41
+ * @param {string} slug - One of {@link GENERATED_SECTIONS}.
42
+ * @returns {string} `# <Heading> {#<slug>}`.
43
+ */
44
+ export function sectionHeading(slug: string): string;
45
+ /**
46
+ * One note's sections, joined in {@link GENERATED_SECTIONS} order.
47
+ *
48
+ * @param {Iterable<Map<string, string>|undefined>} parts - Each a map of slug
49
+ * to that section's Markdown, heading included.
50
+ * @returns {string} The sections, or `""` when there are none.
51
+ */
52
+ export function joinSections(parts: Iterable<Map<string, string> | undefined>): string;
53
+ /**
54
+ * A note's body with its generated sections after it — the one way the two
55
+ * are joined, so the pass that answers their fences and every pass that
56
+ * expands them read the same text.
57
+ *
58
+ * @param {string} body - The authored body.
59
+ * @param {string|undefined} sections - Its sections, from {@link joinSections}.
60
+ * @returns {string} The body the surfaces receive.
61
+ */
62
+ export function appendGeneratedSections(body: string, sections: string | undefined): string;
63
+ /**
64
+ * Mark where a note's generated sections begin.
65
+ *
66
+ * @param {string} markdown - The expanded body.
67
+ * @param {number|undefined} from - The 0-based line the sections start on,
68
+ * from {@link module:engine/content-tables.expandContentTables}.
69
+ * @returns {string} The body, with {@link GENERATED_BOUNDARY} on its own line
70
+ * before the sections; unchanged where there are none.
71
+ */
72
+ export function markGenerated(markdown: string, from: number | undefined): string;
73
+ /**
74
+ * Split a body at its {@link GENERATED_BOUNDARY}.
75
+ *
76
+ * @param {string} markdown - A body {@link markGenerated} marked.
77
+ * @returns {{authored: string, generated: string}} The author's text, and the
78
+ * generated sections after it — `""` when there are none.
79
+ */
80
+ export function splitGenerated(markdown: string): {
81
+ authored: string;
82
+ generated: string;
83
+ };
84
+ /**
85
+ * A note's **generated sections**: the H1 sections the build appends after
86
+ * everything the author wrote, each under a fixed anchor.
87
+ *
88
+ * Two families share the one mechanism. The derived lists —
89
+ * {@link module:engine/derived-sections} — say where a place sits, who governs
90
+ * it, what it governs, which works concern the note and what the map from a
91
+ * place shows. The event views — {@link module:engine/event-views} — list the
92
+ * events concerning a note. Each section is Markdown an author could have
93
+ * written, so the website, the Foundry journal and the book receive one text
94
+ * and set it as they set an authored section: Foundry starts a page at the
95
+ * heading, the website a section in its table of contents, the book a section
96
+ * of the entry.
97
+ *
98
+ * Three rules hold for every section:
99
+ *
100
+ * - **An author's own anchor replaces it.** A note whose body declares a prose
101
+ * anchor with the section's slug keeps its own section and is given no
102
+ * generated one.
103
+ * - **A section with nothing to show is not generated.**
104
+ * - **Sections follow the author's text in the order of
105
+ * {@link GENERATED_SECTIONS}.**
106
+ *
107
+ * This module is a leaf: it holds the order, the join and the boundary, and
108
+ * imports nothing, so the table expansion every surface runs can read it
109
+ * without reaching the derivations.
110
+ *
111
+ * @module
112
+ */
113
+ /**
114
+ * Every generated section, in the order it follows the author's text: where a
115
+ * place sits and who governs it, then what happened, then what was written
116
+ * about it, then the map.
117
+ *
118
+ * @type {ReadonlyArray<Readonly<{slug: string, heading: string}>>}
119
+ */
120
+ export const GENERATED_SECTIONS: ReadonlyArray<Readonly<{
121
+ slug: string;
122
+ heading: string;
123
+ }>>;
124
+ /**
125
+ * The directory, inside a package's own pathname space, that holds the
126
+ * drawings the build makes. A generated section names a drawing as
127
+ * `generated/<name>`, and each surface serves it from where it drew it: the
128
+ * website inlines it, the Foundry compile stages it into the module under
129
+ * `assets/generated/`, and the book draws it beside its Typst source. An
130
+ * authored image is never addressed here.
131
+ *
132
+ * @type {string}
133
+ */
134
+ export const GENERATED_DRAWING_DIR: string;
135
+ /**
136
+ * The line a surface inserts where a note's generated sections begin, when it
137
+ * treats them differently from the author's text. Private-use characters, so
138
+ * no pass between the expansion and the split reads it as markup, and no
139
+ * output carries it: {@link splitGenerated} removes it.
140
+ *
141
+ * @type {string}
142
+ */
143
+ export const GENERATED_BOUNDARY: string;
@@ -1,4 +1,4 @@
1
- /** @typedef {{title:string,url?:string,type:string,subType?:string}} HoldingsEntry */
1
+ /** @typedef {{title:string,url?:string,address:string,type:string,subType?:string}} HoldingsEntry */
2
2
  /**
3
3
  * @typedef {object} HoldingsNode
4
4
  * @property {string} shortcode
@@ -14,21 +14,22 @@
14
14
  * @property {unknown} [government] Null is explicit anarchy; absence is omission.
15
15
  */
16
16
  /** @typedef {{contains?:HoldingsEntry[],governed_by?:HoldingsEntry[],governed_places?:HoldingsEntry[]}} Holdings */
17
- /** Historical shortcode projection for callers that explicitly need one.
17
+ /** The shortcodes a `parents` value names, bare or qualified.
18
18
  * @param {unknown} value
19
19
  * @returns {string[]}
20
20
  */
21
21
  export function shortcodesOf(value: unknown): string[];
22
22
  /** Read local facts without converting government omission into anarchy.
23
23
  * @param {object} fm
24
- * @param {{title:string,url?:string,package?:string,system?:string,governmentSystem?:string}} page
24
+ * @param {{title:string,url?:string,package?:string,system?:string,canonical?:string,governmentSystem?:string}} page
25
25
  * @returns {HoldingsNode|null}
26
26
  */
27
- export function holdingsNode(fm: object, { title, url, package: pkg, system, governmentSystem }: {
27
+ export function holdingsNode(fm: object, { title, url, package: pkg, system, canonical, governmentSystem }: {
28
28
  title: string;
29
29
  url?: string;
30
30
  package?: string;
31
31
  system?: string;
32
+ canonical?: string;
32
33
  governmentSystem?: string;
33
34
  }): HoldingsNode | null;
34
35
  /** @param {Map<string,object>|undefined} foreignIndex @returns {HoldingsNode[]} */
@@ -57,25 +58,10 @@ export function holdingsPages(nodes: Iterable<HoldingsNode | null>, { government
57
58
  * @returns {object[]} Located warning findings.
58
59
  */
59
60
  export function checkGovernment(note: object): object[];
60
- /**
61
- * The historical API name for the government advisory. Tenure is no longer checked.
62
- * @deprecated Use checkGovernment.
63
- * @param {object} note - The place note.
64
- * @param {object} [_opts] - Historical options, no longer needed.
65
- * @returns {object[]} Government advisory findings.
66
- */
67
- export function checkHeld(note: object, _opts?: object): object[];
68
- /** Derived keys, including retired keys removed from generated pages.
69
- * @type {readonly string[]}
70
- */
71
- export const HOLDINGS_KEYS: readonly string[];
72
- /** @deprecated Government advisories apply to every inhabited place subtype.
73
- * @type {readonly string[]}
74
- */
75
- export const HELD_SUBTYPES: readonly string[];
76
61
  export type HoldingsEntry = {
77
62
  title: string;
78
63
  url?: string;
64
+ address: string;
79
65
  type: string;
80
66
  subType?: string;
81
67
  };
@@ -7,6 +7,13 @@
7
7
  * @returns {string} A 16-character hexadecimal Foundry id.
8
8
  */
9
9
  export function makeId(namespace: string, value: string): string;
10
+ /**
11
+ * Whether a content note's type compiles into a Scene.
12
+ *
13
+ * @param {string} [type] - The note's `type` frontmatter.
14
+ * @returns {boolean} True for a map type.
15
+ */
16
+ export function isMapType(type?: string): boolean;
10
17
  /**
11
18
  * Throw if `type` names a retired content type.
12
19
  *
@@ -105,24 +112,20 @@ export function compendiumUuid(packageId: string, type: string, id: string, pack
105
112
  */
106
113
  export function pageUuid(entryUuid: string, pageId: string): string;
107
114
  /**
108
- * Every content type that compiles into a Foundry `Scene` — a **map note**.
109
- * The three differ only in derived canvas defaults, which is the map
110
- * compiler's business; everything else treats them alike.
115
+ * Every content type that compiles into a Foundry `Scene` — a **map note**,
116
+ * which carries its Scene as exported from Foundry.
111
117
  *
112
- * Declared in this leaf module because several passes that must not depend on
113
- * the map compiler need it: the pack router below, and the doc-carrying type
114
- * set in `item-docs.mjs` (a map note's prose becomes a JournalEntry, exactly as
115
- * an item's or a macro's does).
118
+ * Declared in this leaf module because several passes need it: the pack router
119
+ * below, the scenes pass, and the doc-carrying type set in `item-docs.mjs` (a
120
+ * map note's prose becomes a JournalEntry, exactly as an item's or a macro's
121
+ * does).
116
122
  *
117
123
  * @type {ReadonlySet<string>}
118
124
  */
119
125
  export const MAP_TYPES: ReadonlySet<string>;
120
126
  /**
121
- * The map subTypes, which differ only in the canvas defaults derived for them.
122
- *
123
- * As three *types* they would cost three entries in the pack
124
- * router, three in the claims set and three in every consumer's section config
125
- * — for one idea that the specification had always described as one type.
127
+ * The map subTypes. A subType says what kind of map a note is; every one
128
+ * carries its Scene as exported from Foundry.
126
129
  *
127
130
  * @type {readonly string[]}
128
131
  */
@@ -81,7 +81,7 @@ export * as pdfBuild from "./pdf-build.mjs";
81
81
  export * as baseCompiler from "./base-compiler.mjs";
82
82
  export * as journals from "./journals.mjs";
83
83
  export * as macros from "./macros.mjs";
84
- export * as mapNotes from "./map-notes.mjs";
84
+ export * as exportedScene from "./exported-scene.mjs";
85
85
  export * as scenes from "./scenes.mjs";
86
86
  export * as bundleNotes from "./bundle-notes.mjs";
87
87
  export * as bundles from "./bundles.mjs";
@@ -423,10 +423,11 @@ export const GEAR_UNITS: Readonly<Record<string, {
423
423
  * Three properties, all optional:
424
424
  *
425
425
  * - `label` — what the row is called. Absent means the key, humanised.
426
- * - `withheld` — why the field carries no row. Two reasons only: it is
426
+ * - `withheld` — why the field carries no row. Three reasons only: it is
427
427
  * machinery — something that steers a build or an interface rather than
428
- * describing the subject — or it is an image, which rule 2 keeps out of the
429
- * box.
428
+ * describing the subject, which includes a calendar's definition and a map's
429
+ * canvas — it is an image, which rule 2 keeps out of the box, or it is a
430
+ * source system's own detail, which no surface's box shows.
430
431
  * - `unit` — what the quantity is measured in, appended to the value verbatim.
431
432
  * See {@link applyUnit}.
432
433
  * - `group` / `phrase` — the field composes into one row with its group mates
@@ -468,3 +469,12 @@ export const NOTE_FIELD_PRESENTATION: Readonly<Record<string, {
468
469
  * @type {readonly string[]}
469
470
  */
470
471
  export const UNSET_VALUES: readonly string[];
472
+ /**
473
+ * The section id and title a being's memberships are drawn under.
474
+ *
475
+ * @type {Readonly<{id: string, label: string}>}
476
+ */
477
+ export const MEMBERSHIPS_SECTION: Readonly<{
478
+ id: string;
479
+ label: string;
480
+ }>;
@@ -13,9 +13,15 @@
13
13
  * calling that page "Introduction" would label the description as a preamble to
14
14
  * nothing.
15
15
  *
16
- * A figure fence carries its own record along onto the page it starts, as
17
- * `figure` — `null` for a page a heading started. {@link buildPages} reads it
18
- * to build the `image` or `text` page a fence begins; nothing else sets it.
16
+ * A captioned item's page holds the item alone, and carries the item's record
17
+ * as `figure` — `null` for every other page. {@link buildPages} reads it to
18
+ * build the `image` or `text` page; nothing else sets it. The page is named
19
+ * for the item's number, or else its caption's visible text.
20
+ *
21
+ * Body that follows an item, up to the next page opening, resumes in a
22
+ * **continuation** of the section the item interrupted: the section's name,
23
+ * level and classes, with `continues` naming the item it follows. A
24
+ * continuation holding nothing is not emitted.
19
25
  *
20
26
  * @param {string} body - Markdown body to split.
21
27
  * @param {string} [leadName] - Name of the page before the first heading.
@@ -24,8 +30,8 @@
24
30
  * name reads `Map 1` rather than `Figure 1` where it is due — see
25
31
  * {@link module:engine/content-figures.scanFigures}.
26
32
  * @returns {Array<{name: string, anchorSlug: string|null, level: number,
27
- * classes: string[], figure: object|null, markdown: string}>} Pages in
28
- * document order.
33
+ * classes: string[], figure: object|null, continues?: string,
34
+ * markdown: string}>} Pages in document order.
29
35
  */
30
36
  export function splitPages(body: string, leadName?: string, resolveRole?: (address: string) => string | undefined): Array<{
31
37
  name: string;
@@ -33,6 +39,7 @@ export function splitPages(body: string, leadName?: string, resolveRole?: (addre
33
39
  level: number;
34
40
  classes: string[];
35
41
  figure: object | null;
42
+ continues?: string;
36
43
  markdown: string;
37
44
  }>;
38
45
  /**
@@ -95,13 +102,18 @@ export function assertUniqueAnchors(rawPages: Array<{
95
102
  * a lint error. {@link assertUniquePages} states the same thing at compile
96
103
  * time, where the packer would otherwise report only an opaque duplicate key.
97
104
  *
105
+ * A continuation page shares its section's name, so it is keyed by that name
106
+ * and the captioned item it follows.
107
+ *
98
108
  * @param {string} entryId - The owning JournalEntry's `_id`.
99
- * @param {{anchorSlug: string|null, name: string}} page - From {@link splitPages}.
109
+ * @param {{anchorSlug: string|null, name: string, continues?: string}} page -
110
+ * From {@link splitPages}.
100
111
  * @returns {string} A 16-character Foundry id.
101
112
  */
102
113
  export function journalPageId(entryId: string, page: {
103
114
  anchorSlug: string | null;
104
115
  name: string;
116
+ continues?: string;
105
117
  }): string;
106
118
  /**
107
119
  * Compile split pages into JournalEntryPage documents.
@@ -109,11 +121,12 @@ export function journalPageId(entryId: string, page: {
109
121
  * @param {Array<object>} rawPages - From {@link splitPages}.
110
122
  * @param {string} entryId - The owning JournalEntry's `_id`.
111
123
  * @param {string} noteName - The note, for error messages.
112
- * A page whose heading carries `.secret` is given to the GM alone, by the one
113
- * ownership value Foundry reads as "nobody but a GM". Every other page states
114
- * no ownership and inherits the journal's. A figure-started page states none
115
- * either: {@link scanFigures} validates a figure's classes against its own
116
- * closed vocabulary, which carries no `.secret`.
124
+ * A page whose opening heading carries `.secret` is given to the GM alone, by
125
+ * the one ownership value Foundry reads as "nobody but a GM"; so is a captioned
126
+ * item's page and a continuation page inside such a section. Every other page
127
+ * states no ownership and inherits the journal's. A caption's own classes carry
128
+ * no `.secret`, because {@link scanFigures} validates them against a closed
129
+ * vocabulary without it.
117
130
  *
118
131
  * @param {Array<object>} figures - From {@link scanFigures}, numbered across
119
132
  * the whole note. Read by a page a heading started; a page a figure started
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Require `data.language` to address a `skill` note whose subType is
3
+ * `language`.
4
+ *
5
+ * An Address that does not resolve is the reference check's to report, so
6
+ * this speaks only about a target that exists and is the wrong kind.
7
+ *
8
+ * @param {object} note
9
+ * @param {{index?: object}} [options]
10
+ * @returns {object[]} The findings.
11
+ */
12
+ export function checkLanguageChoice(note: object, { index }?: {
13
+ index?: object;
14
+ }): object[];
15
+ /**
16
+ * Refuse a literature field on a lore note of any other subType.
17
+ *
18
+ * @param {object} note
19
+ * @returns {object[]} One error per literature key written off `literature`.
20
+ */
21
+ export function checkLiteratureNote(note: object): object[];
22
+ /** The `lore` subType whose notes are works of literature. */
23
+ export const LITERATURE_SUBTYPE: "literature";
24
+ /**
25
+ * The fields a `literature` note may state. Every one is optional.
26
+ *
27
+ * @type {ReadonlyArray<object>}
28
+ */
29
+ export const LITERATURE_FIELDS: ReadonlyArray<object>;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * One local page's node.
3
+ *
4
+ * @param {object} fm - The note's frontmatter.
5
+ * @param {{title: string, url?: string, package?: string}} page
6
+ * @returns {WorksNode|null} Null for a note with no type or shortcode.
7
+ */
8
+ export function worksNode(fm: object, { title, url, package: pkg }: {
9
+ title: string;
10
+ url?: string;
11
+ package?: string;
12
+ }): WorksNode | null;
13
+ /**
14
+ * The works a fetched index carries, as nodes. Only a work can list itself on
15
+ * a page, and only a page of this package can carry the list, so a foreign
16
+ * entry that is not a work is never needed here.
17
+ *
18
+ * @param {Map<string, object>|undefined} foreignIndex
19
+ * @returns {WorksNode[]}
20
+ */
21
+ export function foreignWorksNodes(foreignIndex: Map<string, object> | undefined): WorksNode[];
22
+ /**
23
+ * Invert every work's subjects into the list each subject's page carries.
24
+ *
25
+ * A subject is resolved in its work's own package. A work naming one subject
26
+ * twice lists once; a work naming itself is not listed on its own page.
27
+ * Entries sort by title.
28
+ *
29
+ * @param {Iterable<WorksNode|null>} nodes - Every local page, then any foreign work.
30
+ * @param {object} options
31
+ * @param {ReadonlySet<string>} options.types - Note types an Address may name.
32
+ * @returns {Map<string, {works: WorkEntry[]}>} Keyed by the subject page's URL.
33
+ */
34
+ export function worksPages(nodes: Iterable<WorksNode | null>, { types }: {
35
+ types: ReadonlySet<string>;
36
+ }): Map<string, {
37
+ works: WorkEntry[];
38
+ }>;
39
+ export type WorkEntry = {
40
+ title: string;
41
+ url?: string;
42
+ address: string;
43
+ form?: string;
44
+ };
45
+ export type WorksNode = {
46
+ /**
47
+ * Own Address, normalized to the `note` system.
48
+ */
49
+ key: string;
50
+ title: string;
51
+ /**
52
+ * Absent for a note that publishes no page.
53
+ */
54
+ url?: string | undefined;
55
+ /**
56
+ * Owning content package.
57
+ */
58
+ package?: string | undefined;
59
+ /**
60
+ * A work's `data.form`.
61
+ */
62
+ form?: string | undefined;
63
+ /**
64
+ * A work's `data.subjects`; empty for any other note.
65
+ */
66
+ subjects: unknown[];
67
+ };
@@ -1,24 +1,16 @@
1
1
  /**
2
- * Render a DOT source file to SVG, plain positions, or a PNG background.
3
- *
4
- * A PNG uses the same Graphviz SVG layout as the vector map. SVG dimensions
5
- * are in points; resvg starts at 96 pixels per inch, so the zoom converts
6
- * the requested DPI to the same physical size as Graphviz's PNG output.
2
+ * Render a DOT source file to SVG.
7
3
  *
8
4
  * @param {string} dotPath - The saved DOT source.
9
5
  * @param {string} outPath - The output file.
10
6
  * @param {object} opts
11
7
  * @param {"dot"|"twopi"|"neato"} opts.engine - Layout engine.
12
- * @param {"svg"|"plain"|"png"} [opts.format="svg"] - Output format.
13
8
  * @param {2} [opts.nop] - Preserve positioned nodes as `neato -n2` does.
14
- * @param {number} [opts.dpi=96] - PNG resolution.
15
9
  * @returns {{warnings: string}} Renderer warnings.
16
10
  */
17
- export function renderDot(dotPath: string, outPath: string, { engine, format, nop, dpi }: {
11
+ export function renderDot(dotPath: string, outPath: string, { engine, nop }: {
18
12
  engine: "dot" | "twopi" | "neato";
19
- format?: "svg" | "png" | "plain" | undefined;
20
13
  nop?: 2 | undefined;
21
- dpi?: number | undefined;
22
14
  }): {
23
15
  warnings: string;
24
16
  };
@@ -7,14 +7,19 @@ export function sqlQueriesInMarkdown(body: any, fm?: {}): any[];
7
7
  * figures?: {get: (id: string) => {label: string, caption: string,
8
8
  * hasCaption: boolean}|undefined, note?: (address: string) =>
9
9
  * {url: string|null, figures: Map<string, object>}|undefined,
10
- * link?: Function}, file?: string, bodyLine?: number}} [options] -
10
+ * link?: Function}, events?: {note: (written: string) => object|undefined,
11
+ * own?: (fm: object) => object|undefined},
12
+ * file?: string, bodyLine?: number}} [options] -
11
13
  * `figures` is the `ref` helper's own view of the corpus: `get` reads this
12
14
  * note's captioned items by id, and `note` resolves another note's the
13
15
  * way a wikilink would — omitted, a cross-note address is refused rather
14
16
  * than looked up. `link` overrides how a resolved reference renders; the
15
- * default is a Markdown link to the target's own anchor.
17
+ * default is a Markdown link to the target's own anchor. `events` is what an
18
+ * event reference reads: every note's events by Address, from
19
+ * {@link module:engine/event-fields.eventNoteIndex}; omitted, an event
20
+ * reference is refused.
16
21
  */
17
- export function renderMarkdownExpressions(body: string, { fm, dates, sqlResults, figures, file, bodyLine }?: {
22
+ export function renderMarkdownExpressions(body: string, { fm, dates, sqlResults, figures, events, file, bodyLine }?: {
18
23
  fm?: object;
19
24
  dates?: object;
20
25
  sqlResults?: Map<string, object>;
@@ -30,6 +35,10 @@ export function renderMarkdownExpressions(body: string, { fm, dates, sqlResults,
30
35
  } | undefined;
31
36
  link?: Function;
32
37
  };
38
+ events?: {
39
+ note: (written: string) => object | undefined;
40
+ own?: (fm: object) => object | undefined;
41
+ };
33
42
  file?: string;
34
43
  bodyLine?: number;
35
44
  }): {
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The near miss a closed vocabulary names when it refuses a key: the declared
3
+ * key an unknown one was most likely meant to be, and the declared list as an
4
+ * English sentence.
5
+ *
6
+ * Shared by every closed region — the top level, `data:`, a system block, and
7
+ * the inner keys of a `data:` field — so a misspelling is answered the same
8
+ * way at every depth.
9
+ *
10
+ * @module
11
+ */
12
+ /**
13
+ * Edit distance, capped — enough to answer "did you mean".
14
+ *
15
+ * A misspelled property is the failure class this check exists for, and a
16
+ * finding that names the key the author *meant* turns a hunt through the
17
+ * reference into a one-character fix.
18
+ *
19
+ * @param {string} a - One string.
20
+ * @param {string} b - The other.
21
+ * @returns {number} The Levenshtein distance.
22
+ */
23
+ export function distance(a: string, b: string): number;
24
+ /**
25
+ * A closed vocabulary as an English list, for the message that names it.
26
+ *
27
+ * Written from the declaration rather than spelled into the message, so a key
28
+ * the vocabulary gains cannot go unmentioned by the finding that refuses its
29
+ * neighbours.
30
+ *
31
+ * @param {readonly string[]} keys - The declared keys, in declared order.
32
+ * @returns {string} `"a, b, or c"`.
33
+ */
34
+ export function listed(keys: readonly string[]): string;
35
+ /**
36
+ * The declared key an unknown one was most likely meant to be.
37
+ *
38
+ * @param {string} key - The unknown key.
39
+ * @param {Iterable<string>} candidates - The declared keys.
40
+ * @returns {string|undefined} The nearest, when it is near enough to suggest.
41
+ */
42
+ export function nearest(key: string, candidates: Iterable<string>): string | undefined;
@@ -19,6 +19,12 @@ export function decodeNoteAddresses(fm: object, context: object): object;
19
19
  export function noteAddressContext(config: object): object;
20
20
  /**
21
21
  * Decode Address properties contributed by an index record.
22
+ *
23
+ * A record read from a published index writes every Address as
24
+ * `{ address, anchor, anchorKind }`; each becomes a tuple, or an
25
+ * {@link AddressLink} where it carries an anchor, before the declared
26
+ * positions are read.
27
+ *
22
28
  * @param {object} record - The record.
23
29
  * @param {object} context - Builder defaults.
24
30
  * @returns {object} The typed record.
@@ -40,4 +46,4 @@ export const STRUCTURED_ADDRESSES: readonly ({
40
46
  accepts: string[];
41
47
  system?: undefined;
42
48
  })[];
43
- export { AddressEntries, encodeAddresses, cloneAddressState } from "./address-values.mjs";
49
+ export { AddressEntries, encodeAddresses, cloneAddressState, publishAddresses, readPublishedAddresses, flattenPublishedAddresses } from "./address-values.mjs";