@heroiclands/package-build 22.26.0 → 22.27.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 (64) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +3 -1
  3. package/assets/styles/content-base.css +46 -3
  4. package/docs/api.md +33 -13
  5. package/docs/authoring/frontmatter.md +2 -2
  6. package/docs/authoring/links-and-markup.md +96 -149
  7. package/docs/content-format.md +5 -3
  8. package/docs/guides/government-migration.md +52 -0
  9. package/docs/guides/site.md +5 -5
  10. package/docs/reference/format-details.md +110 -219
  11. package/docs/reference/note-types.md +27 -29
  12. package/docs/reference/theme-pages.md +31 -29
  13. package/engine/anchors.mjs +85 -13
  14. package/engine/art-fields.mjs +1 -1
  15. package/engine/base-compiler.mjs +9 -1
  16. package/engine/bundles.mjs +1 -1
  17. package/engine/code-fences.mjs +6 -2
  18. package/engine/content-alerts.mjs +195 -0
  19. package/engine/content-blocks.mjs +119 -241
  20. package/engine/content-embeds.mjs +1 -1
  21. package/engine/content-figures.mjs +166 -230
  22. package/engine/content-format-check.mjs +3 -2
  23. package/engine/content-format.yaml +0 -5
  24. package/engine/content-images.mjs +3 -3
  25. package/engine/content-poetry.mjs +141 -0
  26. package/engine/content-spans.mjs +177 -0
  27. package/engine/foundry-entries.mjs +2 -0
  28. package/engine/frontmatter-lint.mjs +2 -1
  29. package/engine/heading-attributes.mjs +1 -1
  30. package/engine/helpers.mjs +8 -3
  31. package/engine/holdings.mjs +165 -273
  32. package/engine/index.mjs +1 -1
  33. package/engine/infobox.mjs +1 -1
  34. package/engine/journals.mjs +8 -6
  35. package/engine/markdown-expressions.mjs +9 -3
  36. package/engine/metadata-index.mjs +2 -3
  37. package/engine/note-vocabulary.mjs +16 -11
  38. package/engine/pdf-build.mjs +1 -1
  39. package/engine/pdf-render.mjs +90 -31
  40. package/engine/populations.mjs +17 -83
  41. package/engine/site-build.mjs +44 -16
  42. package/engine/site-preview.mjs +22 -6
  43. package/engine/wikilinks.mjs +18 -4
  44. package/hugo-theme/layouts/partials/holdings/entry.html +2 -2
  45. package/hugo-theme/layouts/partials/holdings.html +14 -14
  46. package/hugo-theme/static/css/style.css +40 -2
  47. package/package.json +1 -1
  48. package/sohl/item-fields.mjs +0 -16
  49. package/types/engine/anchors.d.mts +13 -4
  50. package/types/engine/art-fields.d.mts +1 -1
  51. package/types/engine/code-fences.d.mts +3 -1
  52. package/types/engine/content-alerts.d.mts +62 -0
  53. package/types/engine/content-blocks.d.mts +3 -10
  54. package/types/engine/content-embeds.d.mts +1 -1
  55. package/types/engine/content-figures.d.mts +13 -20
  56. package/types/engine/content-images.d.mts +1 -1
  57. package/types/engine/content-poetry.d.mts +32 -0
  58. package/types/engine/content-spans.d.mts +18 -0
  59. package/types/engine/holdings.d.mts +59 -105
  60. package/types/engine/markdown-expressions.d.mts +1 -1
  61. package/types/engine/note-vocabulary.d.mts +10 -2
  62. package/types/engine/populations.d.mts +4 -13
  63. package/types/engine/site-build.d.mts +3 -3
  64. package/types/engine/wikilinks.d.mts +5 -1
@@ -1,57 +1,50 @@
1
+ /** @typedef {{title:string,url?:string,type:string,subType?:string}} HoldingsEntry */
1
2
  /**
2
- * A `parents` or `domains` value as the shortcodes it names, in order,
3
- * empties dropped and repeats collapsed.
4
- *
5
- * @param {unknown} value - The authored value — a list, or a lone entry.
6
- * @returns {string[]} The shortcodes.
3
+ * @typedef {object} HoldingsNode
4
+ * @property {string} shortcode
5
+ * @property {"place"|"affiliation"} type
6
+ * @property {string} [subType]
7
+ * @property {string} title
8
+ * @property {string} [url]
9
+ * @property {string} [package] Owning content package.
10
+ * @property {string} [system] Own document system.
11
+ * @property {string} [canonical] Full own Address.
12
+ * @property {string} [governmentSystem] Affiliation reference default system.
13
+ * @property {unknown[]} parents
14
+ * @property {unknown} [government] Null is explicit anarchy; absence is omission.
15
+ */
16
+ /** @typedef {{contains?:HoldingsEntry[],governed_by?:HoldingsEntry[],governed_places?:HoldingsEntry[]}} Holdings */
17
+ /** Historical shortcode projection for callers that explicitly need one.
18
+ * @param {unknown} value
19
+ * @returns {string[]}
7
20
  */
