@heroiclands/package-build 25.0.0 → 25.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -0
  3. package/bin/content-commands.mjs +30 -96
  4. package/bin/encoding-commands.mjs +146 -0
  5. package/bin/package-build.mjs +35 -24
  6. package/config.mjs +25 -0
  7. package/convert.mjs +182 -0
  8. package/docs/api.md +144 -6
  9. package/docs/authoring/links-and-markup.md +260 -481
  10. package/docs/commands.md +110 -119
  11. package/docs/configuration.md +31 -13
  12. package/docs/content-format.md +11 -4
  13. package/docs/diagnostics.md +43 -16
  14. package/docs/encoding-core.md +193 -0
  15. package/docs/guides/book.md +2 -2
  16. package/docs/guides/module-project.md +23 -1
  17. package/docs/guides/site.md +2 -2
  18. package/docs/guides/writing-in-invented-scripts.md +458 -575
  19. package/docs/reference/format-details.md +292 -404
  20. package/docs/reference/note-types.md +83 -63
  21. package/docs/source-preview.md +8 -0
  22. package/e2e.mjs +1 -1
  23. package/engine/base-compiler.mjs +27 -9
  24. package/engine/content-charset.mjs +13 -1
  25. package/engine/content-format.yaml +6 -2
  26. package/engine/content-index.mjs +6 -2
  27. package/engine/content-links.mjs +1 -0
  28. package/engine/content-scripts.mjs +614 -459
  29. package/engine/content-scroll.mjs +4 -4
  30. package/engine/content-spans.mjs +40 -9
  31. package/engine/content-verse.mjs +1 -1
  32. package/engine/converter-data.mjs +70 -0
  33. package/engine/dictionary-rows.mjs +2 -34
  34. package/engine/encoding-integrity.mjs +94 -0
  35. package/engine/encoding-language.mjs +506 -0
  36. package/engine/encoding-lexicon.mjs +701 -0
  37. package/engine/encoding-notes.mjs +186 -0
  38. package/engine/encoding-standard.mjs +42 -0
  39. package/engine/encoding-template.mjs +370 -0
  40. package/engine/encoding-terms.mjs +178 -0
  41. package/engine/encoding.mjs +952 -0
  42. package/engine/extension-attributes.mjs +2 -0
  43. package/engine/helpers.mjs +1 -1
  44. package/engine/index.mjs +7 -0
  45. package/engine/language-terms.mjs +17 -16
  46. package/engine/{logographic.mjs → language-writings.mjs} +29 -38
  47. package/engine/markup-validation.mjs +1 -1
  48. package/engine/note-vocabulary.mjs +4 -158
  49. package/engine/pdf-render.mjs +31 -3
  50. package/engine/roman-characters.mjs +135 -16
  51. package/engine/roman-run.mjs +149 -0
  52. package/engine/roman-verse.mjs +95 -0
  53. package/engine/run-rows.mjs +29 -31
  54. package/engine/run-words.mjs +2 -2
  55. package/engine/script-emphasis-terms.mjs +3 -0
  56. package/engine/script-emphasis.mjs +3 -10
  57. package/engine/script-font-delivery.mjs +9 -12
  58. package/engine/script-fonts.mjs +2 -1
  59. package/engine/site-build.mjs +14 -5
  60. package/engine/site-preview.mjs +12 -2
  61. package/engine/sql-tables.mjs +36 -31
  62. package/engine/verse-metre.mjs +1 -1
  63. package/engine/word-forms.mjs +1 -1
  64. package/engine/word-inflections.mjs +48 -0
  65. package/engine/word-rows.mjs +1 -1
  66. package/engine/word-terms.mjs +16 -17
  67. package/package.json +11 -5
  68. package/types/config.d.mts +5 -0
  69. package/types/convert.d.mts +44 -0
  70. package/types/e2e.d.mts +1 -1
  71. package/types/engine/base-compiler.d.mts +4 -2
  72. package/types/engine/content-index.d.mts +4 -1
  73. package/types/engine/content-scripts.d.mts +103 -42
  74. package/types/engine/converter-data.d.mts +11 -0
  75. package/types/engine/dictionary-rows.d.mts +1 -25
  76. package/types/engine/encoding-integrity.d.mts +14 -0
  77. package/types/engine/encoding-language.d.mts +36 -0
  78. package/types/engine/encoding-lexicon.d.mts +259 -0
  79. package/types/engine/encoding-notes.d.mts +39 -0
  80. package/types/engine/encoding-standard.d.mts +11 -0
  81. package/types/engine/encoding-template.d.mts +44 -0
  82. package/types/engine/encoding-terms.d.mts +143 -0
  83. package/types/engine/encoding.d.mts +155 -0
  84. package/types/engine/helpers.d.mts +1 -1
  85. package/types/engine/index.d.mts +4 -0
  86. package/types/engine/language-terms.d.mts +1 -1
  87. package/types/engine/{logographic.d.mts → language-writings.d.mts} +6 -6
  88. package/types/engine/markup-validation.d.mts +1 -1
  89. package/types/engine/pdf-render.d.mts +1 -1
  90. package/types/engine/roman-characters.d.mts +2 -2
  91. package/types/engine/roman-run.d.mts +101 -0
  92. package/types/engine/roman-verse.d.mts +23 -0
  93. package/types/engine/run-rows.d.mts +13 -20
  94. package/types/engine/script-emphasis-terms.d.mts +2 -0
  95. package/types/engine/script-emphasis.d.mts +1 -1
  96. package/types/engine/script-font-delivery.d.mts +2 -3
  97. package/types/engine/script-fonts.d.mts +5 -0
  98. package/types/engine/site-preview.d.mts +1 -1
  99. package/types/engine/word-inflections.d.mts +25 -0
  100. package/engine/map-lexicon.mjs +0 -1045
  101. package/engine/text-maps.mjs +0 -654
  102. package/engine/written-in.mjs +0 -204
  103. package/types/engine/map-lexicon.d.mts +0 -330
  104. package/types/engine/text-maps.d.mts +0 -189
  105. package/types/engine/written-in.d.mts +0 -76
