@heroiclands/package-build 25.5.4 → 25.6.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 (108) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +7 -0
  3. package/assets/styles/content-base.css +1 -1
  4. package/bin/content-commands.mjs +32 -8
  5. package/docs/api.md +81 -32
  6. package/docs/authoring/frontmatter.md +1 -1
  7. package/docs/authoring/links-and-markup.md +59 -10
  8. package/docs/commands.md +60 -17
  9. package/docs/configuration.md +3 -2
  10. package/docs/content-format.md +50 -1
  11. package/docs/diagnostics.md +17 -0
  12. package/docs/guides/module-project.md +11 -3
  13. package/docs/guides/reference-pages.md +4 -1
  14. package/docs/guides/site.md +13 -3
  15. package/docs/guides/writing-in-invented-scripts.md +5 -2
  16. package/docs/reference/format-details.md +233 -138
  17. package/docs/reference/note-types.md +165 -152
  18. package/docs/reference/theme-pages.md +1 -0
  19. package/e2e.mjs +1 -1
  20. package/engine/base-compiler.mjs +2 -0
  21. package/engine/compile-corpus.mjs +6 -2
  22. package/engine/content-charset.mjs +1 -1
  23. package/engine/content-format.yaml +9 -7
  24. package/engine/content-html.mjs +3 -2
  25. package/engine/content-index.mjs +23 -0
  26. package/engine/content-links.mjs +8 -0
  27. package/engine/content-render.mjs +14 -2
  28. package/engine/content-scripts.mjs +44 -6
  29. package/engine/content-session.mjs +11 -7
  30. package/engine/content-spans.mjs +3 -4
  31. package/engine/content-tables.mjs +12 -5
  32. package/engine/content-verse.mjs +52 -10
  33. package/engine/core-report.mjs +27 -18
  34. package/engine/culture-reach.mjs +3 -0
  35. package/engine/declared-sections.mjs +100 -0
  36. package/engine/derived-sections.mjs +36 -2
  37. package/engine/dictionary-rows.mjs +2 -1
  38. package/engine/generated-sections.mjs +2 -0
  39. package/engine/holdings.mjs +107 -3
  40. package/engine/index-records.mjs +3 -1
  41. package/engine/index.mjs +1 -1
  42. package/engine/language-data.mjs +0 -1
  43. package/engine/language-names.mjs +53 -23
  44. package/engine/language-rows.mjs +1 -3
  45. package/engine/language-terms.mjs +7 -10
  46. package/engine/map-dot.mjs +22 -0
  47. package/engine/markdown-blocks.mjs +23 -8
  48. package/engine/markdownlint-run.mjs +1 -1
  49. package/engine/markup-validation.mjs +2 -0
  50. package/engine/metadata-index.mjs +1 -0
  51. package/engine/note-addresses.mjs +16 -0
  52. package/engine/note-vocabulary.mjs +29 -13
  53. package/engine/npc-generate.mjs +52 -7
  54. package/engine/office-holders.mjs +76 -0
  55. package/engine/page-breaks.mjs +143 -0
  56. package/engine/pdf-build.mjs +12 -4
  57. package/engine/pdf-render.mjs +12 -2
  58. package/engine/place-kinds.mjs +106 -0
  59. package/engine/preview-index.mjs +4 -2
  60. package/engine/settlement-tables.mjs +410 -675
  61. package/engine/settlement-terms.mjs +118 -0
  62. package/engine/site-build.mjs +14 -7
  63. package/engine/site-preview.mjs +3 -0
  64. package/engine/site-render.mjs +18 -4
  65. package/engine/site-root.mjs +10 -1
  66. package/engine/site-serve-http.mjs +151 -0
  67. package/engine/site-serve.mjs +196 -126
  68. package/engine/sql-tables.mjs +101 -7
  69. package/engine/standing-terms.mjs +9 -5
  70. package/engine/standings.mjs +83 -31
  71. package/engine/unique-items.mjs +85 -0
  72. package/engine/verse-metre.mjs +50 -5
  73. package/engine/verse-regions.mjs +16 -0
  74. package/package.json +9 -4
  75. package/site-theme/data/banner-kinds.yaml +2 -0
  76. package/sohl/actors.mjs +4 -3
  77. package/types/e2e.d.mts +1 -1
  78. package/types/engine/content-html.d.mts +2 -1
  79. package/types/engine/content-scripts.d.mts +9 -1
  80. package/types/engine/content-verse.d.mts +11 -2
  81. package/types/engine/core-report.d.mts +6 -2
  82. package/types/engine/culture-reach.d.mts +3 -0
  83. package/types/engine/declared-sections.d.mts +30 -0
  84. package/types/engine/derived-sections.d.mts +5 -1
  85. package/types/engine/holdings.d.mts +34 -2
  86. package/types/engine/index-records.d.mts +2 -1
  87. package/types/engine/language-names.d.mts +18 -6
  88. package/types/engine/language-terms.d.mts +5 -1
  89. package/types/engine/markdown-blocks.d.mts +5 -1
  90. package/types/engine/npc-generate.d.mts +3 -0
  91. package/types/engine/office-holders.d.mts +33 -0
  92. package/types/engine/page-breaks.d.mts +38 -0
  93. package/types/engine/pdf-render.d.mts +2 -0
  94. package/types/engine/place-kinds.d.mts +18 -0
  95. package/types/engine/settlement-tables.d.mts +25 -158
  96. package/types/engine/settlement-terms.d.mts +53 -0
  97. package/types/engine/site-build.d.mts +3 -1
  98. package/types/engine/site-render.d.mts +6 -2
  99. package/types/engine/site-root.d.mts +3 -1
  100. package/types/engine/site-serve-http.d.mts +1 -0
  101. package/types/engine/site-serve.d.mts +12 -6
  102. package/types/engine/sql-tables.d.mts +35 -3
  103. package/types/engine/standing-terms.d.mts +3 -2
  104. package/types/engine/standings.d.mts +14 -2
  105. package/types/engine/unique-items.d.mts +12 -0
  106. package/types/engine/verse-metre.d.mts +2 -1
  107. package/types/engine/verse-regions.d.mts +8 -0
  108. package/vendor/markdownlint.mjs +855 -569
