@heroiclands/package-build 23.2.2 → 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.
- package/CHANGELOG.md +17 -0
- package/ci/content-format-reference.mjs +28 -5
- package/docs/api.md +37 -23
- package/docs/authoring/frontmatter.md +2 -0
- package/docs/content-format.md +4 -0
- package/docs/guides/e2e.md +8 -1
- package/docs/reference/format-details.md +260 -7
- package/docs/reference/note-types.md +27 -27
- package/e2e.mjs +37 -10
- package/engine/content-format.yaml +6 -0
- package/engine/data-keys.mjs +6 -2
- package/engine/index.mjs +3 -0
- package/engine/infobox.mjs +1 -1
- package/engine/note-vocabulary.mjs +209 -17
- package/engine/settlement-tables.mjs +777 -0
- package/package.json +1 -1
- package/types/e2e.d.mts +5 -1
- package/types/engine/index.d.mts +1 -0
- package/types/engine/infobox.d.mts +1 -1
- package/types/engine/note-vocabulary.d.mts +31 -0
- package/types/engine/settlement-tables.d.mts +164 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 23.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
**Being notes**
|
|
8
|
+
|
|
9
|
+
- A being's eye, hair and skin colour and its complexion now take words from a fixed list, alongside gender and frame, and any other value fails `package-build lint` naming the accepted words.
|
|
10
|
+
- Variant spellings and empty values are refused too: write `grey` rather than `gray`, and leave a field out when it is unrecorded.
|
|
11
|
+
- A complexion takes one word or a list of them; distinguishing marks stay free text in `extra_features`.
|
|
12
|
+
- The format reference lists every word with what it means.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
A region can list its settlements in a table under `## Settlements` — name, market, people and holder, one row each — tagged with how its countryside is held: `held`, `endowed`, `registered`, `kin` or `polis`. `package-build lint` checks the table's columns, its market classes and figures, that a holder suits the region's model, and that every linked row agrees with the settlement's own note.
|
|
17
|
+
|
|
18
|
+
`e2e` now says when the Foundry licence is unsigned, and how to sign it, instead of timing out waiting for a world.
|
|
19
|
+
|
|
3
20
|
## 23.2.2
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -18,6 +18,7 @@ import { formatGenerated } from "../engine/format-generated.mjs";
|
|
|
18
18
|
import { loadContentFormat } from "../engine/content-format.mjs";
|
|
19
19
|
import {
|
|
20
20
|
BEING_ARCHETYPES,
|
|
21
|
+
BEING_LOOK_VOCABULARY,
|
|
21
22
|
NOTE_TOP_LEVEL_FIELDS,
|
|
22
23
|
NOTE_VOCABULARY,
|
|
23
24
|
SHARED_DATA_FIELDS,
|
|
@@ -236,20 +237,42 @@ const details = fs.readFileSync(detailsPath, "utf8");
|
|
|
236
237
|
if (!/<!-- archetypes:start -->[\s\S]*?<!-- archetypes:end -->/.test(details)) {
|
|
237
238
|
throw new Error("The archetype reference requires its generation markers");
|
|
238
239
|
}
|
|
240
|
+
if (!/<!-- being-look:start -->[\s\S]*?<!-- being-look:end -->/.test(details)) {
|
|
241
|
+
throw new Error("The being-look reference requires its generation markers");
|
|
242
|
+
}
|
|
239
243
|
const archetypes = Object.entries(BEING_ARCHETYPES)
|
|
240
244
|
.map(([name, meaning]) => `- ${name}: ${meaning}`)
|
|
241
245
|
.join("\n");
|
|
246
|
+
// One table per field of a being's look, every word with its label and meaning,
|
|
247
|
+
// written from the declaration the lint closes each field to.
|
|
248
|
+
const beingLook = Object.entries(BEING_LOOK_VOCABULARY)
|
|
249
|
+
.flatMap(([field, words]) => [
|
|
250
|
+
`**\`data.${field}\`**`,
|
|
251
|
+
"",
|
|
252
|
+
"| Word | Label | Meaning |",
|
|
253
|
+
"| --- | --- | --- |",
|
|
254
|
+
...words.map(
|
|
255
|
+
({ value, label, describe }) => `| \`${value}\` | ${cell(label)} | ${cell(describe)} |`,
|
|
256
|
+
),
|
|
257
|
+
"",
|
|
258
|
+
])
|
|
259
|
+
.join("\n");
|
|
242
260
|
const updatedDetails = await formatGenerated(
|
|
243
|
-
details
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
261
|
+
details
|
|
262
|
+
.replace(
|
|
263
|
+
/<!-- archetypes:start -->[\s\S]*?<!-- archetypes:end -->/,
|
|
264
|
+
`<!-- archetypes:start -->\n${archetypes}\n<!-- archetypes:end -->`,
|
|
265
|
+
)
|
|
266
|
+
.replace(
|
|
267
|
+
/<!-- being-look:start -->[\s\S]*?<!-- being-look:end -->/,
|
|
268
|
+
`<!-- being-look:start -->\n\n${beingLook}\n<!-- being-look:end -->`,
|
|
269
|
+
),
|
|
247
270
|
detailsPath,
|
|
248
271
|
);
|
|
249
272
|
if (process.argv.includes("--check")) {
|
|
250
273
|
if (details !== updatedDetails) {
|
|
251
274
|
console.error(
|
|
252
|
-
"docs/reference/format-details.md: error: run node ci/content-format-reference.mjs to refresh the archetype
|
|
275
|
+
"docs/reference/format-details.md: error: run node ci/content-format-reference.mjs to refresh the archetype and being-look references",
|
|
253
276
|
);
|
|
254
277
|
process.exitCode = 1;
|
|
255
278
|
}
|
package/docs/api.md
CHANGED
|
@@ -323,29 +323,30 @@ The note types the engine itself declares — vocabulary that is a fact about th
|
|
|
323
323
|
|
|
324
324
|
An addressed content note accepts exactly these top-level keys, in this order: `shortcode`, `name`, `type`, `subType`, `description`, `tags`, `data`, `dnd5e`, `hm3`, `sohl`. A key outside this list is an error at its own line. The system blocks are one per system the address vocabulary recognizes, sorted by name after the fixed keys, so a further system is a change to `SYSTEM_IDS` alone. No dnd5e-specific document types are declared. Within that shape, the closed vocabularies are the `data:` container and each type's `subType`.
|
|
325
325
|
|
|
326
|
-
| Export | Signature | Returns
|
|
327
|
-
| ------------------------- | -------------------------------------------- |
|
|
328
|
-
| `DRAFT_TAG` | `const DRAFT_TAG` | —
|
|
329
|
-
| `GM_TAG` | `const GM_TAG` | —
|
|
330
|
-
| `BEING_ARCHETYPES` | `const BEING_ARCHETYPES` | `Readonly<Record<string, string>>`
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
344
|
-
| `
|
|
345
|
-
| `
|
|
346
|
-
| `
|
|
347
|
-
| `
|
|
348
|
-
| `
|
|
326
|
+
| Export | Signature | Returns | Use it when |
|
|
327
|
+
| ------------------------- | -------------------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
328
|
+
| `DRAFT_TAG` | `const DRAFT_TAG` | — | naming the declared tag that marks a note as unfinished |
|
|
329
|
+
| `GM_TAG` | `const GM_TAG` | — | naming the declared tag that marks a GM-only note |
|
|
330
|
+
| `BEING_ARCHETYPES` | `const BEING_ARCHETYPES` | `Readonly<Record<string, string>>` | looking up the case-sensitive being archetypes and their meanings |
|
|
331
|
+
| `BEING_LOOK_VOCABULARY` | `const BEING_LOOK_VOCABULARY` | `Readonly<Record<string, readonly LookWord[]>>` | reading the closed words a being's gender, frame and appearance take, each with its label and meaning, keyed by `data:` field |
|
|
332
|
+
| `NOTE_VOCABULARY` | `const NOTE_VOCABULARY` | — | looking up, per content type, its `data:` field list and its closed `subType` values |
|
|
333
|
+
| `NOTE_TOP_LEVEL_FIELDS` | `const NOTE_TOP_LEVEL_FIELDS` | `readonly TopLevelFieldSpec[]` | reading the top-level keys a note accepts, in formatted order, with what each one means |
|
|
334
|
+
| `NOTE_TOP_LEVEL_KEYS` | `const NOTE_TOP_LEVEL_KEYS` | `readonly string[]` | reading just the key names, in the order the formatter writes them |
|
|
335
|
+
| `NOTE_TOP_LEVEL_KEY_SET` | `const NOTE_TOP_LEVEL_KEY_SET` | `ReadonlySet<string>` | testing whether a top-level key is one the note format declares |
|
|
336
|
+
| `SHARED_DATA_FIELDS` | `const SHARED_DATA_FIELDS` | `readonly DataFieldSpec[]` | reading the `data:` keys every type accepts, whatever it is — the art slots legal everywhere |
|
|
337
|
+
| `EVENTS_FIELD` | `const EVENTS_FIELD` | `DataFieldSpec` | reading the one `events` declaration that `lore`, `place` and `affiliation` share, with its check |
|
|
338
|
+
| `DECLARED_TAGS` | `const DECLARED_TAGS` | — | looking up the tags a note type may declare, grouped |
|
|
339
|
+
| `declaredTags` | `declaredTags(type, groups)` | `readonly string[]` | reading the declared tags a note of a type may carry, flattened |
|
|
340
|
+
| `applicableTagGroups` | `applicableTagGroups(type, groups)` | `object[]` | reading the declared tag groups that apply to a note type |
|
|
341
|
+
| `exclusiveTagGroups` | `exclusiveTagGroups(type, groups)` | `Array<{slot, tags}>` | reading single-valued tag slots declared for a note type |
|
|
342
|
+
| `hasTag` | `hasTag(fm, tag)` | `boolean` | checking whether a note carries a given tag, whatever scalar-or-list form it was authored in |
|
|
343
|
+
| `isDraftNote` | `isDraftNote(fm)` | `boolean` | checking whether a note is tagged as an unfinished draft |
|
|
344
|
+
| `isGmNote` | `isGmNote(fm)` | `boolean` | checking whether a note is restricted to GM-facing output |
|
|
345
|
+
| `subTypeCharsetMessage` | `subTypeCharsetMessage(value)` | `string` | building the message for a `subType` outside the address charset |
|
|
346
|
+
| `typeCharsetMessage` | `typeCharsetMessage(type)` | `string` | building the message for a `type` outside the address charset |
|
|
347
|
+
| `assertVocabularyCharset` | `assertVocabularyCharset(vocabulary, where)` | throws | refusing a vocabulary declaration whose type or subType breaks the address charset |
|
|
348
|
+
| `dataFields` | `dataFields(type, vocabulary)` | `readonly DataFieldSpec[] \| undefined` | looking up the `data:` keys a note type may carry |
|
|
349
|
+
| `subTypes` | `subTypes(type, vocabulary)` | `readonly string[] \| null \| undefined` | looking up the closed `subType` values a note type declares |
|
|
349
350
|
|
|
350
351
|
### `engine.infobox`
|
|
351
352
|
|
|
@@ -507,6 +508,19 @@ What trade a settlement supports (`data.market`): the six-step scale, stated onc
|
|
|
507
508
|
| `marketClass` | `marketClass(value)` | `object\|undefined` | the class a value names, for rendering what a number means |
|
|
508
509
|
| `checkMarket` | `checkMarket(note)` | `object[]` | linting a place's `market` — a value off the scale, located at the value that states it |
|
|
509
510
|
|
|
511
|
+
### `engine.settlementTables`
|
|
512
|
+
|
|
513
|
+
A region's settlements table — a markdown table under `## Settlements` on a `place` note, one row per settlement with its market, its people and its holder — held to its declared columns, to the holding model the region's tags name, and to the notes its rows link. `package-build lint` runs it as part of the `place` check; a note with no such table is not read.
|
|
514
|
+
|
|
515
|
+
| Export | Signature | Returns | Use it when |
|
|
516
|
+
| ------------------------ | ---------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
517
|
+
| `HOLDING_MODELS` | `const HOLDING_MODELS` | `readonly object[]` | the holding models in order, each its `tag`, the `holder` its Held by cell names, and whether a `person` may hold |
|
|
518
|
+
| `SETTLEMENT_COLUMNS` | `const SETTLEMENT_COLUMNS` | `readonly object[]` | the table's columns in header order, each its `name` and whether it is `required` |
|
|
519
|
+
| `SETTLEMENTS_HEADING` | `const SETTLEMENTS_HEADING` | `string` | the level-two heading text a settlements table stands under |
|
|
520
|
+
| `SETTLEMENT_TABLE_RULES` | `const SETTLEMENT_TABLE_RULES` | `readonly object[]` | the rules in order, each its `name` — the prefix its findings carry — and what it `describe`s |
|
|
521
|
+
| `findSettlementTables` | `findSettlementTables(raw)` | `{ heading: number, tables: object[] }` | reading a note's settlements tables, each with its header, its rows' cells and their 1-based lines and columns |
|
|
522
|
+
| `checkSettlementTables` | `checkSettlementTables(note, { index })` | `object[]` | linting a place note's settlements tables against the corpus the index holds |
|
|
523
|
+
|
|
510
524
|
### `engine.mapPlaces`
|
|
511
525
|
|
|
512
526
|
The places a map is drawn from — this package's index records and every fetched dependency's entries, read through one shape — and what their `parents` say: the world, the continents, each place's continent, and everything the containment tree can get wrong, reported as findings located at the entry that states it.
|
|
@@ -35,6 +35,8 @@ The [note-type reference](../reference/note-types.md) lists every field accepted
|
|
|
35
35
|
|
|
36
36
|
A being's `data.archetypes` names the roles it can fill in an adventure. Choose every specific role that fits, such as `entertainer` for a performer or `guildsperson` for someone whose professional training or connections matter. Use `[commoner]` when no specific archetype fits. `commoner` cannot share the list with another value. The [archetype reference](../reference/format-details.md#actors) defines the available roles.
|
|
37
37
|
|
|
38
|
+
A being's look is stated in a closed vocabulary. `data.gender` and `data.frame` take one word each, as do `data.appearance.eye_color`, `hair_color` and `skin_color`; `data.appearance.complexion` takes one word or a list of them. A value outside a field's list — a variant spelling such as `gray`, a word from another field's list, or an empty string — is an error naming the words the field takes. Leave a field out when the fact is unrecorded. `data.appearance.extra_features` is a free-text list for the marks no word covers. The [look reference](../reference/format-details.md#a-beings-look) gives every word and what it means.
|
|
39
|
+
|
|
38
40
|
A `sohl:`, `hm3:` or `dnd5e:` block holds values for that Foundry system. Its `system:` child contains values sent to the system's DataModel. The system block can override shared routing and art where the declared field permits it. `data.pack` and `data.packFolder` are shared routes; a system-specific route belongs in that system block. The [detailed mapping reference](../reference/format-details.md#mappings-every-type-shares) and [system-block explanation](../reference/format-details.md#frontmatter-has-three-regions) cover precedence and emitted fields.
|
|
39
41
|
|
|
40
42
|
One body describes the subject for both systems. A being's `{#appearance}` and `{#dossier}` sections feed SoHL Actor `system.appearance` and `system.dossier`, and HM3 Actor `system.description` and `system.biography`. An Item's `{#description}` page becomes a shared JournalEntryPage. Its resolved `@UUID[...]` pointer is stored in SoHL Item `system.docHtml` and HM3 Item `system.description`. An Item with no `{#description}` anchor uses its first page. Other H1 pages remain linkable.
|
package/docs/content-format.md
CHANGED
|
@@ -90,6 +90,10 @@ The [first-note guide](authoring/first-note.md) shows the build commands and how
|
|
|
90
90
|
|
|
91
91
|
Place notes may declare a governing affiliation with `data.government`, or explicit `null` for complete anarchy. Positive population with an omitted government produces an advisory. See [place governments](authoring/frontmatter.md#place-governments).
|
|
92
92
|
|
|
93
|
+
A region may list its settlements in a table under `## Settlements` — name, market, people and holder, one row each — tagged with the holding model it is written in. A row links the settlement's note where one exists, and `package-build lint` holds the two to agreement. See [a region's settlements table](reference/format-details.md#a-regions-settlements-table).
|
|
94
|
+
|
|
95
|
+
A being states its gender, frame and appearance in words from one closed vocabulary: `data.gender`, `data.frame`, and `data.appearance.eye_color`, `hair_color`, `skin_color` and `complexion` each take only the words listed for them, and any other value is an error at the value. `data.appearance.extra_features` stays free text. See [a being's look](reference/format-details.md#a-beings-look).
|
|
96
|
+
|
|
93
97
|
Places, affiliations, lore and beings may name their culture in `data.culture`, and a `doc` of `subType: settingguide` must. A place or affiliation that names none inherits the culture of its parents. See [culture in the index](reference/format-details.md#culture-in-the-index).
|
|
94
98
|
|
|
95
99
|
Blockquote alerts use `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, or `[!]`, with optional attributes after the marker. They replace the former info and warn div fences; secret blocks remain supported. See [alerts](authoring/links-and-markup.md#alerts).
|
package/docs/guides/e2e.md
CHANGED
|
@@ -91,7 +91,14 @@ image made for that build. The first run downloads the release, which needs
|
|
|
91
91
|
`FOUNDRYVTT_CACHE`, or in `container_cache` beneath the data root when that is
|
|
92
92
|
unset. Once the archive is cached and the stage has a licence, later runs
|
|
93
93
|
start without signing in to foundryvtt.com, so its rate limit never stops a
|
|
94
|
-
run.
|
|
94
|
+
run. A key alone does not sign the licence. The image applies
|
|
95
|
+
`FOUNDRYVTT_TEST_LICENSE_KEY` and nothing more; the signature comes from
|
|
96
|
+
accepting the licence agreement in Foundry's own page, once per data root, and
|
|
97
|
+
then persists in `Config/license.json` there. On a fresh data root, start the
|
|
98
|
+
stage with no world (`package-build container test start`), open it in a
|
|
99
|
+
browser and accept the agreement. A run against an unsigned licence fails at
|
|
100
|
+
once saying so, naming the data root, instead of waiting for a world that never
|
|
101
|
+
activates. Under rootless Docker, set
|
|
95
102
|
`FOUNDRYVTT_CONTAINER_USER=0:0`: container root is then the host user, so every
|
|
96
103
|
file under the data root belongs to them, where the image would otherwise run
|
|
97
104
|
Foundry as user 1000. With the local settings in place, seed the world:
|
|
@@ -3505,7 +3505,7 @@ See [a being's subtype describes the subject](#a-beings-subtype-describes-the-su
|
|
|
3505
3505
|
| `affiliations.<Address>.office` | `string` | A post that body names in its `governance.offices`, where the being holds one |
|
|
3506
3506
|
| `affiliations.<Address>.societies` | `string[]` | The societies the membership is held in, by name; SoHL carries the first as `system.society` |
|
|
3507
3507
|
| `socialTies` | `Map<Address, Tie>` | Defining support and opposition, directed from this being to others |
|
|
3508
|
-
| `gender` | `male \| female \| other`
|
|
3508
|
+
| `gender` | `male \| female \| nonbinary \| none \| other` | Gender of the being — see [a being's look](#a-beings-look) |
|
|
3509
3509
|
| `species` | `Address` | Being's species (lore) |
|
|
3510
3510
|
| `born` | `date \| unknown` | When the being was born; absent, it was never born |
|
|
3511
3511
|
| `calendar` | `Address` | Calendar note that prints the being's dates |
|
|
@@ -3514,12 +3514,12 @@ See [a being's subtype describes the subject](#a-beings-subtype-describes-the-su
|
|
|
3514
3514
|
| `ageYears` | `number` | Written by the compiler beside an `age` estimate — the `~` stripped; a note never authors this |
|
|
3515
3515
|
| `height` | `1.91m \| 6' 3"` | Height in metres or feet and inches |
|
|
3516
3516
|
| `weight` | `85kg \| 187 lbs` | Body weight in kilograms or pounds |
|
|
3517
|
-
| `frame` | `scant \| light \| medium \|
|
|
3518
|
-
| `appearance.eye_color` |
|
|
3519
|
-
| `appearance.hair_color` |
|
|
3520
|
-
| `appearance.skin_color` |
|
|
3521
|
-
| `appearance.complexion` | `
|
|
3522
|
-
| `appearance.extra_features` | `string[]` |
|
|
3517
|
+
| `frame` | `scant \| light \| medium \| heavy \| massive` | Relative frame — see [a being's look](#a-beings-look) |
|
|
3518
|
+
| `appearance.eye_color` | a word | Eye colour — see [a being's look](#a-beings-look) |
|
|
3519
|
+
| `appearance.hair_color` | a word | Hair colour — see [a being's look](#a-beings-look) |
|
|
3520
|
+
| `appearance.skin_color` | a word | Skin colour — see [a being's look](#a-beings-look) |
|
|
3521
|
+
| `appearance.complexion` | `word \| word[]` | The skin's condition, one word or several — see [a being's look](#a-beings-look) |
|
|
3522
|
+
| `appearance.extra_features` | `string[]` | Anything else a stranger would notice, in free text |
|
|
3523
3523
|
|
|
3524
3524
|
Author `data.height` as a string of decimal metres (`1.91m` or `1.91 m`) or
|
|
3525
3525
|
whole feet with optional inches (`6'`, `6'3"`, or `6' 3"`). Inches must be
|
|
@@ -3543,6 +3543,142 @@ data:
|
|
|
3543
3543
|
lore: [lore-marchlaw]
|
|
3544
3544
|
```
|
|
3545
3545
|
|
|
3546
|
+
#### A being's look
|
|
3547
|
+
|
|
3548
|
+
**A being's gender, frame and appearance are stated in words from one closed
|
|
3549
|
+
vocabulary**, so every package describes a face in the same terms and a
|
|
3550
|
+
misspelt or invented word is caught. `data.gender`, `data.frame`,
|
|
3551
|
+
`data.appearance.eye_color`, `data.appearance.hair_color` and
|
|
3552
|
+
`data.appearance.skin_color` each take one word from their own list.
|
|
3553
|
+
`data.appearance.complexion` takes one word or a list of them, since a face
|
|
3554
|
+
carries more than one condition at once; a single word means a list of one.
|
|
3555
|
+
Any other value — a word from another field's list, a variant spelling such as
|
|
3556
|
+
`gray` for `grey`, or an empty string — is an error at the value, naming the
|
|
3557
|
+
words the field takes. Leave a field out when the fact is unrecorded.
|
|
3558
|
+
|
|
3559
|
+
`data.appearance.extra_features` is not closed. It is a list of free-text
|
|
3560
|
+
marks — a scar and where it came from, a missing finger, a limp — for what no
|
|
3561
|
+
word in the vocabulary covers.
|
|
3562
|
+
|
|
3563
|
+
```yaml
|
|
3564
|
+
data:
|
|
3565
|
+
gender: female
|
|
3566
|
+
frame: light
|
|
3567
|
+
appearance:
|
|
3568
|
+
eye_color: dark_brown
|
|
3569
|
+
hair_color: greying_black
|
|
3570
|
+
skin_color: olive
|
|
3571
|
+
complexion: [weathered, freckled]
|
|
3572
|
+
extra_features:
|
|
3573
|
+
- a burn scar across the back of the left hand
|
|
3574
|
+
```
|
|
3575
|
+
|
|
3576
|
+
The words, and what each means:
|
|
3577
|
+
|
|
3578
|
+
<!-- being-look:start -->
|
|
3579
|
+
|
|
3580
|
+
**`data.gender`**
|
|
3581
|
+
|
|
3582
|
+
| Word | Label | Meaning |
|
|
3583
|
+
| ----------- | --------- | ------------------------------------------------------------------ |
|
|
3584
|
+
| `female` | Female | Female. |
|
|
3585
|
+
| `male` | Male | Male. |
|
|
3586
|
+
| `nonbinary` | Nonbinary | Neither male nor female. |
|
|
3587
|
+
| `none` | None | The being has no gender, as against one that is simply unrecorded. |
|
|
3588
|
+
| `other` | Other | A gender none of these words fits. |
|
|
3589
|
+
|
|
3590
|
+
**`data.frame`**
|
|
3591
|
+
|
|
3592
|
+
| Word | Label | Meaning |
|
|
3593
|
+
| --------- | ------- | --------------------------------------------- |
|
|
3594
|
+
| `scant` | Scant | Very thin, with little flesh over the bone. |
|
|
3595
|
+
| `light` | Light | Slender, narrow through shoulder and hip. |
|
|
3596
|
+
| `medium` | Medium | The ordinary build, neither slight nor heavy. |
|
|
3597
|
+
| `heavy` | Heavy | Broad and solid, in muscle or in flesh. |
|
|
3598
|
+
| `massive` | Massive | Exceptionally large in frame. |
|
|
3599
|
+
|
|
3600
|
+
**`data.appearance.eye_color`**
|
|
3601
|
+
|
|
3602
|
+
| Word | Label | Meaning |
|
|
3603
|
+
| ------------ | ---------- | ---------------------------------------------------------------------------------- |
|
|
3604
|
+
| `amber` | Amber | Golden or coppery, with no grey or green in it; the honey-toned eye. |
|
|
3605
|
+
| `black` | Black | An iris that cannot be told from the pupil in any light, darker than `dark_brown`. |
|
|
3606
|
+
| `blue` | Blue | Unmixed blue, from pale ice to deep sea. |
|
|
3607
|
+
| `brown` | Brown | Mid-brown, the iris pattern still legible in ordinary light. |
|
|
3608
|
+
| `dark_brown` | Dark Brown | Brown so deep the iris barely separates from the pupil. |
|
|
3609
|
+
| `grey` | Grey | Grey or grey-blue, cool and without green. |
|
|
3610
|
+
| `green` | Green | Green dominant, with no brown ring worth naming. |
|
|
3611
|
+
| `hazel` | Hazel | Brown and green together, often shifting with the light; the commonest mixed eye. |
|
|
3612
|
+
| `violet` | Violet | The pink-violet of an iris carrying no pigment. |
|
|
3613
|
+
|
|
3614
|
+
**`data.appearance.hair_color`**
|
|
3615
|
+
|
|
3616
|
+
| Word | Label | Meaning |
|
|
3617
|
+
| ------------------ | ---------------- | ------------------------------------------------------------------------- |
|
|
3618
|
+
| `auburn` | Auburn | Red-brown with the red dominant. |
|
|
3619
|
+
| `black` | Black | True black, with no brown cast in sunlight. |
|
|
3620
|
+
| `blonde` | Blonde | Light yellow, from near-white to wheat. |
|
|
3621
|
+
| `brown` | Brown | Mid-brown, neither dark nor reddish. |
|
|
3622
|
+
| `chestnut` | Chestnut | Mid-brown with a red cast, the brown dominant — between brown and auburn. |
|
|
3623
|
+
| `dark_blonde` | Dark Blonde | Blonde darkened towards light brown. |
|
|
3624
|
+
| `dark_brown` | Dark Brown | Brown approaching black, still brown in sunlight. |
|
|
3625
|
+
| `grey` | Grey | Grey throughout, with nothing of the original colour left to read. |
|
|
3626
|
+
| `greying_black` | Greying Black | Black still dominant, grey coming in. |
|
|
3627
|
+
| `greying_brown` | Greying Brown | Brown still dominant, grey coming in. |
|
|
3628
|
+
| `red` | Red | Ginger or copper, the red unmixed with brown. |
|
|
3629
|
+
| `silver` | Silver | Grey with a bright metallic sheen rather than a dull cast. |
|
|
3630
|
+
| `strawberry_blond` | Strawberry Blond | Pale red-gold: blonde with a red cast, lighter than red. |
|
|
3631
|
+
| `white` | White | Wholly white, whether from age or from carrying no pigment. |
|
|
3632
|
+
|
|
3633
|
+
**`data.appearance.skin_color`**
|
|
3634
|
+
|
|
3635
|
+
| Word | Label | Meaning |
|
|
3636
|
+
| ------------ | ---------- | ------------------------------------------------------------------------------------------- |
|
|
3637
|
+
| `pale` | Pale | The lightest skin, which burns rather than browns; also skin carrying no pigment. |
|
|
3638
|
+
| `fair` | Fair | Light with a pink cast, burning before it browns. |
|
|
3639
|
+
| `light` | Light | Light and neutral, browning without burning readily. |
|
|
3640
|
+
| `medium` | Medium | Neither light nor dark, with no strong cast either way. |
|
|
3641
|
+
| `olive` | Olive | Medium with a green-grey cast. |
|
|
3642
|
+
| `tawny` | Tawny | Light brown, warm rather than olive. |
|
|
3643
|
+
| `golden` | Golden | Light to medium with a yellow cast. |
|
|
3644
|
+
| `tanned` | Tanned | Medium, darkened by sun rather than by birth. |
|
|
3645
|
+
| `swarthy` | Swarthy | Dark with an olive or sallow cast, between olive and brown. |
|
|
3646
|
+
| `brown` | Brown | Mid-brown. |
|
|
3647
|
+
| `dark` | Dark | Darker than brown with no particular cast; the general word where no finer shade is stated. |
|
|
3648
|
+
| `dark_brown` | Dark Brown | Deep brown. |
|
|
3649
|
+
| `ebony` | Ebony | The darkest skin, near-black. |
|
|
3650
|
+
|
|
3651
|
+
**`data.appearance.complexion`**
|
|
3652
|
+
|
|
3653
|
+
| Word | Label | Meaning |
|
|
3654
|
+
| ------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
3655
|
+
| `ashen` | Ashen | Grey and drained; the skin of serious illness, shock or terror. |
|
|
3656
|
+
| `blotchy` | Blotchy | Uneven in colour, patched red or pale. |
|
|
3657
|
+
| `chapped` | Chapped | Reddened and cracked by cold and wind. |
|
|
3658
|
+
| `clear` | Clear | Free of blemish, mark or broken vessel. |
|
|
3659
|
+
| `freckled` | Freckled | Freckled, in patches or across the whole face. |
|
|
3660
|
+
| `jaundiced` | Jaundiced | Yellowed, the colour a failing liver gives. |
|
|
3661
|
+
| `leathery` | Leathery | Thickened and toughened by years of exposure. |
|
|
3662
|
+
| `oily` | Oily | Carrying a greasy sheen. |
|
|
3663
|
+
| `pasty` | Pasty | Pale and doughy; the skin of indoor work and poor feeding. |
|
|
3664
|
+
| `pimpled` | Pimpled | Presently broken out, with pimples at brow, cheek or jaw. |
|
|
3665
|
+
| `pockmarked` | Pockmarked | Pitted by pox, or by deep pimples long since healed. |
|
|
3666
|
+
| `rough` | Rough | Coarse in texture, without the wear of outdoor work. |
|
|
3667
|
+
| `ruddy` | Ruddy | High colour at cheek and nose, from weather, drink or constitution. |
|
|
3668
|
+
| `sallow` | Sallow | Yellowish and bloodless. |
|
|
3669
|
+
| `scabrous` | Scabrous | Rough and scaling, the skin of a lasting complaint such as eczema. |
|
|
3670
|
+
| `scarred` | Scarred | Marked by healed wounds. `extra_features` says where and from what. |
|
|
3671
|
+
| `smooth` | Smooth | Even in texture, whatever marks it carries. |
|
|
3672
|
+
| `sun_kissed` | Sun-Kissed | Browned by sun on skin not naturally that dark. |
|
|
3673
|
+
| `sunburnt` | Sunburnt | Presently burned, red and peeling. |
|
|
3674
|
+
| `translucent` | Translucent | So pale the vessels show through. |
|
|
3675
|
+
| `vitiligo` | Vitiligo | Patched with white where the skin has lost its colour, most often at face, hands and mouth. The tone it has lost is still what `skin_color` states. |
|
|
3676
|
+
| `wan` | Wan | Pale and drained; the skin of exhaustion or convalescence. |
|
|
3677
|
+
| `weathered` | Weathered | Worn and lined by sun and wind; the skin of outdoor work. |
|
|
3678
|
+
| `wrinkled` | Wrinkled | Deeply lined by age. |
|
|
3679
|
+
|
|
3680
|
+
<!-- being-look:end -->
|
|
3681
|
+
|
|
3546
3682
|
#### The bodies a being belongs to, and its standing in each
|
|
3547
3683
|
|
|
3548
3684
|
**Membership**: `{rank: number, office: string, societies: string[]}` — `rank`
|
|
@@ -5294,6 +5430,123 @@ The place's `lore` links cover its peoples, calendar, law and history. Political
|
|
|
5294
5430
|
languages belong to a polity's `sohl.system.commonSkills`, while the note's
|
|
5295
5431
|
`description` provides its page summary.
|
|
5296
5432
|
|
|
5433
|
+
#### A region's settlements table
|
|
5434
|
+
|
|
5435
|
+
A region lists its settlements in a table on its own note: one row for each
|
|
5436
|
+
settlement, stating what its market is, how many people it holds and who holds
|
|
5437
|
+
it. **A row is the whole record of a settlement that has no note.** Where a
|
|
5438
|
+
note exists the row links it, and the two must agree. A package that writes no
|
|
5439
|
+
such table is not affected by anything in this section.
|
|
5440
|
+
|
|
5441
|
+
The table is a markdown table under a level-two `## Settlements` heading on the
|
|
5442
|
+
region's `place` note. Its header is exactly these columns, in this order. `For`
|
|
5443
|
+
may be left out; the header carries no other column:
|
|
5444
|
+
|
|
5445
|
+
| Name | Market | People | Held by | For |
|
|
5446
|
+
| ---- | ------ | ------ | ------- | --- |
|
|
5447
|
+
|
|
5448
|
+
- **Name** — the settlement. Where it has a note, a link to it with the pipe
|
|
5449
|
+
escaped for the table, `[[place-ashford\|Ashford]]`; otherwise plain text.
|
|
5450
|
+
- **Market** — the market class as its number and its name, lower case:
|
|
5451
|
+
`1 hamlet`, `2 village`, `3 town`, `4 market town`, `5 city`, `6 great city`.
|
|
5452
|
+
The scale is the one [`data.market`](#what-a-settlements-market-supports)
|
|
5453
|
+
states.
|
|
5454
|
+
- **People** — the population, a whole number, grouped with commas or not:
|
|
5455
|
+
`60`, `420`, `3,400`.
|
|
5456
|
+
- **Held by** — who holds it, written in the region's holding model. Link the
|
|
5457
|
+
holder where it has a note.
|
|
5458
|
+
- **For** — a short phrase saying why the place is there: the ford, the mine,
|
|
5459
|
+
the shrine.
|
|
5460
|
+
|
|
5461
|
+
At least one sentence of prose follows the table, before the next heading,
|
|
5462
|
+
saying what the table leaves out. A section filled by an `sql` fence is
|
|
5463
|
+
generated from the notes and is not read as a settlements table.
|
|
5464
|
+
|
|
5465
|
+
**The region names its holding model as a tag.** A note carrying a settlements
|
|
5466
|
+
table carries at least one of these tags; a region whose countryside is held
|
|
5467
|
+
two ways carries both. Tags stay open, so a misspelled model is not reported as
|
|
5468
|
+
such: the table's note is reported for naming no model.
|
|
5469
|
+
|
|
5470
|
+
| `holdingModel` value | the Held by cell names |
|
|
5471
|
+
| -------------------- | ---------------------- |
|
|
5472
|
+
| `held` | a person or a house |
|
|
5473
|
+
| `endowed` | an institution |
|
|
5474
|
+
| `registered` | an office |
|
|
5475
|
+
| `kin` | a kindred |
|
|
5476
|
+
| `polis` | the city |
|
|
5477
|
+
|
|
5478
|
+
A linked holder is an `affiliation` or a `being`, and a `being` is a person: it
|
|
5479
|
+
may hold land only in a region tagged `held`.
|
|
5480
|
+
|
|
5481
|
+
**A settlement belongs to one table** — that of the nearest place above it, by
|
|
5482
|
+
`parents`, that carries a settlements table. Every `settlement` note that table
|
|
5483
|
+
covers has a row there and nowhere else.
|
|
5484
|
+
|
|
5485
|
+
A worked example. `Vale.md`:
|
|
5486
|
+
|
|
5487
|
+
```markdown
|
|
5488
|
+
---
|
|
5489
|
+
shortcode: vale
|
|
5490
|
+
name: { full: The Vale }
|
|
5491
|
+
type: place
|
|
5492
|
+
subType: region
|
|
5493
|
+
tags: [region, held]
|
|
5494
|
+
data:
|
|
5495
|
+
population: 100000
|
|
5496
|
+
government: crown
|
|
5497
|
+
---
|
|
5498
|
+
|
|
5499
|
+
## Settlements
|
|
5500
|
+
|
|
5501
|
+
| Name | Market | People | Held by | For |
|
|
5502
|
+
| -------------------------- | ------------- | -----: | ---------------------------------------- | -------------------------- |
|
|
5503
|
+
| [[place-ashford\|Ashford]] | 4 market town | 3,400 | [[affiliation-crown\|the Crown]] | the ford on the drove road |
|
|
5504
|
+
| Weyshott | 2 village | 420 | [[being-aldwyn\|Sir Aldwyn of Brynwold]] | the manor's mill |
|
|
5505
|
+
| Cold Hatch | 1 hamlet | 60 | Sir Aldwyn of Brynwold | the sheepwalk |
|
|
5506
|
+
|
|
5507
|
+
Some four hundred further villages lie in the vale, none of them named here.
|
|
5508
|
+
```
|
|
5509
|
+
|
|
5510
|
+
`Ashford.md` states `parents: [vale]`, `population: 3400` and `market: 4`, so its
|
|
5511
|
+
row agrees with it. Weyshott and Cold Hatch have no notes; their rows are their
|
|
5512
|
+
whole record. Change Ashford's row to `3,000` and `package-build lint` reports:
|
|
5513
|
+
|
|
5514
|
+
```text
|
|
5515
|
+
assets/content/Vale.md:16:49: error: figure disagrees: Ashford is carried at 3,000 here and 3,400 on its own note
|
|
5516
|
+
```
|
|
5517
|
+
|
|
5518
|
+
`package-build lint` reports each of these as an error, each named by the
|
|
5519
|
+
phrase its message begins with:
|
|
5520
|
+
|
|
5521
|
+
- **`settlements columns`** — the header is not the declared columns in
|
|
5522
|
+
order. The table's rows are not read until it is.
|
|
5523
|
+
- **`no holding model`** — the note carries a settlements table and none of
|
|
5524
|
+
the holding-model tags. Reported at its `tags`.
|
|
5525
|
+
- **`market class`** — a Market cell is not a class written as its number and
|
|
5526
|
+
its name.
|
|
5527
|
+
- **`people figure`** — a People cell is not a positive whole number.
|
|
5528
|
+
- **`no holder`** — a Held by cell is empty.
|
|
5529
|
+
- **`not a holder`** — a Held by link names a note that is neither an
|
|
5530
|
+
affiliation nor a being.
|
|
5531
|
+
- **`holder out of model`** — a Held by link names a being in a region not
|
|
5532
|
+
tagged `held`.
|
|
5533
|
+
- **`not a settlement`** — a Name link names a note that is not a place.
|
|
5534
|
+
- **`figure disagrees`** — a linked row's People differs from its note's
|
|
5535
|
+
`data.population`, or the note states none.
|
|
5536
|
+
- **`market disagrees`** — a linked row's Market differs from its note's
|
|
5537
|
+
`data.market`, or the note states none.
|
|
5538
|
+
- **`unlinked settlement`** — an unlinked Name is the name or an alias of a
|
|
5539
|
+
settlement note the table covers. The finding gives the link to write.
|
|
5540
|
+
- **`missing row`** — a settlement note the table covers has no row. Reported
|
|
5541
|
+
at the table's header.
|
|
5542
|
+
- **`duplicate settlement`** — a settlement has a second row in one table, or
|
|
5543
|
+
a row in a table other than the one covering it.
|
|
5544
|
+
- **`no tail`** — no sentence follows the table before the next heading.
|
|
5545
|
+
Reported at the table's last row.
|
|
5546
|
+
|
|
5547
|
+
A cell's finding is located at the cell. A link in a cell that resolves to no
|
|
5548
|
+
note is reported by the link check, once, and not again here.
|
|
5549
|
+
|
|
5297
5550
|
### type: scenario
|
|
5298
5551
|
|
|
5299
5552
|
Content prepared to be played — a situation with its cast, places, and possible outcomes.
|