package/docs/commands.md CHANGED
@@ -2583,14 +2583,11 @@ with visible text, nullable type/subtype and original source line/column.
2583
2583
  Local and dependency SQL schemas expose them through `names`; they travel in
2584
2584
  the metadata artifact.
2585
2585
 
2586
- Metadata also includes each own note's spans, divs and verse fences marked with
2587
- `lang=`, `font=` or `map=` under `runs`, with the language as written, the tag
2588
- it resolves to, the font, the map and the original source line/column. Native
2589
- runs carry `nativefont: true` in the metadata; language-only Roman runs omit
2590
- the flag and do not receive script defaults. The `runs` SQL columns stay the
2591
- same. Local
2592
- and dependency SQL schemas expose them through `runs`, and each mapping note's
2593
- rows through `maps`.
2586
+ Metadata includes each own note's spans, divs and verse fences marked with
2587
+ `lang=`, `font=` or `enc=` under `runs`, with the language as written, its
2588
+ resolved tag, font, encoding document Address and original source line/column.
2589
+ Roman runs use the default encoding and receive no inferred script face.
2590
+ Local and dependency SQL schemas expose these records through `runs`.
2594
2591
 
2595
2592
  The command prepares SQL tables, page lists, automatic sections and scalar
2596
2593
  expressions before publishing their prose targets. Each source uses its own
@@ -3159,173 +3156,167 @@ $ package-build reachability assets/content
3159
3156
  `package-build links [root]`, `package-build lint [root]`, [Diagnostics](diagnostics.md),
3160
3157
  [Configuration](configuration.md).
3161
3158
 
3162
- ### `package-build transliterate <map> [text..]`
3159
+ ### `package-build encode [text..]`
3163
3160
 
3164
3161
  **NAME**
3165
3162
 
3166
- Map a passage into a script exactly as the build maps a marked run.
3163
+ Encode roman text using an encoding document.
3167
3164
 
3168
3165
  **SYNOPSIS**
3169
3166
 