package/docs/commands.md CHANGED
@@ -2255,11 +2255,12 @@ dependencies; exact Item UUID validation remains part of compilation. Reads
2255
2255
  the content tree named by `root`, defaulting to
2256
2256
  `paths.content`; writes nothing.
2257
2257
 
2258
- Every configured language note declares `data.roman`, its exact NFC Roman
2259
- source characters. Lint checks language-tagged text before mapping, using the
2258
+ Every configured language note declares `data.roman`, the NFC Roman characters
2259
+ the language adds to the shared standard: letters in accepted cases, accents,
2260
+ catch signs and digits. Lint checks language-tagged text before mapping, using the
2260
2261
  same inventory for a configured name and its BCP 47 tag. Visible linked labels
2261
2262
  are checked; destinations, attributes and verse structure are excluded. An
2262
- explicit empty inventory declares no written characters. External tags without
2263
+ explicit empty inventory declares no additions. External tags without
2263
2264
  a language-note association retain their ordinary behavior. Standalone
2264
2265
  `package-build markdown` does not load these inventories.
2265
2266
 
@@ -2698,6 +2699,11 @@ links, tables, expressions, generated sections, maps — and rendered by the
2698
2699
  same renderer the Foundry journals and the editor preview use, then drawn by
2699
2700
  the site theme's layouts.
2700
2701
 
2702
+ Progress goes to stdout as each phase starts: indexing content, rendering
2703
+ pages, writing pages, and building the search index. Rendering and writing
2704
+ include page counts; the search summary gives the number indexed. Diagnostics
2705
+ remain on stderr in `file:line:column: severity: message` form.
2706
+
2701
2707
  **A site is its homepage and its pages.** The `type: homepage` note is the
2702
2708
  package's front page at `/<contentPackage>/`; every other note is one page at
2703
2709
  `/<contentPackage>/<type>-<shortcode>/`. Nothing is generated between them
@@ -2770,8 +2776,12 @@ findings of severity `warning` included.
2770
2776
 
