@heroiclands/package-build 23.1.1 → 23.2.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 +63 -0
- package/bin/content-commands.mjs +68 -149
- package/bin/package-build.mjs +56 -10
- package/ci/check-banners.mjs +42 -6
- package/ci/confirm-npm-version.mjs +135 -0
- package/ci/content-format-reference.mjs +14 -5
- package/config.mjs +1 -0
- package/container.mjs +185 -4
- package/content-config.mjs +333 -210
- package/deploy.mjs +116 -10
- package/docs/api.md +238 -246
- package/docs/authoring/assets.md +11 -5
- package/docs/authoring/frontmatter.md +1 -1
- package/docs/authoring/links-and-markup.md +87 -0
- package/docs/commands.md +138 -99
- package/docs/configuration.md +277 -125
- package/docs/content-format.md +2 -0
- package/docs/diagnostics.md +48 -13
- package/docs/guides/book.md +341 -21
- package/docs/guides/e2e.md +13 -2
- package/docs/guides/icons.md +14 -4
- package/docs/guides/module-project.md +18 -8
- package/docs/guides/release-and-deploy.md +32 -0
- package/docs/guides/site.md +5 -2
- package/docs/project-setup.md +30 -10
- package/docs/reference/format-details.md +373 -170
- package/docs/reference/note-types.md +128 -109
- package/docs/reference/theme-pages.md +31 -6
- package/e2e.mjs +140 -28
- package/engine/actor-compiler.mjs +22 -31
- package/engine/address-charset.mjs +4 -17
- package/engine/address-fields.mjs +1 -1
- package/engine/address-render.mjs +12 -1
- package/engine/address-values.mjs +6 -0
- package/engine/address.mjs +46 -33
- package/engine/art-fields.mjs +30 -5
- package/engine/art-slots.mjs +10 -1
- package/engine/asset-bindings.mjs +12 -1
- package/engine/base-compiler.mjs +34 -65
- package/engine/being-age.mjs +2 -7
- package/engine/being-measurements.mjs +12 -1
- package/engine/calendar-artifacts.mjs +6 -0
- package/engine/calendar-choice.mjs +12 -1
- package/engine/calendar-format.mjs +12 -1
- package/engine/calendar-human.mjs +12 -1
- package/engine/compile-corpus.mjs +3 -1
- package/engine/content-address.mjs +9 -12
- package/engine/content-alerts.mjs +13 -1
- package/engine/content-blocks.mjs +14 -3
- package/engine/content-embeds.mjs +11 -3
- package/engine/content-figures.mjs +9 -0
- package/engine/content-footnotes.mjs +12 -1
- package/engine/content-format-check.mjs +11 -262
- package/engine/content-format.yaml +5 -2
- package/engine/content-images.mjs +3 -0
- package/engine/content-index.mjs +443 -20
- package/engine/content-links.mjs +29 -35
- package/engine/content-lint.mjs +2 -3
- package/engine/content-poetry.mjs +12 -1
- package/engine/content-slug.mjs +2 -14
- package/engine/content-spans.mjs +13 -1
- package/engine/content-tables.mjs +12 -1
- package/engine/culture-choice.mjs +210 -13
- package/engine/data-keys.mjs +19 -16
- package/engine/date-conversion.mjs +12 -1
- package/engine/declaration-check.mjs +9 -0
- package/engine/derived-fields.mjs +6 -7
- package/engine/diagnostics.mjs +34 -4
- package/engine/docs-checks.mjs +9 -0
- package/engine/document-subtypes.mjs +47 -34
- package/engine/event-views.mjs +139 -14
- package/engine/exported-scene.mjs +92 -28
- package/engine/extension-attributes.mjs +12 -1
- package/engine/field-spec.mjs +11 -102
- package/engine/folder-notes.mjs +0 -64
- package/engine/foreign-catalog.mjs +2 -1
- package/engine/format-generated.mjs +9 -0
- package/engine/foundry-entries.mjs +10 -28
- package/engine/frontmatter-lint.mjs +83 -392
- package/engine/frontmatter.mjs +20 -70
- package/engine/generate.mjs +10 -15
- package/engine/heading-attributes.mjs +12 -1
- package/engine/helpers.mjs +41 -102
- package/engine/holdings.mjs +1 -1
- package/engine/homepage.mjs +3 -10
- package/engine/ids.mjs +1 -167
- package/engine/index-records.mjs +6 -4
- package/engine/index.mjs +0 -3
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +13 -14
- package/engine/item-compiler.mjs +4 -10
- package/engine/item-docs.mjs +3 -5
- package/engine/item-registry.mjs +2 -10
- package/engine/journals.mjs +1 -5
- package/engine/literature-notes.mjs +4 -12
- package/engine/macros.mjs +1 -2
- package/engine/map-graphviz.mjs +12 -1
- package/engine/markdown-expressions.mjs +12 -1
- package/engine/markdownlint-run.mjs +567 -0
- package/engine/metadata-index.mjs +42 -12
- package/engine/note-addresses.mjs +143 -35
- package/engine/note-claims.mjs +14 -28
- package/engine/note-dates.mjs +3 -3
- package/engine/note-frontmatter.mjs +6 -0
- package/engine/note-ids.mjs +8 -14
- package/engine/note-package.mjs +8 -25
- package/engine/note-state.mjs +1 -3
- package/engine/note-vocabulary.mjs +148 -84
- package/engine/number-words.mjs +12 -1
- package/engine/pack-config.mjs +15 -25
- package/engine/pack-router.mjs +10 -16
- package/engine/pathnames.mjs +8 -22
- package/engine/pdf-build.mjs +773 -121
- package/engine/pdf-coverage.mjs +188 -0
- package/engine/pdf-index.mjs +54 -7
- package/engine/pdf-pages.mjs +247 -0
- package/engine/pdf-render.mjs +114 -4
- package/engine/pdf-toc.mjs +29 -32
- package/engine/project-init.mjs +46 -6
- package/engine/prose-config.mjs +1 -1
- package/engine/prose-lint.mjs +52 -88
- package/engine/readability-lint.mjs +9 -0
- package/engine/reckoning-markers.mjs +12 -1
- package/engine/reference-targets.mjs +7 -0
- package/engine/runtime-only-fields.mjs +5 -8
- package/engine/scene-levels.mjs +2 -2
- package/engine/scenes.mjs +1 -1
- package/engine/shortcode-references.mjs +7 -0
- package/engine/site-build.mjs +30 -16
- package/engine/site-index.mjs +10 -16
- package/engine/site-preview.mjs +6 -0
- package/engine/site-root.mjs +8 -1
- package/engine/social-tie-terms.mjs +12 -1
- package/engine/social-ties.mjs +3 -0
- package/engine/sql-tables.mjs +56 -20
- package/engine/standing-terms.mjs +11 -1
- package/engine/standings.mjs +11 -27
- package/engine/system-block.mjs +39 -141
- package/engine/system-vocabulary.mjs +6 -0
- package/engine/walk-files.mjs +69 -0
- package/engine/web-wikilinks.mjs +23 -3
- package/engine/wikilink-syntax.mjs +32 -21
- package/engine/wikilinks.mjs +27 -16
- package/githooks/attribution.mjs +8 -0
- package/githooks/commit-message.mjs +9 -0
- package/hm3/actors.mjs +9 -48
- package/hm3/default-item-art.mjs +9 -9
- package/hm3/item-fields.mjs +2 -9
- package/hm3/template-priority.mjs +6 -7
- package/hugo-theme/data/banner-kinds.yaml +78 -0
- package/hugo-theme/data/banners.yaml +2 -3
- package/hugo-theme/layouts/404.html +3 -3
- package/hugo-theme/layouts/partials/banner-url.html +31 -7
- package/hugo-theme/layouts/partials/hero-banner.html +13 -14
- package/hugo-theme/layouts/partials/related.html +1 -1
- package/hugo-theme/layouts/partials/warn-missing-banner.html +1 -1
- package/hugo-theme/static/css/style.css +1 -1
- package/manifest.mjs +11 -4
- package/markdownlint-config.mjs +1 -1
- package/package.json +6 -3
- package/release.mjs +21 -14
- package/sohl/actors.mjs +16 -27
- package/sohl/default-item-art.mjs +3 -3
- package/sohl/document-subtypes.mjs +1 -16
- package/sohl/infobox.mjs +2 -3
- package/sohl/item-builders.mjs +5 -8
- package/sohl/item-fields.mjs +5 -35
- package/sohl/items.mjs +0 -4
- package/sohl/kb-passes.mjs +3 -3
- package/types/container.d.mts +116 -5
- package/types/content-config.d.mts +83 -35
- package/types/deploy.d.mts +42 -6
- package/types/e2e.d.mts +35 -3
- package/types/engine/address-charset.d.mts +4 -17
- package/types/engine/address.d.mts +17 -8
- package/types/engine/art-fields.d.mts +7 -4
- package/types/engine/art-slots.d.mts +6 -0
- package/types/engine/base-compiler.d.mts +15 -17
- package/types/engine/content-address.d.mts +9 -12
- package/types/engine/content-embeds.d.mts +4 -2
- package/types/engine/content-format-check.d.mts +0 -64
- package/types/engine/content-index.d.mts +82 -3
- package/types/engine/content-links.d.mts +2 -4
- package/types/engine/culture-choice.d.mts +51 -8
- package/types/engine/data-keys.d.mts +2 -2
- package/types/engine/derived-fields.d.mts +1 -2
- package/types/engine/diagnostics.d.mts +27 -4
- package/types/engine/document-subtypes.d.mts +12 -31
- package/types/engine/event-views.d.mts +14 -2
- package/types/engine/exported-scene.d.mts +3 -2
- package/types/engine/field-spec.d.mts +13 -122
- package/types/engine/folder-notes.d.mts +0 -39
- package/types/engine/foreign-catalog.d.mts +2 -1
- package/types/engine/foundry-entries.d.mts +4 -5
- package/types/engine/frontmatter-lint.d.mts +2 -2
- package/types/engine/frontmatter.d.mts +19 -45
- package/types/engine/generate.d.mts +1 -1
- package/types/engine/helpers.d.mts +25 -42
- package/types/engine/homepage.d.mts +3 -10
- package/types/engine/ids.d.mts +0 -114
- package/types/engine/index-records.d.mts +6 -4
- package/types/engine/index.d.mts +0 -1
- package/types/engine/infobox-render.d.mts +7 -1
- package/types/engine/infobox.d.mts +3 -2
- package/types/engine/item-docs.d.mts +1 -1
- package/types/engine/item-registry.d.mts +2 -4
- package/types/engine/literature-notes.d.mts +1 -1
- package/types/engine/markdownlint-run.d.mts +40 -0
- package/types/engine/metadata-index.d.mts +9 -1
- package/types/engine/note-addresses.d.mts +27 -2
- package/types/engine/note-claims.d.mts +3 -5
- package/types/engine/note-ids.d.mts +2 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-state.d.mts +1 -3
- package/types/engine/note-vocabulary.d.mts +28 -21
- package/types/engine/pack-config.d.mts +2 -6
- package/types/engine/pack-router.d.mts +4 -4
- package/types/engine/pathnames.d.mts +3 -3
- package/types/engine/pdf-build.d.mts +98 -12
- package/types/engine/pdf-coverage.d.mts +60 -0
- package/types/engine/pdf-index.d.mts +34 -5
- package/types/engine/pdf-pages.d.mts +143 -0
- package/types/engine/pdf-render.d.mts +45 -1
- package/types/engine/pdf-toc.d.mts +12 -14
- package/types/engine/prose-config.d.mts +1 -1
- package/types/engine/prose-lint.d.mts +11 -10
- package/types/engine/runtime-only-fields.d.mts +2 -2
- package/types/engine/site-build.d.mts +9 -5
- package/types/engine/site-index.d.mts +4 -5
- package/types/engine/site-root.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -2
- package/types/engine/standing-terms.d.mts +2 -1
- package/types/engine/standings.d.mts +7 -9
- package/types/engine/system-block.d.mts +10 -44
- package/types/engine/walk-files.d.mts +15 -0
- package/types/engine/wikilink-syntax.d.mts +18 -19
- package/types/hm3/actors.d.mts +1 -2
- package/types/hm3/item-fields.d.mts +2 -4
- package/types/hm3/template-priority.d.mts +6 -7
- package/types/manifest.d.mts +3 -2
- package/types/release.d.mts +8 -7
- package/types/sohl/actors.d.mts +2 -1
- package/types/sohl/document-subtypes.d.mts +1 -2
- package/types/sohl/item-fields.d.mts +3 -7
- package/engine/retired-fields.mjs +0 -631
- package/types/engine/retired-fields.d.mts +0 -354
|
@@ -104,6 +104,11 @@ A note profile begins with `Name`. For a being with a top-level `subType`, it
|
|
|
104
104
|
follows with `Type: Character`, `Type: NPC`, or `Type: Creature`. A being with
|
|
105
105
|
no subtype has no `Type` row.
|
|
106
106
|
|
|
107
|
+
The `Culture` row shows the note's resolved culture, so a place or an
|
|
108
|
+
affiliation shows the culture it inherits. A culture note has no `Culture` row:
|
|
109
|
+
its resolved culture is its own Address, whether it leaves the field out or
|
|
110
|
+
names itself. See [Culture in the index](#culture-in-the-index).
|
|
111
|
+
|
|
107
112
|
**Embedded models link to documentation in an infobox.** The model Address
|
|
108
113
|
continues to identify the native Item used for compilation. Its displayed link
|
|
109
114
|
uses that same package, type and Shortcode under `note`, which names the
|
|
@@ -135,7 +140,7 @@ or it is a **source system's own detail**, which no surface's box shows:
|
|
|
135
140
|
| a calendar's `months`, `weekdays`, `seasons`, `namedDays`, `eras`, `formats` | calendar machinery, not a summary row |
|
|
136
141
|
| a map's `scene`, `fixup` | canvas machinery, not a summary row |
|
|
137
142
|
| `harnworld` | HârnWorld source detail, which no surface's box shows |
|
|
138
|
-
| the art slots
|
|
143
|
+
| the art slots, and a map's `thumbnail` | an image, which rule 2 keeps out of the box |
|
|
139
144
|
|
|
140
145
|
**A field whose value holds maps is drawn by what its declaration says the
|
|
141
146
|
maps are**, and a map is never set as text:
|
|
@@ -735,14 +740,14 @@ no SoHL form, so its SoHL column is. Nothing else varies — which is why these
|
|
|
735
740
|
rows are worth stating once: repeated sixteen times they buried the differences
|
|
736
741
|
that matter.
|
|
737
742
|
|
|
738
|
-
**`data.icon`
|
|
739
|
-
The row is shared
|
|
740
|
-
|
|
741
|
-
compile into a JournalEntry, which has no image of any
|
|
742
|
-
compiles into a
|
|
743
|
-
into
|
|
744
|
-
|
|
745
|
-
|
|
743
|
+
**`data.icon` is declared only for the types whose document carries art.**
|
|
744
|
+
The row is not shared: `being`, every Item type, `macro` and `bundle` compile
|
|
745
|
+
into a document with an image, and only those declare `icon`. `doc`, `place`,
|
|
746
|
+
`lore` and `scenario` compile into a JournalEntry, which has no image of any
|
|
747
|
+
kind; a `map` compiles into a Scene whose art is its own; a `folder` compiles
|
|
748
|
+
into a Foundry `Folder`; and a `homepage` compiles into no compendium document
|
|
749
|
+
at all. On any of those `icon` is not a declared property, so the note is
|
|
750
|
+
refused at the key's own line rather than compiled with the value dropped.
|
|
746
751
|
|
|
747
752
|
**What a note writes is an address; what a document carries is a path.**
|
|
748
753
|
`data.icon` is an `Address` defaulting to type `icon`, so a being writes
|
|
@@ -751,20 +756,13 @@ file the owning package ships and writes the resulting path into `img`. The two
|
|
|
751
756
|
sides of this row are therefore in two different currencies, which is why the
|
|
752
757
|
row reads `data.icon → img` rather than naming one thing twice.
|
|
753
758
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
true and harmless thing to say.
|
|
762
|
-
|
|
763
|
-
Which types those are is **not a list**. It is asked of the passes: a type routes
|
|
764
|
-
to a document, a document to the pass that compiles it, and each pass declares
|
|
765
|
-
the art it writes (`emitsArt`). A second table of iconless types would be a table
|
|
766
|
-
free to drift from what is actually emitted, which is the defect rather than the
|
|
767
|
-
check.
|
|
759
|
+
Which types declare `icon` is **not a list**. It is asked of the passes: a type
|
|
760
|
+
routes to a document, a document to the pass that compiles it, and each pass
|
|
761
|
+
declares the art it writes (`emitsArt`). A pass that emits `icon` is a type that
|
|
762
|
+
declares the key. Any other art key authored where no pass emits it, such as a
|
|
763
|
+
`tokenIcon` on an Item type, is a warning naming the note and the key, because
|
|
764
|
+
the note still compiles correctly and a site template may read there what no
|
|
765
|
+
document carries. `null` is never reported.
|
|
768
766
|
|
|
769
767
|
#### The art slots
|
|
770
768
|
|
|
@@ -774,11 +772,14 @@ exactly as `seat` declares `place` — a bare shortcode takes its type from the
|
|
|
774
772
|
declaration, and qualification climbs the same short-form ladder every other
|
|
775
773
|
link uses.
|
|
776
774
|
|
|
777
|
-
| field | default type | accepts | resolves into | on
|
|
778
|
-
| ----------- | ------------ | --------------- | ----------------------------- |
|
|
779
|
-
| `icon` | `icon` | `icon`, `image` | `document.img` | every
|
|
780
|
-
| `tokenIcon` | `icon` | `icon`, `image` | `prototypeToken.texture.src` | Actor types
|
|
781
|
-
| `banner` | `image` | `icon`, `image` | the site hero image, 1792×768 | any note; not a Foundry field
|
|
775
|
+
| field | default type | accepts | resolves into | on |
|
|
776
|
+
| ----------- | ------------ | --------------- | ----------------------------- | ------------------------------------------- |
|
|
777
|
+
| `icon` | `icon` | `icon`, `image` | `document.img` | `being`, every Item type, `macro`, `bundle` |
|
|
778
|
+
| `tokenIcon` | `icon` | `icon`, `image` | `prototypeToken.texture.src` | Actor types |
|
|
779
|
+
| `banner` | `image` | `icon`, `image` | the site hero image, 1792×768 | any note; not a Foundry field |
|
|
780
|
+
|
|
781
|
+
A map's `thumbnail` is not an art slot. It is a map field resolved into the
|
|
782
|
+
Scene's `thumb` as a fixup — see [the thumbnail](#the-thumbnail).
|
|
782
783
|
|
|
783
784
|
Every slot is authored under `data:`:
|
|
784
785
|
|
|
@@ -788,6 +789,11 @@ data:
|
|
|
788
789
|
banner: packagebuild-none-image-skillbnr
|
|
789
790
|
```
|
|
790
791
|
|
|
792
|
+
**An empty value is an error.** `icon: ""`, `tokenIcon: ""` and `banner: ""`
|
|
793
|
+
are each a finding at the key, in `data:` or in a system block. A slot names an
|
|
794
|
+
image, or the key is removed and the document takes its type's default;
|
|
795
|
+
`icon: null` says the same as removing it.
|
|
796
|
+
|
|
791
797
|
**Every slot accepts a second type beyond the one it defaults to**, and the two
|
|
792
798
|
defaults pair with the same accepted set: `icon` and `tokenIcon` default to
|
|
793
799
|
`icon`, `banner` defaults to `image`, and every slot accepts `icon` **and**
|
|
@@ -815,16 +821,15 @@ are, so a key legal everywhere is stated once here rather than repeated in
|
|
|
815
821
|
twenty-five tables where the one that was mistyped would be the one nobody
|
|
816
822
|
noticed:
|
|
817
823
|
|
|
818
|
-
| shared `data` property | Values | Description
|
|
819
|
-
| ---------------------- | --------------------- |
|
|
820
|
-
| `id` | `string` | A pinned document identity.
|
|
821
|
-
| `pack` | `string` | The shared compendium route.
|
|
822
|
-
| `packFolder` | `Address` or pack map | The shared compendium folder Address.
|
|
823
|
-
| `harnworld` | `{ realm?, ritual? }` | HârnWorld source details.
|
|
824
|
-
| `harnworld.realm` | `string` | The HârnWorld realm the subject belongs to.
|
|
825
|
-
| `harnworld.ritual` | `string[]` | The HârnWorld religions the subject observes.
|
|
826
|
-
| `
|
|
827
|
-
| `banner` | `Address` | The page's hero image — an `image` address, cut to 1792×768. |
|
|
824
|
+
| shared `data` property | Values | Description |
|
|
825
|
+
| ---------------------- | --------------------- | ------------------------------------------------------------ |
|
|
826
|
+
| `id` | `string` | A pinned document identity. |
|
|
827
|
+
| `pack` | `string` | The shared compendium route. |
|
|
828
|
+
| `packFolder` | `Address` or pack map | The shared compendium folder Address. |
|
|
829
|
+
| `harnworld` | `{ realm?, ritual? }` | HârnWorld source details. |
|
|
830
|
+
| `harnworld.realm` | `string` | The HârnWorld realm the subject belongs to. |
|
|
831
|
+
| `harnworld.ritual` | `string[]` | The HârnWorld religions the subject observes. |
|
|
832
|
+
| `banner` | `Address` | The page's hero image — an `image` address, cut to 1792×768. |
|
|
828
833
|
|
|
829
834
|
`data.harnworld` takes two keys and nothing else: `realm`, a string naming the
|
|
830
835
|
HârnWorld realm the subject belongs to, and `ritual`, a list of strings naming
|
|
@@ -837,10 +842,9 @@ data:
|
|
|
837
842
|
ritual: [Larani, Peoni]
|
|
838
843
|
```
|
|
839
844
|
|
|
840
|
-
`icon` is
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
compiled document at all, and a page is what every note publishes.
|
|
845
|
+
`icon` is declared only for the types whose document carries art; see
|
|
846
|
+
the art slots below. `banner` reaches no compiled document at
|
|
847
|
+
all, and a page is what every note publishes, so it is legal everywhere.
|
|
844
848
|
|
|
845
849
|
`tokenIcon` is narrower, and the Actor types' own tables name it. A map takes
|
|
846
850
|
no art slot: its Scene is exported from Foundry and names its own art.
|
|
@@ -870,12 +874,9 @@ header carries. `data.tokenIcon` is what a token on the canvas wears. Both are
|
|
|
870
874
|
addresses and both resolve the same way; only the destination differs. An Item
|
|
871
875
|
has one piece of art, so this row applies to actor types alone.
|
|
872
876
|
|
|
873
|
-
**A `data:` source is
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
one and reported as retiring. This is the shared level's counterpart to the
|
|
877
|
-
in-block `<system>.<key>` retirement, and the two are separate: a note may have
|
|
878
|
-
moved one and not the other.
|
|
877
|
+
**A `data:` source is authored in `data:` alone.** The same key written at the
|
|
878
|
+
top level is outside the closed top-level region, and written inside a system
|
|
879
|
+
block it is reported at its own line with the `data:` key it belongs to.
|
|
879
880
|
|
|
880
881
|
**No image key is one of those.** A top-level `img:` is not authored at all:
|
|
881
882
|
`data.icon` is a different key holding a different kind of value, and a note
|
|
@@ -1006,10 +1007,10 @@ nothing of (`/systems/dnd5e/icons/spell.webp`).
|
|
|
1006
1007
|
replacement. It is a Foundry address written where an ownership statement
|
|
1007
1008
|
belongs: it resolves for Foundry and for nothing else, because neither the
|
|
1008
1009
|
website nor the book has any such directory. `systems/sohl/assets/ui/logo.webp`
|
|
1009
|
-
is written `sohl/assets/ui/logo.webp`, and `systems/hm3/
|
|
1010
|
+
is written `sohl/assets/ui/logo.webp`, and `systems/hm3/assets/icons/sword.svg` —
|
|
1010
1011
|
where the package serves its pictures from its own root — is written
|
|
1011
|
-
`hm3/assets/
|
|
1012
|
-
|
|
1012
|
+
`hm3/assets/icons/sword.svg`, because `assets/` is where a package's files sit
|
|
1013
|
+
in every derived form.
|
|
1013
1014
|
|
|
1014
1015
|
`worlds/` is not a Foundry root for this purpose. A package may not ship files
|
|
1015
1016
|
out of a world, so a note writing one has made a different mistake and gets the
|
|
@@ -1052,8 +1053,11 @@ writes `banner: skillbnr` and a note borrowing another package's plate writes
|
|
|
1052
1053
|
owning package, and each surface joins the suffix onto its own root — the site
|
|
1053
1054
|
onto `site.assets`, the book onto the directory it stages banners into.
|
|
1054
1055
|
|
|
1055
|
-
**`banner:
|
|
1056
|
-
|
|
1056
|
+
**`banner: none` is how a note declines its hero image.** The word is never
|
|
1057
|
+
read as an Address: it resolves to no image, the page publishes a blank
|
|
1058
|
+
`data.banner`, and the theme draws the band with no picture and no warning. An
|
|
1059
|
+
Address that names no image is a finding at its own line and column, and `""`
|
|
1060
|
+
is an error. `banner: null` names no art and the page takes its type's default.
|
|
1057
1061
|
|
|
1058
1062
|
#### The pack a note compiles into
|
|
1059
1063
|
|
|
@@ -1147,20 +1151,9 @@ which of several competing templates a player is actually offered.
|
|
|
1147
1151
|
The shared mapping table above names it `data.templatePriority`, targeting
|
|
1148
1152
|
`system.templatePriority` in SoHL and `flags.hm3.templatePriority` in HM3.
|
|
1149
1153
|
|
|
1150
|
-
>
|
|
1151
|
-
>
|
|
1152
|
-
>
|
|
1153
|
-
> what is compiled and emitted is `templatePriority` on all three sides.
|
|
1154
|
-
>
|
|
1155
|
-
> It is more than a rename, and the collision is **already live** rather than
|
|
1156
|
-
> pending: `archetypes` is specified above as the _sort_ a character is, and a
|
|
1157
|
-
> being's row declares it. So a number deciding which template wins and a list of
|
|
1158
|
-
> what sort of character this is would otherwise be distinguished **only by a
|
|
1159
|
-
> plural `s`**.
|
|
1160
|
-
>
|
|
1161
|
-
> A note carrying both spellings with **different** values is refused rather than
|
|
1162
|
-
> resolved quietly — `templatePriority: null` and `archetype: 0` say opposite
|
|
1163
|
-
> things, and picking either silently would decide it on the author's behalf.
|
|
1154
|
+
> `archetypes` is a different field: specified above as the _sort_ a character
|
|
1155
|
+
> is, and declared by a being's row. The priority that decides which template
|
|
1156
|
+
> wins is always `templatePriority`, on all three sides.
|
|
1164
1157
|
|
|
1165
1158
|
```yaml
|
|
1166
1159
|
data:
|
|
@@ -1311,8 +1304,7 @@ the journals pack having to declare anything. A folder nothing references
|
|
|
1311
1304
|
materialises nowhere.
|
|
1312
1305
|
|
|
1313
1306
|
One folder note and one Address supply every pack that references it.
|
|
1314
|
-
`data.packFolder` names a folder by Address.
|
|
1315
|
-
refused with a finding that names `data.packFolder` and the authored line.
|
|
1307
|
+
`data.packFolder` names a folder by Address.
|
|
1316
1308
|
|
|
1317
1309
|
#### The knowledgebase category
|
|
1318
1310
|
|
|
@@ -1472,9 +1464,25 @@ note, while `[[none-macro-autoattack|Automated Attack]]` names the Foundry Macro
|
|
|
1472
1464
|
|
|
1473
1465
|
**A complete Address is lowercase throughout.** Every segment — package,
|
|
1474
1466
|
system, type and shortcode alike — contains only lowercase ASCII letters and
|
|
1475
|
-
digits (`^[a-z0-9]+$`).
|
|
1476
|
-
|
|
1477
|
-
|
|
1467
|
+
digits (`^[a-z0-9]+$`). Every Address is validated as written, whether a field
|
|
1468
|
+
declares it or a wikilink or embed writes it, so a capital in any segment, the
|
|
1469
|
+
shortcode included, is an error at the value or at the link. Nothing is
|
|
1470
|
+
lowercased on the author's behalf. Where the lowercase spelling is a declared
|
|
1471
|
+
shortcode, the error names it:
|
|
1472
|
+
|
|
1473
|
+
```text
|
|
1474
|
+
Beings/Guard.md:8:15: error: `sohl.items.0.model` shortcode `LLeg` must be lowercase; the declared shortcode is `lleg`
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1477
|
+
A link is reported the same way, at its own line and column:
|
|
1478
|
+
|
|
1479
|
+
```text
|
|
1480
|
+
Skills/Jumping.md:10:5: error: address [[skill-Clmb]] shortcode `Clmb` must be lowercase; the declared shortcode is `clmb`
|
|
1481
|
+
```
|
|
1482
|
+
|
|
1483
|
+
Each such reference in a note's frontmatter is reported at its own position,
|
|
1484
|
+
and the note is left out of the index, so the build fails rather than
|
|
1485
|
+
compiling without it.
|
|
1478
1486
|
|
|
1479
1487
|
**Parsing is positional counting from the right, and nothing else.** Every
|
|
1480
1488
|
segment is lowercase alphanumeric — shortcodes, **types** and **subTypes** are
|
|
@@ -1546,18 +1554,18 @@ A `draft` note exists, resolves, compiles and publishes; a link to it renders
|
|
|
1546
1554
|
visibly marked. An Address landing nowhere is a typo or an omission and earns
|
|
1547
1555
|
an error.
|
|
1548
1556
|
|
|
1549
|
-
|
|
1550
|
-
wherever it is met:
|
|
1557
|
+
Each way a link can fail is one **error** with one message wherever it is met:
|
|
1551
1558
|
|
|
1552
|
-
| finding
|
|
1553
|
-
|
|
|
1554
|
-
| `unlabelled`
|
|
1555
|
-
| `not-an-address`
|
|
1556
|
-
| `not-lowercase`
|
|
1557
|
-
| `
|
|
1558
|
-
| `
|
|
1559
|
-
| `
|
|
1560
|
-
| `
|
|
1559
|
+
| finding | what it means | the fix |
|
|
1560
|
+
| ------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
|
|
1561
|
+
| `unlabelled` | no `\|`, so the link addresses nothing | write `[[type-shortcode\|Text]]` |
|
|
1562
|
+
| `not-an-address` | labelled, but the target is not an address | write the address, not the name |
|
|
1563
|
+
| `not-lowercase` | a package, system or type segment is capitalised | lowercase it — every segment is lowercase |
|
|
1564
|
+
| `shortcode-not-lowercase` | the shortcode is capitalised; the message names the declared shortcode when the lowercase spelling is one | lowercase it — a shortcode is lowercase |
|
|
1565
|
+
| `unknown-type` | qualified, but names no type this build knows | correct the type segment |
|
|
1566
|
+
| `unresolved` | parses as an address; nothing publishes it | fix the shortcode, or qualify to reach another package |
|
|
1567
|
+
| `ambiguous` | _unreachable; kept for the manifest_ | — |
|
|
1568
|
+
| `unknown-anchor` | the address resolves; the `#section` does not | correct the anchor |
|
|
1561
1569
|
|
|
1562
1570
|
`ambiguous` is a reserved reason in the result vocabulary. An omitted segment
|
|
1563
1571
|
defaults rather than wildcarding, so each written target expands to one
|
|
@@ -1590,7 +1598,7 @@ prose: a field value is a reference something else will compile against, and it
|
|
|
1590
1598
|
should say exactly what it points at.
|
|
1591
1599
|
|
|
1592
1600
|
**A field can supply the type.** A field naming one kind of note declares its
|
|
1593
|
-
default — `seat` a `place`, `parents` an `affiliation`, `
|
|
1601
|
+
default — `seat` a `place`, `parents` an `affiliation`, `lore` a `lore` — so
|
|
1594
1602
|
the type segment defaults from the declaration and a bare shortcode is the
|
|
1595
1603
|
ordinary case, not an abbreviation of one. That is why the examples above read
|
|
1596
1604
|
`tashal` rather than `place-tashal`: the shorter form carries the same
|
|
@@ -1747,7 +1755,6 @@ is always the same: write `[[type-shortcode|Text]]`.
|
|
|
1747
1755
|
|
|
1748
1756
|
The bare form does not resolve by display name or alias. `name.aliases` is
|
|
1749
1757
|
indexed for search and completion, while an authored link names an Address.
|
|
1750
|
-
A top-level `aliases:` key is refused.
|
|
1751
1758
|
|
|
1752
1759
|
Requiring the label is also what makes positional parsing safe. Note names
|
|
1753
1760
|
contain hyphens — `Grukar-ahk` is a name, not a `Grukar` of type `ahk` — so a
|
|
@@ -1755,7 +1762,7 @@ target that does not parse as an address is reported as one that does not, rathe
|
|
|
1755
1762
|
than split at an arbitrary place or quietly looked up somewhere else.
|
|
1756
1763
|
|
|
1757
1764
|
The **empty** label is not a way of writing no label. It says _address this
|
|
1758
|
-
target, and show whatever it calls itself_ — so a note
|
|
1765
|
+
target, and show whatever it calls itself_ — so a note whose name changes takes its new
|
|
1759
1766
|
name at every citation with no link edited. `[[x|]]` is labelled; `[[x]]` is not.
|
|
1760
1767
|
|
|
1761
1768
|
It is the label that is required, not a target: the anchor-only form above
|
|
@@ -2611,7 +2618,9 @@ documentation entry, so `type = 'miscgear'` selects the items and never their
|
|
|
2611
2618
|
journals. A nested field is addressed exactly as a note authors it —
|
|
2612
2619
|
`sohl.weight`, `name.full`, `file.path` — because the index is read as JSON and
|
|
2613
2620
|
every nested object is inferred as a struct. A field a note type does not carry
|
|
2614
|
-
reads `NULL` rather than failing.
|
|
2621
|
+
reads `NULL` rather than failing. `data.culture` is the one field that reads as
|
|
2622
|
+
a derived value: the note's own culture, or the one it inherits. See
|
|
2623
|
+
[Culture in the index](#culture-in-the-index).
|
|
2615
2624
|
|
|
2616
2625
|
**`notes` leaves out stubs; `entries` does not.** Both carry a derived `state`
|
|
2617
2626
|
column — `stub`, `draft` or `full` — and `notes` is exactly
|
|
@@ -2706,6 +2715,136 @@ table would otherwise need: the authored `ORDER BY` decides the section order to
|
|
|
2706
2715
|
**Beware `packFolder`.** It is a note's _pack_ folder, not its directory — the
|
|
2707
2716
|
directory is `file.folder`.
|
|
2708
2717
|
|
|
2718
|
+
##### Culture in the index
|
|
2719
|
+
|
|
2720
|
+
`data.culture` in the index is the note's **resolved** culture, which is its
|
|
2721
|
+
authored value where it states one and a derived value where it does not. The
|
|
2722
|
+
resolved value is written into the index as a canonical Address string, such as
|
|
2723
|
+
`reedflats-note-lore-reedfolk`, so a table selects by it directly.
|
|
2724
|
+
|
|
2725
|
+
The culture of a note, in order:
|
|
2726
|
+
|
|
2727
|
+
1. Its own `data.culture`, when it states one.
|
|
2728
|
+
2. For a `lore` note of `subType: culture`: itself. A culture note may leave the
|
|
2729
|
+
field out or state it as its own Address, and its resolved culture is its own
|
|
2730
|
+
Address either way.
|
|
2731
|
+
3. For a `place` or an `affiliation`: the resolved cultures of its
|
|
2732
|
+
`data.parents` — places through their parent places, affiliations through
|
|
2733
|
+
their parent affiliations — found recursively, so a culture stated three
|
|
2734
|
+
levels up reaches the bottom.
|
|
2735
|
+
4. For an affiliation of `subType: polity` that still has none: the resolved
|
|
2736
|
+
cultures of its places, pooled as one set — its `data.seat` and every place
|
|
2737
|
+
whose `data.government` names the polity.
|
|
2738
|
+
5. Otherwise none. A parent or place that resolves to nothing contributes
|
|
2739
|
+
nothing.
|
|
2740
|
+
|
|
2741
|
+
A `being` and a `doc` of `subType: settingguide` read as the value they state and
|
|
2742
|
+
nothing more; every other `lore` note reads as its own value, and every other
|
|
2743
|
+
note type reads as none.
|
|
2744
|
+
|
|
2745
|
+
Sources that agree give that culture. Sources that name different cultures, on a
|
|
2746
|
+
note that states none of its own, are an **error**, and that note gets no
|
|
2747
|
+
culture. The error is located at the `parents:` key; for the pooled places of a
|
|
2748
|
+
polity it is located at the `seat:` key, or at the `data:` line when the polity
|
|
2749
|
+
states no seat. Stating `data.culture` on the note settles the matter, because
|
|
2750
|
+
an own value is never compared with its sources. A note whose parent raised the
|
|
2751
|
+
error reads that parent as resolving to nothing, so one disagreement is reported
|
|
2752
|
+
once, at the note where the sources meet.
|
|
2753
|
+
|
|
2754
|
+
Here a region states a culture and the places inside it carry it down:
|
|
2755
|
+
|
|
2756
|
+
```markdown
|
|
2757
|
+
---
|
|
2758
|
+
shortcode: reedflats
|
|
2759
|
+
name: { full: Reed Flats }
|
|
2760
|
+
type: place
|
|
2761
|
+
subType: region
|
|
2762
|
+
description: A marsh region.
|
|
2763
|
+
data:
|
|
2764
|
+
culture: lore-reedfolk
|
|
2765
|
+
---
|
|
2766
|
+
```
|
|
2767
|
+
|
|
2768
|
+
```markdown
|
|
2769
|
+
---
|
|
2770
|
+
shortcode: saltmarsh
|
|
2771
|
+
name: { full: Saltmarsh }
|
|
2772
|
+
type: place
|
|
2773
|
+
subType: district
|
|
2774
|
+
description: A salt marsh.
|
|
2775
|
+
data:
|
|
2776
|
+
parents: [place-reedflats]
|
|
2777
|
+
---
|
|
2778
|
+
```
|
|
2779
|
+
|
|
2780
|
+
```markdown
|
|
2781
|
+
---
|
|
2782
|
+
shortcode: eelwick
|
|
2783
|
+
name: { full: Eelwick }
|
|
2784
|
+
type: place
|
|
2785
|
+
subType: settlement
|
|
2786
|
+
description: A fishing village.
|
|
2787
|
+
data:
|
|
2788
|
+
parents: [place-saltmarsh]
|
|
2789
|
+
---
|
|
2790
|
+
```
|
|
2791
|
+
|
|
2792
|
+
`saltmarsh` and `eelwick` state no culture and index as `reedflats-note-lore-reedfolk`.
|
|
2793
|
+
Because the index carries the resolved value, one query selects the region and
|
|
2794
|
+
everything beneath it, and `IS NULL` selects the notes that have no culture:
|
|
2795
|
+
|
|
2796
|
+
````markdown
|
|
2797
|
+
```sql
|
|
2798
|
+
SELECT address.slug AS _ref, name.full AS "Name"
|
|
2799
|
+
FROM notes
|
|
2800
|
+
WHERE type = 'place' AND data.culture = 'reedflats-note-lore-reedfolk'
|
|
2801
|
+
ORDER BY name.full
|
|
2802
|
+
```
|
|
2803
|
+
````
|
|
2804
|
+
|
|
2805
|
+
````markdown
|
|
2806
|
+
```sql
|
|
2807
|
+
SELECT address.slug AS _ref, name.full AS "Name"
|
|
2808
|
+
FROM notes
|
|
2809
|
+
WHERE type = 'place' AND data.culture IS NULL
|
|
2810
|
+
```
|
|
2811
|
+
````
|
|
2812
|
+
|
|
2813
|
+
A place whose parents sit in different cultures must say which it belongs to.
|
|
2814
|
+
With a second region `stonecrest` that states `culture: lore-hillfolk`, a place
|
|
2815
|
+
on the border between the two:
|
|
2816
|
+
|
|
2817
|
+
```markdown
|
|
2818
|
+
---
|
|
2819
|
+
shortcode: causeway
|
|
2820
|
+
name: { full: The Causeway }
|
|
2821
|
+
type: place
|
|
2822
|
+
subType: site
|
|
2823
|
+
description: A road between marsh and ridge.
|
|
2824
|
+
data:
|
|
2825
|
+
parents: [place-reedflats, place-stonecrest]
|
|
2826
|
+
---
|
|
2827
|
+
```
|
|
2828
|
+
|
|
2829
|
+
fails the content-index build with one located error per conflict:
|
|
2830
|
+
|
|
2831
|
+
```text
|
|
2832
|
+
assets/content/Places/Causeway.md:8:3: error: data.parents resolve to different cultures (reedflats-note-lore-reedfolk via reedflats, reedflats-note-lore-hillfolk via stonecrest); state data.culture
|
|
2833
|
+
```
|
|
2834
|
+
|
|
2835
|
+
The conflict fails the content-index build, and every other command that reads
|
|
2836
|
+
the index without collecting problems, listing every conflict in one run. Adding
|
|
2837
|
+
`culture: lore-reedfolk` under `data:` on `causeway` removes it. A fetched
|
|
2838
|
+
dependency's index carries each note's resolved culture, so a parent in another
|
|
2839
|
+
package contributes the culture that package resolved for it.
|
|
2840
|
+
|
|
2841
|
+
The index record carries the resolved culture, and every pass that reads the
|
|
2842
|
+
record reads it too: lint, the pack compile and the site build all see a
|
|
2843
|
+
place's inherited culture, and a culture note's own Address, as its
|
|
2844
|
+
`data.culture`. A resolved value always passes the checks that scope the field,
|
|
2845
|
+
because a culture note resolves to itself and an inherited value names a culture
|
|
2846
|
+
note. The infobox shows a note's resolved culture, except a culture note's own.
|
|
2847
|
+
|
|
2709
2848
|
##### Reading another package's notes
|
|
2710
2849
|
|
|
2711
2850
|
Each package this one **depends on** is attached as a schema named after it, so
|
|
@@ -3352,35 +3491,35 @@ Generates a living (or undead, or spirit) being.
|
|
|
3352
3491
|
|
|
3353
3492
|
See [a being's subtype describes the subject](#a-beings-subtype-describes-the-subject).
|
|
3354
3493
|
|
|
3355
|
-
| `data` property
|
|
3356
|
-
|
|
|
3357
|
-
| `tokenIcon`
|
|
3358
|
-
| `templatePriority`
|
|
3359
|
-
| `archetypes`
|
|
3360
|
-
| `occupation`
|
|
3361
|
-
| `
|
|
3362
|
-
| `
|
|
3363
|
-
| `
|
|
3364
|
-
| `
|
|
3365
|
-
| `affiliations`
|
|
3366
|
-
| `affiliations.<Address>.
|
|
3367
|
-
| `affiliations.<Address>.
|
|
3368
|
-
| `socialTies`
|
|
3369
|
-
| `gender`
|
|
3370
|
-
| `species`
|
|
3371
|
-
| `born`
|
|
3372
|
-
| `calendar`
|
|
3373
|
-
| `died`
|
|
3374
|
-
| `age`
|
|
3375
|
-
| `ageYears`
|
|
3376
|
-
| `height`
|
|
3377
|
-
| `weight`
|
|
3378
|
-
| `frame`
|
|
3379
|
-
| `appearance.eye_color`
|
|
3380
|
-
| `appearance.hair_color`
|
|
3381
|
-
| `appearance.skin_color`
|
|
3382
|
-
| `appearance.complexion`
|
|
3383
|
-
| `appearance.extra_features`
|
|
3494
|
+
| `data` property | Values | Description |
|
|
3495
|
+
| ---------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
3496
|
+
| `tokenIcon` | `Address` | What a token on the canvas wears — an `icon` address; defaults to `icon` |
|
|
3497
|
+
| `templatePriority` | `number` | Template priority, _null_ = not a template |
|
|
3498
|
+
| `archetypes` | `Archetype[]` | What sort of character this is. **Always an array** — character and npc require at least one; creature may omit it or write `[]`; `null` is an error. |
|
|
3499
|
+
| `occupation` | `string` | Name of the character's occupation |
|
|
3500
|
+
| `lore` | `Address[]` | Other lore concerning this being, such as social standing or law |
|
|
3501
|
+
| `culture` | `Address` | Primary culture, naming a lore note with `subType: culture` |
|
|
3502
|
+
| `homes` | `Address[]` | Place the being calls home |
|
|
3503
|
+
| `affiliations` | `Map<Address, Membership>` | Bodies the being belongs to, keyed by Address, each entry the standing it holds there |
|
|
3504
|
+
| `affiliations.<Address>.rank` | `integer`, required | The level on that body's own `governance.ranks` ladder; `1` is an ordinary member, `0` someone cast out |
|
|
3505
|
+
| `affiliations.<Address>.office` | `string` | A post that body names in its `governance.offices`, where the being holds one |
|
|
3506
|
+
| `affiliations.<Address>.societies` | `string[]` | The societies the membership is held in, by name; SoHL carries the first as `system.society` |
|
|
3507
|
+
| `socialTies` | `Map<Address, Tie>` | Defining support and opposition, directed from this being to others |
|
|
3508
|
+
| `gender` | `male \| female \| other` | Gender of the character |
|
|
3509
|
+
| `species` | `Address` | Being's species (lore) |
|
|
3510
|
+
| `born` | `date \| unknown` | When the being was born; absent, it was never born |
|
|
3511
|
+
| `calendar` | `Address` | Calendar note that prints the being's dates |
|
|
3512
|
+
| `died` | `date \| unknown` | When the being died; absent, it is alive |
|
|
3513
|
+
| `age` | `34 \| ~34` | Age in years, stated only to override what `born` says; `~` marks an estimate |
|
|
3514
|
+
| `ageYears` | `number` | Written by the compiler beside an `age` estimate — the `~` stripped; a note never authors this |
|
|
3515
|
+
| `height` | `1.91m \| 6' 3"` | Height in metres or feet and inches |
|
|
3516
|
+
| `weight` | `85kg \| 187 lbs` | Body weight in kilograms or pounds |
|
|
3517
|
+
| `frame` | `scant \| light \| medium \| large \| massive` | Relative frame size |
|
|
3518
|
+
| `appearance.eye_color` | `string` | Eye color |
|
|
3519
|
+
| `appearance.hair_color` | `string` | Hair color |
|
|
3520
|
+
| `appearance.skin_color` | `string` | Skin color |
|
|
3521
|
+
| `appearance.complexion` | `string` | Complexion |
|
|
3522
|
+
| `appearance.extra_features` | `string[]` | Extra features |
|
|
3384
3523
|
|
|
3385
3524
|
Author `data.height` as a string of decimal metres (`1.91m` or `1.91 m`) or
|
|
3386
3525
|
whole feet with optional inches (`6'`, `6'3"`, or `6' 3"`). Inches must be
|
|
@@ -3406,14 +3545,15 @@ data:
|
|
|
3406
3545
|
|
|
3407
3546
|
#### The bodies a being belongs to, and its standing in each
|
|
3408
3547
|
|
|
3409
|
-
**Membership**: `{rank: number, office: string}` — `rank`
|
|
3548
|
+
**Membership**: `{rank: number, office: string, societies: string[]}` — `rank`
|
|
3549
|
+
required, `office` and `societies` not.
|
|
3410
3550
|
|
|
3411
3551
|
`data.affiliations` is a **map keyed by the body's Address**, and each entry is
|
|
3412
3552
|
the standing the being holds in that body. The key is what makes the pair
|
|
3413
3553
|
expressible: a being in two bodies holds a standing in each, and two bodies may
|
|
3414
3554
|
call a rung the same word.
|
|
3415
3555
|
|
|
3416
|
-
An entry carries
|
|
3556
|
+
An entry carries three keys and nothing else:
|
|
3417
3557
|
|
|
3418
3558
|
- **`rank`** — **required**, a **number**, the level on that body's own
|
|
3419
3559
|
`governance.ranks` ladder. The body declares `{level, title, description}` for
|
|
@@ -3421,6 +3561,9 @@ An entry carries two keys and nothing else:
|
|
|
3421
3561
|
for what its level 5 is called.
|
|
3422
3562
|
- **`office`** — optional, a **string**, matched against the keys of that body's
|
|
3423
3563
|
`governance.offices` map.
|
|
3564
|
+
- **`societies`** — optional, a **list of names**, the societies the membership
|
|
3565
|
+
is held in. It is always a list, even with one name; a bare string is an
|
|
3566
|
+
error at the key.
|
|
3424
3567
|
|
|
3425
3568
|
**Every entry states a `rank`**, because belonging to a body is holding some
|
|
3426
3569
|
standing in it. Where nothing more is known the rung is `1`, the ordinary
|
|
@@ -3438,15 +3581,15 @@ An entry carrying a rank and no office is complete.
|
|
|
3438
3581
|
```yaml
|
|
3439
3582
|
data:
|
|
3440
3583
|
affiliations:
|
|
3441
|
-
affiliation-vrystwldtrbs: { rank: 5, office: War Chief }
|
|
3584
|
+
affiliation-vrystwldtrbs: { rank: 5, office: War Chief, societies: [Vrystwald] }
|
|
3442
3585
|
affiliation-greenwardens: { rank: 1 }
|
|
3443
3586
|
affiliation-silverguild: { rank: 0 }
|
|
3444
3587
|
```
|
|
3445
3588
|
|
|
3446
3589
|
Both values are checked against the body the entry is keyed by. A `rank` that
|
|
3447
3590
|
is not a level the body confers and an `office` that is not one of its keys are
|
|
3448
|
-
each an error naming the file, line and column — so a
|
|
3449
|
-
|
|
3591
|
+
each an error naming the file, line and column — so a rung or a post that does
|
|
3592
|
+
not exist fails on every being pointing at it. Naming one body twice, by its short
|
|
3450
3593
|
and full Address, still names one body and is an error.
|
|
3451
3594
|
|
|
3452
3595
|
The infobox prints one line per membership, in the order the note writes them,
|
|
@@ -3456,14 +3599,16 @@ Vrystwald Tribes`, or `Hárár (5), of Vrystwald Tribes` with no office. The tit
|
|
|
3456
3599
|
is read from the body's own `governance.ranks`; where the body declares no rung
|
|
3457
3600
|
at that level, or its ladder is not available, the rung reads as `Rank 5` —
|
|
3458
3601
|
`Rank 5, of Vrystwald Tribes`. The body's name links to its page, and is plain
|
|
3459
|
-
text where it publishes none. A membership
|
|
3460
|
-
standing
|
|
3602
|
+
text where it publishes none. A membership stating no
|
|
3603
|
+
standing is the body's name alone. The lines are the same on the website, in
|
|
3461
3604
|
a Foundry journal and in the book. On the body's own page each office is a row
|
|
3462
3605
|
anchored by its name, so the post a being holds is described where the body
|
|
3463
3606
|
declares it.
|
|
3464
3607
|
|
|
3465
3608
|
For SoHL, a being embeds one affiliation item per entry: `rank` **is** that
|
|
3466
|
-
item's `system.level
|
|
3609
|
+
item's `system.level`, `office` its `system.office`, and the first name in
|
|
3610
|
+
`societies` its `system.society`. The SoHL item holds one society, so only the
|
|
3611
|
+
first name reaches it. A standing is a fact
|
|
3467
3612
|
about the setting rather than about one system, so the `sohl:` block states
|
|
3468
3613
|
none of it.
|
|
3469
3614
|
|
|
@@ -3546,7 +3691,7 @@ absent `born` — there is nothing there to disagree with — and silent whereve
|
|
|
3546
3691
|
the package declares no present, for the same reason no age is computed at
|
|
3547
3692
|
all.
|
|
3548
3693
|
|
|
3549
|
-
Use `born:` for a being's birth date.
|
|
3694
|
+
Use `born:` for a being's birth date.
|
|
3550
3695
|
|
|
3551
3696
|
#### The lead image
|
|
3552
3697
|
|
|
@@ -3666,8 +3811,7 @@ embedded document has no page for.
|
|
|
3666
3811
|
`model:` carries the catalogue item's art, and an entry copying nothing takes
|
|
3667
3812
|
the default its type pairs in `itemBuilders` — the same default an item note of
|
|
3668
3813
|
that type compiles with. An entry naming an address of its own overrides either.
|
|
3669
|
-
|
|
3670
|
-
it.
|
|
3814
|
+
An empty `icon: ""` is an error, as it is on a note.
|
|
3671
3815
|
|
|
3672
3816
|
**`data:` reaches no compiled document.** It is where a note names art, and a
|
|
3673
3817
|
compiled Item has `img` instead; the container is read and goes no further.
|
|
@@ -3919,9 +4063,16 @@ rank names the standing, and the standing says.
|
|
|
3919
4063
|
| `economy` | `Address[]` | Economic life: `affiliation` or `lore` Addresses, with an explicit type and no default |
|
|
3920
4064
|
| `lore` | `Address[]` | Lore concerning it — the peoples it draws on, the god a faith venerates, its law, its calendar |
|
|
3921
4065
|
| `parents` | `Address[]` | Affiliations that this affiliation is subordinate to |
|
|
4066
|
+
| `culture` | `Address` | The people this affiliation belongs to, naming a lore note with `subType: culture` |
|
|
3922
4067
|
| `relations` | `Map<Address, Standing>` | Standing with other affiliations, keyed by the other body's Address |
|
|
3923
4068
|
| `relations.<Address>` | `aligned`, `unaligned`, `rival` or `nemesis` | The standing this body holds toward that one; any other value is an error at the value |
|
|
3924
4069
|
|
|
4070
|
+
**An affiliation names the people it belongs to in `data.culture`.** An
|
|
4071
|
+
affiliation that names none takes its culture from its `data.parents`. A
|
|
4072
|
+
`polity` that still has none takes the culture of its places: its `data.seat`
|
|
4073
|
+
together with every place whose `data.government` names it. See
|
|
4074
|
+
[Culture in the index](#culture-in-the-index).
|
|
4075
|
+
|
|
3925
4076
|
**A faith tradition is not its god.** An `affiliation` of subType
|
|
3926
4077
|
`faithtradition` is a _religion_ — a practice, with an ordained priesthood, a
|
|
3927
4078
|
calendar and a body of observance — and it can outlive belief in the god
|
|
@@ -4556,44 +4707,48 @@ data:
|
|
|
4556
4707
|
The saga lists under **In song and story** on `place-ironfells`, which holds the
|
|
4557
4708
|
sack, on `place-east` and on `lore-fords`.
|
|
4558
4709
|
|
|
4559
|
-
Calendar fields are written only on a `calendar` note, and `
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
| `
|
|
4568
|
-
|
|
|
4569
|
-
| `
|
|
4570
|
-
| `
|
|
4571
|
-
| `
|
|
4572
|
-
| `
|
|
4573
|
-
| `
|
|
4574
|
-
| `
|
|
4575
|
-
| `
|
|
4576
|
-
| `
|
|
4577
|
-
| `
|
|
4578
|
-
| `
|
|
4579
|
-
| `
|
|
4580
|
-
| `
|
|
4581
|
-
| `
|
|
4582
|
-
| `
|
|
4583
|
-
| `
|
|
4584
|
-
| `
|
|
4585
|
-
| `eras[]
|
|
4586
|
-
| `eras[].
|
|
4587
|
-
| `eras[].
|
|
4588
|
-
| `eras[].
|
|
4589
|
-
| `eras[].
|
|
4590
|
-
| `eras[].
|
|
4591
|
-
| `
|
|
4592
|
-
| `
|
|
4593
|
-
| `
|
|
4594
|
-
| `
|
|
4595
|
-
| `
|
|
4596
|
-
| `
|
|
4710
|
+
Calendar fields are written only on a `calendar` note, and `form`, `subjects` and `language`
|
|
4711
|
+
only on a `literature` note; written on any other lore subType, each is an error at its own key.
|
|
4712
|
+
`culture` may be written on any lore subType. A culture note is itself the culture, so it
|
|
4713
|
+
leaves the field out or names itself, by its shortcode or by any longer form of its Address;
|
|
4714
|
+
naming any other note is an error at the value. A `lore` note that states no culture has
|
|
4715
|
+
none, since a `lore` note has no `data.parents` to inherit through; a culture note reads as
|
|
4716
|
+
its own Address in the index. See [Culture in the index](#culture-in-the-index).
|
|
4717
|
+
|
|
4718
|
+
| `data` property | Values | Description |
|
|
4719
|
+
| -------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
4720
|
+
| `epoch` | canonical `<year>.<day>` | The canonical day that equals calendar year 1, day 1 |
|
|
4721
|
+
| `months` | `{ name, abbreviation?, days }[]` | Ordered months; their days sum to the world's year |
|
|
4722
|
+
| `months[].name` | `string`, required | The month's name |
|
|
4723
|
+
| `months[].abbreviation` | `string` | Its short form, for a compact date |
|
|
4724
|
+
| `months[].days` | `integer`, required | How many days the month holds |
|
|
4725
|
+
| `weekdays` | `{ name, abbreviation? }[]` | Ordered week days, indexed from zero; weeks run continuously |
|
|
4726
|
+
| `weekdays[].name` | `string`, required | The day's name |
|
|
4727
|
+
| `weekdays[].abbreviation` | `string` | Its short form, for a compact date |
|
|
4728
|
+
| `seasons` | `{ name, abbreviation?, start }[]` | Seasons starting on one-based days of year |
|
|
4729
|
+
| `seasons[].name` | `string`, required | The season's name |
|
|
4730
|
+
| `seasons[].abbreviation` | `string` | Its short form, for a compact date |
|
|
4731
|
+
| `seasons[].start` | `integer`, required | The one-based day of the year it begins; starts increase down the list |
|
|
4732
|
+
| `namedDays` | `{ name, abbreviation?, day }[]` | Names assigned to one-based days of year |
|
|
4733
|
+
| `namedDays[].name` | `string`, required | The day's name |
|
|
4734
|
+
| `namedDays[].abbreviation` | `string` | Its short form, for a compact date |
|
|
4735
|
+
| `namedDays[].day` | `integer`, required | The one-based day of the year it names, distinct within the calendar |
|
|
4736
|
+
| `eras` | `{ shortcode, name, abbreviation?, marker?, proclaimedBy?, start, label? }[]` | Year counts; `start` is `null` or an in-calendar year |
|
|
4737
|
+
| `eras[].shortcode` | `string`, required | The era's own segment of `<calendar>.<era>`, unique within the calendar |
|
|
4738
|
+
| `eras[].name` | `string`, required | The era's name |
|
|
4739
|
+
| `eras[].marker` | `string` | Uppercase letters and digits, beginning with a letter, unique across the corpus; an authored date names the era by it |
|
|
4740
|
+
| `eras[].abbreviation` | `string` | Its short form, for a compact date |
|
|
4741
|
+
| `eras[].proclaimedBy` | `Address` | The body that began the reckoning |
|
|
4742
|
+
| `eras[].start` | `null` or `integer`, required | The calendar year the era begins; `null` for the era before year 1 |
|
|
4743
|
+
| `eras[].label` | `string` or `{ after?, before? }` | How a date in the era reads, around one `{date}` slot; a string is `after` |
|
|
4744
|
+
| `eras[].label.after` | `string` | How a date from the era's start reads, with exactly one `{date}` |
|
|
4745
|
+
| `eras[].label.before` | `string` | How a date before the era's start reads, with exactly one `{date}` |
|
|
4746
|
+
| `formats` | map of names to Calendaria patterns | Named date formats; `std` is the preferred default |
|
|
4747
|
+
| `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 |
|
|
4748
|
+
| `form` | `string` | `literature` only: the kind of work in its people's own terms — `epic`, `saga`, `praise-song`, `elegy`. Free text |
|
|
4749
|
+
| `subjects` | `Address[]` | `literature` only: the beings, places, gods and other notes the work concerns, and any event, as `note#id` |
|
|
4750
|
+
| `language` | `Address` | `literature` only: the tongue it is composed in, naming a skill note with `subType: language` |
|
|
4751
|
+
| `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
|
|
4597
4752
|
|
|
4598
4753
|
`data.events` is available on every `lore` subType, and is described in full under [Events](#events).
|
|
4599
4754
|
|
|
@@ -4700,7 +4855,7 @@ Braced custom forms such as `{era}` are equivalent to bracketed custom forms. A
|
|
|
4700
4855
|
|
|
4701
4856
|
A map note has its own prose and a Foundry Scene. A map can depict a place or an encounter. Several maps can depict the same place; the map names that place with `data.place`, while the place note does not list its maps.
|
|
4702
4857
|
|
|
4703
|
-
**The Scene is made in Foundry.** Walls, lights, sounds, regions, levels and pins are drawn in Foundry's Scene editor, exported, and carried by the note at `data.scene`. The build passes the Scene through: it applies `data.fixup
|
|
4858
|
+
**The Scene is made in Foundry.** Walls, lights, sounds, regions, levels and pins are drawn in Foundry's Scene editor, exported, and carried by the note at `data.scene`. The build passes the Scene through: it applies the fixups — `data.fixup` and `data.thumbnail` — binds pins marked `#anchor` to this note's pages, and checks nothing else inside it.
|
|
4704
4859
|
|
|
4705
4860
|
**subType**:
|
|
4706
4861
|
|
|
@@ -4718,6 +4873,7 @@ A subtype says what kind of map the note is. Every subtype carries an exported S
|
|
|
4718
4873
|
| `fixup[].path` | `string`, required | The exported field to replace, as a property path from `data.scene` |
|
|
4719
4874
|
| `fixup[].type` | `address`, required | What `value` is |
|
|
4720
4875
|
| `fixup[].value` | `Address`, required | The asset Address whose path replaces the exported one |
|
|
4876
|
+
| `thumbnail` | Address | The map's thumbnail, an `image` Address written into the Scene's `thumb` as a fixup — see [The thumbnail](#the-thumbnail) |
|
|
4721
4877
|
| `place` | Address | Depicted place, when one exists |
|
|
4722
4878
|
|
|
4723
4879
|
`data.scene` must be an object, and that is the only check made of it: its keys
|
|
@@ -4775,6 +4931,32 @@ data:
|
|
|
4775
4931
|
# Big Bad Wolf {#myanchor1}
|
|
4776
4932
|
```
|
|
4777
4933
|
|
|
4934
|
+
#### The thumbnail
|
|
4935
|
+
|
|
4936
|
+
`data.thumbnail` names the picture Foundry shows for the Scene in its
|
|
4937
|
+
directory and compendium lists. It is an `image` Address, and a bare shortcode
|
|
4938
|
+
reads as one: `thumbnail: wolfdenthumb` names `image-wolfdenthumb`. An Address
|
|
4939
|
+
of any other type, `icon` included, is an error at the key.
|
|
4940
|
+
|
|
4941
|
+
The thumbnail is a fixup the note does not have to spell. The map vocabulary
|
|
4942
|
+
declares that `thumbnail` belongs in the Scene's `thumb`, so the build adds
|
|
4943
|
+
`{ path: ".thumb", type: address, value: <thumbnail> }` to the note's fixups
|
|
4944
|
+
and applies it with the rest: the Address must resolve, and the exported Scene
|
|
4945
|
+
must carry `thumb`, as every Foundry export does. A `data.fixup` entry whose
|
|
4946
|
+
`path` is also `.thumb` is an error, because one would overwrite the other.
|
|
4947
|
+
The thumbnail is independent of the background art, which keeps its exported
|
|
4948
|
+
path or its own fixup.
|
|
4949
|
+
|
|
4950
|
+
```yaml
|
|
4951
|
+
data:
|
|
4952
|
+
thumbnail: wolfdenthumb
|
|
4953
|
+
scene:
|
|
4954
|
+
name: Wolf Den Scene
|
|
4955
|
+
thumb: null
|
|
4956
|
+
levels:
|
|
4957
|
+
- { _id: defaultLevel0000, background: { src: modules/maps/den.webp } }
|
|
4958
|
+
```
|
|
4959
|
+
|
|
4778
4960
|
When the Scene has pins, its Adventure bundle carries the Scene and the JournalEntry generated from its Markdown. Importing that bundle preserves the IDs the pins address. The maps naming one `data.place` share one Adventure.
|
|
4779
4961
|
|
|
4780
4962
|
#### A map in the book
|
|
@@ -4800,11 +4982,12 @@ level with no background prints nothing.
|
|
|
4800
4982
|
| `data` property | Values | Description |
|
|
4801
4983
|
| --------------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
4802
4984
|
| `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
|
|
4803
|
-
| `calendar` | `Address` | Calendar note
|
|
4985
|
+
| `calendar` | `Address` | Calendar note that prints this place's dates |
|
|
4804
4986
|
| `demonym` | `string` | What a person from this place is called — a Vylarian |
|
|
4805
4987
|
| `purpose` | `placeCharacter` tag | The reason a settlement, site, or structure exists |
|
|
4806
4988
|
| `lore` | `Address[]` | Lore concerning this place — its peoples, its law, its calendar, its history |
|
|
4807
4989
|
| `parents` | `Address[]` | Enclosing places within which this place is located |
|
|
4990
|
+
| `culture` | `Address` | The people this place belongs to, naming a lore note with `subType: culture` |
|
|
4808
4991
|
| `population` | `number` | Approximate population (precision 2 significant digits) |
|
|
4809
4992
|
| `government` | `Address` or `null` (default type: `affiliation`) | Governing affiliation; explicit null means complete anarchy. Omission warns only for positive population. |
|
|
4810
4993
|
| `market` | `number` | Market class, 1 to 6 — what trade a settlement supports |
|
|
@@ -5102,6 +5285,11 @@ urban.
|
|
|
5102
5285
|
|
|
5103
5286
|
**A place declares what is true of its ground.** It names its governing affiliation
|
|
5104
5287
|
in `data.government`; maps name the place they depict through `data.place`.
|
|
5288
|
+
A place may name the people it belongs to in `data.culture`. A place that names
|
|
5289
|
+
none takes its culture from its `data.parents`, so a region states the culture
|
|
5290
|
+
once and the districts and settlements inside it carry it without repeating it;
|
|
5291
|
+
[Culture in the index](#culture-in-the-index) gives the rule and a worked
|
|
5292
|
+
example.
|
|
5105
5293
|
The place's `lore` links cover its peoples, calendar, law and history. Political
|
|
5106
5294
|
languages belong to a polity's `sohl.system.commonSkills`, while the note's
|
|
5107
5295
|
`description` provides its page summary.
|
|
@@ -5136,9 +5324,22 @@ Content prepared to be played — a situation with its cast, places, and possibl
|
|
|
5136
5324
|
- reference: Out-of-world lookup material about the setting or system — correspondences, conversions, glossaries.
|
|
5137
5325
|
- howto: A task with an outcome, written as the steps that reach it.
|
|
5138
5326
|
- concept: An explanation of how something works and why it is shaped that way, read to understand rather than to follow.
|
|
5139
|
-
- settingguide:
|
|
5140
|
-
|
|
5141
|
-
|
|
5327
|
+
- settingguide: A culture's guide to the setting, which names its culture in `data.culture`. It orients a reader to a setting or region, bringing its places, peoples, institutions, and daily life into one usable frame with links to detailed notes.
|
|
5328
|
+
|
|
5329
|
+
| `data` property | Values | Description |
|
|
5330
|
+
| --------------- | --------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
5331
|
+
| `culture` | `Address` | `settingguide` only, and required there: the culture the guide introduces, naming a lore note with `subType: culture` |
|
|
5332
|
+
|
|
5333
|
+
A setting guide introduces one culture's view of the setting, so it names that
|
|
5334
|
+
culture, and a `doc` of any other `subType` has no culture of its own to name.
|
|
5335
|
+
A setting guide without `data.culture` is an error at its `subType:` line;
|
|
5336
|
+
`data.culture` on any other `doc` subType is an error at its key. The value
|
|
5337
|
+
names a `lore` note of `subType: culture`, and a setting guide's culture is the
|
|
5338
|
+
one it states: it inherits nothing, because a `doc` has no `data.parents`. The
|
|
5339
|
+
other notes that may state a culture are described under
|
|
5340
|
+
[`place`](#type-place), [`affiliation`](#type-affiliation) and
|
|
5341
|
+
[`lore`](#type-lore), and [Culture in the index](#culture-in-the-index) gives
|
|
5342
|
+
the value each one reads as.
|
|
5142
5343
|
|
|
5143
5344
|
Choose `settingguide` for an entry point that stands on its own while guiding
|
|
5144
5345
|
players and GMs into a setting. A `concept` explains one subject, a `reference`
|
|
@@ -5154,6 +5355,8 @@ name: { full: The Reed Flats Guide }
|
|
|
5154
5355
|
type: doc
|
|
5155
5356
|
subType: settingguide
|
|
5156
5357
|
description: A starting point for adventures in the Reed Flats.
|
|
5358
|
+
data:
|
|
5359
|
+
culture: lore-reedfolk
|
|
5157
5360
|
---
|
|
5158
5361
|
|
|
5159
5362
|
The Reed Flats are a network of marsh settlements linked by river trade.
|