@heroiclands/package-build 22.25.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 (67) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +4 -0
  3. package/assets/styles/content-base.css +46 -3
  4. package/docs/api.md +35 -12
  5. package/docs/authoring/frontmatter.md +21 -0
  6. package/docs/authoring/links-and-markup.md +96 -149
  7. package/docs/content-format.md +6 -2
  8. package/docs/guides/government-migration.md +52 -0
  9. package/docs/guides/site.md +5 -5
  10. package/docs/reference/format-details.md +152 -246
  11. package/docs/reference/note-types.md +27 -28
  12. package/docs/reference/theme-pages.md +33 -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/calendar-notes.mjs +1 -1
  18. package/engine/code-fences.mjs +6 -2
  19. package/engine/content-alerts.mjs +195 -0
  20. package/engine/content-blocks.mjs +119 -241
  21. package/engine/content-embeds.mjs +1 -1
  22. package/engine/content-figures.mjs +166 -230
  23. package/engine/content-format-check.mjs +3 -2
  24. package/engine/content-format.yaml +1 -5
  25. package/engine/content-images.mjs +3 -3
  26. package/engine/content-poetry.mjs +141 -0
  27. package/engine/content-spans.mjs +177 -0
  28. package/engine/foundry-entries.mjs +2 -0
  29. package/engine/frontmatter-lint.mjs +2 -1
  30. package/engine/heading-attributes.mjs +1 -1
  31. package/engine/helpers.mjs +8 -3
  32. package/engine/holdings.mjs +197 -333
  33. package/engine/index.mjs +1 -1
  34. package/engine/infobox.mjs +11 -1
  35. package/engine/journals.mjs +8 -6
  36. package/engine/markdown-expressions.mjs +9 -3
  37. package/engine/metadata-index.mjs +5 -3
  38. package/engine/note-vocabulary.mjs +30 -13
  39. package/engine/pdf-build.mjs +1 -1
  40. package/engine/pdf-render.mjs +90 -31
  41. package/engine/populations.mjs +17 -83
  42. package/engine/site-build.mjs +44 -16
  43. package/engine/site-preview.mjs +22 -6
  44. package/engine/wikilinks.mjs +18 -4
  45. package/hugo-theme/layouts/partials/holdings/entry.html +2 -2
  46. package/hugo-theme/layouts/partials/holdings.html +14 -14
  47. package/hugo-theme/static/css/style.css +40 -2
  48. package/package.json +1 -1
  49. package/sohl/item-fields.mjs +0 -16
  50. package/types/engine/anchors.d.mts +13 -4
  51. package/types/engine/art-fields.d.mts +1 -1
  52. package/types/engine/calendar-notes.d.mts +1 -1
  53. package/types/engine/code-fences.d.mts +3 -1
  54. package/types/engine/content-alerts.d.mts +62 -0
  55. package/types/engine/content-blocks.d.mts +3 -10
  56. package/types/engine/content-embeds.d.mts +1 -1
  57. package/types/engine/content-figures.d.mts +13 -20
  58. package/types/engine/content-images.d.mts +1 -1
  59. package/types/engine/content-poetry.d.mts +32 -0
  60. package/types/engine/content-spans.d.mts +18 -0
  61. package/types/engine/holdings.d.mts +75 -118
  62. package/types/engine/infobox.d.mts +1 -0
  63. package/types/engine/markdown-expressions.d.mts +1 -1
  64. package/types/engine/note-vocabulary.d.mts +14 -2
  65. package/types/engine/populations.d.mts +4 -13
  66. package/types/engine/site-build.d.mts +3 -3
  67. package/types/engine/wikilinks.d.mts +5 -1
