@heroiclands/package-build 22.20.0 → 22.21.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.
- package/CHANGELOG-content-build.md +0 -8
- package/CHANGELOG.md +13 -0
- package/docs/api.md +10 -10
- package/docs/reference/format-details.md +51 -6
- package/docs/reference/note-types.md +28 -28
- package/engine/frontmatter-lint.mjs +15 -2
- package/engine/helpers.mjs +5 -0
- package/engine/infobox-render.mjs +6 -1
- package/engine/infobox.mjs +85 -0
- package/engine/note-addresses.mjs +17 -8
- package/engine/note-vocabulary.mjs +46 -7
- package/engine/reference-targets.mjs +13 -1
- package/engine/site-index.mjs +21 -2
- package/engine/standing-terms.mjs +19 -0
- package/engine/standings.mjs +455 -0
- package/engine/svg-theme.mjs +15 -4
- package/engine/wikilinks.mjs +3 -1
- package/package.json +1 -1
- package/sohl/actors.mjs +61 -5
- package/types/engine/note-vocabulary.d.mts +16 -2
- package/types/engine/standing-terms.d.mts +16 -0
- package/types/engine/standings.d.mts +129 -0
- package/types/engine/wikilinks.d.mts +2 -1
- package/types/sohl/actors.d.mts +19 -0
package/engine/svg-theme.mjs
CHANGED
|
@@ -45,7 +45,7 @@ const INK_LIGHT = "#211d16";
|
|
|
45
45
|
const INK_DARK = "#ece3cf";
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* The shapes a
|
|
48
|
+
* The shapes a fill rule may repaint.
|
|
49
49
|
*
|
|
50
50
|
* Explicitly black, or black by default for want of a `fill`. A shape painted
|
|
51
51
|
* some other colour is deliberate — a white highlight in a two-tone badge — and
|
|
@@ -53,7 +53,7 @@ const INK_DARK = "#ece3cf";
|
|
|
53
53
|
*
|
|
54
54
|
* @type {string}
|
|
55
55
|
*/
|
|
56
|
-
const
|
|
56
|
+
const FILL_SELECTOR = [
|
|
57
57
|
'[fill="#000"]',
|
|
58
58
|
'[fill="#000000"]',
|
|
59
59
|
'[fill="black"]',
|
|
@@ -67,10 +67,21 @@ const SELECTOR = [
|
|
|
67
67
|
"g:not([fill])",
|
|
68
68
|
].join(",");
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* The shapes a stroke rule may repaint.
|
|
72
|
+
*
|
|
73
|
+
* Explicitly black only — SVG's default stroke is `none`, so there is no
|
|
74
|
+
* want-of-a-`stroke` case to opt in the way a want-of-a-`fill` case is. A
|
|
75
|
+
* broad match would paint an outline onto a shape that has none.
|
|
76
|
+
*
|
|
77
|
+
* @type {string}
|
|
78
|
+
*/
|
|
79
|
+
const STROKE_SELECTOR = ['[stroke="#000"]', '[stroke="#000000"]', '[stroke="black"]'].join(",");
|
|
80
|
+
|
|
70
81
|
/** @type {string} */
|
|
71
82
|
const STYLE =
|
|
72
|
-
`<style>${
|
|
73
|
-
`@media(prefers-color-scheme:dark){${
|
|
83
|
+
`<style>${FILL_SELECTOR}{fill:${INK_LIGHT}}${STROKE_SELECTOR}{stroke:${INK_LIGHT}}` +
|
|
84
|
+
`@media(prefers-color-scheme:dark){${FILL_SELECTOR}{fill:${INK_DARK}}${STROKE_SELECTOR}{stroke:${INK_DARK}}}</style>`;
|
|
74
85
|
|
|
75
86
|
/**
|
|
76
87
|
* Every `style="…"` attribute, capturing its declarations.
|
package/engine/wikilinks.mjs
CHANGED
|
@@ -583,7 +583,7 @@ export function convertWikilinks(markdown, { type, id, pack, docPack, index, cap
|
|
|
583
583
|
* @param {object} index - From {@link buildWikilinkIndex}.
|
|
584
584
|
* @param {unknown} ref - The reference, as authored.
|
|
585
585
|
* @param {object} [hint] - `{type}`, where the caller knows what it expects.
|
|
586
|
-
* @returns {{name?: string, uuid?: string, address?: import("./address.mjs").AddressTuple, subType?: string}|undefined}
|
|
586
|
+
* @returns {{name?: string, uuid?: string, address?: import("./address.mjs").AddressTuple, subType?: string, standings?: object}|undefined}
|
|
587
587
|
* The target, or `undefined` where nothing answers.
|
|
588
588
|
*/
|
|
589
589
|
export function resolveReference(index, ref, hint) {
|
|
@@ -611,6 +611,7 @@ export function resolveReference(index, ref, hint) {
|
|
|
611
611
|
return {
|
|
612
612
|
name: published.name,
|
|
613
613
|
subType: published.subType,
|
|
614
|
+
...(published.standings ? { standings: published.standings } : {}),
|
|
614
615
|
...(published.uuid ? { uuid: published.uuid } : {}),
|
|
615
616
|
address: tuple,
|
|
616
617
|
};
|
|
@@ -638,6 +639,7 @@ export function resolveReference(index, ref, hint) {
|
|
|
638
639
|
return {
|
|
639
640
|
name: local.name,
|
|
640
641
|
subType: local.subType,
|
|
642
|
+
...(local.standings ? { standings: local.standings } : {}),
|
|
641
643
|
...(uuid ? { uuid } : {}),
|
|
642
644
|
address: tuple,
|
|
643
645
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.21.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/sohl/actors.mjs
CHANGED
|
@@ -29,16 +29,19 @@
|
|
|
29
29
|
* `ACTOR_VAULT_TYPE = "being"` here and emitted `type: "being"` several hundred
|
|
30
30
|
* lines below, which made the two vocabularies agree by coincidence.
|
|
31
31
|
*
|
|
32
|
-
* It was two content types — `character` and `creature` — which compiled to the
|
|
33
|
-
* same `being` with no branch anywhere between them; they were retired in
|
|
34
|
-
* retired, and are reported by `assertTypeNotRetired` in
|
|
35
|
-
* `engine/ids.mjs`.
|
|
36
|
-
*
|
|
37
32
|
* Attributes (`sohl.attributes` map) become embedded attribute items with
|
|
38
33
|
* `scoreBase` set from the map value. Each entry in `sohl.items` is similarly
|
|
39
34
|
* resolved by `(type, shortcode)` and deep-merged with the entry's other
|
|
40
35
|
* properties. `sohl.skills` is ignored.
|
|
41
36
|
*
|
|
37
|
+
* **A membership is derived, never authored here.** `data.affiliations` names
|
|
38
|
+
* the bodies a being belongs to and the standing it holds in each, and each
|
|
39
|
+
* entry becomes one embedded affiliation item: the entry's `rank` is that
|
|
40
|
+
* item's `system.level` and its `office` is `system.office`. A standing is a
|
|
41
|
+
* fact about the setting rather than about one system — it does not become true
|
|
42
|
+
* because SoHL is installed — so the system block states none of it, and a
|
|
43
|
+
* sheet and a page cannot come to disagree.
|
|
44
|
+
*
|
|
42
45
|
* Not a standalone script — exports the `Actors` compiler class, imported and
|
|
43
46
|
* driven by `engine/generate.mjs`. Must run after the items passes, since it
|
|
44
47
|
* reads their generated JSON trees.
|
|
@@ -58,6 +61,10 @@ import { SOHL_DOCUMENT_SUBTYPES } from "./document-subtypes.mjs";
|
|
|
58
61
|
// verbatim, and `sohl.img` / `sohl.effects` / `sohl.flags` overriding their
|
|
59
62
|
// shared top-level forms for this system alone.
|
|
60
63
|
import { blockProperty, mergeSystemData } from "../engine/system-block.mjs";
|
|
64
|
+
// A being's memberships and the standing it holds in each, read from the one
|
|
65
|
+
// place they are authored. The rank *is* the affiliation item's `level`, so
|
|
66
|
+
// there is nothing to map and nowhere for a second authoring to disagree.
|
|
67
|
+
import { readStandings } from "../engine/standings.mjs";
|
|
61
68
|
|
|
62
69
|
/**
|
|
63
70
|
* The system this pass compiles for — the block its notes write.
|
|
@@ -256,10 +263,59 @@ export class Actors extends SystemActorCompiler {
|
|
|
256
263
|
});
|
|
257
264
|
}
|
|
258
265
|
|
|
266
|
+
for (const embedded of this.buildMemberships(itemsMap, actorId, fm, ctx)) {
|
|
267
|
+
items.push(embedded);
|
|
268
|
+
}
|
|
269
|
+
|
|
259
270
|
this.openUnopenedSkills(items, ctx);
|
|
260
271
|
return items;
|
|
261
272
|
}
|
|
262
273
|
|
|
274
|
+
/**
|
|
275
|
+
* One embedded affiliation item per body the being belongs to.
|
|
276
|
+
*
|
|
277
|
+
* The body's own compiled item is the model, so a membership carries
|
|
278
|
+
* whatever that body declares — its subtype, its common skills, its
|
|
279
|
+
* standings toward others — and the being adds only what is true of *this*
|
|
280
|
+
* membership: the rung it stands on and the post it holds.
|
|
281
|
+
*
|
|
282
|
+
* A being naming a body that compiles to no item is a finding rather than a
|
|
283
|
+
* silently dropped membership: the note says the being belongs somewhere,
|
|
284
|
+
* and a sheet that shows nothing says it does not.
|
|
285
|
+
*
|
|
286
|
+
* @param {Map<string, object>} itemsMap - The predefined-item catalogue.
|
|
287
|
+
* @param {string} actorId - The owning actor's id.
|
|
288
|
+
* @param {object} fm - The note's frontmatter.
|
|
289
|
+
* @param {string} ctx - Diagnostic context.
|
|
290
|
+
* @returns {object[]} The embedded items, in the order the note names them.
|
|
291
|
+
*/
|
|
292
|
+
buildMemberships(itemsMap, actorId, fm, ctx) {
|
|
293
|
+
const { entries } = readStandings(fm?.data?.affiliations);
|
|
294
|
+
const items = [];
|
|
295
|
+
for (const { body, standing } of entries) {
|
|
296
|
+
const shortcode = body?.shortcode;
|
|
297
|
+
if (!shortcode) continue;
|
|
298
|
+
const level = Number(standing?.rank);
|
|
299
|
+
const office = typeof standing?.office === "string" ? standing.office.trim() : "";
|
|
300
|
+
const system = {
|
|
301
|
+
...(Number.isFinite(level) ? { level } : {}),
|
|
302
|
+
...(office ? { office } : {}),
|
|
303
|
+
};
|
|
304
|
+
const embedded = this.resolveEmbedded(
|
|
305
|
+
itemsMap,
|
|
306
|
+
actorId,
|
|
307
|
+
"affiliation",
|
|
308
|
+
shortcode,
|
|
309
|
+
Object.keys(system).length ? { system } : {},
|
|
310
|
+
`affiliations:${shortcode}`,
|
|
311
|
+
ctx,
|
|
312
|
+
{ fmKey: "affiliations", modelPackage: body.package ?? null },
|
|
313
|
+
);
|
|
314
|
+
if (embedded) items.push(embedded);
|
|
315
|
+
}
|
|
316
|
+
return items;
|
|
317
|
+
}
|
|
318
|
+
|
|
263
319
|
/**
|
|
264
320
|
* Bake each unopened skill's opening mastery level into the document.
|
|
265
321
|
*
|
|
@@ -296,15 +296,29 @@ export type DataFieldSpec = {
|
|
|
296
296
|
* value — which is the honest answer wherever the specification's stated
|
|
297
297
|
* shape and the shape notes are authored in today disagree.
|
|
298
298
|
*/
|
|
299
|
-
kind?: "string" | "number" | "boolean" | "map" | "address" | "list" | "shortcode" | "scalar-or-map" | undefined;
|
|
299
|
+
kind?: "string" | "number" | "boolean" | "map" | "address" | "list" | "shortcode" | "list-or-map" | "scalar-or-map" | undefined;
|
|
300
300
|
/**
|
|
301
301
|
* - Type of each list or pack-map value.
|
|
302
302
|
*/
|
|
303
303
|
entryKind?: "address" | "shortcode" | undefined;
|
|
304
304
|
/**
|
|
305
|
-
* - Type of each map key.
|
|
305
|
+
* - Type of each map key. On a
|
|
306
|
+
* `list-or-map` field it describes the map form alone, and `entryKind` the
|
|
307
|
+
* list form alone: reading both of one value would check a map's entries as
|
|
308
|
+
* if they were its keys.
|
|
306
309
|
*/
|
|
307
310
|
keyKind?: "address" | "shortcode" | undefined;
|
|
311
|
+
/**
|
|
312
|
+
* - The map's entries are standings held in the
|
|
313
|
+
* body each is keyed by, so a row names the two together — see
|
|
314
|
+
* {@link module :engine/standings}.
|
|
315
|
+
*/
|
|
316
|
+
standings?: boolean | undefined;
|
|
317
|
+
/**
|
|
318
|
+
* - The map names posts, each with a description,
|
|
319
|
+
* so each takes a row labelled and anchored by the post's own name.
|
|
320
|
+
*/
|
|
321
|
+
roster?: boolean | undefined;
|
|
308
322
|
/**
|
|
309
323
|
* - An alternative `subType:<skill-subtype>` key.
|
|
310
324
|
*/
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The note type a standing is held in.
|
|
3
|
+
*
|
|
4
|
+
* A standing is always held in a body: the entry is keyed by that body's
|
|
5
|
+
* Address, which is what lets the rung and the post be checked against what
|
|
6
|
+
* the body itself declares.
|
|
7
|
+
*/
|
|
8
|
+
export const STANDING_BODY_TYPES: readonly string[];
|
|
9
|
+
/**
|
|
10
|
+
* The two keys one standing carries.
|
|
11
|
+
*
|
|
12
|
+
* `rank` is the level on the body's own `governance.ranks` ladder, as a number.
|
|
13
|
+
* `office` is a key of its `governance.offices` map, as a string. Both are
|
|
14
|
+
* optional — a membership with neither is the ordinary shape.
|
|
15
|
+
*/
|
|
16
|
+
export const STANDING_KEYS: readonly string[];
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The standings a being authored, in one shape whichever shape it wrote.
|
|
3
|
+
*
|
|
4
|
+
* The list form names bodies and no standings; the map form names both. Three
|
|
5
|
+
* spellings reach here and every reader downstream takes the same entries, so
|
|
6
|
+
* none of them asks which it was handed:
|
|
7
|
+
*
|
|
8
|
+
* - an **{@link AddressEntries}** — the map after the note boundary decoded its
|
|
9
|
+
* keys into typed Addresses, which is the shape every compile sees;
|
|
10
|
+
* - a **plain map**, which is the shape a checker reading raw YAML sees;
|
|
11
|
+
* - a **list**, which names bodies and says nothing about standing in them.
|
|
12
|
+
*
|
|
13
|
+
* An emptied map arrives from the property editor as `[]` and means what `{}`
|
|
14
|
+
* means — this being authors no membership — so both read as no entries.
|
|
15
|
+
*
|
|
16
|
+
* Each entry carries `body` for a message and `sourceKey` for a position: the
|
|
17
|
+
* authored key is what a reader has to find in the file, and the decoded
|
|
18
|
+
* Address is what a finding should name.
|
|
19
|
+
*
|
|
20
|
+
* @param {unknown} value - The authored `data.affiliations`.
|
|
21
|
+
* @returns {{form: "absent"|"list"|"map"|"malformed",
|
|
22
|
+
* entries: Array<{body: unknown, sourceKey: string|number, standing: unknown}>}}
|
|
23
|
+
* The form it was written in, and its entries.
|
|
24
|
+
*/
|
|
25
|
+
export function readStandings(value: unknown): {
|
|
26
|
+
form: "absent" | "list" | "map" | "malformed";
|
|
27
|
+
entries: Array<{
|
|
28
|
+
body: unknown;
|
|
29
|
+
sourceKey: string | number;
|
|
30
|
+
standing: unknown;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The rungs an affiliation's ladder declares, as level → title.
|
|
35
|
+
*
|
|
36
|
+
* A rung states its own `level`, so the ladder is read by that number rather
|
|
37
|
+
* than by its position in the list: a body may write its rungs in any order,
|
|
38
|
+
* and several start at zero.
|
|
39
|
+
*
|
|
40
|
+
* @param {unknown} ranks - An affiliation's `data.governance.ranks`.
|
|
41
|
+
* @returns {Map<number, string>} Level → the title that level is called.
|
|
42
|
+
*/
|
|
43
|
+
export function rankLadder(ranks: unknown): Map<number, string>;
|
|
44
|
+
/**
|
|
45
|
+
* The offices an affiliation names, as key → description.
|
|
46
|
+
*
|
|
47
|
+
* An office is authored either as a bare description or as a `{description,
|
|
48
|
+
* holders}` map, and a reader of the post's name wants the same string from
|
|
49
|
+
* both.
|
|
50
|
+
*
|
|
51
|
+
* @param {unknown} offices - An affiliation's `data.governance.offices`.
|
|
52
|
+
* @returns {Map<string, string>} Office key → its description.
|
|
53
|
+
*/
|
|
54
|
+
export function officeRoster(offices: unknown): Map<string, string>;
|
|
55
|
+
/**
|
|
56
|
+
* The anchor an office's row is addressed by.
|
|
57
|
+
*
|
|
58
|
+
* Declared once, because the row that carries the anchor and the link that
|
|
59
|
+
* reaches it are drawn by different passes: two spellings of the same
|
|
60
|
+
* derivation is a link into a page that offers no such destination.
|
|
61
|
+
*
|
|
62
|
+
* An office whose name reduces to nothing URL-safe has no anchor, and the
|
|
63
|
+
* caller is the one that can say what to do without one.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} office - The office's key, as the body wrote it.
|
|
66
|
+
* @returns {string} The anchor, or `""` where the name carries nothing.
|
|
67
|
+
*/
|
|
68
|
+
export function officeAnchor(office: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* What an affiliation lends to a reference to it.
|
|
71
|
+
*
|
|
72
|
+
* A reference's value answers what was found as well as where it is — the same
|
|
73
|
+
* reason a target's `subType` travels with it. A standing is read on the
|
|
74
|
+
* *being*, and what it is called is declared on the *body*, so the ladder and
|
|
75
|
+
* the office roster ride along to the one place that needs them.
|
|
76
|
+
*
|
|
77
|
+
* Nothing rides for a note that declares neither.
|
|
78
|
+
*
|
|
79
|
+
* @param {object} fm - The affiliation note's frontmatter.
|
|
80
|
+
* @returns {{ranks?: Record<string, string>, offices?: Record<string, string>}|undefined}
|
|
81
|
+
* What a reference carries, or nothing.
|
|
82
|
+
*/
|
|
83
|
+
export function standingsDigest(fm: object): {
|
|
84
|
+
ranks?: Record<string, string>;
|
|
85
|
+
offices?: Record<string, string>;
|
|
86
|
+
} | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* How a standing reads beside the body that confers it.
|
|
89
|
+
*
|
|
90
|
+
* The office leads, because it is the more particular of the two: a reader
|
|
91
|
+
* meeting "War Chief" has been told the rung as well. The body closes the
|
|
92
|
+
* phrase, which is the whole point of keying the entry by it — a standing with
|
|
93
|
+
* no body named is the lossy form.
|
|
94
|
+
*
|
|
95
|
+
* No article is supplied. One body's name reads with a "the" in front of it and
|
|
96
|
+
* the next does not, and inventing one is this build editing the corpus.
|
|
97
|
+
*
|
|
98
|
+
* @param {object} standing - `{rank, office}`, either or both absent.
|
|
99
|
+
* @param {string} body - What the body is called.
|
|
100
|
+
* @param {{ranks?: Record<string, string>}} [digest] - The body's ladder.
|
|
101
|
+
* @returns {string} The phrase, or the body's name where no standing is held.
|
|
102
|
+
*/
|
|
103
|
+
export function standingPhrase(standing: object, body: string, digest?: {
|
|
104
|
+
ranks?: Record<string, string>;
|
|
105
|
+
}): string;
|
|
106
|
+
/**
|
|
107
|
+
* Validate a being's memberships and the standing it holds in each.
|
|
108
|
+
*
|
|
109
|
+
* Four questions, and the last two are what keying the entry by its body buys:
|
|
110
|
+
*
|
|
111
|
+
* 1. the value is a map keyed by Address (or the list this window still takes);
|
|
112
|
+
* 2. every key names an affiliation that resolves, once;
|
|
113
|
+
* 3. a `rank` is a level the named body's `governance.ranks` declares;
|
|
114
|
+
* 4. an `office` is a key of that body's `governance.offices`.
|
|
115
|
+
*
|
|
116
|
+
* Both of the last two are read from the named body's own frontmatter as the
|
|
117
|
+
* lint runs, so a renamed rung or a renamed post fails on every being pointing
|
|
118
|
+
* at it rather than on a list somebody has to remember to edit.
|
|
119
|
+
*
|
|
120
|
+
* @param {object} note - The note.
|
|
121
|
+
* @param {{index?: object}} [options] - The lint's options.
|
|
122
|
+
* @returns {object[]} Located findings.
|
|
123
|
+
*/
|
|
124
|
+
export function checkStandings(note: object, { index }?: {
|
|
125
|
+
index?: object;
|
|
126
|
+
}): object[];
|
|
127
|
+
import { STANDING_BODY_TYPES } from "./standing-terms.mjs";
|
|
128
|
+
import { STANDING_KEYS } from "./standing-terms.mjs";
|
|
129
|
+
export { STANDING_BODY_TYPES, STANDING_KEYS };
|
|
@@ -133,7 +133,7 @@ export function convertWikilinks(markdown: string, { type, id, pack, docPack, in
|
|
|
133
133
|
* @param {object} index - From {@link buildWikilinkIndex}.
|
|
134
134
|
* @param {unknown} ref - The reference, as authored.
|
|
135
135
|
* @param {object} [hint] - `{type}`, where the caller knows what it expects.
|
|
136
|
-
* @returns {{name?: string, uuid?: string, address?: import("./address.mjs").AddressTuple, subType?: string}|undefined}
|
|
136
|
+
* @returns {{name?: string, uuid?: string, address?: import("./address.mjs").AddressTuple, subType?: string, standings?: object}|undefined}
|
|
137
137
|
* The target, or `undefined` where nothing answers.
|
|
138
138
|
*/
|
|
139
139
|
export function resolveReference(index: object, ref: unknown, hint?: object): {
|
|
@@ -141,6 +141,7 @@ export function resolveReference(index: object, ref: unknown, hint?: object): {
|
|
|
141
141
|
uuid?: string;
|
|
142
142
|
address?: import("./address.mjs").AddressTuple;
|
|
143
143
|
subType?: string;
|
|
144
|
+
standings?: object;
|
|
144
145
|
} | undefined;
|
|
145
146
|
import { ITEM_PACK } from "./ids.mjs";
|
|
146
147
|
import { PACK_BY_TYPE } from "./ids.mjs";
|
package/types/sohl/actors.d.mts
CHANGED
|
@@ -21,6 +21,25 @@ export class Actors extends SystemActorCompiler {
|
|
|
21
21
|
* entry plus one per `sohl.items` entry. `sohl.skills` is ignored.
|
|
22
22
|
*/
|
|
23
23
|
buildEmbeddedItems(itemsMap: any, actorId: any, fm: any, ctx: any): object[];
|
|
24
|
+
/**
|
|
25
|
+
* One embedded affiliation item per body the being belongs to.
|
|
26
|
+
*
|
|
27
|
+
* The body's own compiled item is the model, so a membership carries
|
|
28
|
+
* whatever that body declares — its subtype, its common skills, its
|
|
29
|
+
* standings toward others — and the being adds only what is true of *this*
|
|
30
|
+
* membership: the rung it stands on and the post it holds.
|
|
31
|
+
*
|
|
32
|
+
* A being naming a body that compiles to no item is a finding rather than a
|
|
33
|
+
* silently dropped membership: the note says the being belongs somewhere,
|
|
34
|
+
* and a sheet that shows nothing says it does not.
|
|
35
|
+
*
|
|
36
|
+
* @param {Map<string, object>} itemsMap - The predefined-item catalogue.
|
|
37
|
+
* @param {string} actorId - The owning actor's id.
|
|
38
|
+
* @param {object} fm - The note's frontmatter.
|
|
39
|
+
* @param {string} ctx - Diagnostic context.
|
|
40
|
+
* @returns {object[]} The embedded items, in the order the note names them.
|
|
41
|
+
*/
|
|
42
|
+
buildMemberships(itemsMap: Map<string, object>, actorId: string, fm: object, ctx: string): object[];
|
|
24
43
|
/**
|
|
25
44
|
* Bake each unopened skill's opening mastery level into the document.
|
|
26
45
|
*
|