3170
- ```
3171
- package-build transliterate <map> [--lang <language>] [--font <slug>] [--hex] [text..]
3167
+ ```text
3168
+ package-build encode --enc <document|default> [--in|-i <file>] [--out|-o <file>] [text..]
3172
3169
  ```
3173
3170
 
3174
3171
  **DESCRIPTION**
3175
3172
 
3176
- Reads the content index, as `package-build lint` does, and prints the passage
3177
- rewritten by the mapping note whose `data.map.name` is `<map>`, through the
3178
- same code the build sets a run marked `lang=<language> .nativefont map=<map> font=<slug>`
3179
- with. With `--lang`, each word the language's lexicon states a native form for
3180
- is written by it and every other word is spelled by the rows; without it, the
3181
- rows alone apply. See
3182
- [a map reads the dictionary first](reference/format-details.md#a-map-reads-the-dictionary-first).
3183
- Under a [logographic map](reference/format-details.md#a-logographic-map) every
3184
- word is written from the language's lexicon, by its own writing or its parts',
3185
- and the rows write only the text between words.
3186
- The text is the words given, joined by single spaces; `-` or no text reads it
3187
- from standard input, less one trailing newline. Writes nothing.
3173
+ Reads an encoding document from the consuming package's content index and
3174
+ writes its Unicode output. `--enc` is an Address whose default type is `doc`,
3175
+ or `default` to keep text unchanged. The note supplies its font, and glyph
3176
+ codes come from that face's `fonts.json`. These commands apply the bare
3177
+ encoding; they do not apply a language's lexical native spellings.
3188
3178
 
3189
- **OPTIONS**
3179
+ Give exactly one string argument, or `--in` with a UTF-8 file; `--in -` drains
3180
+ standard input. `--out` writes the exact result to a file. Standard output adds
3181
+ one newline only for string arguments; file and stream input add nothing.
3182
+ A refusal writes no result and preserves an existing output file.
3190
3183
 
3191
- | Positional | Type | Default | Description |
3192
- | ---------- | ---------------- | ------- | -------------------------------------- |
3193
- | `map` | string | — | The `data.map.name` of a mapping note. |
3194
- | `text` | string, variadic | stdin | The passage; `-` reads it from stdin. |
3184
+ **OPTIONS**
3195
3185
 
3196
- | Option | Type | Default | Description |
3197
- | -------- | ------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
3198
- | `--lang` | string | — | A language declared in `languages`, whose lexicon is read first. |
3199
- | `--font` | string | the language's face where the map is drawn in it, else the map's one face, if one | The face, whose own rows come first; required when neither gives one and the map lists more than one. |
3200
- | `--hex` | boolean | `false` | Print the code points, as `U+XXXX` separated by spaces. |
3186
+ | Option | Description |
3187
+ | ------------- | -------------------------------------------------- |
3188
+ | `--enc` | Required encoding document Address, or `default`. |
3189
+ | `--in`, `-i` | Read a UTF-8 file, or standard input with `-`. |
3190
+ | `--out`, `-o` | Write the exact result to a file. |
3191
+ | `[text..]` | One quoted input string, used only without `--in`. |
3201
3192
 
3202
3193
  **EXIT STATUS**
3203
3194
 
3204
- 1 if the content index could not be built for any note, or the map, the
3205
- language or the face names nothing, each reported as a finding: an unknown
3206
- language at `languages` in the configuration, an unknown map or face at the
3207
- content tree. 1, with the build's own message, if a capitalised word of the
3208
- passage has a native form the rows cannot capitalise, or, under a logographic
3209
- map, a word has no writing or stands for entries written differently.
3210
- Otherwise 0.
3195
+ 0 on success; 1 for unreadable files or an encoding refusal; 2 for a usage
3196
+ error. Findings go to standard error as `file:line:column: error: message`.
3197
+ Line and column count Unicode code points, starting at one. String input is
3198
+ named `<text>` and standard input `<stdin>`.
3211
3199
 
3212
3200
  **EXAMPLES**
3213
3201
 
3214
- With Vylari's `zaron` stating a native form for `semaron`, and `lonak` stating
3215
- none:
3216
-
3217
- ```
3218
- $ package-build transliterate semaron --lang vyl --hex zaron lonak
3219
- U+F024F U+F0230 U+F023F U+F023C U+0020 U+F023A U+F023D U+F023C U+F0230 U+F0239
3220
- $ package-build transliterate semaron --hex zaron
3221
- U+F0255 U+F0230 U+F023F U+F023D U+F023C
3222
- $ package-build transliterate semoran zaron
3223
- assets/content: error: `semoran` is not a map: a map is named by the `data.map.name` of a mapping note; did you mean `semaron`?
3202
+ ```sh
3203
+ package-build encode --enc vylsemaronenc "zaron"
3204
+ package-build encode --enc khelqalezuenc --in roman.txt --out native.txt
3205
+ package-build encode --enc khelzethuenc "⟦MAN⟧"
3206
+ printf 'zaron' | package-build encode --enc vylsemaronenc -i - -o native.txt
3224
3207
  ```
3225
3208
 
