@heroiclands/package-build 23.2.1 → 23.3.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.
@@ -15,7 +15,7 @@
15
15
  enough — the system deliberately uses no Pro-only icons — and the
16
16
  game-icons webfont is subset to just the glyphs the docs reference
17
17
  (~3 KB), generated by the SoHL repo. */}}
18
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
18
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.1/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
19
19
  <link rel="stylesheet" href="{{ "css/sohl-icons.css" | relURL }}">
20
20
  </head>
21
21
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heroiclands/package-build",
3
- "version": "23.2.1",
3
+ "version": "23.3.0",
4
4
  "description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",
package/types/e2e.d.mts CHANGED
@@ -208,15 +208,19 @@ export function deployForContainer({ config, env, log, runScript, }: {
208
208
  * @param {string} opts.url - The container's base URL.
209
209
  * @param {string} opts.container - The container name, for its log.
210
210
  * @param {string} opts.stage - The stage, named in a licence failure.
211
+ * @param {string} [opts.dataRoot] - The stage's data root, named when its licence is unsigned.
212
+ * @param {(container: string) => string} [opts.readLog] - Reads the container's log since it started.
211
213
  * @param {number} [opts.timeoutMs] - How long to wait.
212
214
  * @param {(message: string) => void} [opts.log] - Progress reporting.
213
215
  * @returns {Promise<void>} Resolves once the world is active.
214
216
  * @throws {Error} On a licence failure or a timeout.
215
217
  */
216
- export function waitForWorld({ url, container, stage, timeoutMs, log }: {
218
+ export function waitForWorld({ url, container, stage, dataRoot, readLog, timeoutMs, log, }: {
217
219
  url: string;
218
220
  container: string;
219
221
  stage: string;
222
+ dataRoot?: string | undefined;
223
+ readLog?: ((container: string) => string) | undefined;
220
224
  timeoutMs?: number | undefined;
221
225
  log?: ((message: string) => void) | undefined;
222
226
  }): Promise<void>;
@@ -22,6 +22,7 @@ export * as placeRelations from "./place-relations.mjs";
22
22
  export * as holdings from "./holdings.mjs";
23
23
  export * as populations from "./populations.mjs";
24
24
  export * as marketClass from "./market-class.mjs";
25
+ export * as settlementTables from "./settlement-tables.mjs";
25
26
  export * as mapPlaces from "./map-places.mjs";
26
27
  export * as mapLayout from "./map-layout.mjs";
27
28
  export * as mapDot from "./map-dot.mjs";
@@ -50,7 +50,7 @@ export function hasValue(value: unknown): boolean;
50
50
  */
51
51
  export function humanizeFieldName(name: string): string;
52
52
  /**
53
- * An enumerated value as a reader sees it: `graying_brown` → `graying brown`.
53
+ * An enumerated value as a reader sees it: `greying_brown` → `greying brown`.
54
54
  *
55
55
  * @param {unknown} value - The authored value.
56
56
  * @returns {string} The text.
@@ -130,6 +130,19 @@ export function dataFields(type: string, vocabulary?: Readonly<Record<string, Ty
130
130
  * it has no `subType` at all — see {@link TypeVocabulary}.
131
131
  */
132
132
  export function subTypes(type: string, vocabulary?: Readonly<Record<string, TypeVocabulary>>): readonly string[] | null | undefined;
133
+ /**
134
+ * The words a being's look is stated in, keyed by the `data:` field that takes
135
+ * them.
136
+ *
137
+ * Each field is closed to its list: any other value, an empty one included, is
138
+ * a finding at the value naming the words it takes. `appearance.complexion`
139
+ * takes one word or a list of them, and each entry is checked on its own.
140
+ * `appearance.extra_features` is not here: it is free text, a list of the marks
141
+ * no word covers.
142
+ *
143
+ * @type {Readonly<Record<string, readonly LookWord[]>>}
144
+ */
145
+ export const BEING_LOOK_VOCABULARY: Readonly<Record<string, readonly LookWord[]>>;
133
146
  /**
134
147
  * What happened to or at a subject — the `events` key, declared once and spread
135
148
  * into every type that carries events, so the schema cannot differ between
@@ -333,6 +346,24 @@ export const BEING_ARCHETYPES: Readonly<{
333
346
  * @type {Readonly<Record<string, TypeVocabulary>>}
334
347
  */
335
348
  export const NOTE_VOCABULARY: Readonly<Record<string, TypeVocabulary>>;
349
+ /**
350
+ * One word of a closed vocabulary: the value a note writes, the label a reader
351
+ * sees it by, and what it means.
352
+ */
353
+ export type LookWord = {
354
+ /**
355
+ * - The word as a note writes it.
356
+ */
357
+ value: string;
358
+ /**
359
+ * - The word as a reader sees it.
360
+ */
361
+ label: string;
362
+ /**
363
+ * - What it means, in one line.
364
+ */
365
+ describe: string;
366
+ };
336
367
  /**
337
368
  * One `data:` key a note type may carry.
338
369
  *
@@ -17,6 +17,9 @@ export function indexMarker(slug: string, main?: boolean): string;
17
17
  * @param {object} [opts] - Options.
18
18
  * @param {(entry: object) => boolean} [opts.owns] - Whether this book is the
19
19
  * entry's home. Every entry when absent.
20
+ * @param {string[]} [opts.heads] - Leading words (`pdf.indexHeads`) matched
21
+ * literally against the start of a name; a name that opens with one is also
22
+ * listed as `<rest>, <head>`, the head without its trailing space or colon. None when absent.
20
23
  * @param {Array<{slug: string, name: string, title: string, page: string|number}>} [opts.foreign] -
21
24
  * Notes another book prints, listed as `Name: Book title, p. N` once this
22
25
  * book mentions them.
@@ -24,8 +27,9 @@ export function indexMarker(slug: string, main?: boolean): string;
24
27
  * foreign?: {title: string, page: string}}>} Terms with `see` set for a
25
28
  * cross-reference to the main name it points at.
26
29
  */
27
- export function indexTerms(entries: object[], { owns, foreign }?: {
30
+ export function indexTerms(entries: object[], { owns, foreign, heads }?: {
28
31
  owns?: ((entry: object) => boolean) | undefined;
32
+ heads?: string[] | undefined;
29
33
  foreign?: {
30
34
  slug: string;
31
35
  name: string;
@@ -10,6 +10,26 @@
10
10
  * @returns {string[]} The arguments, in order.
11
11
  */
12
12
  export function evalArgs(typPath: string, fontArgs: string[]): string[];
13
+ /**
14
+ * Say why a finished Typst process failed.
15
+ *
16
+ * A process killed by a signal has no exit status and prints nothing, so the
17
+ * signal is named; `SIGKILL` is the kernel's out-of-memory kill. Otherwise the
18
+ * first line the compiler printed is the reason, and the exit code stands in
19
+ * when it printed none.
20
+ *
21
+ * @param {{status: number | null, signal: string | null, stderr?: string | null, stdout?: string | null}} result -
22
+ * The finished process.
23
+ * @param {string} binary - The Typst binary.
24
+ * @param {string} subcommand - The Typst subcommand that ran.
25
+ * @returns {string} The reason, ready to follow the failing command's name.
26
+ */
27
+ export function typstFailure(result: {
28
+ status: number | null;
29
+ signal: string | null;
30
+ stderr?: string | null;
31
+ stdout?: string | null;
32
+ }, binary: string, subcommand: string): string;
13
33
  /**
14
34
  * Measure the page each labelled entry of a book starts on.
15
35
  *
@@ -0,0 +1,164 @@
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.
24
+ */
25
+ export function checkSettlementTables(note: object, { index }?: {
26
+ index?: object | undefined;
27
+ }): 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
+ /**
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 aliases, 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
+ };