@heroiclands/package-build 22.15.0 → 22.16.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 (223) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +39 -678
  3. package/bin/{content-build.mjs → content-commands.mjs} +197 -118
  4. package/bin/package-build.mjs +303 -42
  5. package/bin/report.mjs +1 -1
  6. package/ci/ci-docker.mjs +6 -3
  7. package/ci/ci-steps.mjs +6 -4
  8. package/ci/content-format-reference.mjs +106 -0
  9. package/config.mjs +22 -2
  10. package/content-config.mjs +74 -134
  11. package/docs/api.md +294 -234
  12. package/docs/authoring/assets.md +31 -0
  13. package/docs/authoring/dates-and-calendars.md +33 -0
  14. package/docs/authoring/first-note.md +48 -0
  15. package/docs/authoring/frontmatter.md +40 -0
  16. package/docs/authoring/links-and-markup.md +137 -0
  17. package/docs/commands.md +631 -162
  18. package/docs/configuration.md +176 -140
  19. package/docs/content-format.md +50 -4229
  20. package/docs/design.md +32 -0
  21. package/docs/diagnostics.md +29 -22
  22. package/docs/getting-started.md +21 -877
  23. package/docs/guides/book.md +153 -0
  24. package/docs/guides/e2e.md +143 -0
  25. package/docs/guides/icons.md +126 -0
  26. package/docs/guides/localization.md +120 -0
  27. package/docs/guides/module-project.md +915 -0
  28. package/docs/guides/packs.md +167 -0
  29. package/docs/guides/reference-pages.md +148 -0
  30. package/docs/guides/release-and-deploy.md +114 -0
  31. package/docs/guides/site.md +152 -0
  32. package/docs/guides/system-project.md +45 -0
  33. package/docs/index.md +16 -0
  34. package/docs/project-setup.md +54 -35
  35. package/docs/reference/format-details.md +4420 -0
  36. package/docs/reference/note-types.md +531 -0
  37. package/engine/address-render.mjs +26 -0
  38. package/engine/address.mjs +3 -20
  39. package/engine/anchors.mjs +15 -6
  40. package/engine/asset-bindings.mjs +6 -2
  41. package/engine/base-compiler.mjs +47 -11
  42. package/engine/being-measurements.mjs +70 -0
  43. package/engine/calendar-artifacts.mjs +1 -1
  44. package/engine/calendar-choice.mjs +32 -0
  45. package/engine/calendar-human.mjs +71 -0
  46. package/engine/calendar-notes.mjs +41 -3
  47. package/engine/calendars.mjs +8 -1
  48. package/engine/changelog-lint.mjs +2 -2
  49. package/engine/code-fences.mjs +23 -97
  50. package/engine/compile-corpus.mjs +6 -7
  51. package/engine/content-admonitions.mjs +114 -0
  52. package/engine/content-captions.mjs +181 -0
  53. package/engine/content-embeds.mjs +2 -2
  54. package/engine/content-footnotes.mjs +34 -0
  55. package/engine/content-format-check.mjs +2 -2
  56. package/engine/content-format.mjs +127 -73
  57. package/engine/content-format.yaml +745 -0
  58. package/engine/content-html.mjs +1 -1
  59. package/engine/content-icons.mjs +45 -92
  60. package/engine/content-images.mjs +22 -74
  61. package/engine/content-index.mjs +12 -3
  62. package/engine/content-links.mjs +21 -26
  63. package/engine/content-lint.mjs +1 -5
  64. package/engine/content-secrets.mjs +3 -1
  65. package/engine/content-tables.mjs +47 -1257
  66. package/engine/culture-choice.mjs +32 -0
  67. package/engine/date-conversion.mjs +47 -0
  68. package/engine/declaration-check.mjs +87 -0
  69. package/engine/docs-checks.mjs +140 -0
  70. package/engine/documentation-links.mjs +31 -0
  71. package/engine/exported-scene.mjs +1 -1
  72. package/engine/extension-attributes.mjs +74 -0
  73. package/engine/field-reference.mjs +1 -1
  74. package/engine/field-spec.mjs +4 -0
  75. package/engine/foreign-catalog.mjs +5 -5
  76. package/engine/format-generated.mjs +15 -0
  77. package/engine/foundry-entries.mjs +3 -1
  78. package/engine/frontmatter-lint.mjs +5 -1
  79. package/engine/frontmatter.mjs +10 -0
  80. package/engine/generate.mjs +2 -2
  81. package/engine/helpers.mjs +71 -117
  82. package/engine/homepage.mjs +2 -3
  83. package/engine/index-records.mjs +1 -0
  84. package/engine/index.mjs +18 -3
  85. package/engine/infobox-registry.mjs +3 -1
  86. package/engine/infobox.mjs +38 -20
  87. package/engine/item-compiler.mjs +10 -8
  88. package/engine/item-docs.mjs +7 -6
  89. package/engine/itinerary-scenes.mjs +4 -2
  90. package/engine/journals.mjs +51 -10
  91. package/engine/macros.mjs +1 -1
  92. package/engine/map-build.mjs +1 -1
  93. package/engine/map-dot.mjs +1 -1
  94. package/engine/map-raster.mjs +4 -2
  95. package/engine/markdown-expressions.mjs +117 -0
  96. package/engine/metadata-index.mjs +7 -3
  97. package/engine/note-addresses.mjs +1 -0
  98. package/engine/note-dates.mjs +283 -61
  99. package/engine/note-package.mjs +5 -25
  100. package/engine/note-state.mjs +6 -2
  101. package/engine/note-vocabulary.mjs +74 -19
  102. package/engine/number-words.mjs +75 -0
  103. package/engine/office-holders.mjs +188 -0
  104. package/engine/pack-config.mjs +2 -15
  105. package/engine/pack-router.mjs +24 -5
  106. package/engine/packages.mjs +3 -2
  107. package/engine/pathnames.mjs +21 -24
  108. package/engine/pdf-build.mjs +217 -55
  109. package/engine/pdf-fonts.mjs +2 -2
  110. package/engine/pdf-images.mjs +82 -0
  111. package/engine/pdf-render.mjs +174 -22
  112. package/engine/populations.mjs +3 -2
  113. package/engine/project-init.mjs +499 -0
  114. package/engine/prose-config.mjs +1 -1
  115. package/engine/prose-lint.mjs +7 -6
  116. package/engine/readability-lint.mjs +86 -0
  117. package/engine/reckoning-markers.mjs +205 -93
  118. package/engine/scenes.mjs +5 -2
  119. package/engine/schema-check.mjs +3 -3
  120. package/engine/site-build.mjs +87 -37
  121. package/engine/site-config.mjs +8 -8
  122. package/engine/site-index.mjs +4 -0
  123. package/engine/site-maps.mjs +1 -1
  124. package/engine/site-preview.mjs +19 -8
  125. package/engine/social-ties.mjs +5 -1
  126. package/engine/sql-tables.mjs +92 -22
  127. package/engine/web-wikilinks.mjs +15 -31
  128. package/engine/wikilink-syntax.mjs +4 -1
  129. package/engine/wikilinks.mjs +12 -14
  130. package/hm3/item-fields.mjs +1 -1
  131. package/hm3/items.mjs +12 -45
  132. package/index.mjs +2 -14
  133. package/manifest.mjs +31 -4
  134. package/markdownlint-config.mjs +1 -1
  135. package/package.json +32 -11
  136. package/prettier-config.mjs +1 -1
  137. package/sohl/being-info.mjs +3 -145
  138. package/sohl/index.mjs +1 -1
  139. package/sohl/infobox.mjs +2 -1
  140. package/sohl/item-builders.mjs +3 -27
  141. package/sohl/item-fields.mjs +61 -22
  142. package/sohl/kb-passes.mjs +2 -2
  143. package/sohl/note-schemas.mjs +0 -8
  144. package/stage.mjs +19 -0
  145. package/types/config.d.mts +12 -3
  146. package/types/content-config.d.mts +15 -81
  147. package/types/engine/address-render.d.mts +13 -0
  148. package/types/engine/address.d.mts +2 -11
  149. package/types/engine/anchors.d.mts +3 -4
  150. package/types/engine/asset-bindings.d.mts +9 -2
  151. package/types/engine/base-compiler.d.mts +1 -2
  152. package/types/engine/being-measurements.d.mts +16 -0
  153. package/types/engine/calendar-choice.d.mts +14 -0
  154. package/types/engine/calendar-human.d.mts +4 -0
  155. package/types/engine/calendar-notes.d.mts +2 -0
  156. package/types/engine/calendars.d.mts +5 -3
  157. package/types/engine/code-fences.d.mts +6 -72
  158. package/types/engine/compile-corpus.d.mts +1 -3
  159. package/types/engine/content-admonitions.d.mts +24 -0
  160. package/types/engine/content-captions.d.mts +45 -0
  161. package/types/engine/content-footnotes.d.mts +10 -0
  162. package/types/engine/content-format-check.d.mts +17 -4
  163. package/types/engine/content-format.d.mts +24 -11
  164. package/types/engine/content-icons.d.mts +14 -23
  165. package/types/engine/content-images.d.mts +2 -2
  166. package/types/engine/content-index.d.mts +9 -2
  167. package/types/engine/content-links.d.mts +3 -5
  168. package/types/engine/content-tables.d.mts +11 -140
  169. package/types/engine/culture-choice.d.mts +14 -0
  170. package/types/engine/date-conversion.d.mts +4 -0
  171. package/types/engine/declaration-check.d.mts +24 -0
  172. package/types/engine/docs-checks.d.mts +28 -0
  173. package/types/engine/documentation-links.d.mts +7 -0
  174. package/types/engine/exported-scene.d.mts +6 -2
  175. package/types/engine/extension-attributes.d.mts +14 -0
  176. package/types/engine/field-spec.d.mts +9 -0
  177. package/types/engine/format-generated.d.mts +7 -0
  178. package/types/engine/frontmatter.d.mts +14 -4
  179. package/types/engine/generate.d.mts +1 -1
  180. package/types/engine/helpers.d.mts +37 -92
  181. package/types/engine/homepage.d.mts +2 -3
  182. package/types/engine/index.d.mts +5 -0
  183. package/types/engine/infobox-registry.d.mts +3 -1
  184. package/types/engine/infobox.d.mts +17 -6
  185. package/types/engine/item-compiler.d.mts +4 -4
  186. package/types/engine/item-docs.d.mts +4 -3
  187. package/types/engine/journals.d.mts +10 -7
  188. package/types/engine/map-graphviz.d.mts +1 -1
  189. package/types/engine/markdown-expressions.d.mts +17 -0
  190. package/types/engine/note-dates.d.mts +47 -1
  191. package/types/engine/note-package.d.mts +3 -19
  192. package/types/engine/note-state.d.mts +2 -1
  193. package/types/engine/note-vocabulary.d.mts +9 -0
  194. package/types/engine/number-words.d.mts +4 -0
  195. package/types/engine/office-holders.d.mts +14 -0
  196. package/types/engine/pack-config.d.mts +1 -1
  197. package/types/engine/packages.d.mts +3 -2
  198. package/types/engine/pdf-images.d.mts +38 -0
  199. package/types/engine/populations.d.mts +2 -2
  200. package/types/engine/project-init.d.mts +17 -0
  201. package/types/engine/prose-config.d.mts +1 -1
  202. package/types/engine/prose-lint.d.mts +3 -2
  203. package/types/engine/readability-lint.d.mts +22 -0
  204. package/types/engine/reckoning-markers.d.mts +4 -2
  205. package/types/engine/schema-check.d.mts +3 -3
  206. package/types/engine/site-build.d.mts +38 -28
  207. package/types/engine/site-config.d.mts +2 -2
  208. package/types/engine/site-index.d.mts +4 -0
  209. package/types/engine/site-preview.d.mts +1 -1
  210. package/types/engine/social-ties.d.mts +8 -2
  211. package/types/engine/sql-tables.d.mts +13 -2
  212. package/types/engine/web-wikilinks.d.mts +2 -1
  213. package/types/engine/wikilinks.d.mts +7 -1
  214. package/types/hm3/items.d.mts +5 -6
  215. package/types/labels.d.mts +40 -0
  216. package/types/manifest.d.mts +3 -3
  217. package/types/sohl/actors.d.mts +2 -2
  218. package/types/sohl/being-info.d.mts +3 -43
  219. package/types/sohl/index.d.mts +1 -1
  220. package/types/sohl/infobox.d.mts +5 -2
  221. package/types/sohl/item-fields.d.mts +4 -13
  222. package/types/stage.d.mts +9 -0
  223. package/CONTENT.md +0 -3239
