@heroiclands/package-build 22.21.0 → 22.23.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 +223 -0
- package/assets/styles/content-base.css +162 -0
- package/bin/content-commands.mjs +77 -17
- package/bin/package-build.mjs +15 -2
- package/ci/content-format-reference.mjs +68 -1
- package/config.mjs +26 -0
- package/content-config.mjs +153 -6
- package/docs/api.md +120 -89
- package/docs/authoring/assets.md +14 -0
- package/docs/authoring/dates-and-calendars.md +41 -3
- package/docs/authoring/frontmatter.md +2 -2
- package/docs/authoring/links-and-markup.md +325 -35
- package/docs/commands.md +12 -10
- package/docs/configuration.md +117 -14
- package/docs/content-format.md +4 -2
- package/docs/guides/book.md +5 -4
- package/docs/guides/reference-pages.md +15 -0
- package/docs/reference/format-details.md +545 -104
- package/docs/reference/note-types.md +30 -13
- package/engine/actor-compiler.mjs +23 -0
- package/engine/anchored-sections.mjs +35 -4
- package/engine/anchors.mjs +26 -30
- package/engine/art-fields.mjs +118 -0
- package/engine/art-slots.mjs +7 -1
- package/engine/asset-index.mjs +160 -10
- package/engine/asset-replacement.mjs +93 -0
- package/engine/asset-types.mjs +240 -0
- package/engine/base-compiler.mjs +139 -22
- package/engine/base-styles.mjs +149 -0
- package/engine/bundles.mjs +13 -2
- package/engine/compendiums.mjs +8 -1
- package/engine/content-blocks.mjs +410 -0
- package/engine/content-embeds.mjs +19 -0
- package/engine/content-figures.mjs +468 -0
- package/engine/content-footnotes.mjs +197 -0
- package/engine/content-format-check.mjs +15 -12
- package/engine/content-format.yaml +1 -1
- package/engine/content-images.mjs +126 -25
- package/engine/content-index.mjs +38 -12
- package/engine/content-links.mjs +14 -6
- package/engine/content-tables.mjs +45 -4
- package/engine/content-tasklists.mjs +189 -0
- package/engine/docs-checks.mjs +4 -4
- package/engine/extension-attributes.mjs +48 -2
- package/engine/field-reference.mjs +31 -10
- package/engine/field-spec.mjs +10 -8
- package/engine/foreign-catalog.mjs +143 -18
- package/engine/frontmatter-lint.mjs +120 -65
- package/engine/frontmatter.mjs +3 -3
- package/engine/heading-attributes.mjs +321 -0
- package/engine/helpers.mjs +109 -41
- package/engine/homepage.mjs +8 -8
- package/engine/index.mjs +3 -0
- package/engine/infobox-registry.mjs +4 -1
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +129 -15
- package/engine/itinerary-scenes.mjs +4 -10
- package/engine/journals.mjs +294 -50
- package/engine/lore-events.mjs +197 -0
- package/engine/macros.mjs +1 -1
- package/engine/markdown-expressions.mjs +434 -59
- package/engine/note-dates.mjs +354 -12
- package/engine/note-frontmatter.mjs +7 -16
- package/engine/note-vocabulary.mjs +183 -42
- package/engine/page-lists.mjs +358 -0
- package/engine/pathnames.mjs +36 -0
- package/engine/pdf-build.mjs +431 -74
- package/engine/pdf-images.mjs +64 -0
- package/engine/pdf-render.mjs +563 -66
- package/engine/rank-ladder.mjs +198 -0
- package/engine/reckoning-markers.mjs +1 -1
- package/engine/retired-fields.mjs +8 -13
- package/engine/scenes.mjs +26 -7
- package/engine/site-build.mjs +166 -23
- package/engine/site-config.mjs +10 -1
- package/engine/site-index.mjs +90 -3
- package/engine/site-preview.mjs +20 -7
- package/engine/social-ties.mjs +52 -14
- package/engine/sql-tables.mjs +66 -9
- package/engine/standings.mjs +89 -6
- package/engine/system-block.mjs +56 -30
- package/engine/web-wikilinks.mjs +48 -1
- package/hm3/actors.mjs +8 -5
- package/manifest.mjs +43 -24
- package/package.json +1 -1
- package/packagebuild-metadata.jsonl +13 -13
- package/sohl/actors.mjs +22 -99
- package/sohl/item-fields.mjs +5 -5
- package/sohl/items.mjs +1 -1
- package/sohl/note-schemas.mjs +11 -21
- package/types/config.d.mts +9 -0
- package/types/content-config.d.mts +48 -1
- package/types/engine/actor-compiler.d.mts +11 -0
- package/types/engine/anchored-sections.d.mts +24 -0
- package/types/engine/anchors.d.mts +9 -4
- package/types/engine/art-fields.d.mts +64 -0
- package/types/engine/asset-index.d.mts +43 -0
- package/types/engine/asset-replacement.d.mts +22 -0
- package/types/engine/asset-types.d.mts +18 -0
- package/types/engine/base-compiler.d.mts +19 -17
- package/types/engine/base-styles.d.mts +93 -0
- package/types/engine/content-blocks.d.mts +87 -0
- package/types/engine/content-embeds.d.mts +16 -0
- package/types/engine/content-figures.d.mts +101 -0
- package/types/engine/content-footnotes.d.mts +80 -0
- package/types/engine/content-format-check.d.mts +8 -6
- package/types/engine/content-images.d.mts +78 -12
- package/types/engine/content-index.d.mts +8 -2
- package/types/engine/content-tables.d.mts +12 -4
- package/types/engine/content-tasklists.d.mts +72 -0
- package/types/engine/extension-attributes.d.mts +22 -1
- package/types/engine/field-reference.d.mts +21 -0
- package/types/engine/field-spec.d.mts +20 -16
- package/types/engine/foreign-catalog.d.mts +39 -0
- package/types/engine/frontmatter.d.mts +1 -1
- package/types/engine/heading-attributes.d.mts +179 -0
- package/types/engine/helpers.d.mts +29 -10
- package/types/engine/homepage.d.mts +7 -7
- package/types/engine/index.d.mts +1 -0
- package/types/engine/infobox-registry.d.mts +4 -1
- package/types/engine/infobox-render.d.mts +6 -1
- package/types/engine/infobox.d.mts +6 -0
- package/types/engine/journals.d.mts +41 -12
- package/types/engine/lore-events.d.mts +14 -0
- package/types/engine/markdown-expressions.d.mts +46 -2
- package/types/engine/note-dates.d.mts +64 -1
- package/types/engine/note-frontmatter.d.mts +1 -4
- package/types/engine/note-vocabulary.d.mts +82 -6
- package/types/engine/page-lists.d.mts +126 -0
- package/types/engine/pathnames.d.mts +26 -0
- package/types/engine/pdf-build.d.mts +28 -6
- package/types/engine/pdf-images.d.mts +52 -0
- package/types/engine/pdf-render.d.mts +84 -2
- package/types/engine/rank-ladder.d.mts +32 -0
- package/types/engine/retired-fields.d.mts +4 -6
- package/types/engine/site-build.d.mts +27 -4
- package/types/engine/site-config.d.mts +9 -0
- package/types/engine/site-index.d.mts +67 -1
- package/types/engine/site-preview.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -7
- package/types/engine/standings.d.mts +21 -3
- package/types/engine/system-block.d.mts +37 -14
- package/types/engine/web-wikilinks.d.mts +3 -1
- package/types/hm3/actors.d.mts +21 -3
- package/types/manifest.d.mts +19 -23
- package/types/sohl/actors.d.mts +6 -7
- package/engine/content-admonitions.mjs +0 -114
- package/engine/content-captions.mjs +0 -181
- package/engine/content-secrets.mjs +0 -112
- package/types/engine/content-admonitions.d.mts +0 -24
- package/types/engine/content-captions.d.mts +0 -45
- package/types/engine/content-secrets.d.mts +0 -17
|
@@ -352,7 +352,9 @@ order without changing the Markdown body.
|
|
|
352
352
|
|
|
353
353
|
#### Dates and calendars
|
|
354
354
|
|
|
355
|
-
A canonical date is `<year>[.<day>[:HHMMSS]]`. The day is one-based within the world's year. `720` covers the whole year; `720.136` covers that day; `720.136:143005` identifies one second. Negative years are valid. Prefix either form with `~` to express uncertainty beyond its written interval. `unknown` is allowed only in fields that accept an unknown occurrence.
|
|
355
|
+
A canonical date is `<year>[.<day>[:HHMMSS]]`. The day is one-based within the world's year, bound against `data.year.days` on the world's `place` note. A tree whose notes declare no world year bounds no day: the value is read as written, however large. `720` covers the whole year; `720.136` covers that day; `720.136:143005` identifies one second. Negative years are valid. Prefix either form with `~` to express uncertainty beyond its written interval. `unknown` is allowed only in fields that accept an unknown occurrence.
|
|
356
|
+
|
|
357
|
+
**Quote a canonical date that states a day.** `born: "667.130"` is read as written; unquoted, YAML parses the scalar as a number and a trailing zero on the day is gone before any date reader sees it, so `667.130` and `667.13` arrive as one value. A number-valued date is an error wherever appending a zero to its day would still name a day inside the world's year — the message names the file, the line and both readings — and is read as written where no such day exists, since `675.2810` is no day of a 365-day year. A bare year loses nothing and needs no quotes.
|
|
356
358
|
|
|
357
359
|
A named date uses `datefrom <calendar> <date>`, where the final text follows the calendar's `data.formats.std` pattern, or its first named pattern when `std` is absent. For example, a calendar with `std: "MM/DD/Y GGG"` reads `datefrom commoncal 01/23/326 VR`, `datefrom commoncal 01/326 VR`, and `datefrom commoncal 326 VR`. Omitting the day or month retains month or year precision in frontmatter. The CLI `datefrom` command requires a day to produce one canonical day. The calendar argument is a shortcode or Address. A time follows the day only when specified in the pattern, or as a trailing `HH:mm:ss` when the pattern has no clock tokens. A named date with an era-relative year names its era.
|
|
358
360
|
|
|
@@ -699,12 +701,12 @@ exactly as `seat` declares `place` — a bare shortcode takes its type from the
|
|
|
699
701
|
declaration, and qualification climbs the same short-form ladder every other
|
|
700
702
|
link uses.
|
|
701
703
|
|
|
702
|
-
| field | default type | accepts | resolves into
|
|
703
|
-
| ----------- | ------------ | --------------- |
|
|
704
|
-
| `icon` | `icon` | `icon`, `image` | `document.img`
|
|
705
|
-
| `tokenIcon` | `icon` | `icon`, `image` | `prototypeToken.texture.src`
|
|
706
|
-
| `bgImage` | `image` | `icon`, `image` | `background.src`
|
|
707
|
-
| `banner` | `image` | `icon`, `image` | the site hero image
|
|
704
|
+
| field | default type | accepts | resolves into | on |
|
|
705
|
+
| ----------- | ------------ | --------------- | ----------------------------- | ----------------------------------------- |
|
|
706
|
+
| `icon` | `icon` | `icon`, `image` | `document.img` | every Actor/Item type, and embedded items |
|
|
707
|
+
| `tokenIcon` | `icon` | `icon`, `image` | `prototypeToken.texture.src` | Actor types |
|
|
708
|
+
| `bgImage` | `image` | `icon`, `image` | `background.src` | map types |
|
|
709
|
+
| `banner` | `image` | `icon`, `image` | the site hero image, 1792×768 | any note; not a Foundry field |
|
|
708
710
|
|
|
709
711
|
All four are authored under `data:`:
|
|
710
712
|
|
|
@@ -748,7 +750,7 @@ noticed:
|
|
|
748
750
|
| `packFolder` | `Address` or pack map | The shared compendium folder Address. |
|
|
749
751
|
| `harnworld` | `Map<string, unknown>` | HârnWorld source details. |
|
|
750
752
|
| `icon` | `Address` | The document's profile art — an `icon` address, resolved into `img`. |
|
|
751
|
-
| `banner` | `Address` | The page's hero image — an `image` address.
|
|
753
|
+
| `banner` | `Address` | The page's hero image — an `image` address, cut to 1792×768. |
|
|
752
754
|
|
|
753
755
|
`icon` is legal everywhere because most types compile into a document that
|
|
754
756
|
carries one; where a type's passes emit none, the lint says so and the value is
|
|
@@ -851,12 +853,12 @@ ships as the Foundry module `harn-ensemble`) writing `images/map.webp`:
|
|
|
851
853
|
And for the same note writing `sohl/assets/icons/noun/shield.svg`, a file the
|
|
852
854
|
system ships and this repository does not hold:
|
|
853
855
|
|
|
854
|
-
| Surface | Address
|
|
855
|
-
| ----------- |
|
|
856
|
-
| **Foundry** | `systems/sohl/assets/icons/noun/shield.svg`
|
|
857
|
-
| **Local** | `assets/icons/noun/shield.svg`, in the `sohl` repository
|
|
858
|
-
| **Web** | `https://cdn.heroiclands.org/sohl/icons/noun/shield.svg`
|
|
859
|
-
| **Book** | not carried
|
|
856
|
+
| Surface | Address |
|
|
857
|
+
| ----------- | ------------------------------------------------------------- |
|
|
858
|
+
| **Foundry** | `systems/sohl/assets/icons/noun/shield.svg` |
|
|
859
|
+
| **Local** | `assets/icons/noun/shield.svg`, in the `sohl` repository |
|
|
860
|
+
| **Web** | `https://cdn.heroiclands.org/sohl/icons/noun/shield.svg` |
|
|
861
|
+
| **Book** | not carried, unless a declared replacement carries it instead |
|
|
860
862
|
|
|
861
863
|
**The content package name and Foundry id are separate values.**
|
|
862
864
|
`harnensemble` is what the content is called, what a note writes, and what the
|
|
@@ -882,6 +884,29 @@ index enabled, an asset with no matching note is a located build error. See
|
|
|
882
884
|
[asset bindings](../configuration.md#packagebuildstagedir-and-packagebuildassets)
|
|
883
885
|
for the configuration and cache requirements.
|
|
884
886
|
|
|
887
|
+
**A package declared as a replacement is carried into the book, from its
|
|
888
|
+
fetched archive, when it answers the address; every other foreign package
|
|
889
|
+
stays not carried.** A relationship declaring `assetReplacement: true` names a
|
|
890
|
+
dependency whose asset tree answers this package's own addresses first — see
|
|
891
|
+
[`relationships`](../configuration.md#relationships) — and the book is the one
|
|
892
|
+
surface that otherwise refuses a foreign file outright, so it is the one
|
|
893
|
+
surface this changes. A `thalorna` note embedding
|
|
894
|
+
`![[thalornaaltart-none-icon-anvil|An anvil]]` names `thalornaaltart`'s own
|
|
895
|
+
address, exactly as a note citing `sohl`'s shared bestiary art would; when
|
|
896
|
+
`thalornaaltart` is declared with `assetReplacement: true` and its fetched
|
|
897
|
+
archive carries `icon-anvil` under its own package, the book stages that file
|
|
898
|
+
from the archive instead of printing the caption with no picture. A note
|
|
899
|
+
citing a different package's own address this way — `sohl`'s bestiary art,
|
|
900
|
+
say — stays refused exactly as the row above states, because `sohl` was never
|
|
901
|
+
declared as a replacement: a package answers in place of another only when it
|
|
902
|
+
opted in, never because its archive happens to carry a file at the same type
|
|
903
|
+
and shortcode.
|
|
904
|
+
|
|
905
|
+
A relationship declaring `assetReplacement: true` whose archive was never
|
|
906
|
+
fetched is a configuration mistake, not an ordinary unresolved address: the
|
|
907
|
+
book reports a located error naming the relationship and instructing
|
|
908
|
+
`package-build deps fetch`, rather than printing a caption with no picture.
|
|
909
|
+
|
|
885
910
|
**The host is configuration.** `site.assets` in `package-build.config.yaml` is
|
|
886
911
|
the root the web form is joined onto, and a package-owned image on a page with
|
|
887
912
|
none set is an error naming that key.
|
|
@@ -925,6 +950,18 @@ Foundry destination: searching a built `packs-json` tree for it turns up
|
|
|
925
950
|
nothing. It reaches the generated page and the book's section plates, and
|
|
926
951
|
nothing else.
|
|
927
952
|
|
|
953
|
+
**A hero image is 1792×768.** It fills one fixed strip wherever it is drawn, so
|
|
954
|
+
every banner is cut to that size and a picture of any other size is a finding
|
|
955
|
+
naming both sizes — resize the picture to match. The size is stated once, by the
|
|
956
|
+
slot itself, which is what gives an artist a figure to work to before any file
|
|
957
|
+
exists.
|
|
958
|
+
|
|
959
|
+
No other art slot states a size, and none of them asks anything of a picture's
|
|
960
|
+
dimensions. An `icon` is drawn at a nominal size per medium whatever its file
|
|
961
|
+
holds; a map's `bgImage` sets its own scene's dimensions, so it is whatever size
|
|
962
|
+
the map is; and a picture written in prose is fitted to the room it has. Those
|
|
963
|
+
three accept whatever they are given.
|
|
964
|
+
|
|
928
965
|
It is an `Address` all the same, defaulting to type `image`, so a section note
|
|
929
966
|
writes `banner: skillbnr` and a note borrowing another package's plate writes
|
|
930
967
|
`banner: packagebuild-none-image-skillbnr`. The resolved record carries the
|
|
@@ -1683,14 +1720,17 @@ carries no frontmatter, no anchors and no `foundry` block: a file declares
|
|
|
1683
1720
|
nothing about itself, compiles into no document, and publishes no page, so the
|
|
1684
1721
|
`address` holds the canonical key and no page slug.
|
|
1685
1722
|
|
|
1686
|
-
| `asset` field | Source | What it says
|
|
1687
|
-
| ------------- | ---------- |
|
|
1688
|
-
| `path` | the walk | Where the file sits inside the emitting package's asset directory.
|
|
1689
|
-
| `attribution` | provenance | The person holding the rights, to whom attribution is legally due.
|
|
1690
|
-
| `source` | provenance | Where it came from — a URL, or a sentence.
|
|
1691
|
-
| `ai` | provenance | Whether the file is machine-generated — `true` or `false`.
|
|
1692
|
-
| `license` | provenance | The licence it is used under — an SPDX identifier, or terms.
|
|
1693
|
-
| `notes` | provenance | Anything else a person reading the attribution needs.
|
|
1723
|
+
| `asset` field | Source | What it says |
|
|
1724
|
+
| ------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1725
|
+
| `path` | the walk | Where the file sits inside the emitting package's asset directory. |
|
|
1726
|
+
| `attribution` | provenance | The person holding the rights, to whom attribution is legally due. |
|
|
1727
|
+
| `source` | provenance | Where it came from — a URL, or a sentence. |
|
|
1728
|
+
| `ai` | provenance | Whether the file is machine-generated — strictly the YAML boolean `true` or `false`; any other value is a finding, never a stringified record. Unstated resolves to `false`. |
|
|
1729
|
+
| `license` | provenance | The licence it is used under — an SPDX identifier, or terms. |
|
|
1730
|
+
| `notes` | provenance | Anything else a person reading the attribution needs. |
|
|
1731
|
+
| `role` | provenance | What the picture is for — `portrait`, `emblem`, `banner`, `plate` or `map`. Absent for an ordinary picture; a value outside that set is a finding. The `image` type only — a value on an `icon` address is a finding and is dropped. |
|
|
1732
|
+
| `width` | the walk | The file's pixel width, read from its own header. Blank for an SVG, which has no pixel dimensions. |
|
|
1733
|
+
| `height` | the walk | The file's pixel height, read from its own header. Blank for an SVG, which has no pixel dimensions. |
|
|
1694
1734
|
|
|
1695
1735
|
Every field is present on every record, blank where nothing states one. A fixed
|
|
1696
1736
|
shape is what lets a consumer read `asset.license` without first asking whether
|
|
@@ -1709,6 +1749,90 @@ joins its own root onto it:
|
|
|
1709
1749
|
Foundry paths use the **Foundry package id**. The two values are both `thalorna`
|
|
1710
1750
|
for this image; `harnensemble` content uses `harn-ensemble` in its Foundry paths.
|
|
1711
1751
|
|
|
1752
|
+
##### What a role declares
|
|
1753
|
+
|
|
1754
|
+
`role` names what the picture is for, from a closed set:
|
|
1755
|
+
|
|
1756
|
+
| Role | What it names |
|
|
1757
|
+
| ---------- | -------------------------------------------------------- |
|
|
1758
|
+
| `portrait` | A picture of a subject — a being, a building, an object. |
|
|
1759
|
+
| `emblem` | A device, arms, a sigil — a mark rather than a scene. |
|
|
1760
|
+
| `banner` | A wide strip across the head of a page or a book plate. |
|
|
1761
|
+
| `plate` | A full-measure illustration meant to be looked at. |
|
|
1762
|
+
| `map` | A plan or chart, read by examining its detail. |
|
|
1763
|
+
|
|
1764
|
+
An asset declaring no role is an ordinary picture: there is no default role
|
|
1765
|
+
name, only the absence of one. A value outside this set is refused with a
|
|
1766
|
+
finding naming the file, the key and the accepted values, and the record
|
|
1767
|
+
carries no role rather than the one it was given. `role` belongs to the
|
|
1768
|
+
`image` type only — an `icon` address carries one nominal size per medium
|
|
1769
|
+
whatever the file holds, so a `role` declared there is a finding and is
|
|
1770
|
+
dropped rather than carried through.
|
|
1771
|
+
|
|
1772
|
+
A declared role makes two checks possible. **Shape**, an error, flags an
|
|
1773
|
+
asset whose aspect ratio departs from the median of every other asset
|
|
1774
|
+
sharing its role — the expectation is derived from the role-sharing group
|
|
1775
|
+
itself at build time, never from a second, hand-kept table. **Resolution**,
|
|
1776
|
+
a warning, flags an asset whose pixel width falls short of what its role's
|
|
1777
|
+
largest print slot needs. Both exempt a vector asset, which carries no pixel
|
|
1778
|
+
dimensions and no aspect that survives being drawn at a nominal size.
|
|
1779
|
+
|
|
1780
|
+
`role: map` also selects a `:::figure` fence's counter — see
|
|
1781
|
+
[figures and numbered references](../authoring/links-and-markup.md#figures-and-numbered-references).
|
|
1782
|
+
A fence whose picture draws an address with that role counts as `Map` rather
|
|
1783
|
+
than `Figure`, on every surface that numbers it, because the role is the one
|
|
1784
|
+
fact the fence's own markup cannot state.
|
|
1785
|
+
|
|
1786
|
+
##### What a role draws at
|
|
1787
|
+
|
|
1788
|
+
A role names what a picture is for; it says nothing about how large one
|
|
1789
|
+
draws. Deciding that is a medium's own job — the book owns a table mapping
|
|
1790
|
+
each role to a maximum, and a website's or a Foundry system's stylesheet owns
|
|
1791
|
+
the equivalent table for its own surface, keyed off the role class and the
|
|
1792
|
+
`width`/`height` attributes the emitted markup carries (blank for a vector).
|
|
1793
|
+
Changing a role's slot is one line in that table, not an edit to every note
|
|
1794
|
+
drawing one.
|
|
1795
|
+
|
|
1796
|
+
**Every size is a maximum, never a target.** The drawn width is the smaller of
|
|
1797
|
+
the role's slot and what the file's own pixels support at the medium's print
|
|
1798
|
+
floor:
|
|
1799
|
+
|
|
1800
|
+
> drawn width = min(the role's slot, natural pixels ÷ the print floor)
|
|
1801
|
+
|
|
1802
|
+
A picture is never drawn larger than it was made: a 512px portrait stretched
|
|
1803
|
+
across the slot a `plate` fills is a soft rectangle that reads as broken. A
|
|
1804
|
+
vector carries no pixel count, so nothing narrows its role's slot; it always
|
|
1805
|
+
draws at the slot. An `icon` address takes the medium's nominal icon size
|
|
1806
|
+
whatever role it might otherwise have had — `role` never reaches one, since
|
|
1807
|
+
the asset record refuses it there.
|
|
1808
|
+
|
|
1809
|
+
The book's table, and the print floor it reads from the same constant its page
|
|
1810
|
+
geometry is set against (300 dpi):
|
|
1811
|
+
|
|
1812
|
+
| Role | The book's slot |
|
|
1813
|
+
| --------------------------- | --------------------------------- |
|
|
1814
|
+
| `portrait`, `emblem` | half the page's text measure |
|
|
1815
|
+
| `banner`, `plate`, `map` | the full page's text measure |
|
|
1816
|
+
| an `icon` address, any role | one inch, whatever the file holds |
|
|
1817
|
+
|
|
1818
|
+
On this book's US Letter page the text measure is about 7.00in, so a
|
|
1819
|
+
`portrait` or an `emblem` draws at up to about 3.50in and a `banner`, a
|
|
1820
|
+
`plate` or a `map` draws at up to about 7.00in — still the smaller of that
|
|
1821
|
+
and what the file's pixels support.
|
|
1822
|
+
|
|
1823
|
+
**A worked example.** A `portrait`-role file measuring 900×1350px, drawn with
|
|
1824
|
+
no named `size=`: at 300 dpi its pixels support 900 ÷ 300 = 3.00in, which is
|
|
1825
|
+
narrower than the role's 3.50in slot, so the book draws it at 3.00in. The same
|
|
1826
|
+
picture at 1200×1800px supports 4.00in, wider than the slot, so the book draws
|
|
1827
|
+
it at its 3.50in slot instead — the slot bounds it, exactly as a maximum
|
|
1828
|
+
should. Either way the emitted markup for the website and for a Foundry
|
|
1829
|
+
journal carries `note-image-role-portrait` as a class and `900`/`1350` (or
|
|
1830
|
+
`1200`/`1800`) as its `width`/`height` attributes, which is what a stylesheet
|
|
1831
|
+
on either surface sizes a `portrait` from.
|
|
1832
|
+
|
|
1833
|
+
A named `size=` written beside the embed overrides a role's slot outright, the
|
|
1834
|
+
same as it always has — a role decides the size nothing else states.
|
|
1835
|
+
|
|
1712
1836
|
##### Where provenance comes from
|
|
1713
1837
|
|
|
1714
1838
|
A `provenance.yaml` states the provenance fields in the table above, and nothing
|
|
@@ -1736,9 +1860,40 @@ resolving a chain by hand.
|
|
|
1736
1860
|
That is also why `attribution` and `license` are **required in any record that
|
|
1737
1861
|
exists**: a key left out is not inherited from above, it is simply absent, so a
|
|
1738
1862
|
record stating neither leaves every file it covers with no rights holder and no
|
|
1739
|
-
terms. Omitting one is a finding. `source`, `ai` and `
|
|
1863
|
+
terms. Omitting one is a finding. `source`, `ai`, `notes` and `role` stay optional,
|
|
1740
1864
|
because a blank is a truthful answer for each of them.
|
|
1741
1865
|
|
|
1866
|
+
##### A declared replacement resolves first
|
|
1867
|
+
|
|
1868
|
+
A package may declare, on a `relationships.<kind>[]` entry, that a
|
|
1869
|
+
dependency's asset tree answers this package's own asset addresses ahead of
|
|
1870
|
+
its local record — `assetReplacement: true` in `package-build.config.yaml`.
|
|
1871
|
+
Once declared, an asset address resolves in this order:
|
|
1872
|
+
|
|
1873
|
+
1. **Every declared replacement, in declaration order.** The package segment
|
|
1874
|
+
of each relationship declaring `assetReplacement: true` is tried in the
|
|
1875
|
+
order those relationships are written, and the first one carrying the
|
|
1876
|
+
address wins.
|
|
1877
|
+
2. **Falling through to the package's own record** when no declared
|
|
1878
|
+
replacement carries the address — the resolution this package already
|
|
1879
|
+
performs with no `assetReplacement` declared at all.
|
|
1880
|
+
|
|
1881
|
+
**This reaches asset types only.** A being, an item or a lore note is never
|
|
1882
|
+
replaced this way, whatever a relationship declares: the rule tests the
|
|
1883
|
+
address's type, not the relationship. A replacement answers only `icon`,
|
|
1884
|
+
`image` and `audio` addresses whose package segment is this package's own; an
|
|
1885
|
+
address naming any other type, or naming a different package, is untouched.
|
|
1886
|
+
|
|
1887
|
+
**A replacement's own output address is never itself looked up against
|
|
1888
|
+
another replacement.** Resolving `thalornaaltart-none-image-thorn` never asks
|
|
1889
|
+
whether something replaces `thalornaaltart` — resolution is a single pass over
|
|
1890
|
+
the declared list, not a chain, which forecloses a cycle by construction.
|
|
1891
|
+
|
|
1892
|
+
This is distinct from a `foreign` lookup, which serves a declared dependency's
|
|
1893
|
+
own content for an address this package's local index does not carry. A
|
|
1894
|
+
replacement is consulted **before** the local address; a foreign lookup only
|
|
1895
|
+
**after** it misses locally.
|
|
1896
|
+
|
|
1742
1897
|
#### A font is not an asset
|
|
1743
1898
|
|
|
1744
1899
|
`assets/fonts` is not a root, and a font has no address.
|
|
@@ -2086,11 +2241,69 @@ See the [authoring examples](../authoring/links-and-markup.md#footnotes-and-defi
|
|
|
2086
2241
|
# Heading {#id .class1 .class2 attr="value"}
|
|
2087
2242
|
```
|
|
2088
2243
|
|
|
2089
|
-
Any header can
|
|
2244
|
+
Any header can end with a braced attribute block, in the same grammar a
|
|
2245
|
+
`:::figure` fence and a named block take. Inside the braces:
|
|
2246
|
+
|
|
2247
|
+
- `#id` names the anchor a link resolves to (only one allowed)
|
|
2248
|
+
- `.class1` names a CSS class (any number of classes allowed)
|
|
2249
|
+
- `attr="value"` names an HTML attribute whose value is `value` (any number of
|
|
2250
|
+
key/value pairs allowed)
|
|
2251
|
+
|
|
2252
|
+
The id is what every surface publishes; a class and an attribute reach only the
|
|
2253
|
+
surfaces that have somewhere to put them.
|
|
2254
|
+
|
|
2255
|
+
| | an `#id` | a `.class` | an `attr="value"` |
|
|
2256
|
+
| --------------- | ----------------------------------------------------------- | --------------------- | ---------------------- |
|
|
2257
|
+
| Website | the heading's `id`, and the target of `[[note#id\|…]]` | the heading's `class` | written on the heading |
|
|
2258
|
+
| Foundry journal | the anchor the page is addressed by, and the heading's `id` | the heading's `class` | written on the heading |
|
|
2259
|
+
| Book | the Typst label the heading is linked to | dropped | dropped |
|
|
2260
|
+
|
|
2261
|
+
**The book drops both**, because Typst has no stylesheet for a class to name
|
|
2262
|
+
and no element for an attribute to sit on. A heading whose appearance matters in
|
|
2263
|
+
print is set by the book's own template, not by a class an author writes.
|
|
2264
|
+
|
|
2265
|
+
An id contains letters, digits, `_` or `-`. A class and an attribute key begin
|
|
2266
|
+
with a letter. Braces holding nothing the grammar recognises — a set, a die
|
|
2267
|
+
expression, a measurement — are one finding at the heading's line, and the
|
|
2268
|
+
heading is set as it was written so nothing is lost while the author reads the
|
|
2269
|
+
message.
|
|
2270
|
+
|
|
2271
|
+
`id=` and `class=` are refused in favour of `#id` and `.class`, and an attribute
|
|
2272
|
+
beginning `on` is refused as an event handler, exactly as on a named block: a
|
|
2273
|
+
heading's attributes are written onto the element, so nothing authored in a note
|
|
2274
|
+
becomes code on a published page.
|
|
2275
|
+
|
|
2276
|
+
#### A section withheld from players
|
|
2277
|
+
|
|
2278
|
+
The class `secret` on the heading that opens a section withholds that section.
|
|
2279
|
+
The heading keeps its id, so the section stays linkable: secrecy is a property
|
|
2280
|
+
of the section, not of the name a link resolves to.
|
|
2281
|
+
|
|
2282
|
+
```markdown
|
|
2283
|
+
# The Cellar {#cellar .secret}
|
|
2284
|
+
|
|
2285
|
+
The contraband is behind the false wall.
|
|
2286
|
+
```
|
|
2287
|
+
|
|
2288
|
+
The section runs from the heading to the next heading that opens a page, which
|
|
2289
|
+
is the span Foundry makes one page of.
|
|
2090
2290
|
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2291
|
+
| Surface | What a reader meets |
|
|
2292
|
+
| ------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
2293
|
+
| Foundry | The journal page is visible to the GM alone — `ownership: { default: 0 }`, `CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE` |
|
|
2294
|
+
| Website | The heading and everything under it sit inside the expandable `<details>` a `:::secret` block renders as |
|
|
2295
|
+
| Book | The heading and everything under it are set in the labelled block a `:::secret` is set in |
|
|
2296
|
+
|
|
2297
|
+
**On the website this is a spoiler and not access control.** The withheld
|
|
2298
|
+
section is in the published page, so a reader who opens the element or reads the
|
|
2299
|
+
source reads it — exactly as a `:::secret` block is. Foundry is the only surface
|
|
2300
|
+
that withholds anything from anybody. Write nothing in a `.secret` section that
|
|
2301
|
+
would matter if a player read it on the web.
|
|
2302
|
+
|
|
2303
|
+
A `:::secret` block inside a withheld section is legal and renders as it does
|
|
2304
|
+
anywhere else. `.secret` on a heading that opens **no** page covers no page, so
|
|
2305
|
+
no surface can honour it: that is a finding at the heading's own line, answered
|
|
2306
|
+
by giving the heading an anchor or raising it to the top level.
|
|
2094
2307
|
|
|
2095
2308
|
#### Images
|
|
2096
2309
|
|
|
@@ -2111,11 +2324,14 @@ either side of it, and every surface renders it as a figure. An image sharing a
|
|
|
2111
2324
|
paragraph with prose is refused, because a width and a position mean nothing
|
|
2112
2325
|
applied to a word in the middle of a sentence.
|
|
2113
2326
|
|
|
2114
|
-
**
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2327
|
+
**Alt text renders as a caption on no surface.** On the website and in a
|
|
2328
|
+
Foundry journal it stays on the `img` element's `alt` attribute alone, and the
|
|
2329
|
+
book prints nothing beneath a picture that carries none. A visible label and
|
|
2330
|
+
caption are drawn only for a picture wrapped in [a `:::figure`
|
|
2331
|
+
fence](#the-figure-fence), and the text drawn is always the fence's own
|
|
2332
|
+
caption. A title — `` — is refused rather than dropped in
|
|
2333
|
+
silence: there is one place for those words, the alt text, and a title is not
|
|
2334
|
+
it.
|
|
2119
2335
|
|
|
2120
2336
|
##### Width is a class, and the ordinary width carries no marker
|
|
2121
2337
|
|
|
@@ -2352,77 +2568,232 @@ errors. Duplicate and unknown attributes are errors.
|
|
|
2352
2568
|
| `allow-empty=true` | Permits a query selecting no rows. Default `false`. |
|
|
2353
2569
|
| `section-level=1` through `section-level=6` | Sets the heading level for `_section`. Default `2`. |
|
|
2354
2570
|
|
|
2355
|
-
#####
|
|
2571
|
+
##### Page lists
|
|
2356
2572
|
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
and contains letters, digits, `_`, or `-`, beginning with a letter. An empty
|
|
2361
|
-
caption, missing ID, missing closer, or missing following block is an error at
|
|
2362
|
-
the opening line.
|
|
2573
|
+
A fenced `pagelist` block renders a list of the pages carrying a tag. It is the
|
|
2574
|
+
companion of a content table and answers the other question: a table says what
|
|
2575
|
+
a set of notes contains, a page list says which pages belong to a group.
|
|
2363
2576
|
|
|
2364
2577
|
````markdown
|
|
2365
|
-
|
|
2578
|
+
```pagelist {tag="key-concept" type=lore sort=type descriptions=true}
|
|
2366
2579
|
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2580
|
+
```
|
|
2581
|
+
````
|
|
2582
|
+
|
|
2583
|
+
**The group is the tag, not an enumeration.** A hand-written list of links is
|
|
2584
|
+
a second place the membership is recorded, and the two drift the moment a page
|
|
2585
|
+
is written and nobody edits the landing that should name it. A page list reads
|
|
2586
|
+
`tags:` instead, so tagging a page files it and untagging it removes it.
|
|
2587
|
+
|
|
2588
|
+
**The fence takes no body.** Every statement about the directive is an
|
|
2589
|
+
attribute in the shared braced grammar, so there is one grammar to learn; text
|
|
2590
|
+
written inside the fence is reported rather than printed, and a fence nobody
|
|
2591
|
+
closed is reported rather than swallowing the rest of the note.
|
|
2592
|
+
|
|
2593
|
+
| Attribute | What it does |
|
|
2594
|
+
| ------------------- | ------------------------------------------------------------------------- |
|
|
2595
|
+
| `tag=` | Required. The tag a page carries to join the list. |
|
|
2596
|
+
| `type=` | Restricts the list to one note type. Every type by default. |
|
|
2597
|
+
| `sort=name` | Alphabetical, case and accents folded, tiebroken on address. The default. |
|
|
2598
|
+
| `sort=type` | Groups the note types and orders by name within each. |
|
|
2599
|
+
| `descriptions=true` | Follows each link with the page's `description`. Default `false`. |
|
|
2600
|
+
| `allow-empty=true` | Permits a tag no page carries. Default `false`. |
|
|
2601
|
+
|
|
2602
|
+
The tag is matched the way `tags:` is read everywhere else — a leading `#`,
|
|
2603
|
+
surrounding space and letter case are all insignificant, while the spelling of
|
|
2604
|
+
the tag itself is exact. Nothing guesses at a near miss.
|
|
2605
|
+
|
|
2606
|
+
**What a list holds.** Every note of this package that carries the tag and
|
|
2607
|
+
publishes a page. A **stub** publishes no page, so it holds no address and joins
|
|
2608
|
+
no list. A documentation journal is not listed beside the note it documents,
|
|
2609
|
+
because they are one page. A note tagged `gm` is listed in Foundry and left out
|
|
2610
|
+
of the website and the book, which is the same audience rule a content table's
|
|
2611
|
+
relations follow.
|
|
2612
|
+
|
|
2613
|
+
**Each entry is a link, resolved by the surface that is building.** The
|
|
2614
|
+
directive is answered before the body is walked and spliced in where the fence
|
|
2615
|
+
sat, so the list reaches a reader as compendium journal links in Foundry and
|
|
2616
|
+
page links on the website and in the book — the same resolution an authored
|
|
2617
|
+
`[[…]]` gets, including the cue on a link into a `draft` note.
|
|
2618
|
+
|
|
2619
|
+
**A tag no page carries is an error at the fence's line and column**, naming
|
|
2620
|
+
the tag and, where the directive restricts one, the type. An empty list under
|
|
2621
|
+
an authored heading is how a misspelled tag survives a build, so the
|
|
2622
|
+
directive's silence is what is refused rather than its output.
|
|
2623
|
+
|
|
2624
|
+
##### The figure fence
|
|
2625
|
+
|
|
2626
|
+
`:::figure {#anchor .border}` declares what it numbers and, optionally,
|
|
2627
|
+
captions: the fence is the unit the counter counts, not the caption text it
|
|
2628
|
+
may or may not carry.
|
|
2629
|
+
|
|
2630
|
+
````markdown
|
|
2631
|
+
:::figure {#trade}
|
|
2370
2632
|
|
|
2371
2633
|
```sql
|
|
2372
2634
|
SELECT name.full AS "Market" FROM notes WHERE type = 'place'
|
|
2373
2635
|
```
|
|
2374
|
-
````
|
|
2375
2636
|
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
its own JournalEntryPage, so its anchor has a page UUID.
|
|
2637
|
+
///
|
|
2638
|
+
Regional trade routes
|
|
2639
|
+
:::
|
|
2640
|
+
|
|
2641
|
+
Refer to {{ref "#trade"}} for the market routes.
|
|
2642
|
+
````
|
|
2383
2643
|
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2644
|
+
The fence displays **Table 1: Regional trade routes** and `{{ref "#trade"}}`
|
|
2645
|
+
displays **Table 1** as a link.
|
|
2646
|
+
|
|
2647
|
+
**The grammar.** `:::figure` opens the fence, on a line of its own and
|
|
2648
|
+
optionally followed by a braced attribute block in the grammar a heading and
|
|
2649
|
+
a named block take too. A line of `:::` alone closes it. Between the
|
|
2650
|
+
two, the first `///` written alone on a line, read at the top level — outside
|
|
2651
|
+
any nested code fence — divides what the fence holds from its caption; a `///`
|
|
2652
|
+
written inside a nested fence is content, not a divider. A second top-level
|
|
2653
|
+
`///` is an error, naming the line: a figure holds one caption, so it carries
|
|
2654
|
+
one `///` line.
|
|
2655
|
+
|
|
2656
|
+
An opening line that is not `:::figure`, optionally followed by one braced
|
|
2657
|
+
attribute block and nothing else, is reported at its own line as
|
|
2658
|
+
`a figure's attributes are written as {#id .border}`.
|
|
2659
|
+
|
|
2660
|
+
**Every part but the fence itself is optional.**
|
|
2661
|
+
|
|
2662
|
+
- **No `{#id}`.** The fence is still numbered and drawn; it carries no anchor,
|
|
2663
|
+
so nothing can address it. An id, when written, must be a name unique within
|
|
2664
|
+
the note — a repeat is `duplicate figure id "<id>"` at the fence's opening
|
|
2665
|
+
line, and an id that collides with a heading anchor in the same note is
|
|
2666
|
+
`heading and figure declare the same anchor "<id>"` at the heading's line.
|
|
2667
|
+
- **No `///`.** The fence draws its label alone, with no caption beneath it. A
|
|
2668
|
+
`///` with nothing after it before the closing `:::` is an error at the
|
|
2669
|
+
`///` line: a figure's `///` section carries no caption — write no `///` to
|
|
2670
|
+
leave the figure uncaptioned.
|
|
2671
|
+
- **No `.border`.** The fence draws without one. `.border` is the only class
|
|
2672
|
+
the construct declares; any other class is reported at the opening line,
|
|
2673
|
+
naming it: a figure takes no such class, and the classes a figure takes
|
|
2674
|
+
are `.border`. A `key="value"` attribute is reported the same way, naming
|
|
2675
|
+
the key: a figure takes an id and classes, nothing else.
|
|
2676
|
+
|
|
2677
|
+
**What is never optional.** A fence with nothing between its opening line and
|
|
2678
|
+
its `///` or its closing `:::` is `a figure has no contents`, at the opening
|
|
2679
|
+
line. An opening `:::figure` with no matching `:::` runs to the end of the
|
|
2680
|
+
note and is `a figure needs a closing :::`, also at the opening line, and
|
|
2681
|
+
nothing after it is scanned as a second fence.
|
|
2682
|
+
|
|
2683
|
+
**The counter is derived, never authored.** The fence's contents decide which
|
|
2684
|
+
of four counters it draws from — `Code`, `Table`, `Figure`, `Prose` — read from
|
|
2685
|
+
the first top-level block inside the fence: a table is `Table`; a fenced `sql`
|
|
2686
|
+
block is `Table`, because its rendered output is one; any other fenced or
|
|
2687
|
+
indented code block is `Code`; one or more pictures and nothing else is
|
|
2688
|
+
`Figure`; everything else is `Prose`. A table or a picture written outside any
|
|
2689
|
+
`:::figure` fence draws no label and is counted nowhere. The website and a
|
|
2690
|
+
Foundry journal number each counter within the note; the book numbers each
|
|
2691
|
+
counter across the book in reading order.
|
|
2692
|
+
|
|
2693
|
+
**A heading that would start its own journal page cannot be written inside a
|
|
2694
|
+
fence.** An H1, or a heading at any level carrying an `{#anchor}`, is reported
|
|
2695
|
+
at its own line inside one: `a heading that starts a page cannot be written
|
|
2696
|
+
inside a figure — keep an H1 or an anchored heading at the top level, or drop
|
|
2697
|
+
the anchor and the level to stay inside it`.
|
|
2698
|
+
|
|
2699
|
+
**The `ref` expression renders a link to a figure's anchor.**
|
|
2700
|
+
`{{ref "#thorn"}}` renders "Figure 13"; `{{ref "#thorn" form="full"}}` renders
|
|
2701
|
+
the number and the caption; `{{ref "#thorn" form="title"}}` renders the
|
|
2702
|
+
caption alone. `form="number"` is the default and may be written explicitly;
|
|
2703
|
+
a `form` outside this closed set is reported naming the three. A link written
|
|
2704
|
+
inside the figure's own caption contributes only its label text to a `full`
|
|
2705
|
+
or `title` reference, because the reference is itself a link, and emphasis
|
|
2706
|
+
inside the caption is kept. `form="full"` or `form="title"` aimed at a figure
|
|
2707
|
+
with no caption is reported naming the anchor: that form needs a caption, and
|
|
2708
|
+
the figure has none. An address naming no figure in the note is reported
|
|
2709
|
+
naming the anchor; an address naming another note's figure —
|
|
2710
|
+
`{{ref "other-note#anchor"}}` — is reported as addressing a figure this build
|
|
2711
|
+
does not resolve outside the note carrying the reference. Only a same-note
|
|
2712
|
+
anchor resolves, on the website and in the book.
|
|
2713
|
+
|
|
2714
|
+
Foundry gives a `:::figure` fence its own JournalEntryPage. A fence holding
|
|
2715
|
+
exactly one picture, captioned in plain text with nothing else — or carrying
|
|
2716
|
+
no caption at all — becomes a page of type `image`: the picture is its `src`,
|
|
2717
|
+
a caption, when there is one, is `image.caption`, and the page is named for
|
|
2718
|
+
the figure's own number. Every other fence becomes a page of type `text`
|
|
2719
|
+
instead: a fence grouping more than one picture; an embedded sound, there
|
|
2720
|
+
being no audio page type; a fence whose caption carries inline markup —
|
|
2721
|
+
emphasis, a link, an embedded icon or image — because `image.caption` is a
|
|
2722
|
+
`StringField` with nowhere to render it; and a fence that shares its split
|
|
2723
|
+
with prose that follows it, because an `image` page has nowhere to carry that
|
|
2724
|
+
prose either. On a `text` page the render is the fence's own content, scanned
|
|
2725
|
+
and labelled as the first of its kind on that page alone and then corrected to
|
|
2726
|
+
the number the note-wide scan already assigned, so a second figure with no id
|
|
2727
|
+
is still named for its true, note-wide number rather than recounted from one.
|
|
2728
|
+
|
|
2729
|
+
##### Named blocks
|
|
2730
|
+
|
|
2731
|
+
`:::secret`, `:::info` and `:::warn` set a passage apart from the prose around
|
|
2732
|
+
it. The opener and the closing `:::` each take a whole line, the content is
|
|
2733
|
+
Markdown and renders normally, and the fences stay outside code blocks. An
|
|
2734
|
+
empty, nested or unclosed block is an error at its opening line, as is a name
|
|
2735
|
+
that is not one of the three.
|
|
2736
|
+
|
|
2737
|
+
A braced attribute block may follow the name. It takes an id as `#id`, classes
|
|
2738
|
+
as `.class`, and any other attribute as `key="value"`. `title` is reserved and
|
|
2739
|
+
supplies the heading; without it a block heads itself **Secret**, **Info** or
|
|
2740
|
+
**Warn**. A title carries its own emphasis and nothing else — a tag written
|
|
2741
|
+
there is escaped. `id=` and `class=` are refused in favour of `#id` and
|
|
2742
|
+
`.class`, and an attribute beginning `on` is refused as an event handler.
|
|
2389
2743
|
|
|
2390
2744
|
```markdown
|
|
2391
2745
|
:::info
|
|
2392
2746
|
The harbor remains open through winter.
|
|
2393
2747
|
:::
|
|
2394
2748
|
|
|
2395
|
-
:::warn {#flood-warning}
|
|
2749
|
+
:::warn {#flood-warning title="Seasonal closure"}
|
|
2396
2750
|
Spring floods close the eastern road.
|
|
2397
2751
|
:::
|
|
2398
|
-
```
|
|
2399
2752
|
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
This is secret text
|
|
2753
|
+
:::secret {#harbor .wide}
|
|
2754
|
+
The harbor master is working for the smugglers.
|
|
2403
2755
|
:::
|
|
2404
2756
|
```
|
|
2405
2757
|
|
|
2406
|
-
|
|
2758
|
+
The block's name is the first class on the emitted element and the author's
|
|
2759
|
+
classes follow it. **No block carries an inline `style`**, so the appearance is
|
|
2760
|
+
a stylesheet's. The base stylesheet styles `section.info` and `section.warn`;
|
|
2761
|
+
`section.secret` is left to Foundry, which styles it and owns the reveal control
|
|
2762
|
+
on it.
|
|
2407
2763
|
|
|
2408
|
-
In FoundryVTT
|
|
2764
|
+
In FoundryVTT a block is a section whose first line is its heading, and a
|
|
2765
|
+
`secret` is the section Foundry shows to the GM and to owners of the journal:
|
|
2409
2766
|
|
|
2410
2767
|
```html
|
|
2411
|
-
<section class="secret" id="
|
|
2412
|
-
<
|
|
2768
|
+
<section class="secret wide" id="harbor">
|
|
2769
|
+
<strong>Secret</strong><br />
|
|
2770
|
+
<p>The harbor master is working for the smugglers.</p>
|
|
2413
2771
|
</section>
|
|
2414
2772
|
```
|
|
2415
2773
|
|
|
2416
|
-
|
|
2774
|
+
A `secret` that states no id of its own is given one derived from its body, so
|
|
2775
|
+
that Foundry can remember the section once a reader reveals it.
|
|
2776
|
+
|
|
2777
|
+
On webpages a block is a disclosure any reader can open, titled in its summary:
|
|
2417
2778
|
|
|
2418
2779
|
```html
|
|
2419
|
-
<details>
|
|
2420
|
-
<summary>
|
|
2421
|
-
<p>
|
|
2780
|
+
<details class="secret wide" id="harbor">
|
|
2781
|
+
<summary class="secret">Secret</summary>
|
|
2782
|
+
<p>The harbor master is working for the smugglers.</p>
|
|
2422
2783
|
</details>
|
|
2423
2784
|
```
|
|
2424
2785
|
|
|
2425
|
-
In
|
|
2786
|
+
In a book each block is a coloured box headed by its title. A printed page has
|
|
2787
|
+
no reader permissions and no interactive disclosure control, so a `secret` is
|
|
2788
|
+
visible there.
|
|
2789
|
+
|
|
2790
|
+
**A secret is a presentation distinction and not access control.** It is in the
|
|
2791
|
+
same authored note as the prose around it, and a reader who inspects source or
|
|
2792
|
+
generated output may see it.
|
|
2793
|
+
|
|
2794
|
+
**A malformed block does not silence the blocks around it.** It is reported at
|
|
2795
|
+
its own line and left as the author wrote it, and every well-formed block in the
|
|
2796
|
+
note still renders.
|
|
2426
2797
|
|
|
2427
2798
|
#### Actors
|
|
2428
2799
|
|
|
@@ -2432,11 +2803,6 @@ The following H1 headers are treated specially:
|
|
|
2432
2803
|
|
|
2433
2804
|
- `# ... {#appearance}`: The contents of this header become the `doc.appearance` property in sohl and `doc.description` in hm3.
|
|
2434
2805
|
- `# ... {#dossier}`: The contents of this header become the `doc.dossier` property in sohl and `doc.biography` in hm3.
|
|
2435
|
-
- `# ... {#spoilers}`: The contents of this header are not written to the actor at all.
|
|
2436
|
-
|
|
2437
|
-
For JournalEntries, the following rules apply:
|
|
2438
|
-
|
|
2439
|
-
- `# ... {#spoilers}`: The contents of this header go into a page which is viewable only by the GM (`CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE`).
|
|
2440
2806
|
|
|
2441
2807
|
**Archetypes** describe characters in broad terms and help match them to an adventure. The list is:
|
|
2442
2808
|
|
|
@@ -2529,31 +2895,41 @@ data:
|
|
|
2529
2895
|
|
|
2530
2896
|
#### The bodies a being belongs to, and its standing in each
|
|
2531
2897
|
|
|
2532
|
-
**Membership**: `{rank: number, office: string}
|
|
2898
|
+
**Membership**: `{rank: number, office: string}` — `rank` required, `office` not.
|
|
2533
2899
|
|
|
2534
2900
|
`data.affiliations` is a **map keyed by the body's Address**, and each entry is
|
|
2535
2901
|
the standing the being holds in that body. The key is what makes the pair
|
|
2536
2902
|
expressible: a being in two bodies holds a standing in each, and two bodies may
|
|
2537
2903
|
call a rung the same word.
|
|
2538
2904
|
|
|
2539
|
-
An entry carries two
|
|
2905
|
+
An entry carries two keys and nothing else:
|
|
2540
2906
|
|
|
2541
|
-
- **`rank`** — a **number**, the level on that body's own
|
|
2542
|
-
ladder. The body declares `{level, title, description}` for
|
|
2543
|
-
number indexes into it and the body stays the single source
|
|
2544
|
-
level 5 is called.
|
|
2545
|
-
- **`office`** — a **string**, matched against the keys of that body's
|
|
2907
|
+
- **`rank`** — **required**, a **number**, the level on that body's own
|
|
2908
|
+
`governance.ranks` ladder. The body declares `{level, title, description}` for
|
|
2909
|
+
every rung, so a number indexes into it and the body stays the single source
|
|
2910
|
+
for what its level 5 is called.
|
|
2911
|
+
- **`office`** — optional, a **string**, matched against the keys of that body's
|
|
2546
2912
|
`governance.offices` map.
|
|
2547
2913
|
|
|
2548
|
-
|
|
2549
|
-
|
|
2914
|
+
**Every entry states a `rank`**, because belonging to a body is holding some
|
|
2915
|
+
standing in it. Where nothing more is known the rung is `1`, the ordinary
|
|
2916
|
+
member; `0` is the rung for someone cast out, which is a real answer rather than
|
|
2917
|
+
a default — the ladders carry `0 Níding`, `0 Outlaw` and `0 Struck from the
|
|
2918
|
+
Roll`. Between them the two ends cover every standing a member can hold, so an
|
|
2919
|
+
entry that states no rank is an **error** at the entry's own line, and the
|
|
2920
|
+
message names both numbers rather than only the gap.
|
|
2921
|
+
|
|
2922
|
+
An entry carrying an **office and no rank** is that same error and not a second
|
|
2923
|
+
one, reported once: an office distinguishes a person within a standing rather
|
|
2924
|
+
than standing in for one, so such an entry puts a person in a post in nothing.
|
|
2925
|
+
An entry carrying a rank and no office is complete.
|
|
2550
2926
|
|
|
2551
2927
|
```yaml
|
|
2552
2928
|
data:
|
|
2553
2929
|
affiliations:
|
|
2554
2930
|
affiliation-vrystwldtrbs: { rank: 5, office: War Chief }
|
|
2555
2931
|
affiliation-greenwardens: { rank: 1 }
|
|
2556
|
-
affiliation-silverguild: {}
|
|
2932
|
+
affiliation-silverguild: { rank: 0 }
|
|
2557
2933
|
```
|
|
2558
2934
|
|
|
2559
2935
|
Both values are checked against the body the entry is keyed by. A `rank` that
|
|
@@ -2942,12 +3318,46 @@ two is the commonest way to get a non-monarchy wrong.
|
|
|
2942
3318
|
**Rank**
|
|
2943
3319
|
Definition of a level within the organization (e.g., Priest, Layperson, Member, Gang Leader, Master, etc.)
|
|
2944
3320
|
|
|
2945
|
-
| Property | Values | Description |
|
|
2946
|
-
| ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
2947
|
-
| `level` |
|
|
2948
|
-
| `title` | string | Title associated with the Rank |
|
|
2949
|
-
| `description` | string | Description of the Rank |
|
|
2950
|
-
| `lore` | `Address` | The standing this rank _is_ — a `lore` note of subType `law`, shared with every other body that confers the same thing |
|
|
3321
|
+
| Property | Required | Values | Description |
|
|
3322
|
+
| ------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
3323
|
+
| `level` | yes | integer | The ranking within the affiliation, increasing values starting with 1, 0 indicates intentional exclusion (expulsion/excommunication) |
|
|
3324
|
+
| `title` | yes | string | Title associated with the Rank |
|
|
3325
|
+
| `description` | yes | string | Description of the Rank |
|
|
3326
|
+
| `lore` | no | `Address` | The standing this rank _is_ — a `lore` note of subType `law`, shared with every other body that confers the same thing |
|
|
3327
|
+
|
|
3328
|
+
**`level`, `title` and `description` together are a complete statement of a
|
|
3329
|
+
rung**, and nothing further is required for a ladder to be correct. Each is an
|
|
3330
|
+
**error** when it is missing or empty, and a `level` that is not a whole number
|
|
3331
|
+
is an error too: the ladder is what a member's `rank` indexes into, so a rung
|
|
3332
|
+
with no title makes a standing that resolves to nothing, and one with no
|
|
3333
|
+
description ships a rung that says nothing on a sheet or a page. A rung accepts
|
|
3334
|
+
only these four keys, and each problem on a rung is reported separately, so a
|
|
3335
|
+
ladder with three is fixed in one pass rather than three builds.
|
|
3336
|
+
|
|
3337
|
+
**A level belongs to one rung.** Two rungs claiming one level is an **error** on
|
|
3338
|
+
the second, naming the first, because the ladder is read by level: a member whose
|
|
3339
|
+
`rank` is that level answers to whichever rung is written higher in the file, and
|
|
3340
|
+
moving two lines renames the standing. A body that confers two titles at one
|
|
3341
|
+
standing writes them as one rung — `title: Knight or Dame` — or gives each its
|
|
3342
|
+
own level.
|
|
3343
|
+
|
|
3344
|
+
```yaml
|
|
3345
|
+
data:
|
|
3346
|
+
governance:
|
|
3347
|
+
ranks:
|
|
3348
|
+
- { level: 0, title: Vrystrith, description: Kinless and owed nothing. }
|
|
3349
|
+
- { level: 4, title: Fródrád, description: A householder whose word carries. }
|
|
3350
|
+
- level: 5
|
|
3351
|
+
title: Hárár
|
|
3352
|
+
description: First among them, by the assent of the householders.
|
|
3353
|
+
lore: lore-harar-standing
|
|
3354
|
+
```
|
|
3355
|
+
|
|
3356
|
+
**Reach for `lore` only where the standing needs more said about it than a
|
|
3357
|
+
description can hold** — obligations, rights, what it takes to enter it, what
|
|
3358
|
+
ends it. Most rungs do not: a description that states what the standing is has
|
|
3359
|
+
already said the whole of it, and a note that restates the rung it hangs off
|
|
3360
|
+
costs a reader a click and tells them nothing.
|
|
2951
3361
|
|
|
2952
3362
|
**A rank's `lore` is shared; its `title` is not.** A Normen kingdom calls it
|
|
2953
3363
|
`Thrall` and a Vylarian province calls it `Slave`, and they mean one standing:
|
|
@@ -3597,18 +4007,49 @@ the setting itself, rather than instructions or other apparatus for the GM.
|
|
|
3597
4007
|
tournament is not a matter of time-reckoning at all — and from `culture`, which is a grouping
|
|
3598
4008
|
of people rather than an occasion they attend.
|
|
3599
4009
|
|
|
3600
|
-
| `data` property
|
|
3601
|
-
|
|
|
3602
|
-
| `epoch`
|
|
3603
|
-
| `months`
|
|
3604
|
-
| `weekdays`
|
|
3605
|
-
| `seasons`
|
|
3606
|
-
| `namedDays`
|
|
3607
|
-
| `eras`
|
|
3608
|
-
| `formats`
|
|
3609
|
-
| `
|
|
4010
|
+
| `data` property | Values | Description |
|
|
4011
|
+
| ----------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
4012
|
+
| `epoch` | canonical `<year>.<day>` | The canonical day that equals calendar year 1, day 1 |
|
|
4013
|
+
| `months` | `{ name, abbreviation?, days }[]` | Ordered months; their days sum to the world's year |
|
|
4014
|
+
| `weekdays` | `{ name, abbreviation? }[]` | Ordered week days, indexed from zero; weeks run continuously |
|
|
4015
|
+
| `seasons` | `{ name, abbreviation?, start }[]` | Seasons starting on one-based days of year |
|
|
4016
|
+
| `namedDays` | `{ name, abbreviation?, day }[]` | Names assigned to one-based days of year |
|
|
4017
|
+
| `eras` | `{ shortcode, name, abbreviation?, marker?, proclaimedBy?, start, label? }[]` | Year counts; `start` is `null` or an in-calendar year |
|
|
4018
|
+
| `formats` | map of names to Calendaria patterns | Named date formats; `std` is the preferred default |
|
|
4019
|
+
| `events` | `{ when, until?, recurs? }[]` | This note's dated occurrences, each with its own relationships and chronicle fields |
|
|
4020
|
+
| `events[].when` | a date, or `"0.<day>"` | The occurrence's anchor and first instance — required |
|
|
4021
|
+
| `events[].until` | a date | Where the occurrence ran to, or where a recurring series stopped |
|
|
4022
|
+
| `events[].recurs` | `{ every }` or `{ on }` | How further occurrences are found, absent for a one-time occurrence |
|
|
4023
|
+
| `events[].recurs.every` | whole number of years, 1 or more | A period counted on the canonical axis from `when` |
|
|
4024
|
+
| `events[].recurs.on` | list of dates, strictly increasing, each later than `when` | Recorded occurrences beyond the first, in place of a period |
|
|
4025
|
+
|
|
4026
|
+
`data.events` is available on every `lore` subType. Each entry's `kind`, `depth`, `summary`, `sources`, `standing`, `accounts`, `who`, `where`, `unresolved`, `follows` and `names` hold its chronicle detail; their shapes belong to whatever design governs chronicle records, and this format only asks that they sit inside an entry. The shared format checks `when`, `until` and `recurs`; a content package can check the rest. `events` itself does not appear as an infobox row, but a recurring entry's computed next occurrence does.
|
|
4027
|
+
|
|
4028
|
+
An entry reads by what it authors beside `when`:
|
|
4029
|
+
|
|
4030
|
+
| authored | reads as |
|
|
4031
|
+
| --------------------------------- | ----------------------------------------------- |
|
|
4032
|
+
| `when` | happened once |
|
|
4033
|
+
| `when` + `until` | ran continuously from then to then |
|
|
4034
|
+
| `when` + `recurs` | happened then and happens still |
|
|
4035
|
+
| `when` + `until` + `recurs.every` | happened then, again on the period, and stopped |
|
|
4036
|
+
|
|
4037
|
+
`recurs.every` and `recurs.on` are exclusive — a period with named exceptions is written as an enumeration instead. `recurs` is refused beside `born` or `died`, and beside a `when` of year `0`. `until` is refused beside `recurs.on`, whose own last entry already bounds it.
|
|
4038
|
+
|
|
4039
|
+
**The period advances the canonical year, never the era-relative year.** There is no year `0` in era-relative numbering — era year `-1` sits immediately before era year `1` — but canonical year `0` is an ordinary integer on the continuous axis `canonicalYear` builds, so a period of whole years steps on it with no special case at an epoch crossing. Precision and approximation carry through untouched: a year-precision anchor yields year-precision occurrences, an approximate anchor's occurrences are approximate too, and an anchor inside a short intercalary month recurs on that same day in every occurrence, with no special case for the month being short. Each occurrence selects its own era by testing its position against the anchor's calendar, so a later occurrence may print in a different era than its anchor, or print bare where no count was proclaimed for that year — neither is ever a finding, since nobody authored the occurrence.
|
|
4040
|
+
|
|
4041
|
+
**Year `0` means any year.** An entry whose `when` states year `0` recurs on that day of every year — `when: "0.5"` is the fifth day of the year, in every year. The value must be quoted, for the reason every canonical date stating a day must be: an unquoted `<year>.<day>` reaches the check as a float, and a day's trailing zero is lost before a date is read. Beside a year-`0` entry, `recurs` is refused (the entry is already annual), `until` is allowed and bounds the series, and the entry carries no `canonicalYear`, era or `sort` — it cannot date its own note. A note's date is its first entry stating a real year.
|
|
4042
|
+
|
|
4043
|
+
```yaml
|
|
4044
|
+
data:
|
|
4045
|
+
events:
|
|
4046
|
+
- when: 412.1
|
|
4047
|
+
recurs: { every: 1 }
|
|
4048
|
+
- when: "0.286"
|
|
4049
|
+
until: 940.1
|
|
4050
|
+
```
|
|
3610
4051
|
|
|
3611
|
-
|
|
4052
|
+
The first entry is an anniversary counted from canonical day `412.1`, recurring every year with no end. The second is an autumn rite — the two-hundred-eighty-sixth day of every year — that was kept until canonical year 940 and no longer is.
|
|
3612
4053
|
|
|
3613
4054
|
#### Calendar note structure
|
|
3614
4055
|
|
|
@@ -3620,7 +4061,7 @@ name: { full: The Common Calendar }
|
|
|
3620
4061
|
type: lore
|
|
3621
4062
|
subType: calendar
|
|
3622
4063
|
data:
|
|
3623
|
-
epoch: 1.1
|
|
4064
|
+
epoch: "1.1"
|
|
3624
4065
|
months:
|
|
3625
4066
|
- { name: Floralis, abbreviation: Flor, days: 30 }
|
|
3626
4067
|
- { name: Lusenar, abbreviation: Luse, days: 31 }
|
|
@@ -3869,7 +4310,7 @@ data:
|
|
|
3869
4310
|
# its moon — a note of its own, because a moon is a body and not a property
|
|
3870
4311
|
data:
|
|
3871
4312
|
body: { diameterKm: 3800, orbitalRadiusKm: 388600, orbit: circular, inclined: true }
|
|
3872
|
-
moon: { cycle: 30, newOn: 720.1, eclipses: rare }
|
|
4313
|
+
moon: { cycle: 30, newOn: "720.1", eclipses: rare }
|
|
3873
4314
|
```
|
|
3874
4315
|
|
|
3875
4316
|
**`year.days` is where the year's length lives, and every calendar in the
|