@heroiclands/package-build 22.15.1 → 22.17.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 +110 -0
  2. package/README.md +39 -678
  3. package/bin/{content-build.mjs → content-commands.mjs} +197 -118
  4. package/bin/package-build.mjs +315 -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 +296 -236
  12. package/docs/authoring/assets.md +31 -0
  13. package/docs/authoring/dates-and-calendars.md +85 -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 +633 -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 +4362 -0
  36. package/docs/reference/note-types.md +532 -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-format.mjs +441 -0
  46. package/engine/calendar-human.mjs +133 -0
  47. package/engine/calendar-notes.mjs +307 -88
  48. package/engine/calendars.mjs +8 -1
  49. package/engine/changelog-lint.mjs +2 -2
  50. package/engine/code-fences.mjs +23 -97
  51. package/engine/compile-corpus.mjs +6 -7
  52. package/engine/content-admonitions.mjs +114 -0
  53. package/engine/content-captions.mjs +181 -0
  54. package/engine/content-embeds.mjs +2 -2
  55. package/engine/content-footnotes.mjs +34 -0
  56. package/engine/content-format-check.mjs +2 -2
  57. package/engine/content-format.mjs +127 -73
  58. package/engine/content-format.yaml +746 -0
  59. package/engine/content-html.mjs +1 -1
  60. package/engine/content-icons.mjs +45 -92
  61. package/engine/content-images.mjs +22 -74
  62. package/engine/content-index.mjs +12 -3
  63. package/engine/content-links.mjs +21 -26
  64. package/engine/content-lint.mjs +1 -5
  65. package/engine/content-secrets.mjs +3 -1
  66. package/engine/content-tables.mjs +47 -1257
  67. package/engine/culture-choice.mjs +32 -0
  68. package/engine/date-conversion.mjs +47 -0
  69. package/engine/declaration-check.mjs +87 -0
  70. package/engine/docs-checks.mjs +140 -0
  71. package/engine/documentation-links.mjs +31 -0
  72. package/engine/exported-scene.mjs +1 -1
  73. package/engine/extension-attributes.mjs +74 -0
  74. package/engine/field-reference.mjs +1 -1
  75. package/engine/field-spec.mjs +4 -0
  76. package/engine/foreign-catalog.mjs +5 -5
  77. package/engine/format-generated.mjs +15 -0
  78. package/engine/foundry-entries.mjs +3 -1
  79. package/engine/frontmatter-lint.mjs +5 -1
  80. package/engine/frontmatter.mjs +10 -0
  81. package/engine/generate.mjs +2 -2
  82. package/engine/helpers.mjs +71 -117
  83. package/engine/homepage.mjs +2 -3
  84. package/engine/index-records.mjs +1 -0
  85. package/engine/index.mjs +18 -3
  86. package/engine/infobox-registry.mjs +3 -1
  87. package/engine/infobox.mjs +38 -20
  88. package/engine/item-compiler.mjs +10 -8
  89. package/engine/item-docs.mjs +7 -6
  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/markdown-expressions.mjs +118 -0
  95. package/engine/metadata-index.mjs +7 -3
  96. package/engine/note-addresses.mjs +1 -0
  97. package/engine/note-dates.mjs +314 -64
  98. package/engine/note-package.mjs +5 -25
  99. package/engine/note-state.mjs +6 -2
  100. package/engine/note-vocabulary.mjs +74 -19
  101. package/engine/number-words.mjs +75 -0
  102. package/engine/office-holders.mjs +188 -0
  103. package/engine/pack-config.mjs +2 -15
  104. package/engine/pack-router.mjs +24 -5
  105. package/engine/packages.mjs +3 -2
  106. package/engine/pathnames.mjs +21 -24
  107. package/engine/pdf-build.mjs +217 -55
  108. package/engine/pdf-fonts.mjs +2 -2
  109. package/engine/pdf-images.mjs +82 -0
  110. package/engine/pdf-render.mjs +174 -22
  111. package/engine/populations.mjs +3 -2
  112. package/engine/project-init.mjs +499 -0
  113. package/engine/prose-config.mjs +1 -1
  114. package/engine/prose-lint.mjs +7 -6
  115. package/engine/readability-lint.mjs +86 -0
  116. package/engine/reckoning-markers.mjs +176 -166
  117. package/engine/scenes.mjs +5 -2
  118. package/engine/schema-check.mjs +3 -3
  119. package/engine/site-build.mjs +87 -37
  120. package/engine/site-config.mjs +8 -8
  121. package/engine/site-index.mjs +4 -0
  122. package/engine/site-maps.mjs +1 -1
  123. package/engine/site-preview.mjs +19 -8
  124. package/engine/social-ties.mjs +5 -1
  125. package/engine/sql-tables.mjs +92 -22
  126. package/engine/web-wikilinks.mjs +15 -31
  127. package/engine/wikilink-syntax.mjs +4 -1
  128. package/engine/wikilinks.mjs +12 -14
  129. package/hm3/item-fields.mjs +1 -1
  130. package/hm3/items.mjs +12 -45
  131. package/index.mjs +2 -14
  132. package/manifest.mjs +31 -4
  133. package/markdownlint-config.mjs +1 -1
  134. package/package.json +32 -11
  135. package/prettier-config.mjs +1 -1
  136. package/sohl/being-info.mjs +3 -145
  137. package/sohl/index.mjs +1 -1
  138. package/sohl/infobox.mjs +2 -1
  139. package/sohl/item-builders.mjs +3 -27
  140. package/sohl/item-fields.mjs +61 -22
  141. package/sohl/kb-passes.mjs +2 -2
  142. package/sohl/note-schemas.mjs +0 -8
  143. package/stage.mjs +19 -0
  144. package/types/config.d.mts +12 -3
  145. package/types/content-config.d.mts +15 -81
  146. package/types/engine/address-render.d.mts +13 -0
  147. package/types/engine/address.d.mts +2 -11
  148. package/types/engine/anchors.d.mts +3 -4
  149. package/types/engine/asset-bindings.d.mts +9 -2
  150. package/types/engine/base-compiler.d.mts +1 -2
  151. package/types/engine/being-measurements.d.mts +16 -0
  152. package/types/engine/calendar-choice.d.mts +14 -0
  153. package/types/engine/calendar-format.d.mts +33 -0
  154. package/types/engine/calendar-human.d.mts +4 -0
  155. package/types/engine/calendar-notes.d.mts +5 -3
  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 +13 -26
  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