2771
2777
  ```
2772
2778
  $ package-build site build
2779
+ […] indexing content
2780
+ […] rendering 4306 page(s)
2781
+ […] writing 4306 page(s)
2773
2782
  package-build.config.yaml:38:24: warning: the page-not-found links to /thalorna/polity/, which the site does not publish, so the link is left out
2774
2783
  […] wrote 4306 page(s) to build/site/thalorna
2784
+ […] building the search index
2775
2785
  […] indexed 4307 page(s) for search into build/site/thalorna/pagefind
2776
2786
  ```
2777
2787
 
@@ -2794,13 +2804,25 @@ package-build site serve [--port <port>] [--host <address>] [--out <dir>]
2794
2804
 
2795
2805
  **DESCRIPTION**
2796
2806
 
2797
- Builds the site as `package-build site build` does, indexes it for search once,
2798
- and serves the deployed directory over HTTP, so every page is at the address it
2807
+ Starts HTTP and prints the listening address before the first build begins.
2808
+ Builds the site as `package-build site build` does and indexes it for search,
2809
+ while serving the deployed directory, so every page is at the address it
2799
2810
  is deployed at: `http://127.0.0.1:1313/<contentPackage>/`, or the path
2800
2811
  `site.base` states. An address the site does not publish is answered with its
2801
2812
  `404.html`. A search index `site.mergeIndexes` names is not served, since it is
2802
2813
  another site's; the site's own index is.
2803
2814
 
2815
+ Existing output stays available while a whole build runs. Incremental page and
2816
+ theme updates also prepare their files separately before replacing the served
2817
+ tree, so requests receive complete pages and styles. The new pages and
2818
+ search index replace it together after a successful build. A failed render,
2819
+ font delivery or search build leaves the previous site available. Without
2820
+ existing output, requests receive HTTP 503 with a message pointing to the
2821
+ terminal until a build succeeds; reload the page after the build completes.
2822
+ The build's indexing, rendering, writing and search phases print to stdout,
2823
+ with page counts where available. Diagnostics keep their located format on
2824
+ stderr. Whole rebuilds also refresh the search index.
2825
+
2804
2826
  The content tree and the theme are watched. A change to a note's body or
2805
2827
  frontmatter writes that note's page again; a note whose name, type or
2806
2828
  shortcode changed, a new or removed note, a note holding an `sql` table, and
@@ -2825,15 +2847,21 @@ running. Interrupt it to stop.
2825
2847
 
2826
2848
  **EXIT STATUS**
2827
2849
 
2828
- 1 when the site's settings or its cached menu cannot be read. Otherwise 0 once
2829
- interrupted.
2850
+ 1 when the site's settings or its cached menu cannot be read, or HTTP cannot
2851
+ start or stops unexpectedly. Build failures are reported while the server keeps running. Otherwise
2852
+ 0 once interrupted.
2830
2853
 
2831
2854
  **EXAMPLES**
2832
2855
 
2833
2856
  ```
2834
2857
  $ package-build site serve
2835
- […] built the site
2836
2858
  […] serving http://127.0.0.1:1313/thalorna/ — interrupt to stop
2859
+ […] indexing content
2860
+ […] rendering 4306 page(s)
2861
+ […] writing 4306 page(s)
2862
+ […] building the search index
2863
+ […] indexed 4307 page(s) for search
2864
+ […] built the site
2837
2865
  […] wrote build/site/thalorna/place-vedyara/index.html
2838
2866
  ```
2839
2867
 
@@ -3389,17 +3417,20 @@ reads the words of its `data.family` chain as its own. The languages are listed
3389
3417
  by name; each block gives the number missing, then the missing concepts under
3390
3418
  their groups in list order, each group with its count, each concept as its `id`
3391
3419
  and `gloss` separated by a tab. A language with no concept missing is reported as
3392
- covering them all. Writes nothing.
3420
+ covering them all. The default report ends with `Not covered (no data.core): …`,
3421
+ naming language notes without `data.core: true` in name order, when any exist.
3422
+ An explicit `--language` measures only the requested language and prints no
3423
+ skip line. Writes nothing.
3393
3424
 
3394
3425
  A missing concept is a fact to work through, never a finding, so the report does
3395
3426
  not change the exit status.
3396
3427
 
3397
3428
  **OPTIONS**
3398
3429
 