3226
- The first run writes `zaron` by its exception; the second, with no `--lang`,
3227
- spells it by the rows.
3209
+ **SEE ALSO**
3210
+
3211
+ `package-build decode`, `package-build lexicon`, [Writing in invented scripts](guides/writing-in-invented-scripts.md#the-commands).
3212
+
3213
+ ### `package-build decode [text..]`
3214
+
3215
+ **NAME**
3216
+
3217
+ Decode Unicode through an encoding document.
3228
3218
 
3229
- Under the logographic `zethu`, with Khelathi's `lekhunet` built from `lekhau`
3230
- and the affix `-unet`, the plural written by its own sign, and `zamlu` given no
3231
- writing:
3219
+ **SYNOPSIS**
3232
3220
 
3221
+ ```text
3222
+ package-build decode --enc <document|default> [--in|-i <file>] [--out|-o <file>] [text..]
3233
3223
  ```
3234
- $ package-build transliterate zethu --lang khel --hex lekhunet halziim.
3235
- U+1EA93 U+1EBC7 U+0020 U+1EABB U+1EBE1 U+1EBED
3236
- $ package-build transliterate zethu --lang khel zamlu
3237
- error: `zamlu` has no `zethu` writing in the `khel` lexicon, and its parts do not give one; state one, or write the word directly in signs
3224
+
3225
+ **DESCRIPTION**
3226
+
3227
+ Reads the encoding's longest output rows back as roman text. `--enc` is
3228
+ required and resolves exactly as for `encode`. Literal spans decode to the
3229
+ encoding's own codes, or `U+XXXX` for an unnamed Unicode scalar. The bare
3230
+ command reads no language vocabulary; the [browser conversion API](api.md#browser-conversion)
3231
+ adds lexical recovery.
3232
+
3233
+ **OPTIONS**
3234
+
3235
+ | Option | Description |
3236
+ | ------------- | -------------------------------------------------- |
3237
+ | `--enc` | Required encoding document Address, or `default`. |
3238
+ | `--in`, `-i` | Read a UTF-8 file, or standard input with `-`. |
3239
+ | `--out`, `-o` | Write the exact result to a file. |
3240
+ | `[text..]` | One quoted input string, used only without `--in`. |
3241
+
3242
+ **EXIT STATUS**
3243
+
3244
+ 0 on success; 1 for unreadable files or a decoding refusal; 2 for a usage
3245
+ error. Diagnostics and output bytes follow the same rules as `encode`.
3246
+
3247
+ **EXAMPLES**
3248
+
3249
+ ```sh
3250
+ package-build decode --enc vylsemaronenc --in native.txt --out roman.txt
3251
+ package-build decode --enc khelqalezuenc -i native.txt
3252
+ package-build decode --enc khelzethuenc --in signs.txt
3238
3253
  ```
3239
3254
 
3240
3255
  **SEE ALSO**
3241
3256
 
3242
- `package-build lexicon <language>`, [Mapping notes](reference/format-details.md#mapping-notes).
3257
+ `package-build encode`, `package-build lexicon`, [Browser conversion](api.md#browser-conversion).
3243
3258
 
3244
3259
  ### `package-build lexicon <language>`
3245
3260
 
3246
3261
  **NAME**
3247
3262
 
3248
- List a language's words with their native forms under a map.
3263
+ List a language's words and native writings under an encoding document.
3249
3264
 
3250
3265
  **SYNOPSIS**
3251
3266
 
3252
3267
  ```
3253
- package-build lexicon <language> [--map <map>] [--font <slug>] [--derived] [--json]
3268
+ package-build lexicon <language> [--enc <encoding>] [--font <slug>] [--derived] [--json]
3254
3269
  ```
3255
3270
 
3256
3271
  **DESCRIPTION**
3257
3272
 
3258
- Reads the content index and lists every word of the language note
3259
- [`languages.<language>.note`](configuration.md#languages) names, in `data.words`
3260
- order, each with its native form under `<map>`, or under the script the
3261
- language note names in `data.writtenIn` when `--map` is left out: the stated exception where the
3262
- word has one, else the rows' spelling, each exactly as
3263
- `package-build transliterate` and the build give it. Each line holds, separated
3264
- by tabs, the word's `form`, its native form, `exception` or `rows`, its `class`
3265
- and its `gloss`. Writes nothing.
3266
-
3267
- Under a [logographic map](reference/format-details.md#a-logographic-map) the
3268
- native form is the word's writing, and the third column says where it comes
3269
- from: `own` for a writing the word states, `parts` for one its `built` pieces
3270
- give, or `none`, with an empty second column, for a word with no writing. A
3271
- word whose form a run cannot write, because the form stands for entries
3272
- written differently or one of its parts does, is marked `ambiguous`, and its
3273
- second column is still that entry's own writing: the signs to write directly
3274
- for that sense. Every word listed with a writing and not `ambiguous` is written
3275
- so by the build and by `package-build transliterate`.
3276
-
3277
- With `--derived`, the forms the language's own rules derive from those words
3278
- follow them: each word's declared `variants`, then plurals, verb forms, replacing suffixes, agreeing forms and
3279
- participles, exactly the regular forms
3280
- [the mapped-run word check](authoring/links-and-markup.md#a-mapped-runs-words)
3281
- accepts. Each is listed once, case folded as the check compares it, and spelled
3282
- by the rows; a form that is itself a lexicon word is not repeated. Every line
3283
- then has a sixth column: the lexicon word a derived form comes from, empty for
3284
- the lexicon's own words. A derived line carries its word's `class` and `gloss`.
3273
+ Reads the content index and lists the words of the note named by
3274
+ [`languages.<language>.note`](configuration.md#languages), in authored order.
3275
+ `--enc` selects an encoding document; its language must agree with the
3276
+ requested language, and `--font`, when supplied, must equal its font.
3277
+ Native writings and composed parts take precedence over encoding mappings.
3278
+
3279
+ Tab-separated output contains `form`, native text, source, class and gloss.
3280
+ Source is `own`, `parts`, `rows`, `none` or `ambiguous`. A missing writing leaves
3281
+ native text empty; an ambiguous entry shows that entry's own writing so the
3282
+ reader can choose signs for its meaning. JSON output preserves these fields
3283
+ and adds `ambiguous: true` where appropriate.
3284
+
3285
+ With `--derived`, declared variants and regular forms follow the citations,
3286
+ each once. The final tab-separated column, or JSON `from`, names its source
3287
+ word. This lists the forms the language's authored grammar supplies; it does
3288
+ not infer grammatical roles from an unlabelled variant.
3285
3289
 
3286
3290
  **OPTIONS**
3287
3291
 
3288
- | Positional | Type | Default | Description |
3289
- | ---------- | ------ | ------- | --------------------------------------------------- |
3290
- | `language` | string | — | A declared language whose `note` names its lexicon. |
3292
+ | Positional | Type | Default | Description |
3293
+ | ---------- | ------ | ------- | ----------------------------------------------------- |
3294
+ | `language` | string | — | A configured language whose `note` names its lexicon. |
3291
3295
 
3292
- | Option | Type | Default | Description |
3293
- | ----------- | ------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
3294
- | `--map` | string | the language's `data.writtenIn` map | The `data.map.name` of a mapping note; required when the language note states no `data.writtenIn`. |
3295
- | `--font` | string | the language's face where the map is drawn in it, else the map's one face, if one | The face; required when neither gives one and the map lists more than one. |
3296
- | `--derived` | boolean | `false` | Also list the forms the language's rules derive, each with the word it comes from. |
3297
- | `--json` | boolean | `false` | Print a JSON array of `{ form, native, exception, class, gloss }` instead; a derived form adds `from`. Under a logographic map `source` (`own`, `parts` or `none`) takes the place of `exception`, and an ambiguous word adds `ambiguous: true`. |
3296
+ | Option | Type | Default | Description |
3297
+ | ----------- | ------- | ------------------------ | ---------------------------------------------------------- |
3298
+ | `--enc` | string | required | An encoding document Address. |
3299
+ | `--font` | string | encoding document's font | A face supported by the encoding. |
3300
+ | `--derived` | boolean | `false` | Include variants and derived forms with their source word. |
3301
+ | `--json` | boolean | `false` | Print JSON records instead of tab-separated lines. |
3298
3302
 
3299
3303
  **EXIT STATUS**
3300
3304
 
3301
- 1 if the content index could not be built for any note, or the language, the
3302
- map or the face names nothing, no map is named and the language note states no
3303
- `data.writtenIn`, the language states no `note`, or a capitalised
3304
- word has a native form the rows cannot capitalise, each reported as a finding.
3305
- Otherwise 0.
3305
+ 0 on success; 1 for content-index findings, an unknown language, encoding or
3306
+ face, a missing language note or encoding selection, or an invalid conversion.
3306
3307
 
3307
3308
  **EXAMPLES**
3308
3309
 
3309
3310
  ```
3310
- $ package-build lexicon vyl --map semaron | head -3
3311
- zaron <native form> exception n an oath
3312
- lonak <native form> rows n a road
3313
- thizaron <native form> rows n a seal
3314
- $ package-build lexicon vyl --map semaron --derived | grep -P '\talathos$'
3315
- alatha <native form> rows pron he, that one alathos
3316
- alathon <native form> rows pron he, that one alathos
3317
- alathoi <native form> rows pron he, that one alathos
3318
- alathai <native form> rows pron he, that one alathos
3319
- $ package-build lexicon khel --map zethu | grep -P '\t(none|ambiguous)\t'
3320
- nelgir <writing> ambiguous n a god
3321
- Nelgir <writing> ambiguous stem god
3322
- zamlu none n music
3311
+ package-build lexicon vyl --enc vylsemaronenc
3312
+ package-build lexicon vyl --enc vylsemaronenc --derived --json
3313
+ package-build lexicon khel --enc khelzethuenc
3323
3314
  ```
3324
3315
 
3325
3316
  **SEE ALSO**
3326
3317
 
3327
- `package-build transliterate <map> [text..]`,
3328
- [A language's words](reference/format-details.md#a-languages-words).
3318
+ `package-build encode`, `package-build decode`,
3319
+ [native spellings and parts](reference/format-details.md#native-spellings-and-parts).
3329
3320
 
3330
3321
  ### `package-build core`
3331
3322
 
@@ -734,7 +734,7 @@ any finding it reports is a refusal, joined into one message:
734
734
  The languages a note may tag text with, by short name. A note writes the short
735
735
  name, as in `[Daimela, helthos.]{lang=vyl}`; the build gives the text the
736
736
  language's tag. See
737
- [marking language, font and mapping](authoring/links-and-markup.md#marking-language-font-and-mapping).
737
+ [marking language, font and encoding](authoring/links-and-markup.md#marking-language-font-and-encoding).
738
738
 
739
739
  ```yaml
740
740
  languages:
@@ -761,20 +761,18 @@ checked.
761
761
  **`note`** names the language note whose `data.words` is the language's
762
762
  lexicon, as an Address in this package: `skill-vylarilng`, or the bare
763
763
  shortcode, whose type defaults to `skill`. A run marked with the language and a
764
- `map=` writes each word the lexicon states a native form for by that form, and
764
+ `enc=` writes each word the lexicon states a native form for by that form, and
765
765
  spells every other word by the map's rows; see
766
- [a map reads the dictionary first](reference/format-details.md#a-map-reads-the-dictionary-first).
766
+ [an encoding reads the dictionary first](reference/format-details.md#an-encoding-reads-the-dictionary-first).
767
767
  Language word-book validation applies to Roman and native runs alike,
768
- independently of `.nativefont` or mapping: every word is a word of the lexicon, of a name the language note's
768
+ independently of encoding selection: every word is a word of the lexicon, of a name the language note's
769
769
  own register lists, or a regular form of a lexicon word, and any other word is an error; see
770
- [a mapped run's words](authoring/links-and-markup.md#a-mapped-runs-words).
771
- The language note may also name the script the language is written in, as
772
- `data.writtenIn: { map, font }`, and a run explicitly marked with both the language and `.nativefont` is
773
- then mapped and set in it. Language-only runs retain authored Roman spelling
774
- and the surrounding prose font. Native `map=` and `font=` override the
775
- configured halves independently; missing halves require explicit overrides; see
776
- [a language's script](authoring/links-and-markup.md#a-languages-script). The
777
- script belongs to the language note, and the configuration never states it.
770
+ [a mapped run's words](authoring/links-and-markup.md#an-encoded-runs-words).
771
+ An encoding document names its configured language in `data.language` and
772
+ its installed face in `data.font`. `enc=` selects that document and infers
773
+ those values; explicit choices must agree. A run without an encoding uses
774
+ `enc=default` and keeps its Roman spelling. See
775
+ [marking language, font and encoding](authoring/links-and-markup.md#marking-language-font-and-encoding).
778
776
  A language with no `note` tags its text and has no lexicon. Whether the note
779
777
  resolves is checked by `package-build lint`, at the key:
780
778
 
@@ -1905,6 +1903,7 @@ packageBuild:
1905
1903
  | [`packageBuild.baseStyles`](#packagebuildbasestyles) | boolean | no | `true` |
1906
1904
  | [`packageBuild.manifest`](#packagebuildmanifest) | object, pass-through | no | `{}` |
1907
1905
  | [`packageBuild.manifestFlags`](#packagebuildassettransform-and-packagebuildmanifestflags) | string (path to a module) | no | `null` |
1906
+ | [`packageBuild.converterData`](#packagebuildconverterdata) | string (stage-relative JSON path) | no | `null` |
1908
1907
  | [`packageBuild.schema`](#packagebuildschema) | object (`{documentType: {from, registry}}`) | no | `[]` |
1909
1908
  | [`packageBuild.clean`](#packagebuildclean) | object | no | `{extra: []}` |
1910
1909
  | [`packageBuild.lang`](#packagebuildlang) | object | no | see below |
@@ -1916,7 +1915,7 @@ packageBuild:
1916
1915
  | [`packageBuild.proseLint`](#packagebuildproselint) | object | no | `{age: 21, threshold: 5, minWords: 8, rules: readability}` |
1917
1916
  | [`packageBuild.proseScore`](#packagebuildprosescore) | object | no | `{minWords: 80, bands: {}}` |
1918
1917
 
1919
- > ``package-build config: `packageBuild.<key>` is not a recognised key (expected one of: stageDir, assets, assetTransform, shippingLicenses, baseStyles, manifest, manifestFlags, schema, clean, lang, deploy, release, bundle, container, e2e, proseLint, proseScore).``
1918
+ > ``package-build config: `packageBuild.<key>` is not a recognised key (expected one of: stageDir, assets, assetTransform, shippingLicenses, baseStyles, manifest, manifestFlags, converterData, schema, clean, lang, deploy, release, bundle, container, e2e, proseLint, proseScore).``
1920
1919
 
1921
1920
  ### `packageBuild.proseLint`
1922
1921
 
@@ -2338,3 +2337,22 @@ the source directory:
2338
2337
  | `packageBuild.manifest.id`, `.version`, `.description`, `.url`, `.bugs`, `.manifest`, `.download`, `.compatibility`, `.relationships`, `.packs` | Forbidden — each is derived from `package.json` or the top level of `package-build.config.yaml`; see [`packageBuild.manifest`](#packagebuildmanifest). |
2339
2338
  | `publish.site` (any value) | Refused — publication follows the authored content tree. |
2340
2339
  | `packs`, `itemBuilders`, `docs`, `compatibility`, `relationships`, `systems`, `requiresSystem`, `stats`, `foundryPackage` | Forbidden in a `documentation` package — each describes a Foundry package this kind is not; see the key's own section for its located refusal message. |
2340
+
2341
+ ### `packageBuild.converterData`
2342
+
2343
+ Optional path for a browser converter's JSON data, relative to
2344
+ `packageBuild.stageDir`. `package-build manifest` writes it during the module
2345
+ build from the same published encodings and language vocabulary that render
2346
+ native text. The path must stay within the stage, end in `.json`, and name an
2347
+ artifact other than `module.json`, `system.json` or `package.json`. Absolute
2348
+ paths and parent traversal are refused. Omission writes no converter file.
2349
+
2350
+ ```yaml
2351
+ packageBuild:
2352
+ converterData: data/converter.json
2353
+ ```
2354
+
2355
+ The result is `build/stage/data/converter.json` with the default stage. It
2356
+ ships with that stage in the release archive. See the
2357
+ [data format](reference/format-details.md#converter-data-format) and
2358
+ [browser API](api.md#browser-conversion).
@@ -31,10 +31,17 @@ Leading `:` captions describe the next supported block; `:@` captions also numbe
31
31
 
32
32
  A code fence with language `verse` keeps verse lines, stanza breaks and relative indentation. Leading periods set indent levels and are removed from the text; leading spaces do not count. Blank lines separate verse units and `***` separates stanzas. Its numbered caption uses the **Poem** label. Generic `:::` divs and `[inline spans]{.class}` accept attributes. See [verse](authoring/links-and-markup.md#verse), [fenced divs](authoring/links-and-markup.md#fenced-divs) and [inline spans](authoring/links-and-markup.md#inline-spans). `numstep=N` numbers every Nth line. `cols=N` sets a positive whole number of columns and defaults to one. With `cols` above one, each content line starts with an integer and one or more spaces; numbers lie in `1..cols` and are nondecreasing within each blank-separated logical row. Any column may be omitted and keeps an empty cell. A column may repeat without limit: its first reading is foreground and its later readings are grey, independently for every column and row. Number prefixes are not displayed; `numstep` counts logical rows. `***` separates stanzas. Inline language and native presentation are explicit on each authored run. See [verse in columns](authoring/links-and-markup.md#verse-in-columns).
33
33
 
34
- A code fence with language `scroll` sets text in a script whose script note states `direction: vertical-rl` as columns, top to bottom, read from the right. The lines of a paragraph are joined, and each paragraph starts a fresh column. `rows=N` is the characters in a column and `cols=M` the columns in a panel, each a whole number above zero; `lang=`, `font=` and `map=` mark the text as on a verse fence, and `.nativefont` requires an explicit language and a font supplied by a language default or an override; mapping is optional when no default supplies it. The site, the preview and Foundry set it with `writing-mode: vertical-rl` in a panel that scrolls sideways from the right; the book draws its panels as images from the face's outlines, each with its roman text as alt text. A scroll fence in a script written in lines is an error. See [scrolls](authoring/links-and-markup.md#scrolls).
35
-
36
- A span, a generic div, a verse fence or a scroll fence identifies its language with `lang=` and keeps its authored spelling and the surrounding prose font. Explicit `.nativefont` on that same construct, with its own explicit `lang=`, requests the language's configured `data.writtenIn` map and font; `map=` and `font=` override their halves independently. A missing font default requires `font=` rather than inference; mapping is optional when the language supplies none. Native font or map keys require `.nativefont`; Roman `font=mono`, `serif` and `sans` remain available independently. Unmarked text follows its passage, while a marked language-only child stays Roman, even in the same language as a native parent. Standalone wikilinks make the same choice: `[[address|Name]]{lang=vyl}` stays Roman and `[[address|Name]]{lang=vyl .nativefont}` uses native presentation without changing its destination or presentation cues. `font=` is a face of the installed `@heroiclands/fonts`, named by its class without `hl-`, or `mono`, `serif` or `sans`. `map=` names a mapping note: a `doc` note whose `data.map` lists the fonts it is drawn in and rows that rewrite the text before it is set, a font's own rows first. With `lang=` naming a language whose configured `note` names its language note, a word whose entry states a `native` form for the map is written by it, and the rows spell every other word. A map stating `logographic: true` spells no word by its rows: each word is written by its own `native` entry or its parts' writings, and a word with neither, or whose form stands for entries written differently, is a located error. Language word-book validation applies to Roman and native runs alike,
37
- independently of `.nativefont` or mapping: every word is a lexicon form, a word of a name the language note's own register lists under a tongue other than `translation`, or a form a plural row, the verb pattern or an affix stating `replaces` derives from a lexicon form, and any other word is an error at the word. A character a face does not draw, after the map, is an error at the character it came from. A verse fence that states `scan=` (the `name` of a `data.metres` entry of a `doc` note) with a `lang=` whose language note states `data.sounds.stress` is counted line by line by the beat convention, and a line that cannot have the metre's beats is a warning at the line; see [metres](authoring/links-and-markup.md#metre). Text with a font, a map or a declared language is plain, except that text set in a face takes `*…*` and `**…**`: they render by the convention its language note's `data.emphasis` states, else the one the script note listing its face states in `data.script` (`rubric` or `overline`), else plainly. Actual bold or italic markup inside a span whose effective language is not English is an error, whether that language is declared or inherited and whether or not the text uses a font; English text remains eligible. Every marked construct is a row of the `runs` relation, every mapping row of the `maps` relation, and every native form of the `natives` relation. See [marking language, font and mapping](authoring/links-and-markup.md#marking-language-font-and-mapping).
34
+ A code fence with language `scroll` sets text in a script whose script note states `direction: vertical-rl` as columns, top to bottom, read from the right. The lines of a paragraph are joined, and each paragraph starts a fresh column. `rows=N` is the characters in a column and `cols=M` the columns in a panel, each a whole number above zero; `lang=`, `font=` and `enc=` mark the text as on a verse fence, an explicit `enc=` selects an encoding document and its language and font. The site, the preview and Foundry set it with `writing-mode: vertical-rl` in a panel that scrolls sideways from the right; the book draws its panels as images from the face's outlines, each with its roman text as alt text. A scroll fence in a script written in lines is an error. See [scrolls](authoring/links-and-markup.md#scrolls).
35
+
36
+ A span, generic div, verse or scroll fence uses `enc=default` unless it selects
37
+ an encoding document. `enc=` is an Address whose default type is `doc`; the
38
+ document names its language and font, and explicit `lang=` or `font=` values
39
+ must agree. Each encoding tries authored native writings, complete parts and
40
+ then its mappings. Unknown characters, undefined glyph codes and conflicting
41
+ selections are located errors. `⟦…⟧` reads the selected font's glyph codes or
42
+ strict Unicode scalars. See [encodings](reference/format-details.md#encodings).
43
+ Language word-book validation applies to both Roman and native runs. Parallel
44
+ verse retains independent authored readings and their column numbers.
38
45
 
39
46
  Mark a name without a note as `[Name]{.name data-type="being"}`; the optional
40
47
  classification uses the declared note vocabulary. The [name-marking
@@ -303,26 +303,25 @@ For example, `[a *word*]{lang=vyl}` locates the finding at the `*` that opens
303
303
  the emphasis. A font does not make the markup valid; the language rule applies
304
304
  to the span whether its text uses a script face or ordinary type.
305
305
 
306
- ## Native presentation is explicit
307
-
308
- A language-only run keeps its authored spelling and prose font. Native
309
- presentation requires `.nativefont` and an explicit `lang=` on that same
310
- span, div, verse fence or scroll fence. An inherited language does not satisfy
311
- this requirement. Findings point to the authored class or override:
306
+ Use `[word]{.emph}` for emphasis in a non-English span. It inherits the
307
+ surrounding run's language, face and encoding. These findings point to the
308
+ opening `[` of the emphasis span:
312
309
 
313
310
  ```text
314
- `.nativefont` requires an explicit `lang=` on the same construct
315
- native `font=semaron-kuriale` requires `.nativefont` and an explicit `lang=` on the same construct
316
- `map=semaron` requires `.nativefont` and an explicit `lang=` on the same construct
317
- `.nativefont` has no default `font=` for `vyl`; state `font=` explicitly
311
+ a span in non-English language `vyl` holds no `.strong` emphasis
312
+ `vyl` marks emphasis with a word, not a mark; write the word
313
+ a span takes `.emph` or `.strong`, not both
318
314
  ```
319
315
 
320
- A missing font needs an explicit `font=` or a language font default. Mapping is
321
- optional when the language supplies none; configured maps still apply to
322
- native runs unless explicitly overridden. `font=serif`, `sans` and `mono`
323
- remain independent Roman choices. Each authored reading makes its own presentation choice in parallel verse,
324
- for example `1 [Zaron]{lang=vyl .nativefont}` and
325
- `3 [Zaron]{lang=vyl}` inside a `cols=3` poem. The Roman repeat stays Roman.
316
+ ## Native presentation is explicit
317
+
318
+ `enc=` resolves an encoding document and infers its language and font.
319
+ `enc=default` leaves Roman text unchanged. A conflicting explicit language or
320
+ font is a finding at that attribute. Encoding-note schema errors point to
321
+ frontmatter; missing, duplicate or malformed font glyph codes point to
322
+ `fonts.json`. Their original source positions survive preview, lint, site,
323
+ Foundry and book builds. Text diagnostics use code-point columns; run offsets
324
+ and captured index coordinates retain UTF-16 units.
326
325
 
327
326
  ## Summary counts and prose are not findings
328
327
 
@@ -510,3 +509,31 @@ and exits `1`, because it saw two `error`-severity diagnostics. The summary
510
509
  line the emitting process printed to stdout, `3 finding(s) across 1
511
510
  note(s).`, never reaches the parser at all — it was never on stderr, and the
512
511
  regex would not have matched it if it had been.
512
+
513
+ ## Standard Roman punctuation
514
+
515
+ Each configured language's `data.roman` adds its own characters to the shared
516
+ Roman standard. Listing standard punctuation or literal boundaries in that
517
+ field is an error at the field. Quote pairs balance and alternate; an English
518
+ double quotation mark, `<<`, `>>` or three periods receives an error at the
519
+ source mark. A terminal is optional, and authored capitalization is preserved.
520
+
521
+ A semicolon or colon needs a comma for a pause or a period between complete
522
+ sentences. An interruption or abandoning ellipsis within a run needs an
523
+ immediate terminal; at the end of the run it may stand alone. A closing
524
+ quotation is not an outer-sentence terminal.
525
+
526
+ A native character pasted directly into a configured language run receives a
527
+ finding naming its `⟦U+XXXX⟧` spelling. Use that notation, or the chosen
528
+ encoding's codage name, inside the literal markers. The encoder checks the
529
+ codes; the Roman validator leaves their contents immutable.
530
+
531
+ A verse fence uses its authored line endings for boundaries. A literal `/`
532
+ inside it is an error at that slash. Visual indentation does not add periods
533
+ to the encoded text. Source positions survive Markdown escapes and nested
534
+ `.emph` or `.name` spans.
535
+
536
+ Language-run diagnostic columns count Unicode code points, so a supplementary
537
+ character occupies one column. Source offsets and the SQL `runs.column` field
538
+ use UTF-16 units for source indexing. An encoding-file finding retains that
539
+ file's own location; a note's frontmatter offset is not added to it.