@@ -14,18 +14,21 @@ export function compilesFoundryDocuments(config: {
14
14
  /**
15
15
  * Whether this package publishes the pages its content tree compiles to.
16
16
  *
17
- * The one question every reader of the mode actually asks — the site build, to
18
- * decide whether to walk the tree at all, and the content index, to
19
- * decide whether an entry carries a web `path`. Written once here so the two
20
- * cannot come to disagree about what a mode means.
17
+ * Every package publishes an authored homepage. Other authored notes provide
18
+ * content pages; a tree containing only the homepage publishes only that page.
21
19
  *
22
- * @param {{publish: {site: SiteMode}}} config - A resolved configuration.
20
+ * Site, PDF, index, and Foundry address emission use the same source-tree
21
+ * decision. A file without note frontmatter is not a content page.
22
+ *
23
+ * @param {{paths: {content: string}, skipDirectories: readonly string[]}} config -
24
+ * A resolved configuration with content and skip paths.
23
25
  * @returns {boolean} Whether content pages are published.
24
26
  */
25
27
  export function publishesContentPages(config: {
26
- publish: {
27
- site: SiteMode;
28
+ paths: {
29
+ content: string;
28
30
  };
31
+ skipDirectories: readonly string[];
29
32
  }): boolean;
30
33
  /**
31
34
  * Validate and normalize a content configuration.
@@ -123,44 +126,6 @@ export const RETIRED_ADDRESS_KEYS: Readonly<Record<string, string>>;
123
126
  export const DEFAULT_ADDRESS_SCHEME: Readonly<{
124
127
  prefix: "";
125
128
  }>;
126
- /**
127
- * How much of a package reaches the web.
128
- *
129
- * Every HeroicLands package publishes something: a top-level, human-authored
130
- * homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
131
- * module is, which system it needs and how to install it. So there is no
132
- * value here meaning *no web presence at all* — homepage-only is the **floor**,
133
- * and the default.
134
- *
135
- * - `homepage` — the authored homepage, and **no other page**. The content tree
136
- * is not walked for pages, and nothing serves a page for its addresses.
137
- * - `content` — the homepage *plus* every page the content tree publishes, one
138
- * per note.
139
- *
140
- * **Homepage-only is a first-class mode, not an accommodation.**
141
- * `sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
142
- * Fan Material Guidelines) and `harn-adventures` (HârnFanon under Lythia's
143
- * terms) must each publish a homepage and nothing beneath it — two packages
144
- * under two different fan-content licences. The boundary is **published
145
- * content**: journal text, artwork, item descriptions, compiled notes. A
146
- * human-authored page announcing the module discloses none of it. Because the
147
- * failure mode is silent — a `site:` block added later ships licensed content
148
- * with nobody noticing — the mode fences the content surfaces off rather than
149
- * trusting a configuration to stay empty.
150
- *
151
- * This was a boolean until 5.0.0, and `false` read as "no web presence", which
152
- * no longer describes any package. Both spellings are refused rather than
153
- * mapped: a value silently reinterpreted reads to its author as though it still
154
- * means what it said.
155
- *
156
- * @typedef {"homepage" | "content"} SiteMode
157
- */
158
- /**
159
- * The publishing modes {@link PublishSwitches.site} may name, floor first.
160
- *
161
- * @satisfies {readonly SiteMode[]}
162
- */
163
- export const SITE_MODES: readonly ["homepage", "content"];
164
129
  /**
165
130
  * How the loader hands {@link defineConfig} the system version it resolved.
166
131
  *
@@ -189,37 +154,6 @@ export const DERIVED_SYSTEM_VERSION: symbol;
189
154
  * @type {Readonly<Record<string, string>>}
190
155
  */
191
156
  export const DERIVED_HUGO_KEYS: Readonly<Record<string, string>>;
192
- /**
193
- * How much of a package reaches the web.
194
- *
195
- * Every HeroicLands package publishes something: a top-level, human-authored
196
- * homepage at `https://www.heroiclands.org/<contentPackage>/` saying what the
197
- * module is, which system it needs and how to install it. So there is no
198
- * value here meaning *no web presence at all* — homepage-only is the **floor**,
199
- * and the default.
200
- *
201
- * - `homepage` — the authored homepage, and **no other page**. The content tree
202
- * is not walked for pages, and nothing serves a page for its addresses.
203
- * - `content` — the homepage *plus* every page the content tree publishes, one
204
- * per note.
205
- *
206
- * **Homepage-only is a first-class mode, not an accommodation.**
207
- * `sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
208
- * Fan Material Guidelines) and `harn-adventures` (HârnFanon under Lythia's
209
- * terms) must each publish a homepage and nothing beneath it — two packages
210
- * under two different fan-content licences. The boundary is **published
211
- * content**: journal text, artwork, item descriptions, compiled notes. A
212
- * human-authored page announcing the module discloses none of it. Because the
213
- * failure mode is silent — a `site:` block added later ships licensed content
214
- * with nobody noticing — the mode fences the content surfaces off rather than
215
- * trusting a configuration to stay empty.
216
- *
217
- * This was a boolean until 5.0.0, and `false` read as "no web presence", which
218
- * no longer describes any package. Both spellings are refused rather than
219
- * mapped: a value silently reinterpreted reads to its author as though it still
220
- * means what it said.
221
- */
222
- export type SiteMode = "homepage" | "content";
223
157
  export type PackageKind = "systems" | "modules" | "documentation";
224
158
  export type PackDocumentType = "Actor" | "Adventure" | "Item" | "JournalEntry" | "Macro" | "Scene";
225
159
  /**
@@ -416,10 +350,11 @@ export type StatsSpec = {
416
350
  export type PackageBuildSection = Record<string, unknown>;
417
351
  export type PublishSwitches = {
418
352
  /**
419
- * How much of this package reaches the web.
420
- * See {@link SITE_MODES}.
353
+ * Where content pages mount within the package.
421
354
  */
422
- site: SiteMode;
355
+ address: Readonly<{
356
+ prefix: string;
357
+ }>;
423
358
  };
424
359
  /**
425
360
  * The **Foundry core** version range this package supports.
@@ -554,13 +489,12 @@ export type DocPageSpec = {
554
489
  export type DocsSpec = {
555
490
  /**
556
491
  * The item-frontmatter reference,
557
- * rendered by `content-build docs
492
+ * rendered by `package-build docs
558
493
  * item-fields`.
559
494
  */
560
495
  itemFields?: DocPageSpec | undefined;
561
496
  };
562
497
  export type PublishSwitchesInput = {
563
- site?: SiteMode | undefined;
564
498
  address?: AddressSchemeInput | undefined;
565
499
  };
566
500
  export type AddressSchemeInput = {
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Render the four segments of a complete Address in lowercase.
3
+ * @param {{package: string, system: string, type: string, shortcode: string}} tuple
4
+ * @returns {string} The canonical Address.
5
+ */
6
+ export function renderAddress(tuple: {
7
+ package: string;
8
+ system: string;
9
+ type: string;
10
+ shortcode: string;
11
+ }): string;
12
+ /** Render every written suffix of one complete Address. */
13
+ export function addressSuffixes(tuple: any): string[];
@@ -112,16 +112,6 @@ export function parseAddress(written: unknown, defaults?: AddressDefaults, { dec
112
112
  * @returns {boolean} Whether it is a typed tuple.
113
113
  */
114
114
  export function isAddressTuple(value: unknown): boolean;
115
- /**
116
- * Render a complete Address as its canonical string.
117
- *
118
- * Lowercased, because an Address has one spelling: two names differing only in
119
- * case are two names nobody can tell apart.
120
- *
121
- * @param {AddressTuple} tuple - The complete Address.
122
- * @returns {string} `package-system-type-shortcode`.
123
- */
124
- export function renderAddress(tuple: AddressTuple): string;
125
115
  /**
126
116
  * Whether the canonical type an Address names is accepted at this position.
127
117
  *
@@ -278,7 +268,6 @@ export function readQualifier(target: string, types: Set<string>, packages?: Set
278
268
  system?: string;
279
269
  reason?: undefined;
280
270
  } | AddressProblem | null;
281
- export { NO_SYSTEM };
282
271
  /**
283
272
  * The one character that separates an Address's segments.
284
273
  *
@@ -381,3 +370,5 @@ export type AddressDefaults = AddressVocabulary & {
381
370
  type?: string;
382
371
  };
383
372
  import { NO_SYSTEM } from "./systems.mjs";
373
+ import { renderAddress } from "./address-render.mjs";
374
+ export { NO_SYSTEM, renderAddress };
@@ -1,9 +1,8 @@
1
1
  /**
2
- * The `{#slug}` anchors a note's body declares, with where each one sits.
2
+ * The `{#slug}` and `:::caption {#slug}` anchors a note declares.
3
3
  *
4
- * Only headings carrying an explicit anchor are collected. A bare `#` heading
5
- * also starts a journal page, but it declares no slug, so nothing can address
6
- * it with `#…` — listing it would offer a link that cannot be written.
4
+ * A bare `#` heading starts a journal page without declaring a slug. Captioned
5
+ * blocks declare a slug and start an addressable journal page.
7
6
  *
8
7
  * @param {string} body - The note's markdown body, frontmatter already removed.
9
8
  * @param {number} [bodyLine] - The 1-based file line the body starts on, from
@@ -1,5 +1,12 @@
1
- /** Check configured foreign Address bindings against fetched indexes. */
2
- export function checkForeignAssetBindings(config: any, { foreignIndex, assets }?: {}): {
1
+ /**
2
+ * Check configured foreign Address bindings against fetched indexes.
3
+ * @param {object} config
4
+ * @param {{foreignIndex?: Map<string, object>, assets?: object[]}} [options]
5
+ */
6
+ export function checkForeignAssetBindings(config: object, { foreignIndex, assets }?: {
7
+ foreignIndex?: Map<string, object>;
8
+ assets?: object[];
9
+ }): {
3
10
  file: string;
4
11
  severity: string;
5
12
  message: string;
@@ -376,7 +376,6 @@ export class BasePackCompiler {
376
376
  prepare(): Promise<void>;
377
377
  reportsCorpusProblems: boolean | undefined;
378
378
  linkIndex: any;
379
- contentDocs: any;
380
379
  sqlTables: any;
381
380
  worldPresent: unknown;
382
381
  /**
@@ -478,7 +477,7 @@ export class BasePackCompiler {
478
477
  * a line rather than at a note.
479
478
  *
480
479
  * Silent where nothing can answer — no published schema, or a subtype the
481
- * artifact does not name. `content-build lint` says that out loud once for
480
+ * artifact does not name. `package-build lint` says that out loud once for
482
481
  * the whole build rather than once per note.
483
482
  *
484
483
  * @param {object} fm - The note's frontmatter.
@@ -0,0 +1,16 @@
1
+ /** Read a being's height as a whole number of inches. */
2
+ export function parseBeingHeight(value: any): number | null;
3
+ /** Read a being's weight as a whole number of pounds. */
4
+ export function parseBeingWeight(value: any): number | null;
5
+ /** Show a being's height in feet and inches. */
6
+ export function displayBeingHeight(value: any): string;
7
+ /** Show a being's weight in pounds. */
8
+ export function displayBeingWeight(value: any): string;
9
+ /** Check one authored being measurement at its frontmatter position. */
10
+ export function checkBeingMeasurement(note: any, key: any, parse: any): {
11
+ severity: string;
12
+ message: string;
13
+ line?: number;
14
+ column?: number;
15
+ file?: any;
16
+ }[];
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Require a being's or place's chosen calendar to address a calendar note.
3
+ * @param {object} note
4
+ * @param {{index?: object}} [options]
5
+ */
6
+ export function checkCalendarChoice(note: object, { index }?: {
7
+ index?: object;
8
+ }): {
9
+ severity: string;
10
+ message: string;
11
+ line?: number;
12
+ column?: number;
13
+ file: any;
14
+ }[];
@@ -0,0 +1,33 @@
1
+ /** Brackets and braces must close; `[[]` is a literal left bracket. */
2
+ export function calendarFormatSyntaxError(pattern: any): string | null;
3
+ /** Split a Calendaria pattern into tokens and literal text. */
4
+ export function calendarFormatSegments(pattern: any): {
5
+ token: boolean;
6
+ value: any;
7
+ }[];
8
+ /** A standard format must identify one calendar day and be readable without context. */
9
+ export function readableCalendarFormatError(pattern: any): string | null;
10
+ /** Whether a selected pattern prints clock components. */
11
+ export function calendarFormatHasClock(pattern: any): boolean;
12
+ /** Keep the fields named by an authored date's precision. */
13
+ export function calendarPatternSegmentsForPrecision(pattern: any, precision?: string, includeClock?: boolean): {
14
+ token: boolean;
15
+ value: any;
16
+ }[];
17
+ /** Choose an authored named format, with `std` as the preferred default. */
18
+ export function selectCalendarFormat(calendar: any, name: any): {
19
+ name: any;
20
+ pattern: any;
21
+ };
22
+ /** Format calendar date components with Calendaria's documented tokens. */
23
+ export function formatCalendarPattern(pattern: any, parts: any, precision?: string, includeClock?: boolean): string;
24
+ /** Read the invertible date fields of one Calendaria pattern. */
25
+ export function parseCalendarPattern(pattern: any, text: any, calendar: any): {
26
+ hour: number;
27
+ };
28
+ /** Convert a calendar month/day into its one-based day of year. */
29
+ export function calendarOrdinal(calendar: any, month: any, day: any): number;
30
+ /** Calendaria's bare date, time, week, season, and zone tokens. */
31
+ export const CALENDAR_FORMAT_TOKENS: Readonly<Set<string>>;
32
+ /** Calendaria's named fields inside brackets or braces. */
33
+ export const CALENDAR_CUSTOM_TOKENS: Readonly<Set<string>>;
@@ -0,0 +1,4 @@
1
+ /** The labels a human date may use to name one era. */
2
+ export function eraNames(era: any): any[];
3
+ /** Translate a named date into the addressed form read by the date parser. */
4
+ export function addressedCalendarDate(text: any, eras: any): string | null;
@@ -18,7 +18,7 @@ export function worldInvariants(index?: object): {
18
18
  yearNote: object | null;
19
19
  moonNote: object | null;
20
20
  };
21
- /** Check each authored format slot and every unescaped letter run in it. */
21
+ /** Check each named pattern and the standard pattern's readable fields. */
22
22
  export function checkCalendarDateFormats(note: any): {
23
23
  severity: any;
24
24
  message: any;
@@ -101,12 +101,14 @@ export function quarterDays(daysPerYear: number): number[];
101
101
  * @param {string} [opts.contentPackage] - The package shipping the note, which
102
102
  * is a fact about the tree rather than about the note: a note never declares
103
103
  * its own package.
104
+ * @param {object} [opts.dateContext] - Calendar conversion context.
104
105
  * @returns {object} The definition.
105
106
  */
106
107
  export function compileCalendar({ note, invariants, contentPackage, dateContext }: {
107
108
  note: object;
108
109
  invariants: object;
109
110
  contentPackage?: string | undefined;
111
+ dateContext?: object | undefined;
110
112
  }): object;
111
113
  /**
112
114
  * Wrap a definition in the envelope a Calendaria settings import reads.
@@ -160,8 +162,7 @@ export const CALENDAR_SUBTYPE: "calendar";
160
162
  export const INVARIANT_SUBTYPES: readonly string[];
161
163
  /** Calendaria's display locations that a calendar note can format. */
162
164
  export const CALENDAR_DATE_FORMAT_KEYS: readonly string[];
163
- /** Bare date tokens Calendaria substitutes inside authored format strings. */
164
- export const CALENDAR_FORMAT_TOKENS: Readonly<Set<string>>;
165
+ export { CALENDAR_FORMAT_TOKENS };
165
166
  /**
166
167
  * The `data:` keys a calendar note may write — the closed list, in authored
167
168
  * order.
@@ -183,3 +184,4 @@ export const CALENDAR_FIELDS: readonly object[];
183
184
  * @type {readonly object[]}
184
185
  */
185
186
  export const INVARIANT_FIELDS: readonly object[];
187
+ import { CALENDAR_FORMAT_TOKENS } from "./calendar-format.mjs";
@@ -16,6 +16,8 @@
16
16
  * @returns {number} The signed year on the axis — authored `-1` is `0`.
17
17
  */
18
18
  export function canonicalYear(year: number, epoch?: number): number;
19
+ /** The signed year a reckoning counts at a canonical year, without year zero. */
20
+ export function eraYear(canonical: any, epoch?: number): number;
19
21
  /**
20
22
  * The total-order key a date sorts on.
21
23
  *
@@ -118,13 +120,13 @@ export function calendarStructure(calendar?: {
118
120
  /**
119
121
  * How long one month of a calendar is, or `null` where the calendar is silent.
120
122
  *
121
- * @param {{months?: readonly CalendarMonth[]|null}} [calendar] - The calendar.
123
+ * @param {{months?: readonly CalendarMonth[]|null}|undefined} calendar - The calendar.
122
124
  * @param {number} month - The month, numbered from 1.
123
125
  * @returns {number|null} Its length in days, or `null`.
124
126
  */
125
- export function daysInMonth(calendar?: {
127
+ export function daysInMonth(calendar: {
126
128
  months?: readonly CalendarMonth[] | null;
127
- }, month: number): number | null;
129
+ } | undefined, month: number): number | null;
128
130
  /**
129
131
  * How many days the months add up to.
130
132
  *
@@ -1,45 +1,13 @@
1
1
  /**
2
- * A fence's info string, read as **org-babel header arguments**.
3
- *
4
- * A directive fence carries statements *about the directive* that are no part of
5
- * the query it holds — whether an empty result is intended, what heading level a
6
- * section takes, later a caption. Those started as an ad-hoc bare word
7
- * (`allow-empty`) and a `key=value` (`section-level=3`), each matched by its own
8
- * regex: a grammar only in the sense that two regexes are one, and with no room
9
- * to add a third property without adding a third spelling.
10
- *
11
- * Org-mode settled this long ago. A babel source block writes them after the
12
- * language as `:key value`, which is a real grammar with a specification, a
13
- * parser, and an editor that already completes it.
14
- *
15
- * ```text
16
- * ```sql :section-level 3 :allow-empty
17
- * ```
18
- *
19
- * **The language word stays first and stays plain.** `sql` is what GitHub,
20
- * Prettier and every other markdown reader match on to syntax-highlight the
21
- * block, so it leads and the header args follow; a reader that does not know
22
- * them sees an ordinary SQL block.
23
- *
24
- * The grammar, matching org's:
25
- *
26
- * - a key is `:name` **starting a word** — a colon inside or ending a word is
27
- * text, so `:caption Gear: the tables` is one argument;
28
- * - a value runs to the next key or the end of the string, spaces included, and
29
- * is trimmed;
30
- * - a key with no value is `true`, which is what a statement like
31
- * `:allow-empty` is;
32
- * - a value may be `"quoted"` to hold a word that would otherwise read as a
33
- * key — the one ambiguity org has too;
34
- * - a repeated key takes its last value.
35
- *
36
- * @param {string} info - The text after the fence marker.
37
- * @returns {{language: string, args: Record<string, string|true>}} The language,
38
- * lowercased, and the header arguments in written order.
2
+ * Read a language name and optional braced attributes from a code fence.
3
+ * @param {string} info - Text after the fence marker.
4
+ * @returns {{language: string, args: Record<string, string>, problems: string[]}}
5
+ * Parsed values and syntax findings.
39
6
  */
40
7
  export function parseHeaderArgs(info: string): {
41
8
  language: string;
42
- args: Record<string, string | true>;
9
+ args: Record<string, string>;
10
+ problems: string[];
43
11
  };
44
12
  /**
45
13
  * Every code region in a markdown body, as character offsets into it.
@@ -107,39 +75,5 @@ export function matchAllOutsideCode(markdown: string, pattern: RegExp, options?:
107
75
  * @returns {string} The transformed body, with every code run restored verbatim.
108
76
  */
109
77
  export function protectCode(body: string, transform: (masked: string) => string): string;
110
- /**
111
- * Where **code** lives in a markdown body, so a rewriter can leave it alone.
112
- *
113
- * A code block is verbatim: its contents are shown to the reader exactly as
114
- * written. Every build-time rewriter that pattern-matches a body therefore has
115
- * to know where code is — otherwise a source listing that happens to contain
116
- * the rewriter's syntax is silently corrupted. Wikilink conversion met this as
117
- * `[[0]]` inside a fence being turned into a link, and it depended on
118
- * the surrounding literal's shape (`[[1,2],[3,4]]` survived), so the corruption
119
- * looked arbitrary.
120
- *
121
- * Three forms are recognised, which is every form the content tree uses:
122
- *
123
- * - **Fenced blocks** — three or more backticks or tildes, closed by the same
124
- * character at least as long, or by the end of the document. A longer fence
125
- * contains a shorter one, so a markdown sample can quote a code sample. The
126
- * opening line, info string and all, is part of the block.
127
- * - **Indented blocks** — four columns past the enclosing context, following a
128
- * blank line (an indent cannot interrupt a paragraph).
129
- * - **Inline spans** — a run of backticks closed by a run of equal length,
130
- * within one paragraph.
131
- *
132
- * The fence syntax is the one `expandContentTables` already reads, and
133
- * this module owns it now so the two can never disagree.
134
- *
135
- * **Known limits.** This is a scanner, not a markdown parser, and it errs
136
- * towards treating something as code — a false positive leaves an author's text
137
- * as written, a false negative rewrites it. List nesting is tracked only to the
138
- * innermost open marker, so an indented block inside a deeply nested list may be
139
- * read as list prose; a backslash-escaped backtick still counts as a span
140
- * delimiter; and HTML blocks are not code (they are not verbatim in markdown
141
- * either). None of these can turn code into a link — the failure this exists to
142
- * prevent.
143
- */
144
78
  /** A fence line, capturing its indent, its marker, and its info string. */
145
79
  export const FENCE_LINE: RegExp;
@@ -15,8 +15,7 @@
15
15
  * created when none is passed, and returned on the corpus either way — a note
16
16
  * the index refuses is a note the compile must still *report*, exactly as the
17
17
  * compile loop reported it when the loop was the first to see it.
18
- * @returns {Promise<{records: object[], linkIndex: object, contentDocs: object[],
19
- * sqlTables: Map<string, object[]>|undefined, problems: object[]}>} The corpus,
18
+ * @returns {Promise<{records: object[], linkIndex: object, sqlTables: Map<string, object[]>|undefined, problems: object[]}>} The corpus,
20
19
  * its indexes, and the notes it could not record.
21
20
  */
22
21
  export function buildCompileCorpus({ contentBase, assetsBase, skipDirectories, router, config, problems, }: {
@@ -29,7 +28,6 @@ export function buildCompileCorpus({ contentBase, assetsBase, skipDirectories, r
29
28
  }): Promise<{
30
29
  records: object[];
31
30
  linkIndex: object;
32
- contentDocs: object[];
33
31
  sqlTables: Map<string, object[]> | undefined;
34
32
  problems: object[];
35
33
  }>;
@@ -0,0 +1,24 @@
1
+ /** Find inline info and warning blocks without interpreting code examples. */
2
+ export function scanAdmonitions(source: any): {
3
+ blocks: {
4
+ end: number;
5
+ body: string;
6
+ start: number;
7
+ kind: string;
8
+ id: string;
9
+ }[];
10
+ errors: {
11
+ line: number;
12
+ column: number;
13
+ message: string;
14
+ }[];
15
+ };
16
+ /** Render info and warning blocks as styled, labelled HTML. */
17
+ export function renderAdmonitions(source: any, renderMarkdown?: (src: string, env?: import("markdown-it").Env) => string): {
18
+ markdown: any;
19
+ errors: {
20
+ line: number;
21
+ column: number;
22
+ message: string;
23
+ }[];
24
+ };
@@ -0,0 +1,45 @@
1
+ /** Number a sequence of captions with counters shared across documents. */
2
+ export function numberCaptions(captions: any, counts: any): any;
3
+ /**
4
+ * Read caption directives and the Markdown block immediately after each one.
5
+ * SQL fences are expanded before this pass, so their output is a table.
6
+ *
7
+ * @param {string} source - A note body with expanded tables.
8
+ * @returns {{captions: Array<{id: string, text: string, kind: string, number: number,
9
+ * label: string, line: number, blockStart: number, blockEnd: number,
10
+ * directiveEnd: number}>, errors: Array<{line: number, column: number, message: string}>}}
11
+ */
12
+ export function scanCaptions(source: string): {
13
+ captions: Array<{
14
+ id: string;
15
+ text: string;
16
+ kind: string;
17
+ number: number;
18
+ label: string;
19
+ line: number;
20
+ blockStart: number;
21
+ blockEnd: number;
22
+ directiveEnd: number;
23
+ }>;
24
+ errors: Array<{
25
+ line: number;
26
+ column: number;
27
+ message: string;
28
+ }>;
29
+ };
30
+ /** Render captioned blocks as HTML, leaving other Markdown untouched. */
31
+ export function renderCaptionBlocks(source: any, renderMarkdown: ((src: string, env?: import("markdown-it").Env) => string) | undefined, numbers: any): {
32
+ markdown: any;
33
+ errors: {
34
+ line: number;
35
+ column: number;
36
+ message: string;
37
+ }[];
38
+ };
39
+ /** A caption's automatically determined kind. */
40
+ export const CAPTION_NAMES: Readonly<{
41
+ code: "Code";
42
+ table: "Table";
43
+ figure: "Figure";
44
+ prose: "Prose";
45
+ }>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Separate top-level footnote definitions from prose while retaining line numbers.
3
+ * Definitions belong to the note and can be used by any rendered page.
4
+ * @param {string} source - Authored Markdown.
5
+ * @returns {{markdown: string, definitions: string}} Body with blanked definitions and their source.
6
+ */
7
+ export function separateFootnotes(source: string): {
8
+ markdown: string;
9
+ definitions: string;
10
+ };
@@ -24,10 +24,17 @@ export function declaredPaths(artifact: object): Set<string>;
24
24
  * mappings" instead of "on a `weapongear`". Reading `on a \`the shared
25
25
  * mappings\`` would be the alternative, and a diagnostic is prose.
26
26
  *
27
- * @param {object} finding - `{system, systemVersion, noteType, source, target, shared}`.
27
+ * @param {{system: string, systemVersion: string, noteType: string, source: string, target: string, shared: boolean}} finding - The unresolved mapping.
28
28
  * @returns {string} The message.
29
29
  */
30
- export function undeclaredTargetMessage({ system, systemVersion, noteType, source, target, shared, }: object): string;
30
+ export function undeclaredTargetMessage({ system, systemVersion, noteType, source, target, shared, }: {
31
+ system: string;
32
+ systemVersion: string;
33
+ noteType: string;
34
+ source: string;
35
+ target: string;
36
+ shared: boolean;
37
+ }): string;
31
38
  /**
32
39
  * Check every `system.*` target the specification names.
33
40
  *
@@ -101,10 +108,16 @@ export function measureCorpus(notes: Iterable<object>, format: import("./content
101
108
  /**
102
109
  * What an author is told when the specification and the declaration disagree.
103
110
  *
104
- * @param {object} finding - `{noteType, source, target, name, to}`.
111
+ * @param {{noteType: string, source: string, target: string, name: string, to: string}} finding - The differing mapping.
105
112
  * @returns {string} The message.
106
113
  */
107
- export function fieldDriftMessage({ noteType, source, target, name, to }: object): string;
114
+ export function fieldDriftMessage({ noteType, source, target, name, to }: {
115
+ noteType: string;
116
+ source: string;
117
+ target: string;
118
+ name: string;
119
+ to: string;
120
+ }): string;
108
121
  /**
109
122
  * The declaration that compiles one mapping row, and what is left over.
110
123
  *