8
21
  export function shortcodesOf(value: unknown): string[];
9
- /**
10
- * Read a local note into a node, or `null` for a note that takes no part.
11
- *
12
- * @param {object} fm - The note's frontmatter.
13
- * @param {object} page - The page it publishes as.
14
- * @param {string} page.title - Its published title.
15
- * @param {string} page.url - Its URL.
16
- * @returns {HoldingsNode|null} The node, or `null` for a note that is neither
17
- * a place nor an affiliation, or that declares no shortcode.
22
+ /** Read local facts without converting government omission into anarchy.
23
+ * @param {object} fm
24
+ * @param {{title:string,url?:string,package?:string,system?:string,governmentSystem?:string}} page
25
+ * @returns {HoldingsNode|null}
18
26
  */
19
- export function holdingsNode(fm: object, { title, url }: {
27
+ export function holdingsNode(fm: object, { title, url, package: pkg, system, governmentSystem }: {
20
28
  title: string;
21
- url: string;
29
+ url?: string;
30
+ package?: string;
31
+ system?: string;
32
+ governmentSystem?: string;
22
33
  }): HoldingsNode | null;
23
- /**
24
- * Read a fetched index's places and affiliations as nodes.
25
- *
26
- * An entry carries what the producer's record stated — its name, `subType`,
27
- * `parents` and `domains` — and its page URL where the package publishes one.
28
- *
29
- * @param {Map<string, object>|undefined} foreignIndex - As
30
- * {@link module:engine/metadata-index.loadForeignIndexes} returns it.
31
- * @returns {HoldingsNode[]} The nodes, in index order.
32
- */
34
+ /** @param {Map<string,object>|undefined} foreignIndex @returns {HoldingsNode[]} */
33
35
  export function foreignHoldingsNodes(foreignIndex: Map<string, object> | undefined): HoldingsNode[];
34
- /**
35
- * Invert `parents` and `domains` into each page's lists.
36
- *
37
- * A shortcode is declared once per type: the first node declaring it wins,
38
- * so local nodes handed in ahead of fetched ones shadow a dependency's, the
39
- * way the link resolver answers. A node with no URL carries no lists of its
40
- * own, since there is no page to write them on — and is still an entry on
41
- * everybody else's, rendered as plain text. A name no node declares is
42
- * dropped: a `parents` naming nowhere is the map's finding, a `domains`
43
- * naming nowhere the reference check's.
44
- *
45
- * The result holds only pages with at least one entry on at least one list,
46
- * and a page's block carries only the keys it has entries for — the theme's
47
- * silent-disappear convention, kept at the source.
48
- *
49
- * @param {Iterable<HoldingsNode|null>} nodes - Every place and affiliation,
50
- * local first. `parents` and `domains` are read as written, so a node
51
- * built by hand may carry them as the note spells them.
52
- * @returns {Map<string, Holdings>} URL → the page's lists, sorted.
36
+ /** Invert direct place facts. A stub remains a plain text entry; a stub's own
37
+ * absent page receives no lists. First declaration of a page Address wins;
38
+ * different document systems for one page normalize to its `note` identity.
39
+ * @param {Iterable<HoldingsNode|null>} nodes
40
+ * @param {object} [options]
41
+ * @param {Iterable<HoldingsNode|null>} [options.governmentNodes] Additional public
42
+ * records without pages, participating only in government relationships.
43
+ * @returns {Map<string,Holdings>}
53
44
  */
54
- export function holdingsPages(nodes: Iterable<HoldingsNode | null>): Map<string, Holdings>;
45
+ export function holdingsPages(nodes: Iterable<HoldingsNode | null>, { governmentNodes }?: {
46
+ governmentNodes?: Iterable<HoldingsNode | null> | undefined;
47
+ }): Map<string, Holdings>;
55
48
  /**
56
49
  * Advise when a place with an authored positive population omits government.
57
50
  * Missing, null or zero population establishes no inhabited population.
@@ -72,89 +65,50 @@ export function checkGovernment(note: object): object[];
72
65
  * @returns {object[]} Government advisory findings.
73
66
  */
74
67
  export function checkHeld(note: object, _opts?: object): object[];
75
- /**
76
- * The keys this module writes, and which a note cannot author: `contains`
77
- * and `held_by` on a place, `holdings` on an affiliation.
78
- *
68
+ /** Derived keys, including retired keys removed from generated pages.
79
69
  * @type {readonly string[]}
80
70
  */
81
71
  export const HOLDINGS_KEYS: readonly string[];
82
- /**
83
- * Legacy subtypes of the retired tenure advisory. Government advisories
84
- * apply to every place subtype when its authored population is positive.
85
- * @deprecated This list no longer gates any advisory.
86
- *
72
+ /** @deprecated Government advisories apply to every inhabited place subtype.
87
73
  * @type {readonly string[]}
88
74
  */
89
75
  export const HELD_SUBTYPES: readonly string[];
90
- /**
91
- * One entry of a holdings list — a page a reader is pointed at.
92
- */
93
76
  export type HoldingsEntry = {
94
- /**
95
- * The page's published title.
96
- */
97
77
  title: string;
98
- /**
99
- * `<base><slug>/` — the page's address as every
100
- * href this build renders composes it. **Absent
101
- * for a stub**, which has no page: an entry with no
102
- * `url` renders as plain text.
103
- */
104
- url?: string | undefined;
105
- /**
106
- * The note's `type` — `place` or `affiliation`.
107
- */
78
+ url?: string;
108
79
  type: string;
109
- /**
110
- * The note's `subType`, where it declares one.
111
- */
112
- subType?: string | undefined;
80
+ subType?: string;
113
81
  };
114
- /**
115
- * One place or affiliation, as the derivation reads it — a local page or a
116
- * fetched index entry through one shape.
117
- */
118
82
  export type HoldingsNode = {
119
- /**
120
- * Lower case.
121
- */
122
83
  shortcode: string;
123
84
  type: "place" | "affiliation";
124
85
  subType?: string | undefined;
125
- /**
126
- * The page's published title.
127
- */
128
86
  title: string;
129
- /**
130
- * The page's URL; absent where the package
131
- * publishes no page for it.
132
- */
133
87
  url?: string | undefined;
134
88
  /**
135
- * What a place sits within, as written.
89
+ * Owning content package.
136
90
  */
137
- parents: string[];
91
+ package?: string | undefined;
138
92
  /**
139
- * What an affiliation holds, as written.
93
+ * Own document system.
140
94
  */
141
- domains: string[];
142
- };
143
- /**
144
- * The lists one page carries. Every key is optional, and a key present holds
145
- * at least one entry.
146
- */
147
- export type Holdings = {
95
+ system?: string | undefined;
148
96
  /**
149
- * Places whose `parents` name this one.
97
+ * Full own Address.
150
98
  */
151
- contains?: HoldingsEntry[] | undefined;
99
+ canonical?: string | undefined;
152
100
  /**
153
- * Affiliations whose `domains` name this one.
101
+ * Affiliation reference default system.
154
102
  */
155
- held_by?: HoldingsEntry[] | undefined;
103
+ governmentSystem?: string | undefined;
104
+ parents: unknown[];
156
105
  /**
157
- * Places this affiliation's `domains` name.
106
+ * Null is explicit anarchy; absence is omission.
158
107
  */
159
- holdings?: HoldingsEntry[] | undefined;
108
+ government?: unknown;
109
+ };
110
+ export type Holdings = {
111
+ contains?: HoldingsEntry[];
112
+ governed_by?: HoldingsEntry[];
113
+ governed_places?: HoldingsEntry[];
160
114
  };
@@ -9,7 +9,7 @@ export function sqlQueriesInMarkdown(body: any, fm?: {}): any[];
9
9
  * {url: string|null, figures: Map<string, object>}|undefined,
10
10
  * link?: Function}, file?: string, bodyLine?: number}} [options] -
