@heroiclands/package-build 23.0.0 → 23.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +1 -1
- package/bin/content-commands.mjs +1 -1
- package/ci/content-format-reference.mjs +46 -0
- package/docs/api.md +124 -141
- package/docs/authoring/assets.md +1 -1
- package/docs/authoring/dates-and-calendars.md +12 -6
- package/docs/authoring/frontmatter.md +2 -2
- package/docs/authoring/links-and-markup.md +145 -29
- package/docs/commands.md +8 -10
- package/docs/configuration.md +13 -11
- package/docs/content-format.md +2 -2
- package/docs/guides/book.md +59 -4
- package/docs/guides/icons.md +4 -5
- package/docs/guides/packs.md +6 -0
- package/docs/guides/reference-pages.md +21 -1
- package/docs/guides/release-and-deploy.md +39 -7
- package/docs/guides/site.md +17 -18
- package/docs/reference/format-details.md +877 -276
- package/docs/reference/note-types.md +278 -91
- package/docs/reference/theme-pages.md +58 -97
- package/engine/address-values.mjs +124 -4
- package/engine/address.mjs +44 -3
- package/engine/anchors.mjs +103 -3
- package/engine/art-slots.mjs +2 -9
- package/engine/base-compiler.mjs +25 -6
- package/engine/calendar-artifacts.mjs +4 -1
- package/engine/calendar-notes.mjs +166 -102
- package/engine/content-format-check.mjs +2 -3
- package/engine/content-format.mjs +44 -1
- package/engine/content-format.yaml +79 -16
- package/engine/content-images.mjs +10 -1
- package/engine/content-index.mjs +37 -9
- package/engine/content-links.mjs +24 -5
- package/engine/content-tables.mjs +24 -3
- package/engine/data-keys.mjs +347 -0
- package/engine/derived-sections.mjs +322 -0
- package/engine/diagnostics.mjs +28 -0
- package/engine/event-fields.mjs +187 -0
- package/engine/event-rows.mjs +126 -0
- package/engine/event-views.mjs +305 -0
- package/engine/exported-scene.mjs +29 -53
- package/engine/frontmatter-lint.mjs +103 -77
- package/engine/frontmatter.mjs +7 -2
- package/engine/generate.mjs +53 -0
- package/engine/generated-sections.mjs +223 -0
- package/engine/heading-attributes.mjs +4 -2
- package/engine/helpers.mjs +12 -1
- package/engine/holdings.mjs +12 -33
- package/engine/ids.mjs +17 -11
- package/engine/index.mjs +4 -4
- package/engine/infobox-render.mjs +21 -6
- package/engine/infobox.mjs +217 -99
- package/engine/journals.mjs +104 -47
- package/engine/literature-notes.mjs +4 -1
- package/engine/literature-works.mjs +21 -13
- package/engine/map-graphviz.mjs +4 -18
- package/engine/markdown-expressions.mjs +116 -11
- package/engine/metadata-index.mjs +26 -0
- package/engine/near-miss.mjs +90 -0
- package/engine/note-addresses.mjs +75 -19
- package/engine/note-dates.mjs +5 -3
- package/engine/note-event-terms.mjs +364 -0
- package/engine/note-events.mjs +823 -0
- package/engine/note-vocabulary.mjs +184 -88
- package/engine/office-holders.mjs +20 -54
- package/engine/packagebuild-index.mjs +16 -1
- package/engine/pdf-build.mjs +97 -60
- package/engine/pdf-index.mjs +263 -0
- package/engine/pdf-render.mjs +47 -5
- package/engine/place-relation-terms.mjs +174 -0
- package/engine/place-relations.mjs +72 -160
- package/engine/rank-ladder.mjs +14 -41
- package/engine/reckoning-markers.mjs +2 -0
- package/engine/region-events.mjs +6 -12
- package/engine/scenes.mjs +73 -468
- package/engine/site-build.mjs +75 -101
- package/engine/site-index.mjs +3 -1
- package/engine/site-maps.mjs +43 -29
- package/engine/site-preview.mjs +40 -31
- package/engine/social-ties.mjs +2 -1
- package/engine/sql-tables.mjs +212 -9
- package/engine/standing-terms.mjs +145 -6
- package/engine/standings.mjs +37 -49
- package/engine/web-wikilinks.mjs +21 -1
- package/engine/wikilink-syntax.mjs +34 -4
- package/engine/wikilinks.mjs +27 -2
- package/engine/yaml-lint.mjs +7 -4
- package/hugo-theme/layouts/partials/infobox/entry.html +4 -1
- package/hugo-theme/layouts/partials/page-body.html +0 -3
- package/hugo-theme/static/css/style.css +25 -55
- package/package.json +1 -2
- package/packagebuild-metadata.jsonl +13 -13
- package/release.mjs +62 -4
- package/sohl/note-schemas.mjs +8 -73
- package/types/engine/address-values.d.mts +50 -3
- package/types/engine/address.d.mts +21 -0
- package/types/engine/anchors.d.mts +49 -2
- package/types/engine/art-slots.d.mts +1 -1
- package/types/engine/base-compiler.d.mts +13 -4
- package/types/engine/calendar-notes.d.mts +7 -0
- package/types/engine/content-format.d.mts +52 -0
- package/types/engine/content-images.d.mts +5 -1
- package/types/engine/content-tables.d.mts +9 -1
- package/types/engine/data-keys.d.mts +145 -0
- package/types/engine/derived-sections.d.mts +73 -0
- package/types/engine/diagnostics.d.mts +15 -0
- package/types/engine/event-fields.d.mts +99 -0
- package/types/engine/event-rows.d.mts +12 -0
- package/types/engine/event-views.d.mts +67 -0
- package/types/engine/exported-scene.d.mts +5 -2
- package/types/engine/frontmatter-lint.d.mts +3 -3
- package/types/engine/generated-sections.d.mts +143 -0
- package/types/engine/holdings.d.mts +6 -20
- package/types/engine/ids.d.mts +15 -12
- package/types/engine/index.d.mts +1 -1
- package/types/engine/infobox.d.mts +13 -3
- package/types/engine/journals.d.mts +24 -11
- package/types/engine/literature-works.d.mts +1 -2
- package/types/engine/map-graphviz.d.mts +2 -10
- package/types/engine/markdown-expressions.d.mts +12 -3
- package/types/engine/near-miss.d.mts +42 -0
- package/types/engine/note-addresses.d.mts +7 -1
- package/types/engine/note-event-terms.d.mts +68 -0
- package/types/engine/note-events.d.mts +71 -0
- package/types/engine/note-vocabulary.d.mts +37 -8
- package/types/engine/office-holders.d.mts +3 -0
- package/types/engine/pdf-index.d.mts +35 -0
- package/types/engine/pdf-render.d.mts +8 -2
- package/types/engine/place-relation-terms.d.mts +83 -0
- package/types/engine/place-relations.d.mts +11 -66
- package/types/engine/rank-ladder.d.mts +2 -0
- package/types/engine/region-events.d.mts +6 -12
- package/types/engine/scenes.d.mts +6 -32
- package/types/engine/site-build.d.mts +8 -22
- package/types/engine/site-maps.d.mts +15 -7
- package/types/engine/sql-tables.d.mts +77 -2
- package/types/engine/standing-terms.d.mts +37 -4
- package/types/engine/standings.d.mts +14 -9
- package/types/engine/wikilink-syntax.d.mts +20 -0
- package/types/engine/wikilinks.d.mts +3 -2
- package/types/engine/yaml-lint.d.mts +5 -4
- package/types/release.d.mts +4 -0
- package/docs/guides/government-migration.md +0 -52
- package/engine/itinerary-scenes.mjs +0 -166
- package/engine/lore-events.mjs +0 -197
- package/engine/map-notes.mjs +0 -1309
- package/engine/map-raster.mjs +0 -51
- package/hugo-theme/layouts/partials/holdings/entry.html +0 -21
- package/hugo-theme/layouts/partials/holdings/kind-groups.html +0 -71
- package/hugo-theme/layouts/partials/holdings.html +0 -61
- package/hugo-theme/layouts/partials/literature-works.html +0 -29
- package/hugo-theme/layouts/partials/place-map.html +0 -9
- package/types/engine/itinerary-scenes.d.mts +0 -29
- package/types/engine/lore-events.d.mts +0 -14
- package/types/engine/map-notes.d.mts +0 -297
- package/types/engine/map-raster.d.mts +0 -8
|
@@ -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 leading caption
|
|
40
|
+
A leading caption gives its item a JournalEntryPage of its own in Foundry, and the body after the item resumes on a continuation of the surrounding section. 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
|
|
|
@@ -59,7 +59,7 @@ The section runs from that heading to the next heading that opens a page. In Fou
|
|
|
59
59
|
|
|
60
60
|
**On the website this is a spoiler, not access control.** The withheld section is in the published page, so anyone who opens the element or reads the page source reads it. Foundry is the only surface that withholds anything. Write nothing in a `.secret` section that would matter if a player read it on the web.
|
|
61
61
|
|
|
62
|
-
A `:::secret` block inside the section is legal and renders as it does anywhere else. `.secret` on a heading that opens no page — a lower-level heading with no anchor — covers no page, and is reported at its own line: give that heading an anchor, or raise it to the top level.
|
|
62
|
+
A captioned item inside the section is withheld with it: in Foundry the item's own page, and the page that resumes the section after it, are the GM's alone. A `:::secret` block inside the section is legal and renders as it does anywhere else. `.secret` on a heading that opens no page — a lower-level heading with no anchor — covers no page, and is reported at its own line: give that heading an anchor, or raise it to the top level.
|
|
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
|
|
|
@@ -98,9 +98,9 @@ Each numbered type has its own counter. Websites and Foundry number within a not
|
|
|
98
98
|
|
|
99
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.
|
|
100
100
|
|
|
101
|
-
Foundry gives a captioned item its
|
|
101
|
+
Foundry gives a captioned item a JournalEntryPage holding the item alone, named for its number or, unnumbered, for the caption's visible text — links and emphasis reduced to the words a reader sees. A solitary image with a plain caption can use an image page; captions with inline markup and other items use text pages. The body after the item resumes on a continuation page carrying the interrupted section's name, level and classes, with its title hidden; nothing is emitted when the next page begins straight after the item. On the website and in the book the item stays in the flow of the surrounding page.
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
To caption a group or passage, put it inside a generic fenced div and caption that div, with an explicit type where the inferred one does not fit.
|
|
104
104
|
|
|
105
105
|
## Images and protected content
|
|
106
106
|
|
|
@@ -168,8 +168,6 @@ Attributes follow the marker and apply to the alert:
|
|
|
168
168
|
|
|
169
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
170
|
|
|
171
|
-
Migrate former info blocks to `[!NOTE]` alerts and warn blocks to `[!WARNING]` alerts. The old named fences are errors. `:::secret` remains supported.
|
|
172
|
-
|
|
173
171
|
### Secret blocks
|
|
174
172
|
|
|
175
173
|
`:::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**:
|
|
@@ -244,7 +242,7 @@ The lantern marks the shore.
|
|
|
244
242
|
```
|
|
245
243
|
````
|
|
246
244
|
|
|
247
|
-
This uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. Use `:` for a caption without a number.
|
|
245
|
+
This uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. Use `:` for a caption without a number.
|
|
248
246
|
|
|
249
247
|
## Footnotes and definition lists
|
|
250
248
|
|
|
@@ -311,14 +309,108 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
|
|
|
311
309
|
|
|
312
310
|
### What a query can read
|
|
313
311
|
|
|
314
|
-
| Relation | What it holds
|
|
315
|
-
| ----------------- |
|
|
316
|
-
| `notes` | Every note except a stub. This is the one to use unless a stub is wanted.
|
|
317
|
-
| `entries` | Every note, stubs included.
|
|
318
|
-
| `
|
|
319
|
-
|
|
|
312
|
+
| Relation | What it holds |
|
|
313
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
314
|
+
| `notes` | Every note except a stub. This is the one to use unless a stub is wanted. |
|
|
315
|
+
| `entries` | Every note, stubs included. |
|
|
316
|
+
| `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
|
|
317
|
+
| `market` | The market scale as three columns — `value`, `name`, `trade` — so a table can print `village` beside the number a note wrote. |
|
|
318
|
+
| `<package>.notes` | The same relations — `notes`, `entries` and `events` — for each package this one declares a dependency on, in a schema named for it. |
|
|
319
|
+
|
|
320
|
+
Nested frontmatter is addressed exactly as a note writes it: `name.full`, `sohl.weight`, `data.born`. Every Address is a string — the full canonical Address, as in `list_contains(data.parents, 'thalorna-note-place-xerathia')` — whichever package published it. Every note carries a computed `state` column of `full`, `draft` or `stub`. Notes tagged `gm` are absent from the relations on public surfaces.
|
|
321
|
+
|
|
322
|
+
### Sections the build adds
|
|
323
|
+
|
|
324
|
+
The build adds sections to the end of a note, after everything you wrote, listing what other notes say about it. Each appears only where it has something to list, under a fixed anchor:
|
|
325
|
+
|
|
326
|
+
| Section | Anchor | Lists |
|
|
327
|
+
| ----------------- | ---------------- | -------------------------------------------------------------------- |
|
|
328
|
+
| Within | `within` | on a place, the places whose `parents` name it, grouped by kind |
|
|
329
|
+
| Governed by | `governedby` | on a place, the affiliation its `government` names |
|
|
330
|
+
| Governed places | `governedplaces` | on an affiliation, the places naming it as their `government` |
|
|
331
|
+
| In song and story | `insongandstory` | the works of literature whose `subjects` name the note or its events |
|
|
332
|
+
| From here | `fromhere` | on a place with borders or routes, the map drawn from it |
|
|
333
|
+
|
|
334
|
+
The event sections below sit among them, and the [format reference](../reference/format-details.md#generated-sections) gives the order. Each entry links to the note it names; a note with no page of its own is named in plain text. Replace a section the way you replace an event view, by writing your own with the same anchor:
|
|
335
|
+
|
|
336
|
+
```markdown
|
|
337
|
+
# Within {#within}
|
|
338
|
+
|
|
339
|
+
The vale holds three villages, of which only [[place-ford|Ford]] is walled.
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Sections the build adds about events
|
|
343
|
+
|
|
344
|
+
A note's events are listed for you on the notes they concern: a place gets a **Chronology** of what happened there and below it, with every `depth: world` event as context, a being, affiliation or people the **Events** it took part in, an affiliation, place or people the **Accounts** it gives, and a note holding events **What followed** them. Each is a section appended after everything you wrote, with a fixed anchor — `chronology`, `events`, `accounts`, `followed` — and it appears only where it has something to list.
|
|
345
|
+
|
|
346
|
+
To replace one, write the section yourself with the same anchor. The build then adds nothing for it and leaves yours exactly as written:
|
|
347
|
+
|
|
348
|
+
````markdown
|
|
349
|
+
# Chronology {#chronology}
|
|
350
|
+
|
|
351
|
+
The fells keep no reckoning before the raising.
|
|
352
|
+
|
|
353
|
+
```sql
|
|
354
|
+
SELECT summary AS "What happened", "when" AS "When"
|
|
355
|
+
FROM events
|
|
356
|
+
WHERE list_contains("where".locus, 'thalorna-note-place-ironfells')
|
|
357
|
+
ORDER BY whenSort
|
|
358
|
+
```
|
|
359
|
+
````
|
|
360
|
+
|
|
361
|
+
The [format reference](../reference/format-details.md#event-views) lists what each view selects.
|
|
362
|
+
|
|
363
|
+
### A century view
|
|
364
|
+
|
|
365
|
+
A view of what happened in one century is a fence an author writes, on whatever note should carry it. Filter `events` on `whenYear`, leave out events of local reach, and order by `whenSort`:
|
|
366
|
+
|
|
367
|
+
````markdown
|
|
368
|
+
# The Third Century {#third-century}
|
|
369
|
+
|
|
370
|
+
```sql
|
|
371
|
+
SELECT note AS _ref,
|
|
372
|
+
summary AS "What happened",
|
|
373
|
+
"when" AS "When",
|
|
374
|
+
array_to_string("where".locus, ', ') AS "Where"
|
|
375
|
+
FROM events
|
|
376
|
+
WHERE whenYear BETWEEN 200 AND 299
|
|
377
|
+
AND depth <> 'local'
|
|
378
|
+
ORDER BY whenSort, address
|
|
379
|
+
```
|
|
380
|
+
````
|
|
381
|
+
|
|
382
|
+
Each row is one event, linked to the note that records it, with its date as the note wrote it and the Addresses of the places it happened at:
|
|
383
|
+
|
|
384
|
+
| What happened | When | Where |
|
|
385
|
+
| -------------------------------------------------- | ---- | -------------------------------------------------- |
|
|
386
|
+
| [Ironfells is sacked.](/thalorna/place-ironfells/) | ~280 | thalorna-note-place-ironfells |
|
|
387
|
+
| [The fords are bridged.](/thalorna/lore-fords/) | ~291 | thalorna-note-place-east, thalorna-note-place-west |
|
|
388
|
+
|
|
389
|
+
`depth <> 'local'` also leaves out an event that states no `depth`; write `depth IS DISTINCT FROM 'local'` to keep those. `whenYear` is the year on the canonical axis, which counts a year `0` that written dates skip: a year written after zero keeps its number, and one written before zero sits one higher. So `whenYear BETWEEN -299 AND -200` selects the events written `-300` to `-201`.
|
|
390
|
+
|
|
391
|
+
To print each place by its name rather than its Address, join `notes` on the place's Address. The `GROUP BY` keeps one row per event when it happened in several places:
|
|
392
|
+
|
|
393
|
+
````markdown
|
|
394
|
+
```sql
|
|
395
|
+
SELECT e.note AS _ref,
|
|
396
|
+
e.summary AS "What happened",
|
|
397
|
+
e."when" AS "When",
|
|
398
|
+
string_agg(p.name.full, ', ') AS "Where"
|
|
399
|
+
FROM events e
|
|
400
|
+
LEFT JOIN notes p ON list_contains(e."where".locus, p.address.canonical)
|
|
401
|
+
WHERE e.whenYear BETWEEN 200 AND 299
|
|
402
|
+
AND e.depth <> 'local'
|
|
403
|
+
GROUP BY e.note, e.address, e.summary, e."when", e.whenSort
|
|
404
|
+
ORDER BY e.whenSort, e.address
|
|
405
|
+
```
|
|
406
|
+
````
|
|
407
|
+
|
|
408
|
+
| What happened | When | Where |
|
|
409
|
+
| -------------------------------------------------- | ---- | ---------- |
|
|
410
|
+
| [Ironfells is sacked.](/thalorna/place-ironfells/) | ~280 | Ironfells |
|
|
411
|
+
| [The fords are bridged.](/thalorna/lore-fords/) | ~291 | East, West |
|
|
320
412
|
|
|
321
|
-
|
|
413
|
+
An event with no `where.locus` keeps its row with an empty **Where** cell.
|
|
322
414
|
|
|
323
415
|
### Fence attributes
|
|
324
416
|
|
|
@@ -418,24 +510,48 @@ There are {{words (sql "SELECT COUNT(*) FROM notes WHERE type = 'being'")}} bein
|
|
|
418
510
|
|
|
419
511
|
<!-- expression-helpers:start -->
|
|
420
512
|
|
|
421
|
-
| Helper | Parameters
|
|
422
|
-
| ------------ |
|
|
423
|
-
| `eq` | `a b`
|
|
424
|
-
| `gt` | `a b`
|
|
425
|
-
| `gte` | `a b`
|
|
426
|
-
| `lt` | `a b`
|
|
427
|
-
| `lte` | `a b`
|
|
428
|
-
| `not` | `value`
|
|
429
|
-
| `and` | `value …`
|
|
430
|
-
| `or` | `value …`
|
|
431
|
-
| `words` | `number`
|
|
432
|
-
| `digits` | `number`
|
|
433
|
-
| `sql` | `"query"`
|
|
434
|
-
| `dateformat` | `calendar date ["format"]`
|
|
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. |
|
|
513
|
+
| Helper | Parameters | What it gives you |
|
|
514
|
+
| ------------ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
515
|
+
| `eq` | `a b` | True when both are the same value. Compares exactly, so 1 and "1" differ. |
|
|
516
|
+
| `gt` | `a b` | True when a is greater than b. Both must be finite numbers. |
|
|
517
|
+
| `gte` | `a b` | True when a is greater than or equal to b. Both must be finite numbers. |
|
|
518
|
+
| `lt` | `a b` | True when a is less than b. Both must be finite numbers. |
|
|
519
|
+
| `lte` | `a b` | True when a is less than or equal to b. Both must be finite numbers. |
|
|
520
|
+
| `not` | `value` | True when the value is false, zero, empty or absent. |
|
|
521
|
+
| `and` | `value …` | True when every value given is true. Takes two or more. |
|
|
522
|
+
| `or` | `value …` | True when any value given is true. Takes two or more. |
|
|
523
|
+
| `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. |
|
|
524
|
+
| `digits` | `number` | The number as a grouped numeral — `1200` becomes 1,200, and a fractional part is kept. |
|
|
525
|
+
| `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. |
|
|
526
|
+
| `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. |
|
|
527
|
+
| `ref` | `address [form="number"\|"full"\|"title"] \| address field="when"\|"until"\|"kind"\|"summary"\|"name"` | 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. With `field` in place of `form`, the address names an event — `"place-ironfells#sack"`, `"#sack"` on this note, or `"lore-founding"` for a note holding one event — and the reference prints that event's `when`, `until`, `kind`, `summary` or `name` as plain text, never a link; a date prints as the note format prints any date. |
|
|
436
528
|
|
|
437
529
|
<!-- expression-helpers:end -->
|
|
438
530
|
|
|
439
531
|
A helper that is given the wrong kind of value reports it rather than printing something wrong: `words` refuses a decimal, the four comparisons refuse anything that is not a finite number, and `dateformat` refuses a date it cannot resolve in the calendar it was given.
|
|
440
532
|
|
|
441
533
|
See [date rules](dates-and-calendars.md) for what `dateformat` accepts and the patterns its third argument names.
|
|
534
|
+
|
|
535
|
+
### An event's date, inline
|
|
536
|
+
|
|
537
|
+
`ref` with `field` in place of `form` prints one field of an [event](../reference/format-details.md#events) as plain text, so a sentence states a date from the one place the event records it rather than typing it a second time:
|
|
538
|
+
|
|
539
|
+
```markdown
|
|
540
|
+
Ironfells fell in {{ref "place-ironfells#sack" field="when"}}, in what the fells call {{ref "place-ironfells#sack" field="name"}}.
|
|
541
|
+
The chronicle records the founding in one line: {{ref "lore-founding" field="summary"}}
|
|
542
|
+
Our own sack was a {{ref "#sack" field="kind"}}.
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
The address names one event: `"<note>#<id>"` for an event of another note, `"#<id>"` for one of this note, or a note's Address alone when that note holds exactly one event. An event a declared dependency publishes is named by its full Address, as any cross-package link is.
|
|
546
|
+
|
|
547
|
+
| `field` | What prints |
|
|
548
|
+
| --------- | ------------------------------------------------------------------ |
|
|
549
|
+
| `when` | The event's date, as the note format prints any date — `~` is kept |
|
|
550
|
+
| `until` | The date it ended, printed the same way |
|
|
551
|
+
| `kind` | Its `kind`, such as `siege` |
|
|
552
|
+
| `summary` | Its `summary`; a link written inside it prints as its label |
|
|
553
|
+
| `name` | The first name its `names` list gives |
|
|
554
|
+
|
|
555
|
+
The value is text and never a link, on the website, in the Foundry journal and in the book alike. `field` is a quoted string, like `form`, and a reference takes one or the other.
|
|
556
|
+
|
|
557
|
+
Each of these is an error at the reference's own line and column, and the reference's text stays in the page: an address naming no note, an anchor the note does not declare, an anchor that is a heading or another `prose` anchor rather than an event, a note holding several events or none named without an `#id`, a `field` outside the five above, and a field the event does not state — `field="until"` on an event with no `until`, or `field="name"` on one with no `names`.
|
package/docs/commands.md
CHANGED
|
@@ -2451,16 +2451,14 @@ not change its viewpoint.
|
|
|
2451
2451
|
|
|
2452
2452
|
Site builds put a linked SVG in each eligible place page. PDF builds put a
|
|
2453
2453
|
vector map on its own page immediately after each selected place entry with
|
|
2454
|
-
relations.
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
`data.fixup` resolves asset Addresses into selected fields of an exported Scene;
|
|
2463
|
-
a missing path or asset is a build error.
|
|
2454
|
+
relations. The drawings are pictures for a reader; no Foundry Scene is made
|
|
2455
|
+
from them.
|
|
2456
|
+
|
|
2457
|
+
A map note is a different thing: it carries a Scene exported from Foundry under
|
|
2458
|
+
`data.scene`, on every map subtype. The pack compiler passes it through, binds
|
|
2459
|
+
pins marked `#anchor` to pages from the map note's Markdown, and applies
|
|
2460
|
+
`data.fixup`, which resolves asset Addresses into selected fields of the
|
|
2461
|
+
exported Scene; a missing path or asset is a build error.
|
|
2464
2462
|
|
|
2465
2463
|
The four drawings, any of which may be asked for in one run:
|
|
2466
2464
|
|
package/docs/configuration.md
CHANGED
|
@@ -1002,15 +1002,16 @@ site:
|
|
|
1002
1002
|
|
|
1003
1003
|
> ``package-build config: `site.search` must be a boolean.``
|
|
1004
1004
|
|
|
1005
|
-
`site.maps` is whether
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
draws
|
|
1005
|
+
`site.maps` is whether a place carries the map from it. On by default: every
|
|
1006
|
+
place that states a border or a route, or is named in one, is given a
|
|
1007
|
+
**From here** [generated section](reference/format-details.md#generated-sections)
|
|
1008
|
+
holding the map `package-build map --from` draws — the place's borders and
|
|
1009
|
+
routes, each neighbour at its bearing. The section reaches every surface: the
|
|
1010
|
+
website sets the drawing inline so every place name on it is a link to that
|
|
1011
|
+
place's page, the Foundry compile stages it into the module, and the book
|
|
1012
|
+
prints it in the place's entry. A place with no relation carries no map. The
|
|
1013
|
+
Graphviz runtime installed with package-build draws the maps. `false` gives no
|
|
1014
|
+
place the section, on any surface, and draws nothing.
|
|
1014
1015
|
|
|
1015
1016
|
```yaml
|
|
1016
1017
|
site:
|
|
@@ -1084,8 +1085,9 @@ determined by the authored content tree: a tree containing only a homepage has
|
|
|
1084
1085
|
no content pages for a book.
|
|
1085
1086
|
|
|
1086
1087
|
Each selected place with a border or route receives a dedicated full-page
|
|
1087
|
-
vector itinerary after its entry. A selected
|
|
1088
|
-
|
|
1088
|
+
vector itinerary after its entry. A selected map note prints each of its
|
|
1089
|
+
exported Scene's level backgrounds on its own page. The npm-installed Graphviz
|
|
1090
|
+
runtime draws itineraries.
|
|
1089
1091
|
|
|
1090
1092
|
```yaml
|
|
1091
1093
|
pdf:
|
package/docs/content-format.md
CHANGED
|
@@ -29,7 +29,7 @@ A nonempty note body creates one system-agnostic Foundry JournalEntry. Content b
|
|
|
29
29
|
|
|
30
30
|
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).
|
|
31
31
|
|
|
32
|
-
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.
|
|
32
|
+
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. 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).
|
|
33
33
|
|
|
34
34
|
Body extensions use braces with space-separated `key=value` attributes:
|
|
35
35
|
`![[icon-harbor|Harbor]]{float=top-left size=medium}` and an SQL fence with
|
|
@@ -88,6 +88,6 @@ The note's readable Address is `<package>-note-lore-harbor`. In prose, link to i
|
|
|
88
88
|
|
|
89
89
|
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.
|
|
90
90
|
|
|
91
|
-
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)
|
|
91
|
+
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).
|
|
92
92
|
|
|
93
93
|
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).
|
package/docs/guides/book.md
CHANGED
|
@@ -92,10 +92,9 @@ columns; a wide table outside a figure fence starts on a new page so it stays
|
|
|
92
92
|
after its introduction. A wide table inside one may float to the page top, and
|
|
93
93
|
its label stays with it. A table too tall for one page takes pages of its own.
|
|
94
94
|
A figure's number runs through the whole book in reading order, counted within
|
|
95
|
-
its own kind.
|
|
96
|
-
|
|
97
|
-
of
|
|
98
|
-
Battle and local maps print each Scene level's background on its own page.
|
|
95
|
+
its own kind. A place on a border or a route prints the map drawn from it in
|
|
96
|
+
its **From here** section, inside its own entry and nowhere else. A map note prints
|
|
97
|
+
each of its exported Scene's level backgrounds on its own landscape page.
|
|
99
98
|
The
|
|
100
99
|
[content format](../content-format.md) describes image sizes, floats, and
|
|
101
100
|
links as they are authored in notes.
|
|
@@ -106,6 +105,49 @@ and map backgrounds fit the landscape map area. An image smaller than that
|
|
|
106
105
|
target keeps its authored pixels and still fills its allotted space on the
|
|
107
106
|
page. SVG art stays vector. The build never changes authored image files.
|
|
108
107
|
|
|
108
|
+
## The index
|
|
109
|
+
|
|
110
|
+
A book that prints at least one note ends with an **Index** chapter, grouped
|
|
111
|
+
under letter headings. Nothing configures it: the build derives it from the
|
|
112
|
+
notes the book prints.
|
|
113
|
+
|
|
114
|
+
| Term | Source | Shown as |
|
|
115
|
+
| ------------------------ | --------------------- | ---------------------------------------------------------------------------------- |
|
|
116
|
+
| A note's name | `name.full` | the page of the note's entry in **bold**, then the pages of every authored mention |
|
|
117
|
+
| An alias | `name.aliases` | _see_ the note's name |
|
|
118
|
+
| An event's in-world name | `data.events[].names` | _see_ the name of the note that holds the event |
|
|
119
|
+
|
|
120
|
+
To get a term into the index, give the note a `name.full`, add an alias or an
|
|
121
|
+
event name, or link to the note from prose with a wikilink. A wikilink to a note
|
|
122
|
+
the book prints adds the page it appears on. A term mentioned several times on
|
|
123
|
+
one page lists that page once, and a note printed under more than one section
|
|
124
|
+
is listed once, with every page it occupies.
|
|
125
|
+
|
|
126
|
+
Two kinds of link add nothing:
|
|
127
|
+
|
|
128
|
+
- **Links in generated sections** such as "Within" or "Governed by". They name
|
|
129
|
+
notes the build chose rather than the author, and would add a page to nearly
|
|
130
|
+
every place and bury the authored mentions. They print the page of the note's
|
|
131
|
+
entry beside the name instead, as
|
|
132
|
+
described under [Build and inspect](#build-and-inspect).
|
|
133
|
+
- **Links to a note the book does not print.** There is no page to point to.
|
|
134
|
+
|
|
135
|
+
Terms sort on the ASCII fold the content index derives for names (`nameAscii`),
|
|
136
|
+
ignoring case, so an accented name files under its base letter and the order
|
|
137
|
+
matches the table of contents. A term that does not begin with a letter files
|
|
138
|
+
first, under `#`. An alias or event name that folds to the same text as the
|
|
139
|
+
note's own name is not listed again.
|
|
140
|
+
|
|
141
|
+
Two notes that print the same name are told apart. Each is qualified with the
|
|
142
|
+
note's subtype, or its type where it has none, as in `Ashkabel (settlement)` and
|
|
143
|
+
`Ashkabel (character)`. Where that still collides, the name of the place the
|
|
144
|
+
note is within is added: `Ashkabel (settlement, Harn)`. An alias or event name
|
|
145
|
+
that points at a qualified name prints the qualifier too.
|
|
146
|
+
|
|
147
|
+
Page numbers come from the typeset book, so they stay correct however the pages
|
|
148
|
+
reflow, and each is a link to its page in the PDF. The Index is reached from the
|
|
149
|
+
Contents and the bookmarks like any other chapter.
|
|
150
|
+
|
|
109
151
|
## Set fonts and icon fonts
|
|
110
152
|
|
|
111
153
|
The build supplies its default book fonts and searches its own font directory
|
|
@@ -152,3 +194,16 @@ a note outside the selection or another package remains a web address.
|
|
|
152
194
|
Anchors on headings are scoped to their entries, so two entries can use the
|
|
153
195
|
same heading anchor. The build reports an unresolved destination while
|
|
154
196
|
keeping the source available for inspection.
|
|
197
|
+
|
|
198
|
+
The [generated sections](../reference/format-details.md#generated-sections)
|
|
199
|
+
an entry carries — **Within**, **Governed by**, **In song and story**, the
|
|
200
|
+
event views and the rest — name notes the build chose rather than the author,
|
|
201
|
+
so their links follow their own rule, because a book is often a selection:
|
|
202
|
+
|
|
203
|
+
- A name whose note is in the book is an internal link followed by the page
|
|
204
|
+
that note's entry starts on, printed as the contents prints it:
|
|
205
|
+
`Ford (p. 12)`. The number is Typst's own, read after layout.
|
|
206
|
+
- A name whose note is not in the book is printed as plain text, with no link,
|
|
207
|
+
no page and no finding.
|
|
208
|
+
|
|
209
|
+
Links an author wrote keep the rules above and carry no page number.
|
package/docs/guides/icons.md
CHANGED
|
@@ -39,15 +39,14 @@ data:
|
|
|
39
39
|
Here `data.icon` resolves an `icon` asset and `data.tokenIcon` resolves an
|
|
40
40
|
`image` asset. A full address, such as `sohl-none-image-smith-token`, names
|
|
41
41
|
another package when that package is available to the build. `data.icon` and
|
|
42
|
-
`data.tokenIcon` default to the `icon` type; `data.
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
`data.tokenIcon` default to the `icon` type; `data.banner` defaults to
|
|
43
|
+
`image`. An explicit `image-` or `icon-` type works in any of the three
|
|
44
|
+
slots. A pathname with slashes or an extension is not an art-slot address.
|
|
45
45
|
|
|
46
46
|
| Art slot | Its use |
|
|
47
47
|
| ---------------- | ----------------------------------------------- |
|
|
48
48
|
| `data.icon` | Profile art on a compiled Actor or Item |
|
|
49
49
|
| `data.tokenIcon` | Actor token art; follows `data.icon` when unset |
|
|
50
|
-
| `data.bgImage` | Background of a map Scene |
|
|
51
50
|
| `data.banner` | Page hero image for the site |
|
|
52
51
|
|
|
53
52
|
An Item without `data.icon` uses its builder's configured default art. An
|
|
@@ -55,7 +54,7 @@ Actor without `data.icon` uses its compiled default art. Write `data.icon`
|
|
|
55
54
|
when the note needs a particular image. A portrait within the prose is an
|
|
56
55
|
image embed, for example `![[image-smith-portrait|The smith]]{size=medium}`;
|
|
57
56
|
it does not set a document's profile art. The
|
|
58
|
-
[art-slot reference](../reference/format-details.md#the-
|
|
57
|
+
[art-slot reference](../reference/format-details.md#the-art-slots) gives each
|
|
59
58
|
slot's type and document destination.
|
|
60
59
|
|
|
61
60
|
A being's `subType` selects its compiled default art: `character` and `npc`
|
package/docs/guides/packs.md
CHANGED
|
@@ -165,3 +165,9 @@ the needed output must already exist. The full compile orders those passes for
|
|
|
165
165
|
you. `package-build package unpack` reads a built pack back into JSON for
|
|
166
166
|
inspection. See the [command reference](../commands.md) for their arguments
|
|
167
167
|
and output paths.
|
|
168
|
+
|
|
169
|
+
A compile also draws the map from each place given a **From here**
|
|
170
|
+
[generated section](../reference/format-details.md#generated-sections) and
|
|
171
|
+
stages it into the module at `assets/generated/from-<shortcode>.svg`, beside
|
|
172
|
+
the compiled packs, where the section's image resolves. Each generated section
|
|
173
|
+
starts its own page of the note's journal, as any H1 does.
|
|
@@ -136,7 +136,27 @@ The index is disposable build output; regenerate it from the authored tree
|
|
|
136
136
|
when the content changes.
|
|
137
137
|
|
|
138
138
|
The record's `address.canonical` is the full Address. Its `address.slug` is a
|
|
139
|
-
local web link target.
|
|
139
|
+
local web link target. Each entry of `anchors` carries its `slug`, `name`, `line`,
|
|
140
|
+
`link` and `kind` — `prose` for an anchor the body declares, `event` for an
|
|
141
|
+
event's `id` — so a note's events are listed there beside its body anchors. A
|
|
142
|
+
dependency's events are resolved through this list and through each event's
|
|
143
|
+
resolved date under `resolvedDates.events`.
|
|
144
|
+
|
|
145
|
+
**Every Address in the file is an object**, wherever it appears — `address.canonical`,
|
|
146
|
+
`documentation`, an anchor's `link`, and every Address a note writes:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{ "address": "thalorna-note-place-xerathia", "anchor": null, "anchorKind": null }
|
|
150
|
+
{ "address": "thalorna-note-lore-crown", "anchor": "founding", "anchorKind": "event" }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`address` is the full canonical Address, `anchor` the anchor's slug or `null`,
|
|
154
|
+
and `anchorKind` its kind, `prose` or `event`, or `null`. A map keyed by
|
|
155
|
+
Address, such as a being's `affiliations`, keeps string keys: JSON keys are
|
|
156
|
+
strings, and no Address-keyed field takes an anchor. A package and every
|
|
157
|
+
package it depends on build with the same index format, since each reads the
|
|
158
|
+
others' published files. The SQL tables present each Address as a plain
|
|
159
|
+
string. A stub has `address: null` and `anchors: null`; its
|
|
140
160
|
frontmatter remains queryable. An Item or Actor note can have both a readable
|
|
141
161
|
`note` record and a game-system document destination. A generated
|
|
142
162
|
`documentation` pointer connects a system document to its readable note.
|
|
@@ -31,7 +31,7 @@ document ID appears under another address, and **withdrawn** when that ID
|
|
|
31
31
|
appears under none. Findings are warnings by default. `--strict` turns them
|
|
32
32
|
into errors for a release gate. The comparison reads shipped Item packs, so it
|
|
33
33
|
reports the surface consumers actually resolve rather than inferring changes
|
|
34
|
-
from filenames. Use the [Address reference](../
|
|
34
|
+
from filenames. Use the [Address reference](../content-format.md#addresses)
|
|
35
35
|
when choosing a durable shortcode.
|
|
36
36
|
|
|
37
37
|
## Build the release files
|
|
@@ -105,10 +105,42 @@ change is minor; an optional command, flag, or key is patch. A major bump
|
|
|
105
105
|
requires the maintainer's direct decision. `package-build changelog check`
|
|
106
106
|
checks the quality of any pending changeset.
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
The repository's primary forge is Gitea, and GitHub is its push mirror. The
|
|
109
|
+
release runs in two halves, one on each:
|
|
110
|
+
|
|
111
|
+
1. **Version, on Gitea.** Merging a changeset to `main` runs
|
|
112
|
+
`.gitea/workflows/release.yml`, which opens or updates the **Version
|
|
113
|
+
Packages** pull request. Its generated changelog section is reviewed as the
|
|
114
|
+
release note. Merging that pull request runs the same workflow again, which
|
|
115
|
+
pushes the tag `v<version>` at the merged version commit. Releasing from
|
|
116
|
+
Gitea is switched on by the repository variable `HL_RELEASE_ENABLED`.
|
|
117
|
+
2. **Publish, on GitHub.** The push mirror carries the tag to GitHub, where it
|
|
118
|
+
starts the **Publish to npm** workflow, `.github/workflows/release.yml`. It
|
|
119
|
+
refuses a tag that names a commit outside `main` or that is not
|
|
120
|
+
`v<version>` of the tagged `package.json`. When npm does not have the
|
|
121
|
+
version yet, it runs the tests and publishes through npm Trusted Publishing
|
|
122
|
+
with provenance. It then creates the GitHub Release from the version's
|
|
123
|
+
changelog section, unless one exists.
|
|
124
|
+
|
|
125
|
+
Nothing on Gitea publishes to npm, and nothing on GitHub runs for a branch
|
|
126
|
+
push. Every step of the GitHub half is safe to repeat: re-running it, or
|
|
127
|
+
dispatching it with the tag as its ref, finishes a release whose publish or
|
|
128
|
+
Release step failed and changes nothing for one that completed. The
|
|
129
|
+
[npm package page](https://www.npmjs.com/package/@heroiclands/package-build)
|
|
114
130
|
shows the published version and README.
|
|
131
|
+
|
|
132
|
+
Two scripts in this repository's own `package.json` run the same steps at a
|
|
133
|
+
desk:
|
|
134
|
+
|
|
135
|
+
- **`npm run build`** runs `package-build ci`: the Build & Test workflow's
|
|
136
|
+
`run:` steps in a `linux/amd64` container over a clean export of `HEAD`.
|
|
137
|
+
`npm run build -- --native` runs them on the host in the working tree instead.
|
|
138
|
+
Off Linux, the Typst, GraphViz and Hugo steps install nothing; each uses the
|
|
139
|
+
tool already on `PATH` and stops with `<tool> is not on PATH` when it is
|
|
140
|
+
missing, so a Mac running `--native` needs `typst`, `dot` and Hugo extended
|
|
141
|
+
installed first.
|
|
142
|
+
- **`npm run deploy:npm`** runs `npm publish`. Provenance is attested only on a
|
|
143
|
+
CI runner that can mint a Sigstore identity — GitHub Actions with an OIDC
|
|
144
|
+
token, or GitLab CI with `SIGSTORE_ID_TOKEN` — and anywhere else the publish
|
|
145
|
+
goes ahead without it. Arguments after `--` reach `npm publish`, so
|
|
146
|
+
`npm run deploy:npm -- --dry-run` lists the tarball without publishing.
|