@heroiclands/package-build 22.26.0 → 22.27.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +3 -1
  3. package/assets/styles/content-base.css +46 -3
  4. package/docs/api.md +33 -13
  5. package/docs/authoring/frontmatter.md +2 -2
  6. package/docs/authoring/links-and-markup.md +96 -149
  7. package/docs/content-format.md +5 -3
  8. package/docs/guides/government-migration.md +52 -0
  9. package/docs/guides/site.md +5 -5
  10. package/docs/reference/format-details.md +110 -219
  11. package/docs/reference/note-types.md +27 -29
  12. package/docs/reference/theme-pages.md +31 -29
  13. package/engine/anchors.mjs +85 -13
  14. package/engine/art-fields.mjs +1 -1
  15. package/engine/base-compiler.mjs +9 -1
  16. package/engine/bundles.mjs +1 -1
  17. package/engine/code-fences.mjs +6 -2
  18. package/engine/content-alerts.mjs +195 -0
  19. package/engine/content-blocks.mjs +119 -241
  20. package/engine/content-embeds.mjs +1 -1
  21. package/engine/content-figures.mjs +166 -230
  22. package/engine/content-format-check.mjs +3 -2
  23. package/engine/content-format.yaml +0 -5
  24. package/engine/content-images.mjs +3 -3
  25. package/engine/content-poetry.mjs +141 -0
  26. package/engine/content-spans.mjs +177 -0
  27. package/engine/foundry-entries.mjs +2 -0
  28. package/engine/frontmatter-lint.mjs +2 -1
  29. package/engine/heading-attributes.mjs +1 -1
  30. package/engine/helpers.mjs +8 -3
  31. package/engine/holdings.mjs +165 -273
  32. package/engine/index.mjs +1 -1
  33. package/engine/infobox.mjs +1 -1
  34. package/engine/journals.mjs +8 -6
  35. package/engine/markdown-expressions.mjs +9 -3
  36. package/engine/metadata-index.mjs +2 -3
  37. package/engine/note-vocabulary.mjs +16 -11
  38. package/engine/pdf-build.mjs +1 -1
  39. package/engine/pdf-render.mjs +90 -31
  40. package/engine/populations.mjs +17 -83
  41. package/engine/site-build.mjs +44 -16
  42. package/engine/site-preview.mjs +22 -6
  43. package/engine/wikilinks.mjs +18 -4
  44. package/hugo-theme/layouts/partials/holdings/entry.html +2 -2
  45. package/hugo-theme/layouts/partials/holdings.html +14 -14
  46. package/hugo-theme/static/css/style.css +40 -2
  47. package/package.json +1 -1
  48. package/sohl/item-fields.mjs +0 -16
  49. package/types/engine/anchors.d.mts +13 -4
  50. package/types/engine/art-fields.d.mts +1 -1
  51. package/types/engine/code-fences.d.mts +3 -1
  52. package/types/engine/content-alerts.d.mts +62 -0
  53. package/types/engine/content-blocks.d.mts +3 -10
  54. package/types/engine/content-embeds.d.mts +1 -1
  55. package/types/engine/content-figures.d.mts +13 -20
  56. package/types/engine/content-images.d.mts +1 -1
  57. package/types/engine/content-poetry.d.mts +32 -0
  58. package/types/engine/content-spans.d.mts +18 -0
  59. package/types/engine/holdings.d.mts +59 -105
  60. package/types/engine/markdown-expressions.d.mts +1 -1
  61. package/types/engine/note-vocabulary.d.mts +10 -2
  62. package/types/engine/populations.d.mts +4 -13
  63. package/types/engine/site-build.d.mts +3 -3
  64. package/types/engine/wikilinks.d.mts +5 -1
@@ -25,9 +25,9 @@ Start with [your first note](authoring/first-note.md). It explains the smallest
25
25
 
26
26
  A nonempty note body creates one system-agnostic Foundry JournalEntry. Content before the first H1 becomes an introduction page; every H1 starts another JournalEntryPage. A lower-level heading with an explicit `{#anchor}` starts a page too, so a link can address it. The same prose becomes a web page and can be selected for a book. The content index records the note and its frontmatter for queries and navigation.
27
27
 