3399
- | Option | Type | Default | Description |
3400
- | ------------ | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3401
- | `--language` | string | — | Report this language alone, by its name, its shortcode or its reference, whether or not it states `data.core`. |
3402
- | `--json` | boolean | `false` | Print `{ concepts, languages }` instead, each language `{ name, language, core, total, covered, missing }` and each missing group `{ group, count, total, concepts }`. |
3430
+ | Option | Type | Default | Description |
3431
+ | ------------ | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3432
+ | `--language` | string | — | Report this language alone, by its name, its shortcode or its reference, whether or not it states `data.core`. |
3433
+ | `--json` | boolean | `false` | Print `{ concepts, notCovered, languages }` instead; `notCovered` lists unmeasured language names (empty with `--language`), each language `{ name, language, core, total, covered, missing }` and each missing group `{ group, count, total, concepts }`. |
3403
3434
 
3404
3435
  **EXIT STATUS**
3405
3436
 
@@ -3505,7 +3536,7 @@ exactly as given, at every depth, and every field it leaves out is generated:
3505
3536
 
3506
3537
  | Field | Generated value |
3507
3538
  | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
3508
- | `name.full` | Drawn from the culture's language's name lists by one of its patterns for `data.gender`, the given name from the list for that gender. |
3539
+ | `name.full` | Drawn by a pattern for `data.gender`; given names use the shared or gendered list, and drawn words start with capitals. |
3509
3540
  | `shortcode` | The name transliterated to lowercase letters and digits and cut to twelve characters; a counter replaces its tail where a being holds it. |
3510
3541
  | `type`, `subType`, `tags` | `being`, `npc`, `[generated, draft]`. |
3511
3542
  | `data.icon`, `data.species`, `data.packFolder` | The commonest value among the package's npcs of the same culture, else among all its npcs; left out where none states one. |