@@ -1,5 +1,5 @@
1
1
  /** Render a note body with Foundry's secret section markup. */
2
- export function renderFoundryMarkdown(body: any): string;
2
+ export function renderFoundryMarkdown(body: any, captions: any, footnoteNumbers: any, docId: any): string;
3
3
  /**
4
4
  * Parses a markdown file with YAML frontmatter.
5
5
  *
@@ -11,19 +11,19 @@ export function renderFoundryMarkdown(body: any): string;
11
11
  * {@link positionInBody}. If the file has no frontmatter block, returns
12
12
  * `{ frontmatter: null, body: "", description: "" }` with a warn log, and no
13
13
  * position: there is no body to have one.
14
+ * @param {string} filePath - Markdown file to read.
15
+ * @param {{addressContext?: object}} [opts] - Address defaults for decoded fields.
16
+ * @returns {{frontmatter: object|null, body: string, description: string,
17
+ * bodyLine?: number, bodyColumn?: number}} Parsed note and body position.
14
18
  */
15
- export function parseMarkdownFile(filePath: any, { addressContext }?: {}): {
16
- frontmatter: null;
17
- body: string;
18
- description: string;
19
- bodyLine?: undefined;
20
- bodyColumn?: undefined;
21
- } | {
22
- frontmatter: any;
19
+ export function parseMarkdownFile(filePath: string, { addressContext }?: {
20
+ addressContext?: object;
21
+ }): {
22
+ frontmatter: object | null;
23
23
  body: string;
24
24
  description: string;
25
- bodyLine: number;
26
- bodyColumn: number;
25
+ bodyLine?: number;
26
+ bodyColumn?: number;
27
27
  };
28
28
  /**
29
29
  * Refuse a corpus read whose scope its caller did not state.
@@ -80,6 +80,7 @@ export function assertSuppliedCorpus(records: readonly object[] | undefined, who
80
80
  * @param {readonly string[]} opts.skipDirectories - Directory names to ignore.
81
81
  * Required: the scope is the caller's to state, so two passes cannot
82
82
  * disagree about which files are the corpus.
83
+ * @param {object} [opts.addressContext] - Address resolution context.
83
84
  * @yields {{frontmatter: object|null, body: string, description: string,
84
85
  * file: string, absPath: string, bodyLine?: number, bodyColumn?: number}}
85
86
  * One entry per `.md` file found.
@@ -88,22 +89,15 @@ export function assertSuppliedCorpus(records: readonly object[] | undefined, who
88
89
  */
89
90
  export function walkMarkdownTree(rootDir: string, { skipDirectories, addressContext }?: {
90
91
  skipDirectories: readonly string[];
92
+ addressContext?: object | undefined;
91
93
  }): Generator<{
92
94
  file: string & NonSharedBuffer;
93
95
  absPath: string;
94
- frontmatter: null;
96
+ frontmatter: object | null;
95
97
  body: string;
96
98
  description: string;
97
- bodyLine?: undefined;
98
- bodyColumn?: undefined;
99
- } | {
100
- file: string & NonSharedBuffer;
101
- absPath: string;
102
- frontmatter: any;
103
- body: string;
104
- description: string;
105
- bodyLine: number;
106
- bodyColumn: number;
99
+ bodyLine?: number;
100
+ bodyColumn?: number;
107
101
  }, void, unknown>;
108
102
  /**
109
103
  * The template priority a note states, for a system that treats an unstated one
@@ -176,8 +170,11 @@ export function systemTemplatePriority(fm: object, label: string): number | null
176
170
  /**
177
171
  * Generates a compendium-source filename: `Name_id.json` with non-
178
172
  * alphanumeric runs replaced by underscores.
173
+ * @param {string} name - Document name.
174
+ * @param {string} id - Document id.
175
+ * @returns {string} Filename for the document.
179
176
  */
180
- export function makeFilename(name: any, id: any): string;
177
+ export function makeFilename(name: string, id: string): string;
181
178
  /**
182
179
  * Translate an authored pathname into the address a Foundry install serves.
183
180
  *
@@ -228,8 +225,11 @@ export function resolveImg(raw: string | null | undefined, config?: {
228
225
  /**
229
226
  * Resolves the display name from frontmatter, preferring `name.full`,
230
227
  * falling back to `name` (if string), then `defaultValue`.
228
+ * @param {object|null|undefined} fm - Parsed frontmatter.
229
+ * @param {string} [defaultValue] - Name when the note provides none.
230
+ * @returns {string} Display name.
231
231
  */
232
- export function resolveName(fm: any, defaultValue?: string): any;
232
+ export function resolveName(fm: object | null | undefined, defaultValue?: string): string;
233
233
  /**
234
234
  * The oldest Foundry core this package supports, stamped into every compiled
235
235
  * document as `_stats.coreVersion`.
@@ -345,21 +345,15 @@ export function defaultStats(): object;
345
345
  * the index and the compile agree about where each note landed; defaults to
346
346
  * this repository's own.
347
347
  * @param {object} [opts]
348
- * @param {readonly string[]} [opts.skipDirectories] - Part of the options bag
349
- * every corpus reader takes; the scope is already settled by `records`.
350
348
  * @param {object} [opts.config] - The resolved build configuration; loaded when
351
349
  * omitted.
352
350
  * @param {readonly object[]} [opts.records] - The corpus, derived once per
353
351
  * compile and handed in. Required: see {@link assertSuppliedCorpus}.
354
- * @param {object[]} [opts.problems] - Part of the same options bag; the notes
355
- * the index cannot record are collected where the corpus is derived.
356
352
  * @returns {{byShortcode: Map, types: Set}} From `buildWikilinkIndex`.
357
353
  */
358
- export function buildContentLinkIndex(contentBase: string, router?: object, { skipDirectories, config, records, problems }?: {
359
- skipDirectories?: readonly string[] | undefined;
354
+ export function buildContentLinkIndex(contentBase: string, router?: object, { config, records }?: {
360
355
  config?: object | undefined;
361
356
  records?: readonly object[] | undefined;
362
- problems?: object[] | undefined;
363
357
  }): {
364
358
  byShortcode: Map<any, any>;
365
359
  types: Set<any>;
@@ -421,68 +415,16 @@ export function convertNoteWikilinks(body: string, { type, id, pack, docPack, in
421
415
  unresolved: Array<object>;
422
416
  };
423
417
  /**
424
- * Every note in the content tree, in the shape the `dataview` table expander
425
- * searches: its frontmatter plus where it sits in the tree. Ordered by path so
426
- * a table that leaves rows tied still emits identically on every build.
427
- *
428
- * @param {string} contentBase - Root of the content tree.
429
- * @param {object} [opts]
430
- * @param {readonly string[]} [opts.skipDirectories] - Part of the options bag
431
- * every corpus reader takes; the scope is already settled by `records`.
432
- * @param {object} [opts.config] - The resolved build configuration; loaded when
433
- * omitted.
434
- * @param {readonly object[]} [opts.records] - The corpus, derived once per
435
- * compile and handed in. Required: see {@link assertSuppliedCorpus}.
436
- * @param {object[]} [opts.problems] - Part of the same options bag; the notes
437
- * the walk cannot read are collected where the corpus is derived.
438
- * @returns {Array<{fm: object, path: string, tld: string, folder: string,
439
- * absPath: string}>}
440
- */
441
- export function collectContentDocs(contentBase: string, { skipDirectories, config, records, problems }?: {
442
- skipDirectories?: readonly string[] | undefined;
443
- config?: object | undefined;
444
- records?: readonly object[] | undefined;
445
- problems?: object[] | undefined;
446
- }): Array<{
447
- fm: object;
448
- path: string;
449
- tld: string;
450
- folder: string;
451
- absPath: string;
452
- }>;
453
- /**
454
- * Expand the fenced `dataview` tables in one note's markdown, before wikilinks
455
- * are resolved — so a generated cell may itself be a wikilink.
456
- *
457
- * A table searches the whole tree, which is one package's notes and nothing
458
- * else — so there is no longer a package to scope on. It used to filter, back
459
- * when a tree could hold several packages' notes and `package:` said which was
460
- * which; that field is retired and the filter with it.
461
- *
462
- * @param {string} body - The note's markdown body.
463
- * @param {object} ctx
464
- * @param {Array<object>} ctx.docs - From {@link collectContentDocs}.
465
- * @param {string} ctx.name - The note, for the error message.
466
- * @param {object} [ctx.fm] - The source note's frontmatter, which is what a
467
- * query's `this` reads. Its entry in `docs` supplies the path as well.
468
- * @param {number} [ctx.bodyLine] - 1-based file line of the body's first line,
469
- * so a failing directive can be reported at its position in the file.
470
- * @param {object[]} [ctx.sqlTables] - This note's prepared `sql` results, in
471
- * document order, from
472
- * {@link module:engine/sql-tables.prepareSqlTables}. An `sql` directive with
473
- * no prepared result fails the note: nothing here runs a query.
474
- * @returns {{markdown: string, lineMap: Array<{line: number,
475
- * generated: boolean}>}} The body with every table expanded, and where each
476
- * emitted line came from — which is what lets a diagnostic about the
477
- * expanded body name an authored position.
478
- * @throws {Error} When a query is malformed or unsupported — the note fails to
479
- * compile rather than shipping a table-shaped hole. The error carries
480
- * `position`, the directive's own line.
418
+ * Expand prepared SQL tables before resolving wikilinks in generated cells.
419
+ * @param {string} body - The note body.
420
+ * @param {object} ctx - Source and prepared query results.
421
+ * @param {string} ctx.name - Name used in diagnostics.
422
+ * @param {number} [ctx.bodyLine] - The first body line in the source file.
423
+ * @param {object[]} [ctx.sqlTables] - Prepared SQL results in document order.
424
+ * @returns {{markdown: string, lineMap: Array<{line: number, generated: boolean}>}}
481
425
  */
482
- export function expandNoteTables(body: string, { docs, name, fm, bodyLine, sqlTables }: {
483
- docs: Array<object>;
426
+ export function expandNoteTables(body: string, { name, bodyLine, sqlTables }: {
484
427
  name: string;
485
- fm?: object | undefined;
486
428
  bodyLine?: number | undefined;
487
429
  sqlTables?: object[] | undefined;
488
430
  }): {
@@ -496,8 +438,11 @@ export function expandNoteTables(body: string, { docs, name, fm, bodyLine, sqlTa
496
438
  * Builds a compendium-source filename for a folder JSON document:
497
439
  * `folder_Name_id.json` with non-alphanumeric runs replaced by
498
440
  * underscores.
441
+ * @param {string} name - Folder name.
442
+ * @param {string} id - Folder id.
443
+ * @returns {string} Filename for the folder.
499
444
  */
500
- export function folderFilename(name: any, id: any): string;
445
+ export function folderFilename(name: string, id: string): string;
501
446
  /**
502
447
  * The markdown renderer every surface shares.
503
448
  *
@@ -87,9 +87,8 @@ export function checkHomepageAddressFields(fm: object | null | undefined, { isAu
87
87
  * {@link module:engine/diagnostics}. {@link lintContentTree} already reports an
88
88
  * empty walk against the same locator.
89
89
  *
90
- * The rule reads no `site:` configuration and does not vary by
91
- * `publish.site`: that setting chooses whether the *content* surfaces are
92
- * published, and the homepage is the floor underneath both modes.
90
+ * The rule applies to every content tree, whether it contains only the
91
+ * homepage or other notes as well.
93
92
  *
94
93
  * @param {ReadonlyArray<{file: string}>} found - The homepage notes, in walk
95
94
  * order. Paths may be absolute or relative to the working directory.
@@ -1,6 +1,7 @@
1
1
  export * as ids from "./ids.mjs";
2
2
  export * as systemBlock from "./system-block.mjs";
3
3
  export * as codeFences from "./code-fences.mjs";
4
+ export { formatGenerated } from "./format-generated.mjs";
4
5
  export * as frontmatter from "./frontmatter.mjs";
5
6
  export * as contentTree from "./content-tree.mjs";
6
7
  export * as packConfig from "./pack-config.mjs";
@@ -31,6 +32,10 @@ export * as siteMaps from "./site-maps.mjs";
31
32
  export * as systems from "./systems.mjs";
32
33
  export * as calendars from "./calendars.mjs";
33
34
  export * as noteDates from "./note-dates.mjs";
35
+ export * as dateConversion from "./date-conversion.mjs";
36
+ export * as markdownExpressions from "./markdown-expressions.mjs";
37
+ export * as calendarChoice from "./calendar-choice.mjs";
38
+ export * as cultureChoice from "./culture-choice.mjs";
34
39
  export * as reckoningMarkers from "./reckoning-markers.mjs";
35
40
  export * as calendarNotes from "./calendar-notes.mjs";
36
41
  export * as calendarArtifacts from "./calendar-artifacts.mjs";
@@ -50,13 +50,15 @@ export function compilesSystemDocument(fm: object, map: object, router: object):
50
50
  * Resolves a reference to `{name, url?, uuid?, address?, subType?}`.
51
51
  * @param {object} [options.router] - The pack router deciding which system
52
52
  * compiles a document for this note. Defaults to the consuming repository's.
53
+ * @param {object} [options.dates] - Calendar conversion context.
53
54
  * @returns {object[]} The boxes, in the order every medium renders them.
54
55
  * @throws {Error} When the built set disagrees with what the note's type maps
55
56
  * to — see {@link module:engine/infobox.assertInfoboxSet}.
56
57
  */
57
- export function noteInfoboxes(fm: object, { resolve, router }?: {
58
+ export function noteInfoboxes(fm: object, { resolve, router, dates }?: {
58
59
  resolve?: ((ref: unknown, hint?: object) => object | undefined) | undefined;
59
60
  router?: object | undefined;
61
+ dates?: object | undefined;
60
62
  }): object[];
61
63
  /**
62
64
  * Every system's infobox declaration, in the order a page shows them.
@@ -236,10 +236,16 @@ export function isDeclaredDefault(field: object, raw: unknown): boolean;
236
236
  *
237
237
  * @param {object} fm - The note's frontmatter.
238
238
  * @param {readonly object[]} fields - The system's field declaration.
239
- * @param {object} ctx - `{ block, resolve, resolveField, taken, presentation }`.
239
+ * @param {{block: string, resolve?: Function, resolveField?: Function, taken?: Set<string>, presentation?: object}} ctx - Rendering context.
240
240
  * @returns {object[]} Zero or one section.
241
241
  */
242
- export function systemRowsSection(fm: object, fields: readonly object[], { block, resolve, resolveField, taken, presentation }: object): object[];
242
+ export function systemRowsSection(fm: object, fields: readonly object[], { block, resolve, resolveField, taken, presentation }: {
243
+ block: string;
244
+ resolve?: Function;
245
+ resolveField?: Function;
246
+ taken?: Set<string>;
247
+ presentation?: object;
248
+ }): object[];
243
249
  /**
244
250
  * Every box a note carries, in the order every medium renders them.
245
251
  *
@@ -290,10 +296,12 @@ export function sectionHolds(section: object): boolean;
290
296
  * against a restatement of it.
291
297
  *
292
298
  * @param {object} fm - The note's frontmatter.
293
- * @param {object} options - `{ maps }`.
299
+ * @param {{maps: readonly object[]}} options - Document subtype mappings.
294
300
  * @returns {string[]} The ids.
295
301
  */
296
- export function requiredInfoboxIds(fm: object, { maps }: object): string[];
302
+ export function requiredInfoboxIds(fm: object, { maps }: {
303
+ maps: readonly object[];
304
+ }): string[];
297
305
  /**
298
306
  * Refuse a page carrying anything but the boxes its type maps to.
299
307
  *
@@ -306,12 +314,15 @@ export function requiredInfoboxIds(fm: object, { maps }: object): string[];
306
314
  *
307
315
  * @param {readonly object[]} boxes - What was built.
308
316
  * @param {object} fm - The note's frontmatter.
309
- * @param {object} options - `{ maps, where }`.
317
+ * @param {{maps: readonly object[], where?: string}} options - Document subtype mappings and context.
310
318
  * @returns {readonly object[]} The boxes, unchanged, so a caller may assert
311
319
  * inline.
312
320
  * @throws {Error} Naming the note, what is missing and what is extra.
313
321
  */
314
- export function assertInfoboxSet(boxes: readonly object[], fm: object, { maps, where }?: object): readonly object[];
322
+ export function assertInfoboxSet(boxes: readonly object[], fm: object, { maps, where }?: {
323
+ maps: readonly object[];
324
+ where?: string;
325
+ }): readonly object[];
315
326
  /**
316
327
  * How a section arranges what it holds.
317
328
  *
@@ -1,13 +1,13 @@
1
1
  /**
2
- * The description an item carries: a pointer to its **item doc**, the
3
- * JournalEntry the journals pass compiles this same body into.
2
+ * The description an item carries: a pointer to a page of its **item doc**,
3
+ * the JournalEntry the journals pass compiles this same body into.
4
4
  *
5
5
  * The prose is not rendered into the item at all. Carrying it would duplicate
6
6
  * it onto every actor holding the item — 7.59 MB of copies across the actors
7
7
  * pack, of which 133 KB was distinct — where a link is 60 bytes and always
8
8
  * current. The two passes derive the target from the note's own id, so neither
9
- * has to see the other's output; both split the *converted* markdown, so an H1
10
- * carrying a wikilink names the same page on both sides.
9
+ * has to see the other's output. `{#description}` selects the named page;
10
+ * an item without that anchor points to its first page.
11
11
  *
12
12
  * An item with no prose points at nothing, exactly as the journals pass writes
13
13
  * no entry for it.
@@ -18,7 +18,7 @@
18
18
  export function itemDocEntryId(itemId: string): string;
19
19
  /**
20
20
  * The description an item carries in place of its prose: a `@UUID` link to the
21
- * first page of its item doc, and nothing else.
21
+ * description page of its item doc, and nothing else.
22
22
  *
23
23
  * "Nothing else" is the whole convention — a description that is *only* a link
24
24
  * is a pointer, and anything alongside it would make it ordinary prose that
@@ -30,11 +30,12 @@ export function itemDocEntryId(itemId: string): string;
30
30
  * @param {string} name - The item's name, used as the link's label. It shows
31
31
  * only if the target ever fails to resolve, where a broken link naming the
32
32
  * item beats a bare UUID.
33
- * @param {string} firstPageId - The id of the entry's first page, from
33
+ * @param {string} pageId - The id of the selected entry page, from
34
34
  * {@link journalPageId}.
35
+ * @param {object} [fm] - The source note, used to route GM-only prose.
35
36
  * @returns {string} The pointer to store in `system.docHtml`.
36
37
  */
37
- export function itemDocPointer(packageId: string, itemId: string, name: string, firstPageId: string): string;
38
+ export function itemDocPointer(packageId: string, itemId: string, name: string, pageId: string, fm?: object): string;
38
39
  export { itemTypes };
39
40
  import { itemTypes } from "./item-registry.mjs";
40
41
  export { docEntryTypes, hasDocEntry } from "./address.mjs";
@@ -4,7 +4,7 @@
4
4
  * a split. Content before the first H1 (if non-empty) becomes a leading
5
5
  * page. Each H1 yields a page whose name is the heading
6
6
  * text (with any `{#anchor-id}` suffix stripped out and surfaced as
7
- * `anchorId`).
7
+ * `anchorSlug`).
8
8
  *
9
9
  * `leadName` names that leading page. A journal note's is "Introduction",
10
10
  * because it introduces the pages that follow. An item doc's is the item — a
@@ -12,14 +12,17 @@
12
12
  * calling that page "Introduction" would label the description as a preamble to
13
13
  * nothing.
14
14
  *
15
- * Returns an array of `{ name, anchorId, markdown }` in document order.
15
+ * @param {string} body - Markdown body to split.
16
+ * @param {string} [leadName] - Name of the page before the first heading.
17
+ * @returns {Array<{name: string, anchorSlug: string|null, level: number,
18
+ * markdown: string}>} Pages in document order.
16
19
  */
17
- export function splitPages(body: any, leadName?: string): {
20
+ export function splitPages(body: string, leadName?: string): Array<{
18
21
  name: string;
19
- anchorSlug: null;
22
+ anchorSlug: string | null;
20
23
  level: number;
21
24
  markdown: string;
22
- }[];
25
+ }>;
23
26
  /**
24
27
  * Two pages in one note that would derive the same id, which the LevelDB packer
25
28
  * reports only as an opaque duplicate-key collision. Catch it here, where the
@@ -66,7 +69,7 @@ export function assertUniqueAnchors(rawPages: Array<{
66
69
  * An anchored page takes the id its inbound links compute from the note id and
67
70
  * the slug, so link and page agree without shared state. Every other page is
68
71
  * keyed by its **name**, which is what lets the items pass address an item
69
- * doc's first page without having compiled it (see
72
+ * doc's selected page without having compiled it (see
70
73
  * {@link sohl.utils.packs.itemDocPointer}).
71
74
  *
72
75
  * **It takes no index**. Keying a page by position *and* name,
@@ -100,7 +103,7 @@ export function journalPageId(entryId: string, page: {
100
103
  * documents, in order.
101
104
  * @throws {Error} When the note has no content at all, or repeats an anchor.
102
105
  */
103
- export function buildPages(rawPages: Array<object>, entryId: string, noteName: string): Array<{
106
+ export function buildPages(rawPages: Array<object>, entryId: string, noteName: string, captions: any): Array<{
104
107
  _id: string;
105
108
  name: string;
106
109
  type: string;
@@ -16,7 +16,7 @@
16
16
  */
17
17
  export function renderDot(dotPath: string, outPath: string, { engine, format, nop, dpi }: {
18
18
  engine: "dot" | "twopi" | "neato";
19
- format?: "svg" | "plain" | "png" | undefined;
19
+ format?: "svg" | "png" | "plain" | undefined;
20
20
  nop?: 2 | undefined;
21
21
  dpi?: number | undefined;
22
22
  }): {
@@ -0,0 +1,17 @@
1
+ /** Find SQL helper calls, including calls nested inside Boolean expressions. */
2
+ export function sqlQueriesInMarkdown(body: any, fm?: {}): any[];
3
+ /**
4
+ * Expand scalar frontmatter references and registered functions in Markdown prose.
5
+ * @param {string} body
6
+ * @param {{fm?: object, dates?: object, sqlResults?: Map<string, object>, file?: string, bodyLine?: number}} [options]
7
+ */
8
+ export function renderMarkdownExpressions(body: string, { fm, dates, sqlResults, file, bodyLine }?: {
9
+ fm?: object;
10
+ dates?: object;
11
+ sqlResults?: Map<string, object>;
12
+ file?: string;
13
+ bodyLine?: number;
14
+ }): {
15
+ markdown: string;
16
+ findings: any[];
17
+ };
@@ -20,8 +20,12 @@
20
20
  * the month it names. A calendar that declares no list bounds nothing.
21
21
  * @param {Map<string, object>} [options.markers] - Resolved era markers from
22
22
  * the corpus, each carrying its calendar and canonical start.
23
+ * @param {Map<string, object>} [options.eras] - Resolved calendar eras, keyed
24
+ * by their addressed qualifier.
25
+ * @param {boolean} [options.ignoreEraBounds=false] - Parse a calendar row's
26
+ * own boundary in a referenced era without applying that era's note span.
23
27
  * @param {number} [options.daysPerYear] - The world's year length, required for
24
- * canonical days and marked dates.
28
+ * canonical days and named dates.
25
29
  * @param {string} [options.field] - The key that carried it, named in every
26
30
  * message. Omitted, a message names the value alone.
27
31
  * @param {boolean} [options.allowUnknown=true] - Whether `"unknown"` is a
@@ -39,6 +43,8 @@ export function parseNoteDate(value: unknown, options?: {
39
43
  months?: readonly object[] | null;
40
44
  } | undefined;
41
45
  markers?: Map<string, object> | undefined;
46
+ eras?: Map<string, object> | undefined;
47
+ ignoreEraBounds?: boolean | undefined;
42
48
  daysPerYear?: number | undefined;
43
49
  field?: string | undefined;
44
50
  allowUnknown?: boolean | undefined;
@@ -49,6 +55,44 @@ export function parseNoteDate(value: unknown, options?: {
49
55
  date: object | null;
50
56
  findings: object[];
51
57
  };
58
+ /** Select the single era covering the full precision of a resolved date. */
59
+ export function eraCovering(date: any, eraRows: any, daysPerYear: any): any;
60
+ /** Resolve a calendar or one of its eras from an Address or shortcode. */
61
+ export function calendarEras(reference: any, context: any): any;
62
+ /** Print a resolved date using the era active in one addressed calendar. */
63
+ export function formatDateInCalendar(date: any, reference: any, context: any): {
64
+ era: null;
65
+ year: number;
66
+ text: any;
67
+ prose: null;
68
+ month?: undefined;
69
+ day?: undefined;
70
+ } | {
71
+ era: any;
72
+ year: number;
73
+ month: number | null;
74
+ day: number | null;
75
+ text: string;
76
+ prose: string | null;
77
+ } | null;
78
+ /** Print a resolved date in one era, retaining its authored precision. */
79
+ export function formatNoteDate(date: any, era: any, daysPerYear: any): {
80
+ era: null;
81
+ year: number;
82
+ text: any;
83
+ prose: null;
84
+ month?: undefined;
85
+ day?: undefined;
86
+ } | {
87
+ era: any;
88
+ year: number;
89
+ month: number | null;
90
+ day: number | null;
91
+ text: string;
92
+ prose: string | null;
93
+ } | null;
94
+ /** Normalize a note's declared dates for indexes and generated pages. */
95
+ export function resolvedDateFields(fm: any, context: any): {};
52
96
  /**
53
97
  * The literal that says a thing happened and the date is not recorded.
54
98
  *
@@ -74,3 +118,5 @@ export const ERA_QUALIFIER_PATTERN: RegExp;
74
118
  * @type {RegExp}
75
119
  */
76
120
  export const NOTE_DATE_PATTERN: RegExp;
121
+ /** A calendar conversion written as a frontmatter date value. */
122
+ export const DATEFROM_PATTERN: RegExp;
@@ -1,24 +1,8 @@
1
1
  /**
2
- * A note's frontmatter as a generated table searches it — its package present,
3
- * though no note declares one.
4
- *
5
- * A `dataview` query resolves `package` out of frontmatter like any other
6
- * field, so a collection note that scopes itself with `WHERE … and package =
7
- * "sohl"` would match nothing now that the field is gone, and would render an
8
- * **empty table** in silence. Supplying the derived value here is what kept the
9
- * sweep mechanical rather than a trap — and a query that never mentions
10
- * `package` is unaffected either way.
11
- *
12
- * The frontmatter is copied rather than written into: it is the note's own
13
- * parsed object, shared with every other reader, and the derived package is a
14
- * property of *this search*, not of the note.
15
- *
2
+ * A copy of frontmatter carrying the configured package for query evaluation.
16
3
  * @param {object|null|undefined} fm - Parsed frontmatter.
17
- * @param {string} [configured] - The package this build compiles. Defaults to
18
- * the configured `contentPackage`; passed explicitly by callers that already
19
- * carry it in a context object, so a caller's configuration drives every read.
20
- * @returns {object|null|undefined} A shallow copy carrying the derived package,
21
- * or whatever was passed when it is not frontmatter at all.
4
+ * @param {string} [configured] - The package this build compiles.
5
+ * @returns {object|null|undefined} Frontmatter with a derived package value.
22
6
  */
23
7
  export function searchableFrontmatter(fm: object | null | undefined, configured?: string): object | null | undefined;
24
8
  /**
@@ -111,7 +111,8 @@ export function placeholderBody(body: string | null | undefined): Array<{
111
111
  *
112
112
  * Fence blocks, headings, thematic breaks and HTML comments are dropped, and a
113
113
  * wikilink counts as the one word it renders — `[[affiliation-meivor|Mëivōr]]`
114
- * is a word, not three. What is left is split on whitespace.
114
+ * is a word, not three. A dash, slash, or ellipsis between words separates
115
+ * them even without surrounding spaces.
115
116
  *
116
117
  * @param {string|null|undefined} body - The note body.
117
118
  * @returns {number} The word count.
@@ -61,6 +61,8 @@ export function hasTag(fm: object | null | undefined, tag: string): boolean;
61
61
  * @returns {boolean} Whether the note carries the `draft` tag.
62
62
  */
63
63
  export function isDraftNote(fm: object | null | undefined): boolean;
64
+ /** Whether a note is restricted to GM-facing output. */
65
+ export function isGmNote(fm: any): boolean;
64
66
  /**
65
67
  * What a note carrying a subType outside the address charset is told.
66
68
  *
@@ -167,6 +169,8 @@ export const SHARED_DATA_FIELDS: readonly DataFieldSpec[];
167
169
  * {@link draftRetiredMessage}.
168
170
  */
169
171
  export const DRAFT_TAG: "draft";
172
+ /** A note intended for the GM rather than the player-facing outputs. */
173
+ export const GM_TAG: "gm";
170
174
  /**
171
175
  * The tags that **classify** a note, grouped by what they classify.
172
176
  *
@@ -243,6 +247,11 @@ export const DECLARED_TAGS: Readonly<{
243
247
  types: null;
244
248
  tags: readonly string[];
245
249
  }>;
250
+ /** Who may read a completed note. */
251
+ audience: Readonly<{
252
+ types: null;
253
+ tags: readonly string[];
254
+ }>;
246
255
  }>;
247
256
  /**
248
257
  * Every note type this toolchain compiles, and the closed vocabulary it
@@ -0,0 +1,4 @@
1
+ /** Spell a SQL integer in running prose, using American cardinal style. */
2
+ export function numberWords(value: any): string;
3
+ /** Render a SQL number with grouped thousands and its fractional part. */
4
+ export function numberDigits(value: any): string;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Validate one affiliation's office roster against dated beings in the corpus.
3
+ * @param {object} note
4
+ * @param {{index?: object}} [options]
5
+ */
6
+ export function checkDatedOffices(note: object, { index }?: {
7
+ index?: object;
8
+ }): {
9
+ severity: string;
10
+ message: any;
11
+ line?: number;
12
+ column?: number;
13
+ file: any;
14
+ }[];
@@ -137,7 +137,7 @@ export const CONFIG_BASENAME: "package-build.config";
137
137
  * the order the names are *reported* in, which is the order a reader should
138
138
  * reach for them: YAML first, `.mjs` last.
139
139
  *
140
- * The `content-build.config.*` stem this package read before the two toolchains
140
+ * The `package-build.config.*` stem this package read before the two toolchains
141
141
  * merged is **not** resolved. 3.0.0 renames the file rather than accepting both:
142
142
  * a deprecation window here would mean a repository could sit indefinitely on a
143
143
  * name for a package that no longer exists, and the upgrade already requires
@@ -40,8 +40,9 @@ export function isReservedPackage(pkg: unknown): boolean;
40
40
  * with, which is the whole point: the alternative is every package depending on
41
41
  * one of the others just to borrow a banner.
42
42
  *
43
- * So nothing may create a real package that collides with the name, and its
44
- * resolution is special-cased, because no installed directory sits behind it.
43
+ * Only this toolchain's own documentation package may share the name. Other
44
+ * repositories cannot claim it, and asset resolution is special-cased because
45
+ * no installed Foundry directory sits behind it.
45
46
  *
46
47
  * This module is a **leaf with no local imports**, so the configuration
47
48
  * validator can name it without closing a cycle around `content-config.mjs`.