11
11
  * `figures` is the `ref` helper's own view of the corpus: `get` reads this
12
- * note's `:::figure` fences by id, and `note` resolves another note's the
12
+ * note's captioned items by id, and `note` resolves another note's the
13
13
  * way a wikilink would — omitted, a cross-note address is refused rather
14
14
  * than looked up. `link` overrides how a resolved reference renders; the
15
15
  * default is a Markdown link to the target's own anchor.
@@ -133,6 +133,15 @@ export function dataFields(type: string, vocabulary?: Readonly<Record<string, Ty
133
133
  * it has no `subType` at all — see {@link TypeVocabulary}.
134
134
  */
135
135
  export function subTypes(type: string, vocabulary?: Readonly<Record<string, TypeVocabulary>>): readonly string[] | null | undefined;
136
+ /**
137
+ * Accepted migration input with no canonical field or emitted value.
138
+ *
139
+ * Legacy affiliation domains are ignored. They never supply a government.
140
+ * @param {string} type - The note type.
141
+ * @param {string} key - An authored data key.
142
+ * @returns {boolean} Whether the obsolete key is accepted during migration.
143
+ */
144
+ export function isLegacyDataField(type: string, key: string): boolean;
136
145
  /**
137
146
  * One top-level frontmatter key.
138
147
  *
@@ -468,8 +477,7 @@ export type TypeVocabulary = {
468
477
  * - A
469
478
  * check of the whole note, run by the frontmatter lint beside the field
470
479
  * checks with the same index. For a rule that is about the note rather than
471
- * one of its fields — a place's tenure is a fact about every affiliation's
472
- * `domains`, and is located at the note's `type:` line.
480
+ * one of its fields, located at the note's `type:` line.
473
481
  */
474
482
  check?: ((note: object, opts: {
475
483
  index?: object;
@@ -16,7 +16,7 @@ export function foreignNode(canonical: string, entry: object): PopulationNode |
16
16
  * runs it with the index every reference check resolves through. Without an
17
17
  * index the questions cannot be asked and nothing is reported.
18
18
  *
19
- * Three rules, each reported on the note being linted: `over-held land` and
19
+ * Two geographical rules, each reported on the note being linted:
20
20
  * `over-full region` on the place whose figure is exceeded, and
21
21
  * `oversized settlement` on the settlement that exceeds one.
22
22
  *
@@ -35,8 +35,8 @@ export function checkPopulation(note: object, { index }?: {
35
35
  * restated figures drift. Each is located at the figure it wrote, counting
36
36
  * repeats so two rows carrying one number land on their own lines.
37
37
  *
38
- * A citation naming a note this package does not hold is skipped: a fetched
39
- * index carries no figure, so there is nothing to disagree with.
38
+ * A citation naming a note with no published population figure is skipped:
39
+ * there is nothing to disagree with.
40
40
  *
41
41
  * Declared as the `doc` vocabulary's type-level check.
42
42
  *
@@ -97,13 +97,9 @@ export type PopulationNode = {
97
97
  * superiors.
98
98
  */
99
99
  parents: string[];
100
- /**
101
- * What an affiliation holds.
102
- */
103
- domains: string[];
104
100
  };
105
101
  /**
106
- * The whole tree, indexed the three ways the rules read it.
102
+ * The whole tree, indexed by place, affiliation and geographical parent.
107
103
  */
108
104
  export type Corpus = {
109
105
  /**
@@ -119,11 +115,6 @@ export type Corpus = {
119
115
  * whose `parents` name it.
120
116
  */
121
117
  childrenOf: Map<string, string[]>;
122
- /**
123
- * Place shortcode → the polities
124
- * whose `domains` name it.
125
- */
126
- holdersOf: Map<string, string[]>;
127
118
  /**
128
119
  * `type/shortcode` → the
129
120
  * node, for the citation rule.
@@ -182,7 +182,7 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
182
182
  * about every other page, known only once the whole tree has resolved — see
183
183
  * {@link module:engine/related-pages} — so an authored value is dropped the
184
184
  * way `aliases` is, and {@link renderPages} writes the derived block once it
185
- * holds the graph. `contains`, `held_by` and `holdings` are dropped for the
185
+ * holds the graph. Derived geographical and government lists are dropped for the
186
186
  * same reason — see {@link module:engine/holdings}. **So is `map`**: the
187
187
  * file a place page names is the one the build drew beside it — see
188
188
  * {@link module:engine/site-maps} — and a page with no drawing names none.
@@ -258,8 +258,8 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
258
258
  secretErrors: {
259
259
  file: any;
260
260
  line: number;
261
- column: number;
262
- message: string;
261
+ column: any;
262
+ message: any;
263
263
  }[];
264
264
  captionErrors: {
265
265
  file: any;
@@ -18,7 +18,8 @@ export function anchorPageId(noteId: string, anchorSlug: string): string;
18
18
  *
19
19
  * @param {Array<{type: string, id: string, shortcode?: string|null,
20
20
  * name?: string, pack?: string, docPack?: string, none?: boolean,
21
- * draft?: boolean}>} docs -
21
+ * draft?: boolean, anchors?: Set<string>, anchorUuids?: Record<string,string>,
22
+ * docAnchorUuids?: Record<string,string>}>} docs -
22
23
  * One entry per content note. `pack` / `docPack` name the packs the note's
23
24
  * document and its documentation entry landed in; omitted, the conventional
24
25
  * one-pack-per-type names stand in. `none` says the note declares
@@ -54,6 +55,9 @@ export function buildWikilinkIndex(docs: Array<{
54
55
  docPack?: string;
55
56
  none?: boolean;
56
57
  draft?: boolean;
58
+ anchors?: Set<string>;
59
+ anchorUuids?: Record<string, string>;
60
+ docAnchorUuids?: Record<string, string>;
57
61
  }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets, noIndexPackages, referenceTargets, foreignReferences }?: {
58
62
  assets?: Map<string, object> | undefined;
59
63
  noIndexPackages?: Set<string> | undefined;