28
- A `:::figure {#anchor}` fence numbers whatever it holds — prose, code, a table, or an image. Its anchor makes the fence a target `{{ref "#anchor"}}` can point to, displaying the generated kind and number, such as **Figure 12**. Foundry gives the fence its own JournalEntryPage. See [figures and numbered references](authoring/links-and-markup.md#figures-and-numbered-references) for the syntax.
28
+ Leading `:` captions describe the next supported block; `:@` captions also number it. The optional type accepts `figure`, `table`, `poetry`, `code`, `prose`, and `example`. Captions support identifiers, classes and named attributes; unsupported following blocks are errors. See [captions and numbered references](authoring/links-and-markup.md#captions-and-numbered-references).
29
29
 
30
- A `:::poetry` fence keeps each authored line as a verse line and blank lines as stanza breaks. Inside a `:::figure`, a poem written first gives that figure the **Poem** counter and an optional caption. See [poetry](authoring/links-and-markup.md#poetry) for attributes and examples.
30
+ A code fence with language `poetry` keeps verse lines, stanza breaks and relative indentation. Its numbered caption uses the **Poem** label. Generic `:::` divs and `[inline spans]{.class}` accept attributes. The former `:::figure` and `:::poetry` forms are removed. See [poetry](authoring/links-and-markup.md#poetry), [fenced divs](authoring/links-and-markup.md#fenced-divs) and [inline spans](authoring/links-and-markup.md#inline-spans).
31
31
 
32
32
  Body extensions use braces with space-separated `key=value` attributes:
33
33
  `![[icon-harbor|Harbor]]{float=top-left size=medium}` and an SQL fence with
@@ -86,4 +86,6 @@ The note's readable Address is `<package>-note-lore-harbor`. In prose, link to i
86
86
 
87
87
  The [first-note guide](authoring/first-note.md) shows the build commands and how to add a system document. Use the [command reference](commands.md) for exact flags and the [diagnostics guide](diagnostics.md) for located errors.
88
88
 
89
- Place notes may declare a governing affiliation with `data.government`, or explicit `null` for complete anarchy. Positive population with an omitted government produces an advisory. See [place governments](authoring/frontmatter.md#place-governments).
89
+ Place notes may declare a governing affiliation with `data.government`, or explicit `null` for complete anarchy. Positive population with an omitted government produces an advisory. See [place governments](authoring/frontmatter.md#place-governments) and [government migration](guides/government-migration.md).
90
+
91
+ Blockquote alerts use `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, or `[!]`, with optional attributes after the marker. They replace the former info and warn div fences; secret blocks remain supported. See [alerts](authoring/links-and-markup.md#alerts).
@@ -0,0 +1,52 @@
1
+ ---
2
+ shortcode: governmentmigration
3
+ name: { full: "Migrating place governments" }
4
+ type: doc
5
+ subType: howto
6
+ ---
7
+
8
+ # Migrating place governments
9
+
10
+ A place's `data.government` is the sole declaration of government. Its type is `Address`, with default target type `affiliation`. Name one governing affiliation, or write explicit `null` for complete anarchy. Omission means unknown. The website derives `governed_by` on a place and `governed_places` on its governing affiliation from resolved references across local and fetched indexes. Neither containment nor organizational parents supplies a government.
11
+
12
+ ```yaml
13
+ type: place
14
+ data:
15
+ government: temple
16
+ ```
17
+
18
+ A temple can be a government when it actually governs the place; so can a company, house or polity. Naming land in an old affiliation `data.domains` list never makes that body a government automatically. When old lists overlap, choose the one body that actually governs each place. Do not choose from subtype or list order. Leave government absent if the answer is unknown; do not write null merely to silence a warning.
19
+
20
+ ## Legacy input and output changes
21
+
22
+ Legacy affiliation `data.domains` is temporarily accepted without a finding so existing trees can migrate. It is ignored: it no longer creates affiliation Domains infobox rows, metadata-index `domains`, SoHL `system.domain`, or website `held_by` and `holdings`. New notes should omit it. A fetched older system schema can still declare `system.domain`; the schema check then reports an advisory that the field receives its system default. No new government is inferred from that default. There is no new authored holdings or tenure field. Preserve distinct ownership, subordinate tenure, property rights or influence in the note's prose, with links where useful, before deleting the old list.
23
+
24
+ The tenure-based `over-held land` population advisory is retired. Geographical `contains` and the remaining population checks continue to use place parents unchanged. Explicit null remains null in published metadata and displays Complete anarchy; omission stays absent. Neither appears in a governing body's reverse list.
25
+
26
+ ## Inventory behind the migration
27
+
28
+ The baseline at commit `ada039d` contains 15 production files, six documentation files and nine test files mentioning `domains`, `held_by` or `holdings` (137, 70 and 99 occurrences respectively). Domains alone appears in 20 files across 127 matching lines. The active consumers are author declarations/schema and infoboxes, metadata indexes, SoHL `system.domain`, direct and reverse website tenure lists, site previews and the polity population advisory. Public holdings APIs and generated reference documentation describe these outputs.
29
+
30
+ The migrated Thalorna baseline has 3,171 notes: 637 places, of which 191 declare government, 446 omit it and none declare null. Its 133 affiliations still carry 196 legacy domains claims covering 191 distinct places: 125 polities account for 184 claims, seven faith traditions for 11 and one order for one. Two places have overlapping claims (`pssshrines`: two; `aukhelathrgq`: five). These are reasons to review actual governance rather than infer it from legacy claims.
31
+
32
+ Those consumers combined governance with independently meaningful direct tenure: houses holding manors, temples and companies claiming property, overlapping provincial and imperial claims. This migration deliberately replaces structured tenure displays with government derived from places, rather than converting every old claim into government. Independent historical facts remain supported in prose. Acceptance of legacy input is transitional; enforced removal will require separate author guidance.
33
+
34
+ ## SQL queries
35
+
36
+ Queries that read affiliation `data.domains` must instead join each place's explicit government to the affiliation's address. For example, to list the governing bodies of places directly within a region:
37
+
38
+ ```sql
39
+ SELECT DISTINCT affiliation.address.slug AS _ref,
40
+ affiliation.name.full AS "Government"
41
+ FROM notes affiliation
42
+ JOIN notes place
43
+ ON place.data.government = concat(affiliation.package, '-note-affiliation-', affiliation.shortcode)
44
+ WHERE affiliation.type = 'affiliation'
45
+ AND place.type = 'place'
46
+ AND list_contains(place.data.parents, 'thalorna-note-place-aelwyth')
47
+ ORDER BY affiliation.name.full COLLATE NOCASE
48
+ ```
49
+
50
+ The equality above uses the canonical journal addresses in the local `notes` table. Explicit Item addresses may use a system segment such as `sohl`; include that address when joining those references. Government lists generated by the site already handle Item and journal addresses for the same page. Null and omitted government do not match the join. A query that can legitimately select no places should declare `{allow-empty=true}` on its SQL fence.
51
+
52
+ The real consumer regression migrated fourteen SQL query sites, including ten Government columns that formerly read reverse domains and four polity queries. Keeping the source field accepted does not preserve queries that depend on its retired semantics.
@@ -116,8 +116,8 @@ notes is therefore a set of authored pages, each choosing its own contents.
116
116
 
117
117
  Wikilinks resolve through the address index. Each emitted page receives
118
118
  derived `related` entries for its outgoing links and backlinks. Place pages
119
- can receive `contains` and `held_by` entries from place parents and
120
- affiliation domains; affiliation pages can receive `holdings`. These values
119
+ can receive `contains` from place parents and `governed_by` from their own explicit
120
+ `data.government`; affiliation pages can receive `governed_places` from resolved government references. These values
121
121
  come from the content graph and should be read as generated page metadata.
122
122
 
123
123
  Place relationships can also produce a map alongside the page. The page
@@ -144,11 +144,11 @@ The build always writes `title`, `slug`, `url`, `kbfolder`, `package` and
144
144
  note. `infoboxes` is assembled from the note's own fields, so no note authors
145
145
  it and nothing in the note format accepts it.
146
146
 
147
- The build writes `resolvedDates`, `related`, `contains`, `held_by`, `holdings`
147
+ The build writes `resolvedDates`, `related`, `contains`, `governed_by`, `governed_places`
148
148
  and `map` only when it has something to write. A page with no links either way
149
149
  carries no `related`, and a place with no drawing carries no `map`.
150
150
 
151
- An authored `aliases`, `related`, `contains`, `held_by`, `holdings` or `map` is
151
+ An authored `aliases`, `related`, `contains`, `governed_by`, `governed_places` or `map` is
152
152
  dropped. Each states a fact about the whole tree rather than about one note, so
153
153
  the build replaces whatever a note wrote.
154
154
 
@@ -170,7 +170,7 @@ and both survive: `null` is a note naming no art, where a default may apply,
170
170
  and `""` is a note refusing art, where no default may replace it.
171
171
 
172
172
  The build writes these keys; [what the theme draws](../reference/theme-pages.md)
173
- describes the panel each one feeds — the infobox, the hero band, the holdings
173
+ describes the panel each one feeds — the infobox, the hero band, the government
174
174
  and related cards, the place map, and search.
175
175
 
176
176
  ## Build and serve
@@ -567,9 +567,9 @@ an author writes — and each type that has any names them under its table.
567
567
 
568
568
  **An `Address` becomes a `Shortcode` where the target field expects one.** SoHL
569
569
  resolves a stored cross-reference among the items one actor holds, and packages do
570
- not exist there, so the field holds a `Shortcode`. Four `affiliation` fields are
570
+ not exist there, so the field holds a `Shortcode`. Three `affiliation` fields are
571
571
  authored as Addresses and stored that way: `data.seat` becomes `system.seat`,
572
- `data.parents` becomes `system.parents`, `data.domains` becomes `system.domain`,
572
+ `data.parents` becomes `system.parents`,
573
573
  and each authored key of `data.relations` becomes a key of `system.relations`. The
574
574
  reduction happens at build time, and two things are errors naming the note: an
575
575
  Address whose type the field does not accept, and two Addresses that reduce to one
@@ -1352,7 +1352,7 @@ Wikilinks contain complete Addresses. For example, `data.parents: [north]` in
1352
1352
 
1353
1353
  SQL queries compare Address-valued fields to complete Addresses. A note's
1354
1354
  `shortcode` is a distinct identity component, so it is not equal to an Address
1355
- stored in `data.parents`, `data.domains` or a governance rank's `lore`. Use the
1355
+ stored in `data.parents`, `data.government` or a governance rank's `lore`. Use the
1356
1356
  target's complete identity for that comparison. A stub has no published page
1357
1357
  address; its note identity still contains the package, system, type and shortcode.
1358
1358
 
@@ -1777,7 +1777,7 @@ a warning, flags an asset whose pixel width falls short of what its role's
1777
1777
  largest print slot needs. Both exempt a vector asset, which carries no pixel
1778
1778
  dimensions and no aspect that survives being drawn at a nominal size.
1779
1779
 
1780
- `role: map` also selects a `:::figure` fence's counter — see
1780
+ `role: map` also selects a captioned image's counter — see
1781
1781
  [figures and numbered references](../authoring/links-and-markup.md#figures-and-numbered-references).
1782
1782
  A fence whose picture draws an address with that role counts as `Map` rather
1783
1783
  than `Figure`, on every surface that numbers it, because the role is the one
@@ -2105,8 +2105,8 @@ so adding a type means answering the question rather than inheriting a default.
2105
2105
  `borders.to` and `routes.to` name a place by `Address`, and those are **index
2106
2106
  relations rather than page links**: a border with a stub on the far side is a
2107
2107
  valid statement about the world and resolves. So does `parents` for the
2108
- containment tree and `domains` for tenure — a stub appears in its region's
2109
- `contains` and on its holder's `holdings`, rendered as plain text. What a stub
2108
+ containment tree and `government` for governance — a stub appears in its region's
2109
+ `contains` and its governing body's `governed_places`, rendered as plain text. What a stub
2110
2110
  cannot be is the target of a wikilink, because a wikilink points at a page.
2111
2111
 
2112
2112
  ### What a note produces
@@ -2242,7 +2242,7 @@ See the [authoring examples](../authoring/links-and-markup.md#footnotes-and-defi
2242
2242
  ```
2243
2243
 
2244
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:
2245
+ caption, fenced div, span and named block take. Inside the braces:
2246
2246
 
2247
2247
  - `#id` names the anchor a link resolves to (only one allowed)
2248
2248
  - `.class1` names a CSS class (any number of classes allowed)
@@ -2327,8 +2327,7 @@ applied to a word in the middle of a sentence.
2327
2327
  **Alt text renders as a caption on no surface.** On the website and in a
2328
2328
  Foundry journal it stays on the `img` element's `alt` attribute alone, and the
2329
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
2330
+ caption are drawn only for a picture preceded by [a caption](#captions-and-numbered-references), and the text drawn is always the fence's own
2332
2331
  caption. A title — `![alt](src "title")` — is refused rather than dropped in
2333
2332
  silence: there is one place for those words, the alt text, and a title is not
2334
2333
  it.
@@ -2621,179 +2620,122 @@ the tag and, where the directive restricts one, the type. An empty list under
2621
2620
  an authored heading is how a misspelled tag survives a build, so the
2622
2621
  directive's silence is what is refused rather than its output.
2623
2622
 
2624
- ##### The figure fence
2623
+ ##### Captions and numbered references
2625
2624
 
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.
2625
+ Write a caption on its own line **before** the item it describes, with a blank line before and after the caption. `:` produces an unnumbered caption; `:@` produces a numbered caption. One or more spaces separate the marker from its text. An optional attribute block at the end accepts an identifier, classes and named attributes:
2629
2626
 
2630
- ````markdown
2631
- :::figure {#trade}
2627
+ ```markdown
2628
+ :@ Regional trade routes {#trade .border type=table}
2632
2629
 
2633
- ```sql
2634
- SELECT name.full AS "Market" FROM notes WHERE type = 'place'
2630
+ | Route | Days |
2631
+ | ----- | ---- |
2632
+ | North | 4 |
2633
+
2634
+ Refer to {{ref "#trade"}} for the market routes.
2635
2635
  ```
2636
2636
 
2637
- ///
2638
- Regional trade routes
2639
- :::
2637
+ This displays **Table 1: Regional trade routes**; the reference links to **Table 1**. An unnumbered `: Regional trade routes {#trade}` displays only its text, has an anchor, and does not consume a number. An item with no caption remains unnumbered.
2640
2638
 
2641
- Refer to {{ref "#trade"}} for the market routes.
2642
- ````
2639
+ The caption attaches to exactly the next supported block:
2640
+
2641
+ | Next item | Inferred type | Numbered label |
2642
+ | ------------------------------------ | ------------- | -------------- |
2643
+ | Markdown table | `table` | Table |
2644
+ | Image, Markdown or wikilink | `figure` | Figure |
2645
+ | SQL fence, including backtick SQL | `table` | Table |
2646
+ | Poetry fence | `poetry` | Poem |
2647
+ | Any other code fence | `code` | Code |
2648
+ | Paragraph, quote block or fenced div | `prose` | Prose |
2649
+
2650
+ The optional `type` attribute overrides inference and accepts `figure`, `table`, `poetry`, `code`, `prose`, and `example`. `type=example` uses **Example 1**, **Example 2**, and so on. It does not allow an unsupported target. A heading, list, thematic break, another caption or end of document after a caption is an error. Caption markers without separating spaces or caption text are errors too.
2651
+
2652
+ Identifiers are optional and must be unique within the note. Classes are unrestricted; `.border` uses the shared border style, while other classes can be styled by the medium. Named attributes use `key=value`, with quoted values for text containing spaces. Use `#id` and `.class` rather than `id=` and `class=`; event-handler attributes are refused.
2643
2653
 
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 or poetry 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 six counters it draws from — `Code`, `Table`, `Figure`, `Map`, `Poem`, `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`; a `:::poetry` fence as the first nonblank content is `Poem`; everything else is `Prose`. A poem, table or 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.
2654
+ Each numbered type has its own counter. Websites and Foundry number within a note; books number across their reading order. Unnumbered captions neither display nor consume a number. A map image can retain its asset-derived **Map** classification when no type is specified.
2655
+
2656
+ `{{ref "#trade"}}` displays the numbered label as a link. `form="full"` includes caption text and `form="title"` displays the caption alone. Use title form for an unnumbered caption. Cross-note references can name the note address before the anchor, such as `{{ref "place-harbor#trade"}}`; the displayed number belongs to the target on the surface rendering it. Links inside caption text contribute their visible text to references, so the reference does not contain a nested link.
2657
+
2658
+ Foundry gives a captioned item its own JournalEntryPage. A solitary image with a plain caption can use an image page; captions with inline markup and other items use text pages. On the website and in the book the item stays in the flow of the surrounding page.
2659
+
2660
+ **Migration:** `:::figure` is no longer supported. Move the former `///` caption before the item as `:@ Caption {#id}` and remove the figure wrapper. To caption a group or passage, put it inside a generic fenced div and caption that div with an explicit type if needed. `///` is no longer a caption delimiter.
2661
+
2662
+ ##### Fenced divs
2663
+
2664
+ A bare `:::` opens a div section. An optional attribute block applies to the whole fenced area. A bare `:::` closes the section:
2743
2665
 
2744
2666
  ```markdown
2745
- :::info
2667
+ ::: {#harbor-note .border lang=en}
2746
2668
  The harbor remains open through winter.
2747
- :::
2748
2669
 
2749
- :::warn {#flood-warning title="Seasonal closure"}
2750
- Spring floods close the eastern road.
2670
+ A second paragraph belongs to the same div.
2751
2671
  :::
2672
+ ```
2752
2673
 
2753
- :::secret {#harbor .wide}
2754
- The harbor master is working for the smugglers.
2755
- :::
2674
+ An attribute-bearing opener allows a nested div to be distinguished from the bare closer. Divs carry no automatic title or number; style their classes for the medium. Use a leading caption to caption the entire div. The same attribute grammar is available on named blocks; identifiers, classes and named attributes belong to the entire section. Headings that would start a Foundry journal page cannot split a fenced section.
2675
+
2676
+ ##### Inline spans
2677
+
2678
+ `[inline content]` represents a span. Follow it immediately with an optional attribute block to apply an identifier, classes and named attributes:
2679
+
2680
+ ```markdown
2681
+ The watch wears [a _blue_ sash]{#watch-sash .uniform lang=en}.
2756
2682
  ```
2757
2683
 
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.
2684
+ Inline Markdown remains active inside the span. Bracket spans have lower priority than URL links, image links, reference links, footnotes and wikilinks. A bracketed form immediately preceded by `!`, followed by `(` or another `[`, or beginning with `[[` is not a span, even when the link is unresolved. Ordinary links retain their existing syntax. Escape a bracket when it should be literal, or put examples inside a code span or fence. A span identifier addresses that point in the note; it does not start a journal page.
2763
2685
 
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:
2686
+ ##### Alerts
2687
+
2688
+ Alerts replace the former `:::info` and `:::warn` fences. Start with a special blockquote marker, optionally followed by an attribute block, then write the alert body as a standard blockquote:
2689
+
2690
+ ```markdown
2691
+ > [!NOTE]
2692
+ > Useful information that users should know, even when skimming content.
2766
2693
 
2767
- ```html
2768
- <section class="secret wide" id="harbor">
2769
- <strong>Secret</strong><br />
2770
- <p>The harbor master is working for the smugglers.</p>
2771
- </section>
2694
+ > [!TIP]
2695
+ > Helpful advice for doing things better or more easily.
2696
+
2697
+ > [!IMPORTANT]
2698
+ > Key information users need to know to achieve their goal.
2699
+
2700
+ > [!WARNING]
2701
+ > Urgent info that needs immediate user attention to avoid problems.
2772
2702
  ```
2773
2703
 
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.
2704
+ | Marker | Label | Appearance |
2705
+ | -------------- | --------- | ------------------------------------------------- |
2706
+ | `[!NOTE]` | Note | Blue rule and `fa-regular fa-message` |
2707
+ | `[!TIP]` | Tip | Green rule and `fa-regular fa-lightbulb` |
2708
+ | `[!IMPORTANT]` | Important | Purple rule and `fa-solid fa-circle-info` |
2709
+ | `[!WARNING]` | Warning | Amber rule and `fa-solid fa-triangle-exclamation` |
2710
+
2711
+ The label and icon sit above the body. Alerts are visible callouts, not expandable sections. Inline Markdown, links, multiple paragraphs, lists and code examples remain available inside the quote. Prefix blank lines within the body with `>` to keep paragraphs in the same alert.
2776
2712
 
2777
- On webpages a block is a disclosure any reader can open, titled in its summary:
2713
+ Attributes follow the marker and apply to the alert:
2778
2714
 
2779
- ```html
2780
- <details class="secret wide" id="harbor">
2781
- <summary class="secret">Secret</summary>
2782
- <p>The harbor master is working for the smugglers.</p>
2783
- </details>
2715
+ ```markdown
2716
+ > [!WARNING] {#flood-warning .seasonal lang=en title="Seasonal closure"}
2717
+ > The eastern road closes during spring floods.
2718
+ >
2719
+ > Use the ridge path instead.
2784
2720
  ```
2785
2721
 
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.
2722
+ Use `#id`, `.class` and named attributes in the shared braced grammar. The marker determines the default label, icon and color. An authored `title` replaces the default **Note**, **Tip**, **Important** or **Warning** heading while preserving the alert type’s icon and color. Event-handler attributes, malformed attributes, unknown alert types and empty alert bodies are errors. Ordinary blockquotes and alert examples inside literal code remain unchanged. A leading caption can describe an alert as a quote block, normally with the `prose` type or an explicit `example` type.
2789
2723
 
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.
2724
+ Migrate former info blocks to `[!NOTE]` alerts and warn blocks to `[!WARNING]` alerts. The old named fences are errors. `:::secret` remains supported.
2793
2725
 
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.
2726
+ ##### Secret blocks
2727
+
2728
+ `:::secret` sets GM material apart. Its optional attributes accept an identifier, classes and named attributes. `title` supplies its heading; without a title the heading is **Secret**:
2729
+
2730
+ ```markdown
2731
+ :::secret {#harbor-secret title="For the GM"}
2732
+ The harbor master is working for the smugglers.
2733
+ :::
2734
+ ```
2735
+
2736
+ A secret block can contain alerts and general divs. It cannot contain another secret block. A heading that starts its own journal page cannot split a secret block or general div; use a lower heading without an anchor within the section.
2737
+
2738
+ Foundry renders a secret section; the website renders an expandable spoiler, and the book renders a labeled box. An untitled secret takes its normal default title, and a Foundry secret without an id receives an id derived from its body. The presentation does not make published HTML private: deliberately inspecting generated source can reveal its content. Use YAML comments for information that must never be published.
2797
2739
 
2798
2740
  #### Actors
2799
2741
 
@@ -3383,7 +3325,6 @@ rank names the standing, and the standing says.
3383
3325
  | `governance.ranks` | `Rank[]` | The ranks available to members of the affiliation |
3384
3326
  | `governance.offices` | `Map<name, description \| {description, holders}>` | Official offices and their dated holders |
3385
3327
  | `seat` | `Address` | Where the affiliation's authority sits |
3386
- | `domains` | `Address[]` | Places over which this affiliation holds sway |
3387
3328
  | `population` | `number` | Number of people in the affiliation (precision 2 significant digits). |
3388
3329
  | `economy` | `Address[]` | Economic life: `affiliation` or `lore` Addresses, with an explicit type and no default |
3389
3330
  | `lore` | `Address[]` | Lore concerning it — the peoples it draws on, the god a faith venerates, its law, its calendar |
@@ -3443,37 +3384,7 @@ data:
3443
3384
  - { being: being-mara, start: "datefrom vrcal 2 Lusenar 725 VR" }
3444
3385
  ```
3445
3386
 
3446
- **`domains` is territorial, and only territorial.** Seventy-seven divine
3447
- affiliations currently spell `domain:` the other way, holding a deity's sphere of
3448
- influence as prose — _Love, Beauty, and Prosperity_; _Fertility, Agriculture,
3449
- Peace, and Healing_. That sense **folds into `description`**, which those notes
3450
- leave empty in all but one case, and it does not become a field of its own.
3451
-
3452
- A sphere is a characterisation, not a reference. Nothing compiles against it, no
3453
- other note points at it, and rendering it as a list would imply a vocabulary that
3454
- does not exist — whereas `description` is exactly the field for a one-line
3455
- statement of what a thing is. The fuller treatment already has a home: `lore` of
3456
- subType `deity` covers a god's nature, domains, epithets and aspects in prose.
3457
-
3458
- That frees the name for the territorial sense, which earns it: every affiliation
3459
- subType holds sway somewhere, while the divine sense applies to one.
3460
-
3461
- **`domains` names what the affiliation holds directly**, and nothing beneath
3462
- it. A polity whose `domains` names a region holds the region; the settlements
3463
- within it are the region's, reached through its `contains`, and are not
3464
- repeated here. A house holds its manors and names each; the crown holds the
3465
- realm and names the realm. What lies below a holder is answered by the two
3466
- hierarchies together — `place.parents` for where a place sits, and
3467
- `affiliation.parents` for whom a holder answers to — so a subinfeudated manor
3468
- sits in one region by the first and under a lord of another polity by the
3469
- second, and both pages say so.
3470
-
3471
- The website reads `domains` across the package and every fetched index and
3472
- writes the affiliation's page a `holdings` list — every place its `domains`
3473
- names, each entry `{ title, url, type, subType }`, sorted by `subType` then
3474
- `title`, and absent when `domains` names nothing. Every place it names carries
3475
- the affiliation back in `held_by`. Both are derived; a note that writes one has
3476
- it replaced.
3387
+ **Governed places are derived from place notes.** Each place names one governing affiliation in `data.government`. The website writes the body's `governed_places` list by resolving those explicit references across local notes and fetched indexes. Each entry is `{ title, url, type, subType }`, sorted by `subType` then `title`; an empty list is omitted. No affiliation-side list supplies government, and neither geographic containment nor organizational parents expands it.
3477
3388
 
3478
3389
  If `sohl` is present, this becomes an `affiliation` item.
3479
3390
 
@@ -3481,7 +3392,6 @@ If `sohl` is present, this becomes an `affiliation` item.
3481
3392
  | ---------------- | ------------------ | ----- |
3482
3393
  | `subType` | `system.subType` | NA |
3483
3394
  | `data.seat` | `system.seat` | NA |
3484
- | `data.domains` | `system.domain` | NA |
3485
3395
  | `data.parents` | `system.parents` | NA |
3486
3396
  | `data.relations` | `system.relations` | NA |
3487
3397
 
@@ -4263,7 +4173,7 @@ map's prose.
4263
4173
  | `lore` | `Address[]` | Lore concerning this place — its peoples, its law, its calendar, its history |
4264
4174
  | `parents` | `Address[]` | Enclosing places within which this place is located |
4265
4175
  | `population` | `number` | Approximate population (precision 2 significant digits) |
4266
- | `government` | affiliation Address or `null` | Governing affiliation; explicit null means complete anarchy. Omission warns only for positive population. |
4176
+ | `government` | `Address` or `null` (default type: `affiliation`) | Governing affiliation; explicit null means complete anarchy. Omission warns only for positive population. |
4267
4177
  | `market` | `number` | Market class, 1 to 6 — what trade a settlement supports |
4268
4178
  | `borders` | `{ to, bearing }[]` | Places sharing a frontier with this one, and where each lies from here |
4269
4179
  | `routes` | `{ to, bearing, mode, days, terrain?, leagues? }[]` | Journeys from this place's centre to another place |
@@ -4484,27 +4394,13 @@ than the package that wrote it.
4484
4394
  | `river` | boat |
4485
4395
  | `lake` | boat |
4486
4396
 
4487
- #### What lies within a place, and who holds it
4488
-
4489
- `parents` states what a place is within; an affiliation's `domains` states
4490
- what it holds. The website reads both across the package and every fetched
4491
- index and writes each place's page two lists, each entry
4492
- `{ title, url, type, subType }` and each absent when empty:
4493
-
4494
- - `contains` — every place whose `parents` names this one, sorted by
4495
- `subType` then `title`. A region lists its settlements, sites, structures
4496
- and features; a settlement lists the structures within it.
4497
- - `held_by` — every affiliation whose `domains` names this one, sorted by
4498
- `title`.
4397
+ #### What lies within a place
4499
4398
 
4500
- Both are derived; a note that writes one has it replaced. **`domains` is
4501
- never expanded**: a region held by a polity lists the polity in `held_by`, and
4502
- a settlement within that region lists only the house or order whose `domains`
4503
- names it — its lord's lord is reached through `affiliation.parents`.
4399
+ `parents` states what a place is within. The website reads this across the package and every fetched index and writes `contains`: every place whose `parents` names this one, sorted by `subType` then `title`. Each entry is `{ title, url, type, subType }`; the list is omitted when empty. A region lists its settlements, sites, structures and features; a settlement lists its structures. Government never changes this geographical containment.
4504
4400
 
4505
4401
  #### Who governs a place
4506
4402
 
4507
- A place may state its governing affiliation in `data.government`. Use an affiliation Address, either a local shortcode or a fully qualified Address from this package or a fetched dependency:
4403
+ A place may state its governing affiliation in `data.government`. The field type is `Address`, with `affiliation` as the default target type when the type is omitted. Use either a local shortcode or a fully qualified affiliation Address from this package or a fetched dependency:
4508
4404
 
4509
4405
  ```yaml
4510
4406
  data:
@@ -4521,20 +4417,15 @@ Write `government: null` for **complete anarchy**. Omitting the key leaves gover
4521
4417
  | Any | Explicit `null` | None; complete anarchy |
4522
4418
  | Any | Affiliation Address | None; the reference must resolve |
4523
4419
 
4524
- These rules apply to every place subtype, including settlements, sites, structures, features, regions and worlds. Empty strings, numbers, lists, maps, references to another note type and unresolved references are errors. They do not declare anarchy. `domains`, `parents`, containment and capitals do not supply a government. Holdings remain tenure facts; the former unconditional “unheld land” warning is retired.
4420
+ These rules apply to every place subtype, including settlements, sites, structures, features, regions and worlds. Empty strings, numbers, lists, maps, references to another note type and unresolved references are errors. They do not declare anarchy. `domains`, `parents`, containment and capitals do not supply a government. Legacy affiliation `data.domains` is accepted temporarily but ignored. Preserve ownership and influence facts in prose; see [government migration](../guides/government-migration.md).
4525
4421
 
4526
4422
  #### Population figures
4527
4423
 
4528
4424
  `population` is an approximate count, written to two significant digits. A
4529
4425
  place states one, and so does an affiliation — how many people it counts,
4530
4426
  wherever they are. `package-build lint` reads those figures against each other
4531
- and reports four warnings, each named by the phrase its message begins with.
4427
+ and reports three warnings, each named by the phrase its message begins with.
4532
4428
 
4533
- - **`over-held land`** — the polities whose `domains` name a place count more
4534
- people than the place states. A polity subordinate to another polity holding
4535
- the same place is already inside that polity's figure and is not counted
4536
- twice. A **settlement is exempt**: the polity of a city-state holds the city
4537
- and counts the hinterland around it, so its figure is properly the larger.
4538
4429
  - **`over-full region`** — the regions whose `parents` name a place count more
4539
4430
  people than the place states. A region naming both its parent and its
4540
4431
  grandparent counts under the nearer of the two, so a place written into two
@@ -4546,7 +4437,7 @@ and reports four warnings, each named by the phrase its message begins with.
4546
4437
  located at the number the page wrote, and a figure written twice is located
4547
4438
  twice.
4548
4439
 
4549
- The first three are reported on the note's own `data.population`; the fourth
4440
+ The first two are reported on the note's own `data.population`; the third
4550
4441
  on the citation.
4551
4442
 
4552
4443
  **A figure is read as a population only where it carries `~`.** That marker is
@@ -4561,7 +4452,7 @@ cent below what it contains is not a finding.
4561
4452
  **An unstated figure is silent.** A place or affiliation with no `population`
4562
4453
  contributes nothing to a sum and is never the subject of a finding, so a
4563
4454
  half-written region is quiet rather than noisy. A fetched index carries
4564
- `population` alongside `parents` and `domains` when its author stated a
4455
+ `population` alongside `parents` and `government` when its author stated a
4565
4456
  figure. An older fetched index with no figure remains silent.
4566
4457
 
4567
4458
  **There is deliberately no urban-share rule.** The share of a region's people
@@ -4570,8 +4461,8 @@ settlement layer names the notable places and is complete nowhere, so the ratio
4570
4461
  reports how much of a region has been written rather than how much of it is
4571
4462
  urban.
4572
4463
 
4573
- **A place declares what is true of its ground.** Its governing affiliations
4574
- carry their own `domains`; maps name the place they depict through `data.place`.
4464
+ **A place declares what is true of its ground.** It names its governing affiliation
4465
+ in `data.government`; maps name the place they depict through `data.place`.
4575
4466
  The place's `lore` links cover its peoples, calendar, law and history. Political
4576
4467
  languages belong to a polity's `sohl.system.commonSkills`, while the note's
4577
4468
  `description` provides its page summary.