@heroiclands/package-build 25.5.4 → 25.6.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 (108) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +7 -0
  3. package/assets/styles/content-base.css +1 -1
  4. package/bin/content-commands.mjs +32 -8
  5. package/docs/api.md +81 -32
  6. package/docs/authoring/frontmatter.md +1 -1
  7. package/docs/authoring/links-and-markup.md +59 -10
  8. package/docs/commands.md +60 -17
  9. package/docs/configuration.md +3 -2
  10. package/docs/content-format.md +50 -1
  11. package/docs/diagnostics.md +17 -0
  12. package/docs/guides/module-project.md +11 -3
  13. package/docs/guides/reference-pages.md +4 -1
  14. package/docs/guides/site.md +13 -3
  15. package/docs/guides/writing-in-invented-scripts.md +5 -2
  16. package/docs/reference/format-details.md +233 -138
  17. package/docs/reference/note-types.md +165 -152
  18. package/docs/reference/theme-pages.md +1 -0
  19. package/e2e.mjs +1 -1
  20. package/engine/base-compiler.mjs +2 -0
  21. package/engine/compile-corpus.mjs +6 -2
  22. package/engine/content-charset.mjs +1 -1
  23. package/engine/content-format.yaml +9 -7
  24. package/engine/content-html.mjs +3 -2
  25. package/engine/content-index.mjs +23 -0
  26. package/engine/content-links.mjs +8 -0
  27. package/engine/content-render.mjs +14 -2
  28. package/engine/content-scripts.mjs +44 -6
  29. package/engine/content-session.mjs +11 -7
  30. package/engine/content-spans.mjs +3 -4
  31. package/engine/content-tables.mjs +12 -5
  32. package/engine/content-verse.mjs +52 -10
  33. package/engine/core-report.mjs +27 -18
  34. package/engine/culture-reach.mjs +3 -0
  35. package/engine/declared-sections.mjs +100 -0
  36. package/engine/derived-sections.mjs +36 -2
  37. package/engine/dictionary-rows.mjs +2 -1
  38. package/engine/generated-sections.mjs +2 -0
  39. package/engine/holdings.mjs +107 -3
  40. package/engine/index-records.mjs +3 -1
  41. package/engine/index.mjs +1 -1
  42. package/engine/language-data.mjs +0 -1
  43. package/engine/language-names.mjs +53 -23
  44. package/engine/language-rows.mjs +1 -3
  45. package/engine/language-terms.mjs +7 -10
  46. package/engine/map-dot.mjs +22 -0
  47. package/engine/markdown-blocks.mjs +23 -8
  48. package/engine/markdownlint-run.mjs +1 -1
  49. package/engine/markup-validation.mjs +2 -0
  50. package/engine/metadata-index.mjs +1 -0
  51. package/engine/note-addresses.mjs +16 -0
  52. package/engine/note-vocabulary.mjs +29 -13
  53. package/engine/npc-generate.mjs +52 -7
  54. package/engine/office-holders.mjs +76 -0
  55. package/engine/page-breaks.mjs +143 -0
  56. package/engine/pdf-build.mjs +12 -4
  57. package/engine/pdf-render.mjs +12 -2
  58. package/engine/place-kinds.mjs +106 -0
  59. package/engine/preview-index.mjs +4 -2
  60. package/engine/settlement-tables.mjs +410 -675
  61. package/engine/settlement-terms.mjs +118 -0
  62. package/engine/site-build.mjs +14 -7
  63. package/engine/site-preview.mjs +3 -0
  64. package/engine/site-render.mjs +18 -4
  65. package/engine/site-root.mjs +10 -1
  66. package/engine/site-serve-http.mjs +151 -0
  67. package/engine/site-serve.mjs +196 -126
  68. package/engine/sql-tables.mjs +101 -7
  69. package/engine/standing-terms.mjs +9 -5
  70. package/engine/standings.mjs +83 -31
  71. package/engine/unique-items.mjs +85 -0
  72. package/engine/verse-metre.mjs +50 -5
  73. package/engine/verse-regions.mjs +16 -0
  74. package/package.json +9 -4
  75. package/site-theme/data/banner-kinds.yaml +2 -0
  76. package/sohl/actors.mjs +4 -3
  77. package/types/e2e.d.mts +1 -1
  78. package/types/engine/content-html.d.mts +2 -1
  79. package/types/engine/content-scripts.d.mts +9 -1
  80. package/types/engine/content-verse.d.mts +11 -2
  81. package/types/engine/core-report.d.mts +6 -2
  82. package/types/engine/culture-reach.d.mts +3 -0
  83. package/types/engine/declared-sections.d.mts +30 -0
  84. package/types/engine/derived-sections.d.mts +5 -1
  85. package/types/engine/holdings.d.mts +34 -2
  86. package/types/engine/index-records.d.mts +2 -1
  87. package/types/engine/language-names.d.mts +18 -6
  88. package/types/engine/language-terms.d.mts +5 -1
  89. package/types/engine/markdown-blocks.d.mts +5 -1
  90. package/types/engine/npc-generate.d.mts +3 -0
  91. package/types/engine/office-holders.d.mts +33 -0
  92. package/types/engine/page-breaks.d.mts +38 -0
  93. package/types/engine/pdf-render.d.mts +2 -0
  94. package/types/engine/place-kinds.d.mts +18 -0
  95. package/types/engine/settlement-tables.d.mts +25 -158
  96. package/types/engine/settlement-terms.d.mts +53 -0
  97. package/types/engine/site-build.d.mts +3 -1
  98. package/types/engine/site-render.d.mts +6 -2
  99. package/types/engine/site-root.d.mts +3 -1
  100. package/types/engine/site-serve-http.d.mts +1 -0
  101. package/types/engine/site-serve.d.mts +12 -6
  102. package/types/engine/sql-tables.d.mts +35 -3
  103. package/types/engine/standing-terms.d.mts +3 -2
  104. package/types/engine/standings.d.mts +14 -2
  105. package/types/engine/unique-items.d.mts +12 -0
  106. package/types/engine/verse-metre.d.mts +2 -1
  107. package/types/engine/verse-regions.d.mts +8 -0
  108. package/vendor/markdownlint.mjs +855 -569