@@ -37,7 +37,7 @@ The harbor faces west.
37
37
  Travelers present their papers here. See [[#harbor|the harbor]].
38
38
  ```
39
39
 
40
- A `:::figure` fence starts a JournalEntryPage too, in Foundry alone — the web and the book keep the fence in the flow of the page around it. A fence holding exactly one picture, captioned with plain text and nothing else, becomes a page of type `image`: the picture is its `src`, the caption is `image.caption`, and the page is named for the figure's own number, such as "Figure 3". A fence carrying no caption still takes the `image` type when it holds one picture, named the same way. Every other fence takes a page of type `text` instead — a grouped fence holding more than one picture, an audio embed, a fence whose caption carries emphasis, an icon, or a link, and a fence that shares its page with trailing prose before the next heading or fence.
40
+ A leading caption starts a captioned-item JournalEntryPage in Foundry. A solitary image with a plain caption can be an image page; other captioned items become text pages. Websites and books keep captioned items in the surrounding flow.
41
41
 
42
42
  The prose introducing a fence and the fence itself land on two different Foundry pages, so a reference such as `{{ref "#trade"}}` written just above a fence sends a Foundry reader to a different page than the one carrying the sentence. Give the introducing prose its own heading, or accept that following the reference leaves the page, before relying on a fence to sit inside a longer page's flow.
43
43
 
@@ -63,178 +63,130 @@ A `:::secret` block inside the section is legal and renders as it does anywhere
63
63
 
64
64
  The special Actor anchors `{#appearance}` and `{#dossier}` feed the same authored sections to each system's Actor fields, and take an H1 only — not the lower-level heading a journal page may otherwise start from. The section runs to the next H1, nested headings included. An anchor declared on a lower heading is still found, and is a build error rather than a quietly empty field: move the heading to the top level, or drop the anchor if the section is meant to stay unaddressed prose.
65
65
 
66
- ## Figures and numbered references
66
+ ## Captions and numbered references
67
67
 
68
- A `:::figure` fence numbers whatever it holds and, written with an id, makes it a target `{{ref}}` can point to:
68
+ 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:
69
69
 
70
- ````markdown
71
- :::figure {#trade}
72
-
73
- ```sql
74
- SELECT name.full AS "Market" FROM notes WHERE type = 'place'
75
- ```
70
+ ```markdown
71
+ :@ Regional trade routes {#trade .border type=table}
76
72
 
77
- ///
78
- Regional trade routes
79
- :::
73
+ | Route | Days |
74
+ | ----- | ---- |
75
+ | North | 4 |
80
76
 
81
77
  Refer to {{ref "#trade"}} for the market routes.
82
- ````
78
+ ```
83
79
 
84
- The fence displays **Table 1: Regional trade routes**, and `{{ref "#trade"}}` displays **Table 1** as a link. **A figure is numbered because it is a fence, not because it carries caption text** — an ordinary table or picture written outside any fence is numbered not at all.
80
+ 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.
85
81
 
86
- **The construct is `:::figure`**, with an optional `{#id .border}` attribute block, closed by `:::`. Everything between the opening line and the closing `:::` is the captioned thing.
82
+ The caption attaches to exactly the next supported block:
87
83
 
88
- **The first `///` at the top level of the fence separates the captioned thing from its caption.** A second `///` at the top level is an error — a figure holds one caption. A `///` written inside a nested code fence is content, not a separator, so a captioned code listing can carry `///` as a comment of its own.
84
+ | Next item | Inferred type | Numbered label |
85
+ | ------------------------------------ | ------------- | -------------- |
86
+ | Markdown table | `table` | Table |
87
+ | Image, Markdown or wikilink | `figure` | Figure |
88
+ | SQL fence, including backtick SQL | `table` | Table |
89
+ | Poetry fence | `poetry` | Poem |
90
+ | Any other code fence | `code` | Code |
91
+ | Paragraph, quote block or fenced div | `prose` | Prose |
89
92
 
90
- **The caption is optional.** A fence with no `///` draws its label alone, with nothing under it. So the counter and the label come from the fence itself, whether or not an author writes a caption.
93
+ 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.
91
94
 
92
- **`{#id}` is optional too.** A fence that declares none is still numbered and drawn; it carries no anchor, so nothing can refer to it. Give a figure an id only when prose needs to point at it.
95
+ 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.
93
96
 
94
- **`.border` draws the figure and its label inside a border.** It is the only class the construct accepts — any other class, such as `.wide`, is an error naming the class. `key="value"` is refused outright: a figure takes an id and classes, nothing else.
97
+ 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.
95
98
 
96
- **The counter is derived from the fence's contents, never authored.** A table is a table; an `sql` fence is a table, because its rendered output is one; any other fence or code block is code; pictures alone, one or several, are a figure; a `:::poetry` fence written first makes it a poem; everything else is prose. A fence around prose with `.border` is a numbered, referable boxed aside — the `Prose` counter's whole purpose. The counters are `Code`, `Table`, `Figure`, `Map`, `Poem`, and `Prose`. The website and a Foundry journal number each counter within the note; a book numbers each counter across the book in reading order.
99
+ `{{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.
97
100
 
98
- **A picture counts as `Map` instead of `Figure` when the asset it draws declares `role: map`** in its provenance — see [the asset provenance reference](../reference/format-details.md). The fence's own markup cannot say so; a picture of a map looks like any other picture, so the fact rides entirely on the asset's own record. A fence grouping several pictures counts as `Map` only when every one of them declares the role; one picture without it keeps the whole fence a `Figure`.
101
+ 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.
99
102
 
100
- **A reference is written `{{ref "#thorn"}}`**, rendering as a link reading "Figure 13". `form="full"` renders the number and the caption; `form="title"` renders the caption alone; `form="number"` is the default, and may be written explicitly. A link written inside the caption contributes only its label text to a `full` or `title` reference, because the reference is itself a link and an anchor cannot nest inside another.
103
+ **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.
101
104
 
102
- **A reference may name another note's figure**, writing the note's address before the anchor: `{{ref "place-thornford#trade"}}` points at the figure `#trade` in `place-thornford`. It renders the number that figure carries **on the surface doing the rendering** — its own count within `place-thornford` on the website and in a Foundry journal, and its place in the book's reading order in the book, which may differ from the number it carries on its own page. An anchor matching no figure in the addressed note is refused, and so is an address naming no note at all.
105
+ ## Images and protected content
103
106
 
104
- In a Foundry journal, a reference resolves to the figure's own JournalEntryPage — the `image` page a solitary, plainly captioned picture becomes, or the `text` page any other fence becomes — addressed exactly as an authored `[[#anchor|Text]]` link to the same anchor would be. A reference naming another note's figure is not resolved there: a journal addresses a page by UUID, and has none for a note outside the one compiling.
107
+ An image or icon embed stands on its own line; one that does not is a lint error naming the line, because a width or a position means nothing applied to a word in the middle of a sentence. `size` accepts `auto`, `small`, `medium`, `large`, `xlarge` and `full-width`; the medium maps those names to suitable dimensions, and `full-width` is the full page in the book and the full content width elsewhere. `float` controls placement and takes `top-left`, `top-right`, `bottom-left`, `bottom-right` or `center`; on a page a float occupies the column measure, so only the vertical half of a corner position has an effect there. The asset remains an Address, so moving the file within its asset root does not change the link. See [assets](assets.md) and [image directives](../reference/format-details.md#images).
105
108
 
106
- **A figure needs contents and a closing `:::`.** Its id, when one is given, must be unique in the note; its caption, when one is given, is the one `///` section the fence carries.
109
+ ### Fenced divs
107
110
 
108
- A few worked examples. A captioned picture:
111
+ A bare `:::` opens a div section. An optional attribute block applies to the whole fenced area. A bare `:::` closes the section:
109
112
 
110
113
  ```markdown
111
- :::figure {#thorn}
112
- ![[being-foobar|The Great Beast]]
113
- ///
114
- The great beast, as drawn by [[person-havard|Havard]].
115
- :::
116
- ```
117
-
118
- This draws **Figure 1**, labelled "Figure 1: The great beast, as drawn by Havard." beneath the picture.
114
+ ::: {#harbor-note .border lang=en}
115
+ The harbor remains open through winter.
119
116
 
120
- A grouped fence holding two pictures as one figure — a plate rather than two separate plates:
121
-
122
- ```markdown
123
- :::figure {#passes}
124
- ![[image-northpass|Northern approach]]
125
- ![[image-southpass|Southern approach]]
126
- ///
127
- The two approaches to the pass.
117
+ A second paragraph belongs to the same div.
128
118
  :::
129
119
  ```
130
120
 
131
- Both pictures draw together under one label, **Figure 2**, because the fence is the unit the counter numbers — not the pictures inside it.
121
+ 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.
132
122
 
133
- A fence with no caption:
123
+ ### Inline spans
124
+
125
+ `[inline content]` represents a span. Follow it immediately with an optional attribute block to apply an identifier, classes and named attributes:
134
126
 
135
127
  ```markdown
136
- :::figure {#anvil}
137
- ![[icon-anvil|A worn anvil]]
138
- :::
128
+ The watch wears [a _blue_ sash]{#watch-sash .uniform lang=en}.
139
129
  ```
140
130
 
141
- This draws **Figure 3**, with no caption line beneath it, and still carries the anchor `#anvil`.
131
+ 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.
142
132
 
143
- A reference in running prose:
133
+ ### Alerts
134
+
135
+ 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:
144
136
 
145
137
  ```markdown
146
- See {{ref "#thorn"}} for the plate, or {{ref "#thorn" form="full"}} for the full description.
147
- ```
138
+ > [!NOTE]
139
+ > Useful information that users should know, even when skimming content.
148
140
 
149
- This displays as "See [Figure 1](#thorn) for the plate, or [Figure 1: The great beast, as drawn by Havard.](#thorn) for the full description," each bracketed phrase a link to the figure.
141
+ > [!TIP]
142
+ > Helpful advice for doing things better or more easily.
150
143
 
151
- A reference to a figure in another note:
144
+ > [!IMPORTANT]
145
+ > Key information users need to know to achieve their goal.
152
146
 
153
- ```markdown
154
- The market routes are drawn in {{ref "place-thornford#trade"}}.
147
+ > [!WARNING]
148
+ > Urgent info that needs immediate user attention to avoid problems.
155
149
  ```
156
150
 
157
- On the website this links into `place-thornford`'s own page, reading "Table 1" — the number that fence carries there, whatever number it carries in the book or in a note of its own.
158
-
159
- ## Images and protected content
160
-
161
- An image or icon embed stands on its own line; one that does not is a lint error naming the line, because a width or a position means nothing applied to a word in the middle of a sentence. `size` accepts `auto`, `small`, `medium`, `large`, `xlarge` and `full-width`; the medium maps those names to suitable dimensions, and `full-width` is the full page in the book and the full content width elsewhere. `float` controls placement and takes `top-left`, `top-right`, `bottom-left`, `bottom-right` or `center`; on a page a float occupies the column measure, so only the vertical half of a corner position has an effect there. The asset remains an Address, so moving the file within its asset root does not change the link. See [assets](assets.md) and [image directives](../reference/format-details.md#images).
151
+ | Marker | Label | Appearance |
152
+ | -------------- | --------- | ------------------------------------------------- |
153
+ | `[!NOTE]` | Note | Blue rule and `fa-regular fa-message` |
154
+ | `[!TIP]` | Tip | Green rule and `fa-regular fa-lightbulb` |
155
+ | `[!IMPORTANT]` | Important | Purple rule and `fa-solid fa-circle-info` |
156
+ | `[!WARNING]` | Warning | Amber rule and `fa-solid fa-triangle-exclamation` |
162
157
 
163
- ### Named blocks
158
+ 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.
164
159
 
165
- Three named blocks set a passage apart from the prose around it. `:::secret`
166
- marks GM material, `:::info` a neutral note, and `:::warn` a caution:
160
+ Attributes follow the marker and apply to the alert:
167
161
 
168
162
  ```markdown
169
- :::warn
170
- The bridge closes during the spring flood.
171
- :::
163
+ > [!WARNING] {#flood-warning .seasonal lang=en title="Seasonal closure"}
164
+ > The eastern road closes during spring floods.
165
+ >
166
+ > Use the ridge path instead.
172
167
  ```
173
168
 
174
- Each heads itself with its own name — **Secret**, **Info**, **Warn** — and takes
175
- a closing `:::`. Poetry has its own fence below; other names are reported.
169
+ 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.
170
+
171
+ Migrate former info blocks to `[!NOTE]` alerts and warn blocks to `[!WARNING]` alerts. The old named fences are errors. `:::secret` remains supported.
176
172
 
177
- **A GM-only section holds a box.** A `:::secret` is a container for whatever the
178
- GM reads, boxes included, and a box written inside one stays inside it. A box
179
- holds no named block of its own, so a second box inside a box is reported. A
180
- `:::figure` fence may be written inside any of them. The two draw a box for
181
- different reasons: a named block says what kind of aside a passage is, while a
182
- `:::figure` fence makes a passage numbered and referable — nesting one inside
183
- the other gives a passage both.
173
+ ### Secret blocks
184
174
 
185
- **An attribute block follows the name.** It is the same braced grammar the other
186
- body extensions use, so it carries an id, classes, and any attribute the element
187
- should have. `title` is reserved and supplies the heading in place of the default:
175
+ `:::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**:
188
176
 
189
177
  ```markdown
190
- :::secret {#harbor title="For the GM" .wide data-stage="two"}
178
+ :::secret {#harbor-secret title="For the GM"}
191
179
  The harbor master is working for the smugglers.
192
180
  :::
193
181
  ```
194
182
 
195
- That block carries the classes `secret wide`, the id `harbor`, and
196
- `data-stage="two"`, and it heads **For the GM**. A title carries emphasis of its
197
- own — `title="The *Genzet* only"` — and nothing else: a tag written there is
198
- shown rather than obeyed. Set the id with `#id` and classes with `.class` rather
199
- than through an `id=` or `class=` key, and note that an event handler such as
200
- `onclick=` is refused rather than written.
201
-
202
- **The name is the first class on the element, and the appearance belongs to a
203
- stylesheet.** No block is emitted with an inline `style`, so a package restyles
204
- one from its own sheet. `info` and `warn` are styled by the base stylesheet;
205
- `secret` is left to Foundry, which styles `section.secret` itself and owns the
206
- reveal control on it.
207
-
208
- Each surface renders the same block its own way:
209
-
210
- | Surface | Output |
211
- | ------- | ---------------------------------------------------------------------------------- |
212
- | Foundry | `<section class="secret" id="harbor">` with the title as its first line |
213
- | Web | `<details class="secret" id="harbor">` the reader opens, titled in its `<summary>` |
214
- | Book | a coloured print box headed by the title |
215
-
216
- A `secret` with no id of its own is given one derived from its body on the
217
- Foundry surface, because Foundry remembers a revealed section by its id.
218
-
219
- **A secret is a presentation distinction, not access control.** Players who
220
- deliberately inspect source or generated output may see it. The
221
- [detailed reference](../reference/format-details.md#what-a-note-produces)
222
- describes each medium's handling.
223
-
224
- **One malformed block does not silence the others.** A block whose attributes do
225
- not parse is reported at its own line and left as written; every well-formed
226
- block in the same note still renders.
227
-
228
- **A heading that would start its own journal page cannot be written inside a
229
- block, or inside a `:::figure` fence.** An H1, or a heading of any level
230
- carrying an `{#anchor}`, is reported at its own line there — starting a page
231
- would tear the block or the figure in two, and a reader could open the second
232
- half with none of the box around it. A lower heading with no anchor is
233
- unaffected and is the ordinary way to structure a long box.
183
+ 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.
184
+
185
+ 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.
234
186
 
235
187
  ### Poetry
236
188
 
237
- Use `:::poetry` to preserve verse lines and stanzas. Every nonblank source line
189
+ Use a code fence with the language `poetry` to preserve verse lines and stanzas. Every nonblank source line
238
190
  is one verse line; blank lines separate stanzas. Inline emphasis, links and
239
191
  footnotes work as they do in prose. The fence itself adds no title, caption or
240
192
  number.
@@ -263,15 +215,15 @@ render at levels zero and `i1` respectively. This also works when the entire
263
215
  fence is indented inside a list item. Poetry is upright by default; use normal
264
216
  Markdown emphasis when italics are part of the poem.
265
217
 
266
- ```markdown
267
- :::poetry {form=ballad meter="common meter" rhyme=ABCB syllables="8,6,8,6" lang=en}
218
+ ````markdown
219
+ ```poetry {form=ballad meter="common meter" rhyme=ABCB syllables="8,6,8,6" lang=en}
268
220
  The lantern burns beside the gate,
269
221
  The harbor sleeps below.
270
222
 
271
223
  The keeper guards the road till dawn,
272
224
  And keeps a light aglow.
273
- :::
274
225
  ```
226
+ ````
275
227
 
276
228
  The optional `form`, `meter` and `rhyme` attributes record the author's intent;
277
229
  the build does not infer stress, rhyme or pronunciation. `syllables` gives a
@@ -281,23 +233,18 @@ spoken. `lang` is a language tag for the rendered HTML. An optional `#id`
281
233
  addresses the poem itself. There are no `title` or `lines` attributes, and no
282
234
  special punctuation for stress, pauses or refrains.
283
235
 
284
- To number and caption a poem, put it first inside a `:::figure`:
236
+ To number and caption a poem, put a leading numbered caption before the poetry fence:
285
237
 
286
- ```markdown
287
- :::figure {#watch-song}
288
- :::poetry {form=ballad}
238
+ ````markdown
239
+ :@ A song sung by the harbor watch. {#watch-song}
240
+
241
+ ```poetry {form=ballad}
289
242
  The watch has gone to sea,
290
243
  The lantern marks the shore.
291
- :::
292
- ///
293
- A song sung by the harbor watch.
294
- :::
295
244
  ```
245
+ ````
296
246
 
297
- The inner `:::` closes the poem; the outer one closes the figure. That figure
298
- uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. The
299
- caption after `///` belongs to the figure. A poem outside a figure is
300
- unnumbered. Prose written before the poem makes the figure a **Prose** figure.
247
+ This uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. Use `:` for a caption without a number. `:::poetry` is no longer supported.
301
248
 
302
249
  ## Footnotes and definition lists
303
250
 
@@ -471,21 +418,21 @@ There are {{words (sql "SELECT COUNT(*) FROM notes WHERE type = 'being'")}} bein
471
418
 
472
419
  <!-- expression-helpers:start -->
473
420
 
474
- | Helper | Parameters | What it gives you |
475
- | ------------ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
476
- | `eq` | `a b` | True when both are the same value. Compares exactly, so 1 and "1" differ. |
477
- | `gt` | `a b` | True when a is greater than b. Both must be finite numbers. |
478
- | `gte` | `a b` | True when a is greater than or equal to b. Both must be finite numbers. |
479
- | `lt` | `a b` | True when a is less than b. Both must be finite numbers. |
480
- | `lte` | `a b` | True when a is less than or equal to b. Both must be finite numbers. |
481
- | `not` | `value` | True when the value is false, zero, empty or absent. |
482
- | `and` | `value …` | True when every value given is true. Takes two or more. |
483
- | `or` | `value …` | True when any value given is true. Takes two or more. |
484
- | `words` | `number` | The number spelled out for running prose — `1200` becomes one thousand two hundred. Whole numbers only; a decimal is a finding, and `digits` takes one. |
485
- | `digits` | `number` | The number as a grouped numeral — `1200` becomes 1,200, and a fractional part is kept. |
486
- | `sql` | `"query"` | The single value a query returns, for use inside a sentence. The query is a quoted string, the same SQL a table fence takes. |
487
- | `dateformat` | `calendar date ["format"]` | A date written in a calendar. The calendar is an Address or its shortcode, the date is the value a note carries, and the optional third argument names an output pattern. |
488
- | `ref` | `address [form="number"\|"full"\|"title"]` | A link to a `:::figure` fence, by its anchor — `"#thorn"` on this note, `"note-address#thorn"` on another. `form` is `number` (the default, and admitted explicitly), rendering "Figure 13"; `full`, the number and the caption; or `title`, the caption alone. Always renders as a link to the figure, and a link inside the caption contributes only its label text. The number rendered is the one the figure carries on the surface doing the rendering, whichever note names it. |
421
+ | Helper | Parameters | What it gives you |
422
+ | ------------ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
423
+ | `eq` | `a b` | True when both are the same value. Compares exactly, so 1 and "1" differ. |
424
+ | `gt` | `a b` | True when a is greater than b. Both must be finite numbers. |
425
+ | `gte` | `a b` | True when a is greater than or equal to b. Both must be finite numbers. |
426
+ | `lt` | `a b` | True when a is less than b. Both must be finite numbers. |
427
+ | `lte` | `a b` | True when a is less than or equal to b. Both must be finite numbers. |
428
+ | `not` | `value` | True when the value is false, zero, empty or absent. |
429
+ | `and` | `value …` | True when every value given is true. Takes two or more. |
430
+ | `or` | `value …` | True when any value given is true. Takes two or more. |
431
+ | `words` | `number` | The number spelled out for running prose — `1200` becomes one thousand two hundred. Whole numbers only; a decimal is a finding, and `digits` takes one. |
432
+ | `digits` | `number` | The number as a grouped numeral — `1200` becomes 1,200, and a fractional part is kept. |
433
+ | `sql` | `"query"` | The single value a query returns, for use inside a sentence. The query is a quoted string, the same SQL a table fence takes. |
434
+ | `dateformat` | `calendar date ["format"]` | A date written in a calendar. The calendar is an Address or its shortcode, the date is the value a note carries, and the optional third argument names an output pattern. |
435
+ | `ref` | `address [form="number"\|"full"\|"title"]` | A link to a captioned item, by its anchor — `"#thorn"` on this note, `"note-address#thorn"` on another. `form` is `number` (the default, and admitted explicitly), rendering "Figure 13"; `full`, the number and the caption; or `title`, the caption alone. Always renders as a link to the figure, and a link inside the caption contributes only its label text. The number rendered is the one the figure carries on the surface doing the rendering, whichever note names it. |
489
436
 
490
437
  <!-- expression-helpers:end -->
491
438
 
@@ -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
@@ -85,3 +85,7 @@ A sheltered place where ships load and unload.
85
85
  The note's readable Address is `<package>-note-lore-harbor`. In prose, link to it with `[[lore-harbor|Harbor]]`. The package segment comes from `package-build.config.yaml`; a regular wikilink defaults to the readable `note` system. An image embed such as `![[icon-harbor|Harbor]]` defaults to `none` instead.
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
+
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