@heroiclands/package-build 23.3.1 → 23.4.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 +14 -0
- package/bin/content-commands.mjs +19 -4
- package/docs/authoring/first-note.md +1 -1
- package/docs/authoring/frontmatter.md +1 -1
- package/docs/commands.md +13 -2
- package/docs/content-format.md +17 -10
- package/docs/guides/release-and-deploy.md +1 -1
- package/docs/reference/format-details.md +150 -14
- package/docs/reference/note-types.md +28 -27
- package/docs/reference/theme-pages.md +5 -4
- package/engine/appearance-features.mjs +418 -0
- package/engine/content-format.yaml +1 -0
- package/engine/content-index.mjs +22 -0
- package/engine/content-links.mjs +9 -0
- package/engine/culture-parents.mjs +301 -0
- package/engine/data-keys.mjs +7 -2
- package/engine/docs-checks.mjs +41 -8
- package/engine/frontmatter-lint.mjs +15 -1
- package/engine/infobox.mjs +5 -5
- package/engine/metadata-index.mjs +11 -0
- package/engine/note-vocabulary.mjs +39 -21
- package/engine/npc-generate.mjs +5 -4
- package/package.json +3 -2
- package/types/engine/appearance-features.d.mts +66 -0
- package/types/engine/culture-parents.d.mts +29 -0
- package/types/engine/data-keys.d.mts +2 -1
- package/types/engine/docs-checks.d.mts +1 -1
- package/types/engine/note-vocabulary.d.mts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 23.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- `package-build lint` requires a being's `complexion` to be a list of complexion words, `[]` where no condition is established, and refuses a single word.
|
|
8
|
+
- `extra_features` admits only short plain descriptions of visible physical marks; colours, skin conditions, gear, voice, manner, looks, handedness, sterility, apparent age and punctuation are errors.
|
|
9
|
+
- `package-build npc new` writes the complexion it draws as a list.
|
|
10
|
+
|
|
11
|
+
## 23.3.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Cultures can inherit their language and appearance from parent cultures when generating characters.
|
|
16
|
+
|
|
3
17
|
## 23.3.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/bin/content-commands.mjs
CHANGED
|
@@ -141,6 +141,7 @@ import { profileFindings } from "../engine/appearance-profile.mjs";
|
|
|
141
141
|
import { namesFindings } from "../engine/language-names.mjs";
|
|
142
142
|
import { parseAddress, renderAddress } from "../engine/address.mjs";
|
|
143
143
|
import { cultureKey, generateNpc, npcDefaults, npcSpecProblems } from "../engine/npc-generate.mjs";
|
|
144
|
+
import { cultureFieldSource, cultureHierarchyProblems } from "../engine/culture-parents.mjs";
|
|
144
145
|
|
|
145
146
|
/**
|
|
146
147
|
* The packs `unpack` extracts.
|
|
@@ -2613,11 +2614,12 @@ function newNpc(config, argv) {
|
|
|
2613
2614
|
throw new Error(`${argv.out} already exists, and \`npc new\` never overwrites a note`);
|
|
2614
2615
|
|
|
2615
2616
|
const root = config.paths.content;
|
|
2617
|
+
const corpusProblems = [];
|
|
2616
2618
|
const records = indexRecordsFor({
|
|
2617
2619
|
contentBase: root,
|
|
2618
2620
|
config,
|
|
2619
2621
|
skipDirectories: config.skipDirectories,
|
|
2620
|
-
problems:
|
|
2622
|
+
problems: corpusProblems,
|
|
2621
2623
|
});
|
|
2622
2624
|
const index = buildLinkIndex(root, {
|
|
2623
2625
|
config,
|
|
@@ -2643,6 +2645,12 @@ function newNpc(config, argv) {
|
|
|
2643
2645
|
`\`data.culture\` ${JSON.stringify(written)} is not a culture: it names a ` +
|
|
2644
2646
|
`${culture.type ?? hit.type ?? "note"} of subType ${culture.subType ?? "none"}`,
|
|
2645
2647
|
);
|
|
2648
|
+
const hierarchyProblems = cultureHierarchyProblems(records, key);
|
|
2649
|
+
for (const problem of hierarchyProblems) emitDiagnostic(problem);
|
|
2650
|
+
if (hierarchyProblems.some((problem) => problem.severity === "error")) {
|
|
2651
|
+
process.exitCode = 1;
|
|
2652
|
+
return;
|
|
2653
|
+
}
|
|
2646
2654
|
const cultureNote = located(hit);
|
|
2647
2655
|
const profile = culture.data?.appearanceProfile;
|
|
2648
2656
|
if (profile === undefined || profile === null)
|
|
@@ -2652,8 +2660,13 @@ function newNpc(config, argv) {
|
|
|
2652
2660
|
`${key} states no \`data.appearanceProfile\`, so \`npc new\` cannot draw its ` +
|
|
2653
2661
|
"people's look",
|
|
2654
2662
|
);
|
|
2663
|
+
const profileSource = cultureFieldSource(records, key, "appearanceProfile") ?? hit;
|
|
2655
2664
|
const profileErrors = profileFindings(
|
|
2656
|
-
{
|
|
2665
|
+
{
|
|
2666
|
+
file: located(profileSource).file,
|
|
2667
|
+
raw: profileSource.raw,
|
|
2668
|
+
fm: profileSource.fm ?? profileSource,
|
|
2669
|
+
},
|
|
2657
2670
|
BEING_LOOK_VOCABULARY,
|
|
2658
2671
|
);
|
|
2659
2672
|
if (profileErrors.length) {
|
|
@@ -2669,6 +2682,8 @@ function newNpc(config, argv) {
|
|
|
2669
2682
|
`${key} states no \`data.language\`, so \`npc new\` has no name lists to draw ` +
|
|
2670
2683
|
"from; name the language skill note its people speak",
|
|
2671
2684
|
);
|
|
2685
|
+
const languageSource = cultureFieldSource(records, key, "language") ?? hit;
|
|
2686
|
+
const languageSourceNote = located(languageSource);
|
|
2672
2687
|
const tuple = parseAddress(tongue, {
|
|
2673
2688
|
package: index.contentPackage,
|
|
2674
2689
|
system: "note",
|
|
@@ -2680,14 +2695,14 @@ function newNpc(config, argv) {
|
|
|
2680
2695
|
const languageHit = languageKey ? index.addressHit(languageKey) : undefined;
|
|
2681
2696
|
if (!languageHit)
|
|
2682
2697
|
throw noteError(
|
|
2683
|
-
|
|
2698
|
+
languageSourceNote,
|
|
2684
2699
|
["data", "language"],
|
|
2685
2700
|
`${key}'s \`data.language\` names no note in this package or its dependencies`,
|
|
2686
2701
|
);
|
|
2687
2702
|
const language = languageHit.fm ?? languageHit;
|
|
2688
2703
|
if (String(language.type ?? languageHit.type) !== "skill" || language.subType !== "language")
|
|
2689
2704
|
throw noteError(
|
|
2690
|
-
|
|
2705
|
+
languageSourceNote,
|
|
2691
2706
|
["data", "language"],
|
|
2692
2707
|
`${key}'s \`data.language\` ${languageKey} is not a language: it names a ` +
|
|
2693
2708
|
`${language.type ?? languageHit.type ?? "note"} of subType ` +
|
|
@@ -26,7 +26,7 @@ A sheltered place where ships load and unload.
|
|
|
26
26
|
|
|
27
27
|
`shortcode` and `type` identify a HeroicLands note; `name.full` gives readers its name. The YAML ends at the second `---`. Everything after it is the shared Markdown body. Run `npm run lint` to check the note, then `npm run build:site` to build its web page. `npm run serve:site` serves the site locally; `npm run build:book` builds the book. A Foundry package's `npm run build:db` also compiles its configured packs. The generated project supplies these scripts and their configuration.
|
|
28
28
|
|
|
29
|
-
For optional writing suggestions, run `npx package-build prose lint assets/content/Places/Harbor.md`. This reports difficult sentences and simpler word choices with line and column numbers. It does not change the note or run as part of `npm run lint`. The [prose analysis command](../commands.md#package-build-prose-lint-path) explains the settings and how to read each suggestion.
|
|
29
|
+
For optional writing suggestions, run `npx package-build prose lint assets/content/Places/Harbor.md`. This reports difficult sentences and simpler word choices with line and column numbers. It does not change the note or run as part of `npm run lint`. The [prose analysis command](../commands.md#package-build-prose-lint-path-and-prose-score-path) explains the settings and how to read each suggestion.
|
|
30
30
|
|
|
31
31
|
## What the note becomes
|
|
32
32
|
|
|
@@ -35,7 +35,7 @@ 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
|
|
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 a list of words, `[]` where no condition is established, and is required once a being states an appearance. 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` lists the visible physical marks no word covers, each a short plain description of one, such as `a burn scar on the left forearm`. The [look reference](../reference/format-details.md#a-beings-look) gives every word and what it means.
|
|
39
39
|
|
|
40
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.
|
|
41
41
|
|
package/docs/commands.md
CHANGED
|
@@ -1898,7 +1898,10 @@ checks frontmatter against the declared vocabulary and each system's `sohl:`
|
|
|
1898
1898
|
/ `hm3:` block, the package's charset (so a book can pick a font that covers
|
|
1899
1899
|
it), that an icon a note writes is one the registry declares, and that
|
|
1900
1900
|
markup inside a note's body does not smuggle in a character the charset
|
|
1901
|
-
check cannot see.
|
|
1901
|
+
check cannot see. A being's appearance is held to
|
|
1902
|
+
[a being's look](reference/format-details.md#a-beings-look): `complexion` a
|
|
1903
|
+
list, and `extra_features` only short plain descriptions of physical marks.
|
|
1904
|
+
`--no-references` turns off the check that a frontmatter
|
|
1902
1905
|
shortcode reference lands, including references in schema-declared system
|
|
1903
1906
|
fields, for a tree whose cross-package references it cannot see. Address
|
|
1904
1907
|
references in system fields resolve against this package and its declared
|
|
@@ -2828,6 +2831,14 @@ culture missing either, with an error at the culture note:
|
|
|
2828
2831
|
`data.names` is an error at the language note. See
|
|
2829
2832
|
[name lists](reference/format-details.md#name-lists).
|
|
2830
2833
|
|
|
2834
|
+
The content-index JSONL resolves a culture's `data.language` and
|
|
2835
|
+
`data.appearanceProfile` before this command reads them. A child culture may
|
|
2836
|
+
inherit each omitted field from its `data.parents`, while a stated value keeps
|
|
2837
|
+
precedence. The command consumes the resolved values and keeps the selected
|
|
2838
|
+
child culture on the generated note. A parent cycle or conflicting inherited
|
|
2839
|
+
sources are errors; complete fields on the selected culture do not excuse a
|
|
2840
|
+
cycle. See [culture parents](reference/format-details.md#culture-parents-and-inherited-fields).
|
|
2841
|
+
|
|
2831
2842
|
A profile or name lists with problems are refused with a finding at each.
|
|
2832
2843
|
|
|
2833
2844
|
A spec that states `name.full` keeps it, and the name must fit the language's
|
|
@@ -2915,7 +2926,7 @@ data:
|
|
|
2915
2926
|
eye_color: brown
|
|
2916
2927
|
hair_color: black
|
|
2917
2928
|
skin_color: brown
|
|
2918
|
-
complexion: clear
|
|
2929
|
+
complexion: [clear]
|
|
2919
2930
|
extra_features: []
|
|
2920
2931
|
---
|
|
2921
2932
|
|
package/docs/content-format.md
CHANGED
|
@@ -13,15 +13,15 @@ Every typed note requires a nonempty body, including drafts, folders and homepag
|
|
|
13
13
|
|
|
14
14
|
Start with [your first note](authoring/first-note.md). It explains the smallest valid note and shows the JournalEntry, web page, book entry, and content-index record made from it. Then use the chapters below in the order your note needs them.
|
|
15
15
|
|
|
16
|
-
| Need | Read
|
|
17
|
-
| --------------------------------------------------------- |
|
|
18
|
-
| Frontmatter, `data`, system blocks, and infoboxes | [Frontmatter](authoring/frontmatter.md)
|
|
19
|
-
| Addresses, links, anchors, fences, and inline expressions | [Links and markup](authoring/links-and-markup.md)
|
|
20
|
-
| Images, icons, audio, provenance, and sidecars | [Assets](authoring/assets.md)
|
|
21
|
-
| Canonical dates, calendars, eras, and conversions | [Dates and calendars](authoring/dates-and-calendars.md)
|
|
22
|
-
| All accepted note types, subtypes, and fields | [Note type reference](reference/note-types.md)
|
|
23
|
-
| Exact format details and system mappings | [Detailed reference](reference/format-details.md)
|
|
24
|
-
| Optional readability and wording suggestions | [Prose analysis](commands.md#package-build-prose-lint-path) |
|
|
16
|
+
| Need | Read |
|
|
17
|
+
| --------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
18
|
+
| Frontmatter, `data`, system blocks, and infoboxes | [Frontmatter](authoring/frontmatter.md) |
|
|
19
|
+
| Addresses, links, anchors, fences, and inline expressions | [Links and markup](authoring/links-and-markup.md) |
|
|
20
|
+
| Images, icons, audio, provenance, and sidecars | [Assets](authoring/assets.md) |
|
|
21
|
+
| Canonical dates, calendars, eras, and conversions | [Dates and calendars](authoring/dates-and-calendars.md) |
|
|
22
|
+
| All accepted note types, subtypes, and fields | [Note type reference](reference/note-types.md) |
|
|
23
|
+
| Exact format details and system mappings | [Detailed reference](reference/format-details.md) |
|
|
24
|
+
| Optional readability and wording suggestions | [Prose analysis](commands.md#package-build-prose-lint-path-and-prose-score-path) |
|
|
25
25
|
|
|
26
26
|
## The shared note
|
|
27
27
|
|
|
@@ -92,10 +92,17 @@ Place notes may declare a governing affiliation with `data.government`, or expli
|
|
|
92
92
|
|
|
93
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
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`
|
|
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. `complexion` is a list, required once a being states an appearance. `data.appearance.extra_features` lists the being's visible physical marks, each a short plain description of one, and an entry stating a colour, a skin condition or anything that is not a mark is an error. See [a being's look](reference/format-details.md#a-beings-look).
|
|
96
96
|
|
|
97
97
|
A culture note may state what its people look like in `data.appearanceProfile`: weighted words for frame, eyes, hair, skin and complexion, and height ranges by gender, all from the same vocabulary. A culture names its tongue in `data.language`, and that language skill note may state `data.names`: the patterns its speakers' names are built by and the lists each part is drawn from. `package-build npc new` writes a complete npc note from a spec of a culture and a gender, drawing the name from those lists and everything else the spec leaves out from the profile. See [appearance profiles](reference/format-details.md#appearance-profiles), [name lists](reference/format-details.md#name-lists) and [the command](commands.md#package-build-npc-new).
|
|
98
98
|
|
|
99
|
+
A culture may name its larger cultures in `data.parents`. Each entry names a
|
|
100
|
+
culture lore note. Omitted `data.language` and `data.appearanceProfile` fields
|
|
101
|
+
inherit independently through those parents; the content-index JSONL contains
|
|
102
|
+
the resolved values, which `npc new` reads directly. A stated field wins over
|
|
103
|
+
its inherited value. See [culture parents](reference/format-details.md#culture-parents-and-inherited-fields)
|
|
104
|
+
for a complete example, parent ordering and findings.
|
|
105
|
+
|
|
99
106
|
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).
|
|
100
107
|
|
|
101
108
|
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).
|
|
@@ -31,7 +31,7 @@ document ID appears under another address, and **withdrawn** when that ID
|
|
|
31
31
|
appears under none. Findings are warnings by default. `--strict` turns them
|
|
32
32
|
into errors for a release gate. The comparison reads shipped Item packs, so it
|
|
33
33
|
reports the surface consumers actually resolve rather than inferring changes
|
|
34
|
-
from filenames. Use the [Address reference](../
|
|
34
|
+
from filenames. Use the [Address reference](../reference/format-details.md#addresses)
|
|
35
35
|
when choosing a durable shortcode.
|
|
36
36
|
|
|
37
37
|
## Build the release files
|
|
@@ -1916,7 +1916,7 @@ largest print slot needs. Both exempt a vector asset, which carries no pixel
|
|
|
1916
1916
|
dimensions and no aspect that survives being drawn at a nominal size.
|
|
1917
1917
|
|
|
1918
1918
|
`role: map` also selects a captioned image's counter — see
|
|
1919
|
-
[
|
|
1919
|
+
[captions and numbered references](../authoring/links-and-markup.md#captions-and-numbered-references).
|
|
1920
1920
|
A fence whose picture draws an address with that role counts as `Map` rather
|
|
1921
1921
|
than `Figure`, on every surface that numbers it, because the role is the one
|
|
1922
1922
|
fact the fence's own markup cannot state.
|
|
@@ -2715,6 +2715,104 @@ table would otherwise need: the authored `ORDER BY` decides the section order to
|
|
|
2715
2715
|
**Beware `packFolder`.** It is a note's _pack_ folder, not its directory — the
|
|
2716
2716
|
directory is `file.folder`.
|
|
2717
2717
|
|
|
2718
|
+
##### Culture parents and inherited fields
|
|
2719
|
+
|
|
2720
|
+
A `lore` note of `subType: culture` may list the larger cultures it belongs to
|
|
2721
|
+
in `data.parents`. Each entry is an Address naming another culture lore note;
|
|
2722
|
+
a missing target, a target of another type or subtype, and a parent cycle are
|
|
2723
|
+
errors at the offending list entry. No other lore subtype accepts the key.
|
|
2724
|
+
|
|
2725
|
+
A culture inherits `data.language` and `data.appearanceProfile` independently
|
|
2726
|
+
when it leaves either field out. A stated value wins for that field. The
|
|
2727
|
+
profile is inherited as one complete object; its weights and ranges are not
|
|
2728
|
+
merged with another profile. Parents are searched in listed order, depth-first:
|
|
2729
|
+
the first parent's chain is searched before the next parent's chain. Sources
|
|
2730
|
+
at the same depth that disagree on a field produce a finding. Nothing is
|
|
2731
|
+
inherited through a broken parent address.
|
|
2732
|
+
|
|
2733
|
+
The emitted content-index JSONL carries the resolved fields in the child's
|
|
2734
|
+
`data`, exactly as if the child had stated them. `package-build npc new` and
|
|
2735
|
+
other consumers read those resolved values; they do not walk culture parents.
|
|
2736
|
+
The child's `data.culture` remains its own Address. A being, place or
|
|
2737
|
+
affiliation naming the parent in `data.culture` belongs to that named culture;
|
|
2738
|
+
it does not match the parent's children.
|
|
2739
|
+
|
|
2740
|
+
These complete notes give Riverfolk their parent culture's tongue and profile:
|
|
2741
|
+
|
|
2742
|
+
```markdown
|
|
2743
|
+
---
|
|
2744
|
+
shortcode: reedfolk
|
|
2745
|
+
name: { full: Reedfolk }
|
|
2746
|
+
type: lore
|
|
2747
|
+
subType: culture
|
|
2748
|
+
data:
|
|
2749
|
+
language: skill-reedtongue
|
|
2750
|
+
appearanceProfile:
|
|
2751
|
+
frame: { medium: 1 }
|
|
2752
|
+
eye_color: { brown: 1 }
|
|
2753
|
+
hair_color: { black: 1 }
|
|
2754
|
+
skin_color: { tawny: 1 }
|
|
2755
|
+
complexion: { clear: 1 }
|
|
2756
|
+
height:
|
|
2757
|
+
female: { min: 1.5m, max: 1.7m }
|
|
2758
|
+
male: { min: 1.6m, max: 1.8m }
|
|
2759
|
+
---
|
|
2760
|
+
|
|
2761
|
+
Reedfolk share the reed tongue and live along the marsh's waterways. Their
|
|
2762
|
+
settlements trade by boat, hold seasonal gatherings and pass their stories
|
|
2763
|
+
between families at those gatherings.
|
|
2764
|
+
```
|
|
2765
|
+
|
|
2766
|
+
```markdown
|
|
2767
|
+
---
|
|
2768
|
+
shortcode: riverfolk
|
|
2769
|
+
name: { full: Riverfolk }
|
|
2770
|
+
type: lore
|
|
2771
|
+
subType: culture
|
|
2772
|
+
data:
|
|
2773
|
+
parents: [lore-reedfolk]
|
|
2774
|
+
---
|
|
2775
|
+
|
|
2776
|
+
Riverfolk belong to the Reedfolk culture and share its tongue. They live
|
|
2777
|
+
beside the river's deep channels, where their boats carry grain, timber and
|
|
2778
|
+
woven reeds between settlements.
|
|
2779
|
+
```
|
|
2780
|
+
|
|
2781
|
+
The parent names this language note, whose lists supply generated names:
|
|
2782
|
+
|
|
2783
|
+
```markdown
|
|
2784
|
+
---
|
|
2785
|
+
shortcode: reedtongue
|
|
2786
|
+
name: { full: Reed Tongue }
|
|
2787
|
+
type: skill
|
|
2788
|
+
subType: language
|
|
2789
|
+
data:
|
|
2790
|
+
pack: skills
|
|
2791
|
+
names:
|
|
2792
|
+
pattern: "{given} {kin}"
|
|
2793
|
+
given:
|
|
2794
|
+
female: [Nara]
|
|
2795
|
+
male: [Taro]
|
|
2796
|
+
kin: [Mori]
|
|
2797
|
+
---
|
|
2798
|
+
|
|
2799
|
+
The reed tongue is spoken beside the marsh's waterways. Its speakers use a
|
|
2800
|
+
given name followed by a family name, and carry those names between river
|
|
2801
|
+
settlements with their trade.
|
|
2802
|
+
```
|
|
2803
|
+
|
|
2804
|
+
In a package named `reedflats`, the Riverfolk index record carries the Reedfolk
|
|
2805
|
+
profile and `data.language` as a published Address object:
|
|
2806
|
+
|
|
2807
|
+
```json
|
|
2808
|
+
{ "address": "reedflats-note-skill-reedtongue", "anchor": null, "anchorKind": null }
|
|
2809
|
+
```
|
|
2810
|
+
|
|
2811
|
+
Adding `language: skill-rivertongue` to Riverfolk's `data` selects that language
|
|
2812
|
+
instead while retaining the inherited profile, provided the named language
|
|
2813
|
+
note exists. Stating an `appearanceProfile` there replaces the inherited
|
|
2814
|
+
profile while leaving the inherited tongue in place.
|
|
2815
|
+
|
|
2718
2816
|
##### Culture in the index
|
|
2719
2817
|
|
|
2720
2818
|
`data.culture` in the index is the note's **resolved** culture, which is its
|
|
@@ -3518,8 +3616,8 @@ See [a being's subtype describes the subject](#a-beings-subtype-describes-the-su
|
|
|
3518
3616
|
| `appearance.eye_color` | a word | Eye colour — see [a being's look](#a-beings-look) |
|
|
3519
3617
|
| `appearance.hair_color` | a word | Hair colour — see [a being's look](#a-beings-look) |
|
|
3520
3618
|
| `appearance.skin_color` | a word | Skin colour — see [a being's look](#a-beings-look) |
|
|
3521
|
-
| `appearance.complexion` | `word
|
|
3522
|
-
| `appearance.extra_features` | `string[]` |
|
|
3619
|
+
| `appearance.complexion` | `word[]`, required with `appearance` | The skin's condition, a list of words — see [a being's look](#a-beings-look) |
|
|
3620
|
+
| `appearance.extra_features` | `string[]` | The visible physical marks no word covers — see [a being's look](#a-beings-look) |
|
|
3523
3621
|
|
|
3524
3622
|
Author `data.height` as a string of decimal metres (`1.91m` or `1.91 m`) or
|
|
3525
3623
|
whole feet with optional inches (`6'`, `6'3"`, or `6' 3"`). Inches must be
|
|
@@ -3550,15 +3648,45 @@ vocabulary**, so every package describes a face in the same terms and a
|
|
|
3550
3648
|
misspelt or invented word is caught. `data.gender`, `data.frame`,
|
|
3551
3649
|
`data.appearance.eye_color`, `data.appearance.hair_color` and
|
|
3552
3650
|
`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
3651
|
Any other value — a word from another field's list, a variant spelling such as
|
|
3556
3652
|
`gray` for `grey`, or an empty string — is an error at the value, naming the
|
|
3557
3653
|
words the field takes. Leave a field out when the fact is unrecorded.
|
|
3558
3654
|
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3655
|
+
**`data.appearance.complexion` is a list, and a being that states an appearance
|
|
3656
|
+
must state it.** A face carries more than one condition at once, so the field
|
|
3657
|
+
is always a list of complexion words: `[weathered, freckled]`, `[clear]` for
|
|
3658
|
+
skin with nothing remarkable about it, or `[]` where no condition is
|
|
3659
|
+
established. A single word written outside a list, such as `complexion: clear`,
|
|
3660
|
+
is an error that asks for the list, and so is an `appearance` map with no
|
|
3661
|
+
`complexion` or a `complexion` of `null`.
|
|
3662
|
+
|
|
3663
|
+
**`data.appearance.extra_features` lists the visible physical marks no word
|
|
3664
|
+
covers** — a scar and where it is, a missing finger, a tattoo, a limp. Each
|
|
3665
|
+
entry is a short plain description of one mark. The closed fields above carry
|
|
3666
|
+
everything else, so an entry is an error at that entry when it:
|
|
3667
|
+
|
|
3668
|
+
- states a hair, eye or skin colour or a skin condition, which belong in
|
|
3669
|
+
`hair_color`, `eye_color`, `skin_color` and `complexion` — `auburn hair`,
|
|
3670
|
+
`red eyes`, `milky white eyes`, `brown and black hair`, `pale skin`,
|
|
3671
|
+
`weathered complexion`, `freckled`;
|
|
3672
|
+
- names gear, clothing or a weapon — `a mail shirt kept oiled`,
|
|
3673
|
+
`carries a heavy battleaxe`;
|
|
3674
|
+
- describes a voice or speech — `speaks with a lisp`;
|
|
3675
|
+
- describes behaviour, manner or temperament — `fidgets constantly`,
|
|
3676
|
+
`an infectious grin`, `hyperactive`;
|
|
3677
|
+
- gives an impression of looks or presence — `startlingly beautiful`,
|
|
3678
|
+
`a commanding presence`, and `a beautiful tattoo of a crane` too, mark or not;
|
|
3679
|
+
- states handedness, sterility or an apparent age — `left handed`, `sterile`,
|
|
3680
|
+
`a boyish face that makes him look younger`;
|
|
3681
|
+
- carries any punctuation, apart from a hyphen or an apostrophe between two
|
|
3682
|
+
letters. `ink-stained fingers` and `a lion's mane` are marks; `Scar: left
|
|
3683
|
+
cheek` and `a scar on the cheek, from a duel` are not.
|
|
3684
|
+
|
|
3685
|
+
A mark that names the skin it sits on is still a mark: `a burn scar on the left
|
|
3686
|
+
forearm` and `a brand scarred into the skin above the heart` are features. A
|
|
3687
|
+
tattoo, scar or brand may show gear or a gesture, as in `a tattoo of a knight's
|
|
3688
|
+
helmet`, and stands; the voice, impression, handedness, sterility and age rules
|
|
3689
|
+
hold even for a mark.
|
|
3562
3690
|
|
|
3563
3691
|
```yaml
|
|
3564
3692
|
data:
|
|
@@ -3571,6 +3699,7 @@ data:
|
|
|
3571
3699
|
complexion: [weathered, freckled]
|
|
3572
3700
|
extra_features:
|
|
3573
3701
|
- a burn scar across the back of the left hand
|
|
3702
|
+
- ink-stained fingers
|
|
3574
3703
|
```
|
|
3575
3704
|
|
|
3576
3705
|
The words, and what each means:
|
|
@@ -3737,8 +3866,9 @@ missing key, a missing `female` or `male` range, a height that does not read,
|
|
|
3737
3866
|
a range whose `min` is above its `max`, and a `height` key that is not a
|
|
3738
3867
|
gender.
|
|
3739
3868
|
|
|
3740
|
-
`package-build npc new` refuses a culture
|
|
3741
|
-
culture note.
|
|
3869
|
+
`package-build npc new` refuses a culture with no resolved profile, naming the
|
|
3870
|
+
culture note. A culture may obtain the complete profile from its
|
|
3871
|
+
[parents](#culture-parents-and-inherited-fields).
|
|
3742
3872
|
|
|
3743
3873
|
#### Name lists
|
|
3744
3874
|
|
|
@@ -5006,13 +5136,18 @@ data:
|
|
|
5006
5136
|
The saga lists under **In song and story** on `place-ironfells`, which holds the
|
|
5007
5137
|
sack, on `place-east` and on `lore-fords`.
|
|
5008
5138
|
|
|
5009
|
-
Calendar fields are written only on a `calendar` note,
|
|
5010
|
-
only on a `literature` note
|
|
5139
|
+
Calendar fields are written only on a `calendar` note, `form` and `subjects`
|
|
5140
|
+
only on a `literature` note, `language` only on `literature` and `culture`, and
|
|
5141
|
+
`parents` only on `culture`. Written on any other lore subtype, each is an
|
|
5142
|
+
error at its own key.
|
|
5011
5143
|
`culture` may be written on any lore subType. A culture note is itself the culture, so it
|
|
5012
5144
|
leaves the field out or names itself, by its shortcode or by any longer form of its Address;
|
|
5013
5145
|
naming any other note is an error at the value. A `lore` note that states no culture has
|
|
5014
|
-
none
|
|
5015
|
-
|
|
5146
|
+
none; a culture note reads as its own Address in the index, including when it
|
|
5147
|
+
names parent cultures. Culture parents supply language and appearance fields,
|
|
5148
|
+
not a different cultural identity. See
|
|
5149
|
+
[Culture parents](#culture-parents-and-inherited-fields) and
|
|
5150
|
+
[Culture in the index](#culture-in-the-index).
|
|
5016
5151
|
|
|
5017
5152
|
| `data` property | Values | Description |
|
|
5018
5153
|
| ------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -5046,6 +5181,7 @@ its own Address in the index. See [Culture in the index](#culture-in-the-index).
|
|
|
5046
5181
|
| `culture` | `Address` | The people this lore belongs to — for a `literature` note, the people whose work it is — naming a lore note with `subType: culture`; not on a `culture` note |
|
|
5047
5182
|
| `form` | `string` | `literature` only: the kind of work in its people's own terms — `epic`, `saga`, `praise-song`, `elegy`. Free text |
|
|
5048
5183
|
| `subjects` | `Address[]` | `literature` only: the beings, places, gods and other notes the work concerns, and any event, as `note#id` |
|
|
5184
|
+
| `parents` | `Address[]` | `culture` only: the larger cultures this one belongs to; each target is a culture lore note — see [culture parents](#culture-parents-and-inherited-fields) |
|
|
5049
5185
|
| `language` | `Address` | `literature` and `culture` only: the tongue a work is composed in, or a culture's people speak, naming a skill note with `subType: language`; `package-build npc new` draws a culture's names from that language's [name lists](#name-lists) |
|
|
5050
5186
|
| `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
|
|
5051
5187
|
| `appearanceProfile` | `{ frame, eye_color, hair_color, skin_color, complexion, height }` | `culture` only: what its people look like, for `package-build npc new` — see [appearance profiles](#appearance-profiles) |
|
|
@@ -53,33 +53,33 @@ These fields are accepted by every note type. A field's value can still be irrel
|
|
|
53
53
|
|
|
54
54
|
**Subtypes:** `npc`, `character`, `creature`.
|
|
55
55
|
|
|
56
|
-
| Field | Shape
|
|
57
|
-
| -------------------------------- |
|
|
58
|
-
| `data.icon` | an Address
|
|
59
|
-
| `data.tokenIcon` | an Address
|
|
60
|
-
| `data.templatePriority` | number
|
|
61
|
-
| `data.archetypes` | list of strings
|
|
62
|
-
| `data.occupation` | string
|
|
63
|
-
| `data.lore` | list of Addresses
|
|
64
|
-
| `data.culture` | an Address
|
|
65
|
-
| `data.homes` | list of Addresses
|
|
66
|
-
| `data.affiliations` | a standing map keyed by Address
|
|
67
|
-
| `data.socialTies` | a map keyed by Address
|
|
68
|
-
| `data.gender` | string
|
|
69
|
-
| `data.species` | an Address
|
|
70
|
-
| `data.born` | string
|
|
71
|
-
| `data.calendar` | an Address
|
|
72
|
-
| `data.died` | string
|
|
73
|
-
| `data.age` | string
|
|
74
|
-
| `data.ageYears` | number
|
|
75
|
-
| `data.height` | metres or feet and inches
|
|
76
|
-
| `data.weight` | kilograms or pounds
|
|
77
|
-
| `data.frame` | string
|
|
78
|
-
| `data.appearance.eye_color` | string
|
|
79
|
-
| `data.appearance.hair_color` | string
|
|
80
|
-
| `data.appearance.skin_color` | string
|
|
81
|
-
| `data.appearance.complexion` |
|
|
82
|
-
| `data.appearance.extra_features` | list of strings
|
|
56
|
+
| Field | Shape | Meaning |
|
|
57
|
+
| -------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `data.icon` | an Address | The document's profile art — an `icon` address, resolved into `img`. |
|
|
59
|
+
| `data.tokenIcon` | an Address | What a token on the canvas wears — an `icon` address; unset, it follows `icon`. |
|
|
60
|
+
| `data.templatePriority` | number | Template priority; unset means the note is not a template. |
|
|
61
|
+
| `data.archetypes` | list of strings | Archetypal behaviours the being fits. |
|
|
62
|
+
| `data.occupation` | string | What the being does for a living. |
|
|
63
|
+
| `data.lore` | list of Addresses | Lore concerning this being — the law it lives under, the customs it is subject to, the traditions it was raised in. |
|
|
64
|
+
| `data.culture` | an Address | The being's primary culture, as a culture lore note. |
|
|
65
|
+
| `data.homes` | list of Addresses | Places the being calls home. |
|
|
66
|
+
| `data.affiliations` | a standing map keyed by Address | Bodies the being belongs to, keyed by Address, each entry holding the standing it holds there — `rank`, required, a level on that body's own ladder, and `office`, optional, a post that body names. |
|
|
67
|
+
| `data.socialTies` | a map keyed by Address | Defining ties directed from this being to others: `patron` (Supports the subject from greater power, wealth, or status.); `friend` (Supports the subject out of goodwill.); `dependent` (Relies on the subject's support or protection.); `acquaintance` (Knows the subject without a strong disposition.); `rival` (Opposes the subject without implacable hostility.); `nemesis` (Opposes the subject personally and implacably.) |
|
|
68
|
+
| `data.gender` | string | One of `female`, `male`, `nonbinary`, `none` or `other`. `none` says the being has no gender; an absent field says its gender is unrecorded. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
69
|
+
| `data.species` | an Address | The being's species, as a lore note. |
|
|
70
|
+
| `data.born` | string | When the being was born — a date, or `unknown` where the birth is unrecorded. Absent, the being was never born. |
|
|
71
|
+
| `data.calendar` | an Address | Calendar that displays this being's dates. |
|
|
72
|
+
| `data.died` | string | When the being died — a date, or `unknown` where the death is unrecorded. Absent, the being is alive. |
|
|
73
|
+
| `data.age` | string | Age in years, stated only to override what `born` says — `34`, or `~34` for an estimate. Unstated beside a dated `born` it is computed; unstated beside an unknown or absent `born` the age is unknown. |
|
|
74
|
+
| `data.ageYears` | number | Written by the compiler beside an `age` estimate — the `~` stripped, the magnitude alone. A note never authors this. |
|
|
75
|
+
| `data.height` | metres or feet and inches | Height in metres or feet and inches. |
|
|
76
|
+
| `data.weight` | kilograms or pounds | Body weight in kilograms or pounds. |
|
|
77
|
+
| `data.frame` | string | Relative frame — one of `scant`, `light`, `medium`, `heavy` or `massive`. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
78
|
+
| `data.appearance.eye_color` | string | Eye colour: one of `amber`, `black`, `blue`, `brown`, `dark_brown`, `grey`, `green`, `hazel` or `violet`. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
79
|
+
| `data.appearance.hair_color` | string | Hair colour: one of `auburn`, `black`, `blonde`, `brown`, `chestnut`, `dark_blonde`, `dark_brown`, `grey`, `greying_black`, `greying_brown`, `red`, `silver`, `strawberry_blond` or `white`. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
80
|
+
| `data.appearance.skin_color` | string | Skin colour: one of `pale`, `fair`, `light`, `medium`, `olive`, `tawny`, `golden`, `tanned`, `swarthy`, `brown`, `dark`, `dark_brown` or `ebony`. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
81
|
+
| `data.appearance.complexion` | a list of words, such as `[weathered]` or `[]` | The skin's condition, as a list of `ashen`, `blotchy`, `chapped`, `clear`, `freckled`, `jaundiced`, `leathery`, `oily`, `pasty`, `pimpled`, `pockmarked`, `rough`, `ruddy`, `sallow`, `scabrous`, `scarred`, `smooth`, `sun_kissed`, `sunburnt`, `translucent`, `vitiligo`, `wan`, `weathered` or `wrinkled`: `[weathered, freckled]`, `[clear]` for unremarked skin, or `[]` where no condition is established. Required once a being states an appearance; a single word outside a list is an error. See [a being's look](format-details.md#a-beings-look) for what each word means. |
|
|
82
|
+
| `data.appearance.extra_features` | list of strings | The visible physical marks no word covers, each a short plain description of one: `a burn scar on the left forearm`, `a missing finger`. An entry stating a hair, eye or skin colour or a skin condition, gear or clothing, a voice, behaviour or manner, an impression, handedness, sterility or an apparent age is an error, as is any punctuation but a hyphen or apostrophe inside a word. See [a being's look](format-details.md#a-beings-look). |
|
|
83
83
|
|
|
84
84
|
**Inner keys** — a key a field's value does not declare is an error at its own line and column.
|
|
85
85
|
|
|
@@ -533,6 +533,7 @@ Lore records in-world knowledge. A `culture` describes a people; a `custom` desc
|
|
|
533
533
|
| `data.namedDays` | list of `{ name, abbreviation?, day }` | Names assigned to particular days of the year. |
|
|
534
534
|
| `data.eras` | list of `{ shortcode, name, marker?, abbreviation?, proclaimedBy?, start, label? }` | The year-counts kept in this calendar. A marker names one era and uses these months. |
|
|
535
535
|
| `data.formats` | map of named Calendaria format strings | Named patterns for reading and writing this calendar's dates. |
|
|
536
|
+
| `data.parents` | list of Addresses | Culture only: parent culture lore notes, searched in listed depth-first order for omitted language and appearance profile fields. |
|
|
536
537
|
| `data.culture` | an Address | The people this lore belongs to — for a work of literature, the people whose work it is — as a culture lore note. A culture note is its own culture, and states the field only as itself. |
|
|
537
538
|
| `data.form` | string | The kind of work in its people's own terms — an epic, a saga, a praise-song, an elegy. Free text. |
|
|
538
539
|
| `data.subjects` | list of Addresses | The beings, places, gods and other notes the work concerns, and each event it concerns, named as `place-ironfells#sack`. |
|
|
@@ -127,7 +127,7 @@ of two ways, and the difference is who resolved it: a content page carries
|
|
|
127
127
|
`data.banner`, which the build resolved from the asset Address the note
|
|
128
128
|
declared into the address its asset host serves; a hand-authored page carries
|
|
129
129
|
a top-level `banner:`, which the theme resolves against `params.cdnBaseURL`
|
|
130
|
-
(see [`params.cdnBaseURL`](../configuration.md#
|
|
130
|
+
(see [`params.cdnBaseURL`](../configuration.md#the-generated-hugo-configuration)).
|
|
131
131
|
|
|
132
132
|
**Resolution order.**
|
|
133
133
|
|
|
@@ -303,7 +303,7 @@ fails this theme's own check until the slot table gives it a maximum.
|
|
|
303
303
|
wrapping. On narrow screens, figures remain in document order without text
|
|
304
304
|
wrapping. An image's label is alternative text, carried on the image itself
|
|
305
305
|
for a reader who cannot see it, and is not drawn beneath the picture. See
|
|
306
|
-
[
|
|
306
|
+
[captions and numbered references](../authoring/links-and-markup.md#captions-and-numbered-references)
|
|
307
307
|
for how an author writes `size`, `float` and a role.
|
|
308
308
|
|
|
309
309
|
## A numbered figure
|
|
@@ -479,8 +479,9 @@ The home page declares no `infoboxes:`, `related:`, `date:` or `tags:`, so
|
|
|
479
479
|
those pieces of a page stay silent.
|
|
480
480
|
|
|
481
481
|
**No `type` at all** — a site whose home page is a set of entry points into
|
|
482
|
-
everything it publishes — renders the featured grid
|
|
483
|
-
|
|
482
|
+
everything it publishes — renders the featured grid from `params.home`.
|
|
483
|
+
A package-build configuration supplies those values through
|
|
484
|
+
[`site.hugo`](../configuration.md#site).
|
|
484
485
|
|
|
485
486
|
### A section landing
|
|
486
487
|
|