@@ -3549,13 +3580,25 @@ cycle. See [culture parents](reference/format-details.md#culture-parents-and-inh
3549
3580
 
3550
3581
  A profile or name lists with problems are refused with a finding at each.
3551
3582
 
3583
+ Generated `name.full` is the English display form: each word drawn from a name
3584
+ list starts with a capital, while its remaining letters and the pattern's
3585
+ connecting words keep their authored case. A caseless tongue can therefore
3586
+ supply `lumawesa` and `simi manik` to produce `Lumawesa of the Simi Manik`.
3587
+ The distinct source form keeps its authored spelling under the culture's language code,
3588
+ such as `name: {full: Lumawesa of the Simi Manik, teyu: [lumawesa of the simi manik]}`.
3589
+ If the selected pattern draws any English `{en.*}` part, the command omits
3590
+ the generated native alias. An unused English pattern does not affect a name
3591
+ drawn from another pattern.
3592
+ Supplied names and language forms keep their exact spelling and case.
3593
+
3552
3594
  A spec that states `name.full` keeps it, and the name must fit the language's
3553
- lists: one of the patterns for `data.gender`, with every placeholder filled by
3595
+ source or English display lists: one of the patterns for `data.gender`, with every placeholder filled by
3554
3596
  a name of its list, the given name from the list for `data.gender`. A name that does not fit is an
3555
3597
  error naming the part that fails and the language it was checked against; from
3556
3598
  a `--specfile`, the error is located at the name in the file. Where the
3557
- gender has no given list of its own, the given name is drawn from, and
3558
- checked against, every given list together.
3599
+ language states one shared `given` list, every gender draws from and is checked
3600
+ against it. With a gender map, a gender with no list of its own draws from and
3601
+ is checked against every given list together.
3559
3602
 
3560
3603
  Two top-level spec keys are section bodies rather than frontmatter.
3561
3604
  `appearance` is the Appearance section's markdown, written verbatim with its
@@ -2307,8 +2307,9 @@ the source directory:
2307
2307
 
2308
2308
  Optional path for a browser converter's JSON data, relative to
2309
2309
  `packageBuild.stageDir`. `package-build manifest` writes it during the module
2310
- build from the same published encodings and language vocabulary that render
2311
- native text. The path must stay within the stage, end in `.json`, and name an
2310
+ build from the same consumer-authored encoding notes, selected fonts' glyph
2311
+ metadata and language vocabulary that render native text. The path must stay
2312
+ within the stage, end in `.json`, and name an
2312
2313
  artifact other than `module.json`, `system.json` or `package.json`. Absolute
2313
2314
  paths and parent traversal are refused. Omission writes no converter file.
2314
2315
 
@@ -27,10 +27,20 @@ Start with [your first note](authoring/first-note.md). It explains the smallest
27
27
 
28
28
  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. Each page name is its heading's visible text: spans, links and emphasis contribute their text without their markup. 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.
29
29
 
30
+ A top-level `--- {.page-break}` line between blank lines starts a fresh book page
31
+ without drawing a rule, and adds no blank page when it already falls at a page
32
+ top. Foundry, the website and both editor preview views omit it. Plain thematic
33
+ breaks remain rules; code and verse keep the marker literally. Other
34
+ attributes, star or underscore markers, and markers inside containers are
35
+ findings. See [book page breaks](authoring/links-and-markup.md#book-page-breaks).
36
+
30
37
  Leading `:` captions describe the next supported block; `:@` captions also number it. The optional type accepts `figure`, `table`, `verse`, `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
38
 
32
39
  A `.verse` div (`::: {.verse ...}` or `:::verse {...}`) sets poetry or prose. `/` ends a logical line; source newlines
33
40
  otherwise join. Blank lines or `//` end stanzas, and a standalone `--- {.canto}` after a blank line ends a canto.
41
+ Blockquotes and list items may contain verse divs, including nested combinations.
42
+ Their container prefixes are excluded from verse text, while findings retain
43
+ authored line and column positions with either LF or CRLF endings.
34
44
  Leading periods indent a logical line, including after `/` within a source line;
35
45
  a period on a joined continuation line is text. `\/` writes a literal slash.
36
46
  A concrete `enc=` on a div sets the original once in two presentations, script on the left
@@ -86,6 +96,8 @@ markers scoped to each note. Definition lists use a term followed by one or
86
96
  more `: definition` lines. See [footnotes and definition lists](authoring/links-and-markup.md#footnotes-and-definition-lists)
87
97
  for examples and placement in journals, web pages, and books.
88
98
 
99
+ A query selects notes by property, tag or address, never by where a note's file sits: a fence that names `file.path`, `file.folder` or `file.name` is an error at the reference, and a note moved between folders changes no query's answer.
100
+
89
101
  An inline `{{sql "SELECT COUNT(*) FROM notes"}}` expression inserts one scalar query result. Use `{{words (sql "SELECT COUNT(*) FROM notes")}}` for a count in running prose, or `{{digits (sql "SELECT COUNT(*) FROM entries")}}` for grouped numerals. The query must return exactly one row and one column with a nonempty value; a mismatch is a located build error. Prefix `\{{` to show the syntax literally. The [expression reference](reference/format-details.md#dates-and-calendars) describes the helpers and the available SQL relations.
90
102
 
91
103
  Add `gm` to `tags` for a GM-only note. Public site and book builds omit it;
@@ -193,7 +205,44 @@ The [first-note guide](authoring/first-note.md) shows the build commands and how
193
205
 
194
206
  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).
195
207
 
196
- A region may list its settlements in a table under `## Settlements` — name, market, people and holder, one row each — tagged with the holding model it is written in. A row links the settlement's note where one exists, and `package-build lint` holds the two to agreement. See [a region's settlements table](reference/format-details.md#a-regions-settlements-table).
208
+ A region declares its table in `data.settlements: { rows, tail }`. The rows
209
+ carry the settlement's `population` and numeric `market`, and either `place`
210
+ (the existing note's Address, default type `place`) or `name` (plain text where
211
+ no note exists), never both. Where the region's culture holds land, a row's
212
+ optional `heldBy` names what holds it by Address (an affiliation or a being,
213
+ default type `affiliation`), and what that note is says how the land is held: a
214
+ temple, a lineage, the city, a kin group. A people who hold no land state no
215
+ `heldBy`, and their table has no Held by column. Optional `for` states why the
216
+ settlement exists. `tail` is the sentence stating what the table leaves out.
217
+
218
+ The guard reads indexed rows. A linked row's population and market agree with
219
+ its note, and every settlement note covered through `parents` has one row in
220
+ the nearest declaring region. `government` states who governs; it never supplies
221
+ who holds the land. HTML, Foundry and Typst render the declared table once.
222
+ A body table under `## Settlements` is an error at its header, naming
223
+ `data.settlements`; no facts are read from it.
224
+
225
+ ```yaml
226
+ data:
227
+ settlements:
228
+ rows:
229
+ - place: ashford
230
+ market: 4
231
+ population: 3400
232
+ heldBy: affiliation-crown
233
+ for: the ford on the drove road
234
+ - name: Weyshott
235
+ market: 2
236
+ population: 420
237
+ heldBy: being-aldwyn
238
+ for: the manor's mill
239
+ - name: Cold Hatch
240
+ market: 1
241
+ population: 60
242
+ tail: Some four hundred further villages lie in the vale, none of them named here.
243
+ ```
244
+
245
+ See [a region's settlements table](reference/format-details.md#a-regions-settlements-table).
197
246
 
198
247
  A being states its gender, frame and appearance in words from one closed vocabulary: `data.gender`, `data.frame`, and `data.appearance.eye_color`, `hair_color`, `skin_color` and `complexion` each take only the words listed for them, and any other value is an error at the value. `complexion` is a list, required once a being states an appearance. `data.appearance.extra_features` lists the being's visible physical marks, each a short plain description of one, and an entry stating a colour, a skin condition or anything that is not a mark is an error. See [a being's look](reference/format-details.md#a-beings-look).
199
248
 
@@ -297,6 +297,23 @@ Like a culture conflict, each fails the index and every command that reads it
297
297
  without collecting problems. The rules are under
298
298
  [a note's language](reference/format-details.md#a-notes-language).
299
299
 
300
+ ## Book page-break findings
301
+
302
+ The optional [book page break](authoring/links-and-markup.md#book-page-breaks)
303
+ uses only `--- {.page-break}` between blocks at the note's top level.
304
+ Other classes, ids or attributes on an attributed `---` line receive findings
305
+ at their opening brace. A `.page-break` on `***` or `___` receives a finding
306
+ at the marker. A marker inside a list, block quote, alert, footnote definition,
307
+ secret block or fenced div receives `a page break stands between blocks at the top level of a
308
+ note`, at that marker's line and column. Missing surrounding blank lines
309
+ receive the same placement finding. Code blocks and complete verse divs are
310
+ literal and receive no page-break findings.
311
+
312
+ The author lint, pack compiler, site build, both preview views and book source
313
+ generation report these errors from the same scanner. A valid marker is
314
+ omitted on screens and emits a weak page break in the book, avoiding an extra
315
+ blank page at a page top.
316
+
300
317
  ## A worked case: versions of a work
301
318
 
302
319
  [Versions of a work](authoring/links-and-markup.md#versions-and-stanza-labels)
@@ -716,13 +716,21 @@ packageBuild:
716
716
  ```
717
717
 
718
718
  `package-build manifest` writes the JSON beneath the build stage, so the
719
- release includes the data alongside the module's other files. It embeds each
720
- language's published encoding and the lexical inputs used by the build.
719
+ release includes the data alongside the module's other files. It embeds the
720
+ consumer's authored encoding definitions, the selected fonts' glyph-code
721
+ snapshots, and the language names and lexical inputs used by the build.
722
+ Conversion rules belong to the consumer's encoding notes; fonts supply the
723
+ glyphs and their metadata.
721
724
 
722
725
  Bundle `@heroiclands/package-build/convert` into the module's browser code,
723
726
  fetch `modules/<module-id>/data/converter.json` once, and pass the parsed data
724
727
  to `encode` or `decode`. A picker can list `Object.entries(data.languages)`
725
- using each entry's `name`; each entry already states its encoding and face.
728
+ using each entry's `name`. Offer the encoding documents in `data.encodings`
729
+ whose `data.language` matches the selected language, and pass the selected
730
+ document Address as `options.enc`. That document supplies its font; language
731
+ entries carry no default encoding or face. Omitting `options.enc`, or choosing
732
+ `default`, preserves Roman text. The JSON includes all conversion inputs, so
733
+ the browser fetches no separate encoding or font metadata files.
726
734
  Show the returned findings alongside the text when a word cannot be recovered.
727
735
  See the [API](../api.md#browser-conversion) and
728
736
  [data format](../reference/format-details.md#converter-data-format).
@@ -134,7 +134,10 @@ its language's code. It also has ASCII-folded `nameAscii` and `formsAscii`, the
134
134
  listed forms by language, for searching names typed without diacritics, and
135
135
  `lang`, the language the note is in, derived as
136
136
  [a note's language](../reference/format-details.md#a-notes-language) describes.
137
- A language note that `languages:` names carries its code as `languageCode`. Asset files under `assets/icons`, `assets/images`, and
137
+ A language note that `languages:` names carries its code as `languageCode`.
138
+ An affiliation carries `officeHolders`, each of its offices that a living
139
+ being holds with those beings' Addresses, derived as
140
+ [office holders](../reference/format-details.md#type-affiliation) describes. Asset files under `assets/icons`, `assets/images`, and
138
141
  `assets/audio` have records in the same index, identified by an `asset` block.
139
142
  The index is disposable build output; regenerate it from the authored tree
140
143
  when the content changes.
@@ -244,7 +244,7 @@ notes' sources. A page is reachable when an authored link leads to it:
244
244
  The links the build generates do not make a page reachable. These are the
245
245
  Related card, the previous and next links, the infobox links, and the sections
246
246
  generated after a note's text (Within, Governed by, Governed places,
247
- Chronology, Events, Accounts, What followed, In song and story). Each is drawn
247
+ Office holders, Chronology, Events, Accounts, What followed, In song and story). Each is drawn
248
248
  without a link to a page outside the reachable set, and a section left with
249
249
  nothing under it is not drawn. An infobox value that names an unreachable page
250
250
  is set as plain text. So is a link in a dictionary or glossary entry, whether
@@ -302,12 +302,22 @@ index inside it. Nothing else renders the pages: the body of each is the same
302
302
  HTML the Foundry journals and the editor preview read, drawn into the site
303
303
  theme's layouts and minified.
304
304
 
305
+ The terminal reports indexing, rendering, writing and search indexing as they
306
+ start, including page counts where available. Progress is on stdout;
307
+ diagnostics retain their file, line and column on stderr.
308
+
305
309
  ```bash
306
310
  package-build site serve
307
311
  ```
308
312
 
309
- `package-build site serve` builds the site the same way and serves it at
310
- `http://127.0.0.1:1313/<contentPackage>/`. Edit a note and its page is written
313
+ `package-build site serve` prints its address as soon as HTTP starts, before
314
+ building the site: `http://127.0.0.1:1313/<contentPackage>/`. Existing output
315
+ remains available during the build. Successful whole builds replace the pages
316
+ and search index together; failed builds leave the last successful output in
317
+ place. A first run with no output answers HTTP 503 until a build succeeds, with
318
+ a message pointing to progress and diagnostics in the terminal.
319
+
320
+ Edit a note and its page is written
311
321
  again and the browser reloads; edit the theme and every page is drawn again.
312
322
  A change that moves, renames or adds a note builds the whole site again. See
313
323
  [`site serve`](../commands.md#package-build-site-serve) for the whole table.
@@ -618,11 +618,14 @@ that the language lists in `data.sounds.syllables.vowelPairs` is one syllable.
618
618
 
619
619
  **The beat convention, in plain words:**
620
620
 
621
- - Every word of two or more syllables has one beat, on its stressed syllable.
621
+ - A word of two or more syllables has one beat, on its stressed syllable,
622
+ but may go unstressed when every lexicon class is a function class: any base
623
+ other than `n`, `v`, `adj`, `num` or `name`. A word with any content class,
624
+ or no lexicon entry, keeps its beat.
622
625
  - A one-syllable noun, verb, adjective, numeral or name has a beat. A
623
626
  one-syllable particle, preposition, conjunction, adverb or pronoun has none.
624
627
  The lexicon entry's class decides, and a form that the language's rules derive
625
- takes its word's class. A word whose entries differ in class is a beat that
628
+ takes its word's class. A one-syllable word with both content and function classes has a beat that
626
629
  may be left out.
627
630
  - A one-syllable word the lexicon does not hold is a content word and has a
628
631
  beat; the word check reports the word separately.