@@ -47,13 +47,45 @@ export function foreignHoldingsNodes(foreignIndex: Map<string, object> | undefin
47
47
  export function holdingsPages(nodes: Iterable<HoldingsNode | null>, { governmentNodes }?: {
48
48
  governmentNodes?: Iterable<HoldingsNode | null> | undefined;
49
49
  }): Map<string, Holdings>;
50
+ /**
51
+ * Whether a record's `data.government` came from a parent rather than its own
52
+ * note.
53
+ *
54
+ * @param {object} record - An index record.
55
+ * @returns {boolean} True for a district that inherited its government.
56
+ */
57
+ export function governmentInherited(record: object): boolean;
58
+ /**
59
+ * Give each district that states no government its parent's.
60
+ *
61
+ * A `place/district` falls under the government of the place it stands
62
+ * within. One stating no `data.government` key takes the value of its nearest
63
+ * parent that states the key, walking `data.parents` breadth first, in the
64
+ * order written, through any parent that states none, and never visiting a
65
+ * place twice. An explicit value on the district, `null` (complete anarchy)
66
+ * included, is its own and is kept; a parent's explicit `null` is inherited as
67
+ * anarchy. Every reader of the index — the Governed by and Governed places
68
+ * sections, the "missing government" advisory, a consumer of the published
69
+ * index — then reads the effective government at `data.government`.
70
+ *
71
+ * @param {object[]} records - Content-index records, edited in place.
72
+ * @param {object} [opts]
73
+ * @param {(key: string) => object|undefined} [opts.foreignRecord] - A fetched
74
+ * index's record by canonical Address, for a parent in a dependency.
75
+ * @returns {void}
76
+ */
77
+ export function inheritDistrictGovernments(records: object[], { foreignRecord }?: {
78
+ foreignRecord?: ((key: string) => object | undefined) | undefined;
79
+ }): void;
50
80
  /**
51
81
  * Advise when a place with an authored positive population omits government.
52
82
  * Missing, null or zero population establishes no inhabited population.
53
83
  * Property presence distinguishes omitted government from explicit null,
54
84
  * which means complete anarchy. Non-null values are validated by the declared
55
- * affiliation reference field. Neither geographic containment nor tenure
56
- * supplies this fact, and the rule is independent of place subtype.
85
+ * affiliation reference field. Tenure never supplies this fact, and
86
+ * containment supplies it only to a district, which the content index gives
87
+ * its nearest parent's government (see {@link inheritDistrictGovernments}), so
88
+ * a district under a governed place is never advised.
57
89
  *
58
90
  * @param {object} note - The note with parsed frontmatter and raw source.
59
91
  * @returns {object[]} Located warning findings.
@@ -122,7 +122,8 @@ export function recordPath(record: Record<string, any>): string;
122
122
  * since a note declaring its own is a hard error — and it matches what
123
123
  * the content-table expander puts on the same field, so a query reads the same
124
124
  * value from either. `file` namespaces the note's place in the tree, again
125
- * matching the expander's `file.*`.
125
+ * matching the expander's `file.*`. `officeHolders` lists, on a body, the
126
+ * living beings whose own standing names each of its offices.
126
127
  *
127
128
  * Both are checked rather than assumed: `folder` is real frontmatter on most
128
129
  * notes, so the neighbouring names are close enough to a real key that a silent
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The genders every `data.names.given` states a list for.
2
+ * The genders a mapped `data.names.given` states a list for.
3
3
  *
4
4
  * A function rather than a `const`: `note-vocabulary.mjs` reads it while the
5
5
  * module graph is still evaluating.
@@ -47,7 +47,7 @@ export function namesProblems(names: unknown, lookVocabulary: Readonly<Record<st
47
47
  * keys cannot: a pattern that does not parse, a placeholder naming no list, a
48
48
  * list no pattern names, a list name a placeholder cannot spell, an empty list
49
49
  * of patterns or of names, an empty name, a pattern or given list keyed by no
50
- * gender, and a missing `female` or `male` list. Each is located at the pattern, list, entry or key at fault.
50
+ * gender, and a missing `female` or `male` list in a gender map. Each is located at the pattern, list, entry or key at fault.
51
51
  *
52
52
  * @param {object} note - The note: `file`, `raw` and parsed `fm`.
53
53
  * @param {Readonly<Record<string, readonly {value: string}[]>>} lookVocabulary -
@@ -70,8 +70,8 @@ export function namesFindings(note: object, lookVocabulary: Readonly<Record<stri
70
70
  value: string;
71
71
  }[]>>): object[];
72
72
  /**
73
- * The given names a gender draws from: its own list, or every given list
74
- * together where it has none.
73
+ * The given names a gender draws from: the shared list, its own list, or
74
+ * every given list together where it has none.
75
75
  *
76
76
  * @param {object} names - Checked `data.names`.
77
77
  * @param {string} gender - A gender word.
@@ -79,8 +79,20 @@ export function namesFindings(note: object, lookVocabulary: Readonly<Record<stri
79
79
  */
80
80
  export function givenNames(names: object, gender: string): string[];
81
81
  /**
82
- * A name drawn from a language's lists: one of the gender's patterns, where it
83
- * has more than one, then each placeholder an even draw from its list.
82
+ * A name's selected literal and placeholder parts. One of the gender's
83
+ * patterns is selected first, then each placeholder is an even draw from its
84
+ * source list.
85
+ *
86
+ * @param {object} names - Checked `data.names`.
87
+ * @param {string} gender - A gender word.
88
+ * @param {() => number} next - A stream of numbers in `[0, 1)`.
89
+ * @returns {(PatternPart & {text: string})[]} The selected parts in pattern order.
90
+ */
91
+ export function drawNameParts(names: object, gender: string, next: () => number): (PatternPart & {
92
+ text: string;
93
+ })[];
94
+ /**
95
+ * A name drawn from a language's lists.
84
96
  *
85
97
  * @param {object} names - Checked `data.names`.
86
98
  * @param {string} gender - A gender word.
@@ -94,7 +94,11 @@ export const JOIN_MEETINGS: readonly string[];
94
94
  * letters between, `drop` loses the first, `double` doubles the consonant.
95
95
  */
96
96
  export const JOIN_RULES: readonly string[];
97
- /** What a written mark says of its letter. */
97
+ /**
98
+ * What a written mark says of its letter: `stress` falls on it, `length` holds
99
+ * it longer, `apart` says it apart from its neighbour, and `quality` changes
100
+ * which vowel is said.
101
+ */
98
102
  export const MARK_KINDS: readonly string[];
99
103
  /** How many of a mark a word may carry: `one` at most, or `any` number. */
100
104
  export const MARK_LIMITS: readonly string[];
@@ -3,6 +3,10 @@
3
3
  * and must not be modified; an `inline` token carries no `children`.
4
4
  *
5
5
  * @param {unknown} source - Markdown.
6
+ * @param {object} [options] - Optional block projection.
7
+ * @param {boolean} [options.footnotes=false] - Include footnote definition containers.
6
8
  * @returns {readonly import("markdown-it").Token[]} The block tokens, in order.
7
9
  */
8
- export function blockTokens(source: unknown): readonly import("markdown-it").Token[];
10
+ export function blockTokens(source: unknown, { footnotes }?: {
11
+ footnotes?: boolean | undefined;
12
+ }): readonly import("markdown-it").Token[];
@@ -57,6 +57,8 @@ export function appearanceParagraph({ name, age, gender, height, frame, appearan
57
57
  * by `namesProblems`.
58
58
  * @param {string} [context.language] - The language's Address, for an error
59
59
  * about a name that does not fit.
60
+ * @param {string} [context.languageCode] - The language code under which a
61
+ * generated name's distinct source form is retained.
60
62
  * @param {string} [context.seed] - Text joined to the spec's own seed, to draw a
61
63
  * different person from the same spec.
62
64
  * @param {unknown} [context.currentDate] - The setting's neutral current date, defaulting to "720.1".
@@ -74,6 +76,7 @@ export function generateNpc(spec: object, context: {
74
76
  profile: object;
75
77
  names: object;
76
78
  language?: string | undefined;
79
+ languageCode?: string | undefined;
77
80
  seed?: string | undefined;
78
81
  currentDate?: unknown;
79
82
  dateContext?: object | undefined;
@@ -1,3 +1,36 @@
1
+ /**
2
+ * A note's identity across its systems: `package-type-shortcode`, lowercased.
3
+ *
4
+ * A body's Item and its journal carry one page, and a being names the body by
5
+ * its `note` Address, so the system is left out.
6
+ *
7
+ * @param {{package?: string, type?: string, shortcode?: string}} tuple
8
+ * @returns {string} The key, or `""` where a part is missing.
9
+ */
10
+ export function officeBodyKey(tuple: {
11
+ package?: string;
12
+ type?: string;
13
+ shortcode?: string;
14
+ }): string;
15
+ /**
16
+ * Each body's offices with the living beings that hold them.
17
+ *
18
+ * Nothing is authored on the office for this: a being states the post it holds
19
+ * in its own `data.affiliations.<body>.office`, and this collects, for every
20
+ * office in a body's `governance.offices`, each being naming it. A being whose
21
+ * `data.died` is set holds nothing, so a former holder drops out and a vacant
22
+ * office lists no one. A post the body does not declare is the standing check's
23
+ * finding and is listed nowhere.
24
+ *
25
+ * Offices keep the body's declared order; holders are ordered by name.
26
+ *
27
+ * @param {object[]} records - Content-index records; only note records are
28
+ * read.
29
+ * @returns {Map<string, Map<string, object[]>>} Body identity
30
+ * (`package-type-shortcode`) → office → the holding beings' records, for every
31
+ * body with at least one held office.
32
+ */
33
+ export function officeHolders(records: object[]): Map<string, Map<string, object[]>>;
1
34
  /**
2
35
  * Validate one affiliation's office roster against dated beings in the corpus.
3
36
  * @param {object} note
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Read page-break markers before any surface rewrites their source.
3
+ * Code, HTML examples and entire verse divs remain literal. Parser ranges
4
+ * retain list and quote membership, including lazy continuation lines.
5
+ * @param {string} source - Authored Markdown body.
6
+ * @returns {{breaks: Array<{line: number, column: number}>, errors: Array<{line: number, column: number, message: string}>}}
7
+ */
8
+ export function scanPageBreaks(source: string): {
9
+ breaks: Array<{
10
+ line: number;
11
+ column: number;
12
+ }>;
13
+ errors: Array<{
14
+ line: number;
15
+ column: number;
16
+ message: string;
17
+ }>;
18
+ };
19
+ /**
20
+ * Omit valid page breaks on a screen, preserving the surrounding block boundaries.
21
+ * @param {string} source - Markdown body.
22
+ * @returns {string} Markdown without valid page-break lines.
23
+ */
24
+ export function omitPageBreaks(source: string): string;
25
+ /**
26
+ * Preserve refused markers as literal Markdown before the book slices blocks.
27
+ * A slice must not make a marker eligible by discarding its original neighbour.
28
+ * Findings are collected from the original source before this rewrite.
29
+ * @param {string} source - Complete Markdown body, before splitting containers.
30
+ * @returns {string} Markdown with invalid markers escaped for literal rendering.
31
+ */
32
+ export function escapeInvalidPageBreaks(source: string): string;
33
+ /**
34
+ * Produce the book's page-break token, leaving ordinary thematic breaks alone.
35
+ * @param {import("markdown-it")} md - The book parser.
36
+ * @returns {void}
37
+ */
38
+ export function pageBreakPlugin(md: typeof import("markdown-it")): void;
@@ -98,6 +98,7 @@ export function stripHtmlComments(markdown: string): string;
98
98
  * @param {Array<{line: number, generated: boolean}>} [opts.lineMap] - From
99
99
  * table expansion, mapping each line handed in back to the line an author
100
100
  * wrote.
101
+ * @param {boolean} [opts.pageBreaks] - Internal: whether this slice remains at the note top level.
101
102
  * @param {boolean} [opts.prepared] - Whether this body has been through the
102
103
  * passes that resolve a wikilink, an embed and an inline expression. A note's
103
104
  * has; a front-matter file's and a prose file's have not, and markup of theirs
@@ -138,6 +139,7 @@ export function markdownToTypst(markdown: string, opts?: {
138
139
  line: number;
139
140
  generated: boolean;
140
141
  }[] | undefined;
142
+ pageBreaks?: boolean | undefined;
141
143
  prepared?: boolean | undefined;
142
144
  url?: string | undefined;
143
145
  elsewhere?: {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Check a district's parent and a route's journeys.
3
+ *
4
+ * A district naming no parent is reported at its `subType`; one whose parents
5
+ * all resolve and none is a settlement or a region is reported at `parents`.
6
+ * A parent that does not resolve is the Address check's finding, so a district
7
+ * whose only parents are unresolved earns nothing more here. A route stating no
8
+ * `data.routes` entry is reported at its `subType`.
9
+ *
10
+ * @param {object} note - The note: `file`, `raw` and parsed `fm`.
11
+ * @param {{index?: object}} [options] - The lint's options.
12
+ * @returns {object[]} Located findings.
13
+ */
14
+ export function checkPlaceKind(note: object, { index }?: {
15
+ index?: object;
16
+ }): object[];
17
+ /** The place kinds a district may stand within. */
18
+ export const DISTRICT_PARENT_KINDS: readonly string[];
@@ -1,164 +1,31 @@
1
1
  /**
2
- * Every settlements table in a note, read from the raw file so each line
3
- * number is the file's own.
4
- *
5
- * @param {string} raw - The whole note, frontmatter included.
6
- * @returns {{heading: number, tables: SettlementTable[]}} The `## Settlements`
7
- * heading's line, 0 when there is none, and its tables.
8
- */
9
- export function findSettlementTables(raw: string): {
10
- heading: number;
11
- tables: SettlementTable[];
12
- };
13
- /**
14
- * Check a place note's settlements tables.
15
- *
16
- * Declared as part of the `place` vocabulary's whole-note check, so the lint
17
- * runs it with the index every reference resolves through. Without an index
18
- * nothing is reported.
19
- *
20
- * @param {object} note - The note, as the link index hands it over.
21
- * @param {object} [opts]
22
- * @param {object} [opts.index] - The link index, holding the whole corpus.
23
- * @returns {object[]} Findings.
2
+ * Check indexed rows, locating each finding in its original YAML.
3
+ * @param {object} note - Indexed note and original locator text.
4
+ * @param {object} [opts] - Captured context.
5
+ * @param {object} [opts.index] - Complete local and dependency reference index.
6
+ * @returns {object[]} Located findings.
24
7
  */
25
8
  export function checkSettlementTables(note: object, { index }?: {
26
9
  index?: object | undefined;
27
10
  }): object[];
28
- /** The heading text a settlements table stands under, at level two. */
29
- export const SETTLEMENTS_HEADING: "Settlements";
30
- /**
31
- * How a region's countryside is held, each the tag a region carries to say so.
32
- *
33
- * `holder` is what the `Held by` cell names under that model. `person` says
34
- * whether that holder may be a person: only where land is held by a person or
35
- * a house may the cell link a `being`.
36
- *
37
- * **The tags stay open.** They are not a declared tag group: a group would
38
- * report every tag within a typo's distance of one — a region tagged `hellad`
39
- * reads as a near miss of `held` — and a misspelled model on a note with a
40
- * table is already reported, because the note then names no model at all.
41
- *
42
- * @type {ReadonlyArray<Readonly<{tag: string, holder: string, person: boolean}>>}
43
- */
44
- export const HOLDING_MODELS: ReadonlyArray<Readonly<{
45
- tag: string;
46
- holder: string;
47
- person: boolean;
48
- }>>;
49
- /**
50
- * The table's columns, in the order the header states them. An optional
51
- * column may be left out; the header carries no other column, and keeps this
52
- * order.
53
- *
54
- * @type {ReadonlyArray<Readonly<{name: string, required: boolean}>>}
55
- */
56
- export const SETTLEMENT_COLUMNS: ReadonlyArray<Readonly<{
57
- name: string;
58
- required: boolean;
59
- }>>;
60
- /**
61
- * The rules this module enforces, each `name` the prefix its findings carry.
62
- *
63
- * @type {ReadonlyArray<Readonly<{name: string, describe: string}>>}
64
- */
65
- export const SETTLEMENT_TABLE_RULES: ReadonlyArray<Readonly<{
66
- name: string;
67
- describe: string;
68
- }>>;
69
11
  /**
70
- * One cell, as authored.
71
- */
72
- export type Cell = {
73
- /**
74
- * - The cell, trimmed.
75
- */
76
- text: string;
77
- /**
78
- * - The 1-based column its text starts at.
79
- */
80
- column: number;
81
- };
82
- /**
83
- * One settlements table.
84
- */
85
- export type SettlementTable = {
86
- /**
87
- * - The 1-based line of its header.
88
- */
89
- line: number;
90
- /**
91
- * - The header cells.
92
- */
93
- header: string[];
94
- /**
95
- * - Whether the header is the declared columns.
96
- */
97
- wellFormed: boolean;
98
- /**
99
- * - Each
100
- * row's cells keyed by column name; empty when the header is not well formed.
101
- */
102
- rows: Array<{
103
- line: number;
104
- cells: Record<string, Cell>;
105
- }>;
106
- /**
107
- * - The 1-based line of its last row.
108
- */
109
- last: number;
110
- /**
111
- * - Whether prose follows it before the next heading.
112
- */
113
- tailed: boolean;
114
- };
115
- /**
116
- * One place note, as the rules read it.
117
- */
118
- export type PlaceNode = {
119
- /**
120
- * - The note.
121
- */
122
- note: object;
123
- /**
124
- * - Lower case.
125
- */
126
- shortcode: string;
127
- subType: string;
128
- title: string;
129
- /**
130
- * - Its name and listed forms, lower case.
131
- */
132
- names: Set<string>;
133
- /**
134
- * - Enclosing places' shortcodes.
135
- */
136
- parents: string[];
137
- section: {
138
- heading: number;
139
- tables: SettlementTable[];
140
- };
141
- };
142
- /**
143
- * Everything the rules ask of the whole tree.
144
- */
145
- export type Corpus = {
146
- /**
147
- * - By shortcode.
148
- */
149
- places: Map<string, PlaceNode>;
150
- /**
151
- * - By note.
152
- */
153
- byNote: Map<object, PlaceNode>;
154
- /**
155
- * - Region shortcode → the
156
- * settlement notes its table covers.
157
- */
158
- covers: Map<string, PlaceNode[]>;
159
- /**
160
- * - Settlement note → the region
161
- * notes whose tables link it, in path order.
162
- */
163
- rowedIn: Map<object, object[]>;
164
- };
12
+ * Fail every publishing surface before it writes invalid settlement output.
13
+ * @param {object[]} records - Indexed records, including documentation projections.
14
+ * @param {object} opts - Captured context.
15
+ * @param {(record: object) => string} opts.fileOf - Source filename for a record.
16
+ * @param {Map<string,object>} [opts.foreignIndex] - Dependency reference targets.
17
+ * @param {(file: string) => string|undefined} [opts.rawOf] - Captured locator text.
18
+ * @returns {void}
19
+ */
20
+ export function assertSettlementRecords(records: object[], { fileOf, foreignIndex, rawOf }?: {
21
+ fileOf: (record: object) => string;
22
+ foreignIndex?: Map<string, object> | undefined;
23
+ rawOf?: ((file: string) => string | undefined) | undefined;
24
+ }): void;
25
+ /**
26
+ * Render rows once as shared Markdown; all surfaces consume the same table.
27
+ * @param {object} record - Indexed region.
28
+ * @returns {string} Generated table and its closing sentence.
29
+ */
30
+ export function settlementMarkdown(record: object): string;
31
+ export { SETTLEMENTS_HEADING, SETTLEMENT_COLUMNS, SETTLEMENT_ROW_FIELDS, SETTLEMENTS_FIELD, SETTLEMENT_TABLE_RULES } from "./settlement-terms.mjs";
@@ -0,0 +1,53 @@
1
+ /** Dependency-free settlement row declarations. @module */
2
+ /** The generated heading. */
3
+ export const SETTLEMENTS_HEADING: "Settlements";
4
+ /** Rendered columns, in their fixed order; Held by and For appear when a row states them. */
5
+ export const SETTLEMENT_COLUMNS: readonly (Readonly<{
6
+ name: "Name";
7
+ required: true;
8
+ }> | Readonly<{
9
+ name: "Market";
10
+ required: true;
11
+ }> | Readonly<{
12
+ name: "People";
13
+ required: true;
14
+ }> | Readonly<{
15
+ name: "Held by";
16
+ required: false;
17
+ }> | Readonly<{
18
+ name: "For";
19
+ required: false;
20
+ }>)[];
21
+ /** The closed row fields; existing subjects use native Addresses. */
22
+ export const SETTLEMENT_ROW_FIELDS: readonly Readonly<unknown>[];
23
+ /** The place vocabulary's single settlement declaration. */
24
+ export const SETTLEMENTS_FIELD: Readonly<{
25
+ name: "settlements";
26
+ kind: "map";
27
+ shape: "{ rows, tail }";
28
+ fields: readonly ({
29
+ name: string;
30
+ kind: string;
31
+ required: boolean;
32
+ shape: string;
33
+ entries: {
34
+ kind: string;
35
+ shape: string;
36
+ fields: readonly Readonly<unknown>[];
37
+ };
38
+ describe: string;
39
+ } | {
40
+ name: string;
41
+ kind: string;
42
+ required: boolean;
43
+ shape: string;
44
+ describe: string;
45
+ entries?: undefined;
46
+ })[];
47
+ describe: "A region's settlement rows and the sentence stating what they leave out; the table is generated from this declaration.";
48
+ }>;
49
+ /** Every semantic finding, named once for the reference and its guards. */
50
+ export const SETTLEMENT_TABLE_RULES: readonly Readonly<{
51
+ name: string;
52
+ describe: string;
53
+ }>[];
@@ -306,6 +306,7 @@ export function sitePageDecorator(config: any, index: any): (data: any, page: an
306
306
  * @param {object} [options] - Options.
307
307
  * @param {object} [options.config] - A resolved configuration; loaded when
308
308
  * omitted.
309
+ * @param {(message: string) => void} [options.progress] - Build phase summaries.
309
310
  * @param {Map<string, object[]>} [options.sqlTables] - Prepared `sql` results,
310
311
  * keyed by the note's absolute file, from
311
312
  * {@link module:engine/sql-tables.prepareSqlTables}. A page authoring an
@@ -322,8 +323,9 @@ export function sitePageDecorator(config: any, index: any): (data: any, page: an
322
323
  * against the rest of the build, or returns `null` when its address, name
323
324
  * or type changed and the whole site must be built again.
324
325
  */
325
- export function buildSite({ config, sqlTables }?: {
326
+ export function buildSite({ config, sqlTables, progress }?: {
326
327
  config?: object | undefined;
328
+ progress?: ((message: string) => void) | undefined;
327
329
  sqlTables?: Map<string, object[]> | undefined;
328
330
  }): {
329
331
  gates: object;
@@ -50,19 +50,21 @@ export function writeThemeFiles(out: string, staticDir?: string): string[];
50
50
  * @param {string} [options.staticDir] - The theme's own files, copied first.
51
51
  * @param {ReadonlySet<string>} [options.only] - The addresses of the pages to
52
52
  * draw again into a site already written. Nothing else is touched.
53
+ * @param {(message: string) => void} [options.progress] - Build phase summaries.
53
54
  * @returns {{files: string[], pages: string[], reachable: string[],
54
55
  * findings: object[]}} Every file written, the address of every page, the
55
56
  * address of each page reachable from the homepage, and the layouts' findings.
56
57
  * @throws {Error} When a page's address is outside the site, or a site served
57
58
  * under a path asks for a sitemap index.
58
59
  */
59
- export function writeSite({ site, pages, out, report, staticDir, only }: {
60
+ export function writeSite({ site, pages, out, report, staticDir, only, progress, }: {
60
61
  site: object;
61
62
  pages: readonly object[];
62
63
  out: string;
63
64
  report?: ((finding: import("./site-theme.mjs").Finding) => void) | undefined;
64
65
  staticDir?: string | undefined;
65
66
  only?: ReadonlySet<string> | undefined;
67
+ progress?: ((message: string) => void) | undefined;
66
68
  }): {
67
69
  files: string[];
68
70
  pages: string[];
@@ -147,6 +149,7 @@ export function deliverSiteFonts(config: object, out: string): {
147
149
  * @param {string} options.out - The directory the site is written to, which
148
150
  * is the package's own directory under the deployed root.
149
151
  * @param {number} [options.year] - The year the footer states.
152
+ * @param {(message: string) => void} [options.progress] - Build phase summaries.
150
153
  * @returns {Promise<{built: object, written: object|null, fonts: object|null,
151
154
  * site?: object, pages?: object[], pageOf?: (entry: object) => object}>}
152
155
  * What the build found, and, when it found nothing that stops it, what was
@@ -154,10 +157,11 @@ export function deliverSiteFonts(config: object, out: string): {
154
157
  * becomes its page. `written` is `null` when a gate fired.
155
158
  * @throws {Error} When the site's settings or its cached menu cannot be read.
156
159
  */
157
- export function buildPackageSite({ config, out, year }: {
160
+ export function buildPackageSite({ config, out, year, progress }: {
158
161
  config: object;
159
162
  out: string;
160
163
  year?: number | undefined;
164
+ progress?: ((message: string) => void) | undefined;
161
165
  }): Promise<{
162
166
  built: object;
163
167
  written: object | null;
@@ -73,6 +73,7 @@ export function indexSite(where: {
73
73
  * `site.search` in the configuration. Default `true`.
74
74
  * @param {SiteIndexer} [options.indexer] - What builds it. Default
75
75
  * {@link indexSite}.
76
+ * @param {(message: string) => void} [options.progress] - Build phase summaries.
76
77
  * @returns {Promise<{files: string[], search: {dir: string, pages: number}|null}>}
77
78
  * The files written, and the index — where it is and how many pages it
78
79
  * holds — or `null` when none was built.
@@ -81,12 +82,13 @@ export function indexSite(where: {
81
82
  * under the prefix; or, located at the rendered site, when the indexer
82
83
  * fails.
83
84
  */
84
- export function writeSiteRoot({ pkg, base, out, search, indexer }: {
85
+ export function writeSiteRoot({ pkg, base, out, search, indexer, progress, }: {
85
86
  pkg: string;
86
87
  base?: string | undefined;
87
88
  out: string;
88
89
  search?: boolean | undefined;
89
90
  indexer?: SiteIndexer | undefined;
91
+ progress?: ((message: string) => void) | undefined;
90
92
  }): Promise<{
91
93
  files: string[];
92
94
  search: {
@@ -0,0 +1 @@
1
+ export {};
@@ -9,16 +9,19 @@
9
9
  * directory above `out` by default; `out` itself for a site served at `/`.
10
10
  * @param {string} [options.host] - The address to listen on.
11
11
  * @param {number} [options.port] - The port; `0` takes any free one.
12
- * @param {boolean} [options.search] - Build the search index after the first
12
+ * @param {boolean} [options.search] - Build the search index with each whole
13
13
  * build, where the site has one.
14
14
  * @param {number} [options.year] - The year the footer states.
15
- * @param {(event: {kind: string, built?: object, files?: string[], findings?: object[], error?: unknown}) => void} [options.report] -
16
- * Told of each build: `built` for a whole build, `page` for one note's page,
15
+ * @param {(event: {kind: string, built?: object, files?: string[], findings?: object[], error?: unknown, message?: string, fatal?: boolean}) => void} [options.report] -
16
+ * Told of progress (`message`) and each build: `built` for a whole build, `page` for one note's page,
17
17
  * `theme` for the theme, `failed` with what the build found, `error` with
18
18
  * what it threw.
19
- * @returns {Promise<{url: string, close: () => Promise<void>, settled: () => Promise<void>}>}
20
- * The address of the site's home page, how to stop serving, and a promise
21
- * for the moment every change seen so far has been written.
19
+ * @returns {Promise<{url: string, close: () => Promise<void>, settled: () => Promise<void>, done: Promise<void>}>}
20
+ * Resolves as soon as HTTP listens, before the first build. The address of
21
+ * the site's home page, how to stop serving, and a promise for the initial
22
+ * build and every change seen so far to finish. Failed builds are reported
23
+ * through `report` and leave the last successful site in service. `done`
24
+ * resolves on close and rejects if HTTP stops unexpectedly.
22
25
  */
23
26
  export function serveSite({ config, out, root, host, port, search, year, report, }: {
24
27
  config: object;
@@ -34,11 +37,14 @@ export function serveSite({ config, out, root, host, port, search, year, report,
34
37
  files?: string[];
35
38
  findings?: object[];
36
39
  error?: unknown;
40
+ message?: string;
41
+ fatal?: boolean;
37
42
  }) => void) | undefined;
38
43
  }): Promise<{
39
44
  url: string;
40
45
  close: () => Promise<void>;
41
46
  settled: () => Promise<void>;
47
+ done: Promise<void>;
42
48
  }>;
43
49
  /** The address a served page listens on for the server's reloads. */
44
50
  export const RELOAD_PATH: "/__package-build/reload";