@heroiclands/package-build 24.0.0 → 24.0.2

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 (61) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/assets/preview/gitea.ini +1 -1
  3. package/assets/styles/content-base.css +33 -0
  4. package/bin/content-commands.mjs +9 -7
  5. package/docs/api.md +6 -5
  6. package/docs/authoring/links-and-markup.md +164 -16
  7. package/docs/commands.md +23 -19
  8. package/docs/configuration.md +16 -0
  9. package/docs/content-format.md +4 -2
  10. package/docs/guides/site.md +43 -0
  11. package/docs/guides/writing-in-invented-scripts.md +68 -6
  12. package/docs/reference/format-details.md +143 -49
  13. package/docs/reference/note-types.md +47 -28
  14. package/docs/source-preview.md +2 -2
  15. package/engine/content-blocks.mjs +6 -2
  16. package/engine/content-format.yaml +2 -0
  17. package/engine/content-index.mjs +5 -1
  18. package/engine/content-render.mjs +2 -1
  19. package/engine/content-scripts.mjs +268 -21
  20. package/engine/content-scroll.mjs +389 -0
  21. package/engine/font-outlines.mjs +394 -0
  22. package/engine/language-data.mjs +154 -63
  23. package/engine/language-rows.mjs +32 -6
  24. package/engine/language-terms.mjs +32 -8
  25. package/engine/map-lexicon.mjs +31 -6
  26. package/engine/note-vocabulary.mjs +58 -6
  27. package/engine/pdf-fonts.mjs +1 -1
  28. package/engine/pdf-render.mjs +52 -11
  29. package/engine/run-rows.mjs +45 -3
  30. package/engine/script-direction.mjs +67 -0
  31. package/engine/script-emphasis-terms.mjs +11 -3
  32. package/engine/script-font-delivery.mjs +42 -9
  33. package/engine/script-fonts.mjs +7 -0
  34. package/engine/site-build.mjs +8 -1
  35. package/engine/site-reach.mjs +213 -0
  36. package/engine/site-render.mjs +120 -45
  37. package/engine/site-root.mjs +68 -26
  38. package/engine/site-serve.mjs +2 -1
  39. package/engine/site-theme.mjs +19 -6
  40. package/engine/sql-tables.mjs +9 -6
  41. package/engine/verse-metre.mjs +1 -0
  42. package/engine/written-in.mjs +208 -0
  43. package/package.json +1 -1
  44. package/site-theme/static/css/style.css +7 -0
  45. package/types/engine/content-scripts.d.mts +31 -6
  46. package/types/engine/content-scroll.d.mts +179 -0
  47. package/types/engine/font-outlines.d.mts +67 -0
  48. package/types/engine/language-data.d.mts +13 -0
  49. package/types/engine/language-rows.d.mts +4 -3
  50. package/types/engine/language-terms.d.mts +7 -0
  51. package/types/engine/map-lexicon.d.mts +4 -3
  52. package/types/engine/pdf-fonts.d.mts +10 -0
  53. package/types/engine/run-rows.d.mts +28 -6
  54. package/types/engine/script-direction.d.mts +10 -0
  55. package/types/engine/script-emphasis-terms.d.mts +10 -3
  56. package/types/engine/script-font-delivery.d.mts +5 -3
  57. package/types/engine/script-fonts.d.mts +9 -0
  58. package/types/engine/site-reach.d.mts +76 -0
  59. package/types/engine/site-render.d.mts +4 -2
  60. package/types/engine/site-root.d.mts +2 -0
  61. package/types/engine/written-in.d.mts +76 -0
@@ -31,7 +31,9 @@ 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. 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. `col1=` and `col2=` set the poem in at most two columns, each a `:`-joined stack of `language[/mapping[/font]]` entries, the first in the normal tone and the rest in grey; with columns, each blank-line group of `[text]{lang=…}` spans is one verse line, every entry sets the span in its language, and a `***` line breaks the stanza. See [verse in columns](authoring/links-and-markup.md#verse-in-columns).
33
33
 
34
- A span, a generic div or a verse fence marks its text's language with `lang=`, the font it is set in with `font=` and a mapping with `map=`, each optional, and the runs inside a div or a fence inherit its keys. `lang=` is a name the package declares in `languages` or a BCP 47 tag, and gives the language tag alone. `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. Every word of such a run 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](reference/format-details.md#metres). 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, and a language whose `data.emphasis` is `words` makes them an error. 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 `map=` mark the text as on a verse fence, and a fence naming no `font=` takes the face of a map drawn in one. 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 marks its text's language with `lang=`, the font it is set in with `font=` and a mapping with `map=`, each optional, and the runs inside a div or a fence inherit its keys. `lang=` is a name the package declares in `languages` or a BCP 47 tag, and gives the language tag; where the language note states `data.writtenIn`, the script the language is written in as a `map` and a `font` the map lists, a run marked with the language alone takes that map and face, and a run's own `map=` or `font=` overrides its half of the default. `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. Every word of such a run 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](reference/format-details.md#metres). 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, and a language whose `data.emphasis` is `words` makes them an error. 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).
35
37
 
36
38
  Mark a name without a note as `[Name]{.name data-type="being"}`; the optional
37
39
  classification uses the declared note vocabulary. The [name-marking
@@ -175,6 +177,6 @@ Places, affiliations, lore and beings may name their culture in `data.culture`,
175
177
 
176
178
  An affiliation may name the trade, temple or order tongue it keeps in its own `data.language`. An affiliation that reaches no culture is a warning, in a tree holding a culture note. A language needs no culture and no affiliation. See [type: affiliation](reference/format-details.md#type-affiliation).
177
179
 
178
- A language note (`type: skill`, `subType: language`) states its words in frontmatter: `data.words` states each word as a map of its form, class, field and gloss — one sense or a list of them, which a dictionary numbers — with its source, its variant forms, the pieces it is built from and a note, beside `data.classModifiers`, `data.fields` and `data.affixes`, each affix with the `kind` it makes, for a given name's ending who the name is `given` to, and the stem closes it is barred after; a zero affix states `zero: true` and no form. The notes a word is cited from are derived, not written: a note cites a word by marking it in italics in its prose, matched by form or a variant with diacritics and case set aside. The language of a word is the note it sits on, and none of it reaches the compiled Item. A daughter language names its parent in `data.family` and reads the parent's words as its own; the `language_lineage` relation joins a language to its ancestors. Classes come from the [master word classes](reference/format-details.md#word-classes). A culture or an affiliation states its own glossary entries in `data.glossary`: common words in its core vocabulary, dictionary words with a context meaning, or phrases, compounds and terms of art outside the dictionary with their own gloss. An entry naming a word of its resolved language takes the word's senses and class and links to its language entry; a `definition` supplies the entry's meaning instead. Common marks belong to the glossary's owner. A language note with nonempty `data.words` receives its full Dictionary section automatically: one alphabetical list with field tags and one key. A culture or affiliation with nonempty `data.glossary` receives only its explicitly declared entries in its Glossary section; ranks and offices stand in the affiliation's own sections. A note without the relevant frontmatter receives no such section. All surfaces show these sections after the authored text, or under an existing `{#dictionary}`, `{#lexicon}` or `{#glossary}` heading after its introduction. There are no setting-wide dictionary or glossary pages. Every entry resolves to a language — its own `language`, else the affiliation's, its parents' or its culture's, else the culture's — or is an error at the entry. The `words`, `affixes`, `fields`, `glossary` and `language_lineage` relations hold them for `sql` fences, the `dictionary` relation lists each word under every language that has it, inherited words included, and the `terms` relation each glossary entry, rank and office with its culture associations; a fence sets custom views with `layout=dictionary` or `layout=glossary`. A language note names the tag a dictionary prints for it in `data.abbreviation`. A `doc` note states a setting's core concepts in `data.concepts`, a language note says it must cover them with `data.core: true`, and a word names the concepts it serves in `concept`; `package-build core` lists what each covering language has no word for (see [the core vocabulary](reference/format-details.md#the-core-vocabulary)). Every fact a check reads about a language's names, sounds and history is frontmatter too: `data.tongues` and `data.register` (every name the setting gives in the language's reach, the notes carrying each derived from the index, and a name tagged `other:<tongue>` or `exonym:<tongue>` one that the tongue's own language note registers under that tongue), `data.retired`, `data.scope`, `data.sounds` (letters with their place, word edges from a closed list, the cluster limit and the groups of clusters inside a word, the stress rule (`two`, `longer` and `mark`), syllable finals, syllable rules and vowel harmony with each vowel's front partner, the joining of parts, written marks, a root's skeleton vowel and frames, the spellings read past, and named mutations such as wearing and voicing), `data.soundChanges` (named sets of ordered steps), `data.elements` (each standing `opening`, `closing`, `either` or `link`, for one kind of name, with the word it is the stem of and its joining form), `data.roots`, `data.cognates` (with a reconstructed `proto` form), `data.callingNames`, `data.older` (the forms older than the rules), `data.negation` (the negative particle and the mutation it brings) and `data.naming` (how long each class of name runs, the edges names keep that words do not, the element kinds each kind of name draws on, what a place name takes from what it is held from, and the near name), each a relation — `sounds` as `letters`, `edges`, `clusters`, `cluster_groups`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past` and `mutations`, `soundChanges` as `sound_changes`, `callingNames` as `calling_names` — that a fence sets back on the page. A word's citations also come from a note whose name, alias or rank or office title spells it whole. See [a language's words](reference/format-details.md#a-languages-words), [a language's register, sounds and history](reference/format-details.md#a-languages-register-sounds-and-history), [glossary terms](reference/format-details.md#glossary-terms) and [dictionaries and glossaries](reference/format-details.md#dictionaries-and-glossaries).
180
+ A language note (`type: skill`, `subType: language`) states its words in frontmatter: `data.words` states each word as a map of its form, class, field and gloss — one sense or a list of them, which a dictionary numbers — with its source, its variant forms, the pieces it is built from and a note, beside `data.classModifiers`, `data.fields` and `data.affixes`, each affix with the `kind` it makes, for a given name's ending who the name is `given` to, and the stem closes it is barred after; a zero affix states `zero: true` and no form. The notes a word is cited from are derived, not written: a note cites a word by marking it in italics in its prose, matched by form or a variant with diacritics and case set aside. The language of a word is the note it sits on, and none of it reaches the compiled Item. A daughter language names its parent in `data.family` and reads the parent's words as its own; the `language_lineage` relation joins a language to its ancestors. Classes come from the [master word classes](reference/format-details.md#word-classes). A culture or an affiliation states its own glossary entries in `data.glossary`: common words in its core vocabulary, dictionary words with a context meaning, or phrases, compounds and terms of art outside the dictionary with their own gloss. An entry naming a word of its resolved language takes the word's senses and class and links to its language entry; a `definition` supplies the entry's meaning instead. Common marks belong to the glossary's owner. A language note with nonempty `data.words` receives its full Dictionary section automatically: one alphabetical list with field tags and one key. A culture or affiliation with nonempty `data.glossary` receives only its explicitly declared entries in its Glossary section; ranks and offices stand in the affiliation's own sections. A note without the relevant frontmatter receives no such section. All surfaces show these sections after the authored text, or under an existing `{#dictionary}`, `{#lexicon}` or `{#glossary}` heading after its introduction. There are no setting-wide dictionary or glossary pages. Every entry resolves to a language — its own `language`, else the affiliation's, its parents' or its culture's, else the culture's — or is an error at the entry. The `words`, `affixes`, `fields`, `glossary` and `language_lineage` relations hold them for `sql` fences, the `dictionary` relation lists each word under every language that has it, inherited words included, and the `terms` relation each glossary entry, rank and office with its culture associations; a fence sets custom views with `layout=dictionary` or `layout=glossary`. A language note names the tag a dictionary prints for it in `data.abbreviation`. A `doc` note states a setting's core concepts in `data.concepts`, a language note says it must cover them with `data.core: true`, and a word names the concepts it serves in `concept`; `package-build core` lists what each covering language has no word for (see [the core vocabulary](reference/format-details.md#the-core-vocabulary)). Every fact a check reads about a language's names, sounds and history is frontmatter too: `data.tongues` and `data.register` (every name the setting gives in the language's reach, the notes carrying each derived from the index, and a name tagged `other:<tongue>` or `exonym:<tongue>` one that the tongue's own language note registers under that tongue), `data.retired`, `data.scope`, `data.sounds` (letters with their place, their IPA and the tongues that write them, each a declared tag or a language note's Address, word edges from a closed list, the cluster limit and the groups of clusters inside a word, the stress rule (`two`, `longer`, which may be `first`, and `mark`), syllable finals with their IPA, syllable rules and vowel harmony with each vowel's front partner, the joining of parts, written marks, a root's skeleton vowel and frames, the spellings read past, and named mutations such as wearing and voicing), `data.soundChanges` (named sets of ordered steps), `data.elements` (each standing `opening`, `closing`, `either` or `link`, for one kind of name, with the word it is the stem of and its joining form), `data.roots`, `data.cognates` (with a reconstructed `proto` form), `data.callingNames`, `data.older` (the forms older than the rules), `data.negation` (the negative particle and the mutation it brings) and `data.naming` (how long each class of name runs, the edges names keep that words do not, the element kinds each kind of name draws on, what a place name takes from what it is held from, and the near name), each a relation — `sounds` as `letters`, `edges`, `clusters`, `cluster_groups`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past` and `mutations`, `soundChanges` as `sound_changes`, `callingNames` as `calling_names` — that a fence sets back on the page. A `doc` note may state a spelling guide's `data.sounds.letters` and `data.sounds.marks` alone, its letter rows naming tongues by language note Addresses, and they join the `letters` and `marks` relations under the guide's Address. A word's citations also come from a note whose name, alias or rank or office title spells it whole. See [a language's words](reference/format-details.md#a-languages-words), [a language's register, sounds and history](reference/format-details.md#a-languages-register-sounds-and-history), [glossary terms](reference/format-details.md#glossary-terms) and [dictionaries and glossaries](reference/format-details.md#dictionaries-and-glossaries).
179
181
 
180
182
  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).
@@ -223,6 +223,49 @@ The build writes these keys; [what the theme draws](../reference/theme-pages.md)
223
223
  describes the panel each one feeds — the infobox, the hero band, the related
224
224
  card, and search — and the generated sections the theme draws as any other.
225
225
 
226
+ ## Decide which pages a reader finds
227
+
228
+ Every note is written as a page, linked or not, and a page is served at its
229
+ address. What a reader can find is what the homepage leads to: the sitemap and
230
+ the site search cover the pages reachable from the homepage, directly or
231
+ through the pages it links, and no others.
232
+
233
+ Reachability is read from the links the rendered pages carry, never from the
234
+ notes' sources. A page is reachable when an authored link leads to it:
235
+
236
+ - a link in the homepage or in the body of a reachable note, including the
237
+ links a `pagelist` or a `sql` table writes into the body;
238
+ - a link in the menu or the rest of the site chrome;
239
+ - a link in a listing: the pages of a section page, a tag page, and the posts
240
+ an Atom feed lists, once a reachable page links the section, the tag or the
241
+ feed. A tag chip on a reachable page links its tag page when `site.tags` is
242
+ on, so every page carrying the tag is then reachable.
243
+
244
+ The links the build generates do not make a page reachable. These are the
245
+ Related card, the previous and next links, the infobox links, and the sections
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
248
+ without a link to a page outside the reachable set, and a section left with
249
+ nothing under it is not drawn. An infobox value that names an unreachable page
250
+ is set as plain text. A link written in prose or produced by a query is kept
251
+ wherever it points, and it is what makes its target reachable.
252
+
253
+ A page that is not reachable is the way to preview a page in place. Write the
254
+ note, build the site, and read the page at its address on the live site; link
255
+ it from the homepage or from a linked page when it is ready to publish. For a
256
+ note `doc-charlie` in the package `setting`:
257
+
258
+ 1. Add `doc-charlie` to the content tree. It is written at
259
+ `/setting/doc-charlie/` and appears in neither the sitemap nor the search.
260
+ 2. Read it at `/setting/doc-charlie/`.
261
+ 3. Link it, for example `[[doc-charlie|Charlie]]` in a linked note, to publish
262
+ it. The next build lists it in the sitemap and the search.
263
+
264
+ An address is a short code and the site serves no directory listing, so an
265
+ unlinked page is found only by someone who knows its address. The content
266
+ index that `package-build content-index` writes is a release asset and is not
267
+ part of the site.
268
+
226
269
  ## Show marked text in its font
227
270
 
228
271
  A site shows text marked with `font=` and one of the faces of
@@ -142,6 +142,29 @@ address of the language's `skill` note of `subType: language`, whose
142
142
  Without `note`, `lang=` only tags: there is no dictionary and no lexicon check.
143
143
  `package-build lint` checks at the key that `note` names a language note.
144
144
 
145
+ **A language names its script.** Most tongues are written in one script, so the
146
+ language note says which, as one map and one face:
147
+
148
+ ```yaml
149
+ data:
150
+ writtenIn: { map: semaron, font: semaron-kuriale }
151
+ ```
152
+
153
+ A run marked with the language alone then takes both: `[Zaron lonak]{lang=vyl}`
154
+ is mapped through Semaron and checked against Vylari exactly as
155
+ `[Zaron lonak]{lang=vyl font=semaron-kuriale map=semaron}` is, and so is a div,
156
+ a verse fence or a `scroll` fence marked `lang=vyl`. A run that states one of
157
+ the two keys keeps it, and takes the other from the language only where the
158
+ two agree: `font=` alone takes the language's map where that map is drawn in
159
+ the face, and `map=` alone takes the language's face where the map is drawn in
160
+ it. So a tongue written in several scripts states its usual one, and a run in
161
+ another names that script's keys. A language whose note states no `writtenIn`
162
+ only tags, as above. The checks are at the key:
163
+
164
+ > `` `data.writtenIn.map` is `semoran`, which no mapping note's `data.map.name` declares; did you mean `semaron`? ``
165
+
166
+ > `` `data.writtenIn.font` is `teng-chou`, which the map `semaron` is not drawn in; it is drawn in `semaron-kuriale` ``
167
+
145
168
  **A run inherits from its passage and overrides it.** A span inside a marked
146
169
  div or fence takes the passage's keys, and its own keys win. A Khelathi phrase
147
170
  inside a Vylari poem is checked against Khelathi's lexicon and tagged Khelathi
@@ -805,8 +828,8 @@ Lokamen lonak zaron.
805
828
 
806
829
  **The stress rule** is `data.sounds.stress`, `{ two, longer, mark }`. `two`
807
830
  (`first` or `last`) places the stress in a word of two syllables; `longer`
808
- (`antepenultimate`, `penultimate` or `final`) places it in a word of three or
809
- more, counted from its end; `mark` (`acute`, `grave` or `circumflex`) is a
831
+ (`first`, `antepenultimate`, `penultimate` or `final`) places it in a word of
832
+ three or more, on its first syllable or counted from its end; `mark` (`acute`, `grave` or `circumflex`) is a
810
833
  diacritic that moves the stress to the syllable it sits on. Syllables are vowel
811
834
  groups: a vowel is a letter whose base is `a`, `e`, `i`, `o` or `u`, and a pair
812
835
  that the language lists in `data.sounds.syllables.vowelPairs` is one syllable.
@@ -850,6 +873,43 @@ A repeated metre name is an error too:
850
873
 
851
874
  > `` `data.metres[1].name` is `trimeter`, which this note declares twice; a metre's name is unique ``
852
875
 
876
+ ## Scripts written in columns
877
+
878
+ A script written in vertical columns, read from the right, states it on its
879
+ script note:
880
+
881
+ ```yaml
882
+ data:
883
+ script:
884
+ fonts: [teng-chou]
885
+ emphasis: rubric
886
+ direction: vertical-rl
887
+ ```
888
+
889
+ A passage in that script goes in a `scroll` fence. Its lines are joined into
890
+ paragraphs, and each paragraph starts at the top of a fresh column. `rows=`
891
+ sets the characters in a column and `cols=` the columns in a panel:
892
+
893
+ ````markdown
894
+ ```scroll {rows=25 cols=12 lang=tsu map=tengchou}
895
+ chen teng chou hing
896
+ tan tsou dou rou
897
+
898
+ gen chei chou tsuen
899
+ ```
900
+ ````
901
+
902
+ Where the Tantsou note states `writtenIn: { map: tengchou, font: teng-chou }`,
903
+ ` ```scroll {rows=25 cols=12 lang=tsu} ` is enough.
904
+
905
+ The site, the preview and Foundry set it in columns, in a panel that scrolls
906
+ sideways from the right. The book draws it as panel images from the face's
907
+ outlines, each with its roman text as alt text. A span in the same script stays
908
+ horizontal, inline in its line. A `scroll` fence in a script that states no
909
+ direction is an error. See
910
+ [scrolls](../authoring/links-and-markup.md#scrolls) for every attribute, the
911
+ defaults on each target and the errors.
912
+
853
913
  ## The core vocabulary
854
914
 
855
915
  A setting can name the concepts every one of its languages has a word for, and
@@ -907,8 +967,9 @@ whose notes set no text in a face, ships none of it.
907
967
  `package-build transliterate <map> [--lang <language>] [--font <slug>] [--hex] [text..]`
908
968
  maps a passage exactly as the build maps a run marked `map=<map> lang=<language>
909
969
  font=<slug>`. The text is the words given; `-` or none reads standard input.
910
- `--font` is required when the mapping lists more than one face, and `--hex`
911
- prints `U+XXXX` code points separated by spaces.
970
+ `--font` defaults to the language's `writtenIn` face where the mapping is drawn
971
+ in it, and is otherwise required when the mapping lists more than one face.
972
+ `--hex` prints `U+XXXX` code points separated by spaces.
912
973
 
913
974
  ```console
914
975
  $ package-build transliterate semaron --lang vyl --hex zaron lonak
@@ -920,8 +981,9 @@ U+F0246 U+F0230 U+F023F U+F023D U+F023C
920
981
  The first run writes `zaron` by its exception, and the second, with no
921
982
  `--lang`, spells it by the rows.
922
983
 
923
- `package-build lexicon <language> --map <map> [--font <slug>] [--derived] [--json]`
924
- lists every word of the language with its native form, tab-separated: the form,
984
+ `package-build lexicon <language> [--map <map>] [--font <slug>] [--derived] [--json]`
985
+ lists every word of the language with its native form under the map, or under
986
+ the language's `writtenIn` script when `--map` is left out, tab-separated: the form,
925
987
  the native form, `exception` or `rows`, the class and the gloss. `--derived`
926
988
  adds the forms the language's rules derive, each with the word it comes from,
927
989
  `--json` prints an array instead, and under a logographic map the third column
@@ -1993,7 +1993,7 @@ errors.
1993
1993
 
1994
1994
  - **`lang=`** is a name declared in [`languages`](../configuration.md#languages),
1995
1995
  and otherwise a BCP 47 tag checked for its form alone. It gives the language
1996
- tag and changes nothing else.
1996
+ tag, and the language's script where its note names one.
1997
1997
  - **`font=`** is a face of the installed `@heroiclands/fonts`, named by its
1998
1998
  `fonts.json` class without `hl-`, or `mono`, `serif` or `sans`.
1999
1999
  - **`map=`** is the `data.map.name` of a [mapping note](#mapping-notes). The
@@ -2003,6 +2003,14 @@ errors.
2003
2003
  - **`lang=` with `map=`** reads the language's lexicon first, when
2004
2004
  [`languages.<name>.note`](../configuration.md#languages) names its language
2005
2005
  note: see [a map reads the dictionary first](#a-map-reads-the-dictionary-first).
2006
+ - **`lang=` without `map=` or `font=`** takes the map and the face its
2007
+ language note names in `data.writtenIn`, where the note states one. A run
2008
+ that states `font=` alone takes the language's map only where the map is
2009
+ drawn in that face, and one that states `map=` alone takes the language's
2010
+ face only where that map is drawn in it. A run stating both takes nothing.
2011
+ The default is read after a div or fence has given the run its keys, and is
2012
+ its own language's. See
2013
+ [a language's script](../authoring/links-and-markup.md#a-languages-script).
2006
2014
 
2007
2015
  **A face draws the code points its `fonts.json` entry lists in `codepoints`,
2008
2016
  and whitespace.** After the map, any other character in a run set in a face is
@@ -2022,9 +2030,10 @@ with a real language's tag alone keeps its Markdown. See
2022
2030
  [marking language, font and mapping](../authoring/links-and-markup.md#marking-language-font-and-mapping).
2023
2031
 
2024
2032
  Each own-note metadata record carries `runs` in source order, an empty array
2025
- when the body marks nothing. Every entry has exactly `kind` (`span`, `block` or
2033
+ when the body marks nothing. Every entry has exactly `kind` (`span`, `block`, `scroll` or
2026
2034
  `verse`), `lang`, `tag`, `font`, `map`, `line` and `column`: `lang`, `font` and
2027
- `map` as written, its own or inherited, `tag` the BCP 47 tag `lang` resolves
2035
+ `map` as written, its own or inherited, else its language's `data.writtenIn`
2036
+ (a scroll fence that names no face takes its map's), `tag` the BCP 47 tag `lang` resolves
2028
2037
  to, each `null` when absent, and the position of the span's `[`, the div's
2029
2038
  `:::` or the fence's opening. Every value is a string or a number and none is a
2030
2039
  key, so tags that differ only in case are separate values. This is derived
@@ -2364,8 +2373,9 @@ the words' native forms; `package-build lexicon` resolves them.
2364
2373
 
2365
2374
  #### Script notes and emphasis
2366
2375
 
2367
- A `skill` note of `subType: script` states the faces its script is written in
2368
- and how the script marks a stressed word, in `data.script`:
2376
+ A `skill` note of `subType: script` states the faces its script is written in,
2377
+ how the script marks a stressed word, and the direction it is written in, in
2378
+ `data.script`:
2369
2379
 
2370
2380
  ```yaml
2371
2381
  data:
@@ -2381,6 +2391,25 @@ data:
2381
2391
  (or `_…_` and `__…__`) inside a run in one of the faces.
2382
2392
  - **`strongEmphasis`**, optional, is `rubric` or `overline`, and sets `**…**`
2383
2393
  alone.
2394
+ - **`direction`**, optional, is `vertical-rl` for a script written in columns,
2395
+ top to bottom, with the columns read from the right. A
2396
+ [`scroll` fence](../authoring/links-and-markup.md#scrolls) sets text in
2397
+ such a script, and is an error in any other. A script that states no
2398
+ direction is written in lines.
2399
+
2400
+ A `skill` note of `subType: language` may state `data.writtenIn`, the script
2401
+ the language is written in: `map`, the `data.map.name` of a mapping note, and
2402
+ `font`, one of the faces that map lists, both required.
2403
+
2404
+ ```yaml
2405
+ data:
2406
+ writtenIn: { map: semaron, font: semaron-kuriale }
2407
+ ```
2408
+
2409
+ A run marked with the language alone is mapped by `map` and set in `font`, as
2410
+ [text marked with a language, a font or a map](#text-marked-with-a-language-a-font-or-a-map)
2411
+ describes. A face a language's `writtenIn` names counts as used, so the
2412
+ package's fonts are delivered for it.
2384
2413
 
2385
2414
  A `skill` note of `subType: language` may state `data.emphasis`: `words`,
2386
2415
  `rubric` or `overline`. It overrides the script's convention in every run of the
@@ -2410,10 +2439,18 @@ Each of these is an error at the key or the entry at fault:
2410
2439
 
2411
2440
  > `` `data.script.emphasis` should be `rubric` or `overline`, but reads "rubrik". Did you mean "rubric"? ``
2412
2441
 
2442
+ > `` `data.script.direction` should be `vertical-rl`, but reads "vertical" ``
2443
+
2413
2444
  > `` `data.script` states a script's faces and emphasis, and this note's `subType` is not `script` ``
2414
2445
 
2415
2446
  > `` `data.emphasis` states how a language marks emphasis, and this note's `subType` is not `language` ``
2416
2447
 
2448
+ > `` `data.writtenIn` names the script a language is written in, and this note's `subType` is not `language` ``
2449
+
2450
+ > `` `data.writtenIn.map` is `semoran`, which no mapping note's `data.map.name` declares; did you mean `semaron`? ``
2451
+
2452
+ > `` `data.writtenIn.font` is `teng-chou`, which the map `semaron` is not drawn in; it is drawn in `semaron-kuriale` ``
2453
+
2417
2454
  > `` `data.script.fonts` is empty; a script lists each face it is written in ``
2418
2455
 
2419
2456
  > `` `data.script.fonts[0]` is `serif`, a generic family; a script lists the faces it is written in ``
@@ -3546,15 +3583,15 @@ for the keys.
3546
3583
  | `tongues` | `data.tongues` | `tag`, `meaning`, and `tongue_language`, the tongue's `language` |
3547
3584
  | `retired` | `data.retired` | `form`, `instead` (always a list, `NULL` where nothing is written instead), `why` |
3548
3585
  | `scope` | `data.scope` | No `position`: `kind`, the key the value is under (`folders`, `cultures`, `lore`, `parents`, `addresses`, `paths`, `types` or `skip`), and `value`, an Address in its canonical form or a path or a type |
3549
- | `letters` | `data.sounds.letters` | `letters` (a list), `kind`, `like`, `place`, `tongue` (a list, `NULL` for every tongue) |
3586
+ | `letters` | `data.sounds.letters` | `letters` (a list), `kind`, `like`, `place`, `ipa`, `tongue` (a list, `NULL` for every tongue); a [spelling guide's](#a-spelling-guides-sounds) rows too, keyed by the guide |
3550
3587
  | `edges` | `data.sounds.edges` | `edge`, `sounds` (a list: `[any]` for every sound, empty for none) |
3551
3588
  | `clusters` | `data.sounds.clusters` | No `position`: `max`, one row per language stating it |
3552
3589
  | `stress` | `data.sounds.stress` | No `position`: `two`, `longer` and `mark` (`NULL` where unstated), one row per language stating it |
3553
- | `finals` | `data.sounds.finals` | `final`, `like` |
3590
+ | `finals` | `data.sounds.finals` | `final`, `like`, `ipa` |
3554
3591
  | `syllables` | `data.sounds.syllables` | No `position`, one row per language stating it: `onsets`, `codas`, `finals`, `doubled`, `vowelPairs`, `neverInitial` and `signature` (lists, `any` a list of one), `initialVowel` and `finalVowel` (`true` or `false`), and the harmony as `harmony_back`, `harmony_front`, `harmony_neutral`, `harmony_neutralAs` and `harmony_partners` (a list of `{ vowel, partner }`) |
3555
3592
  | `joining` | `data.sounds.joining` | `first` and `second` (lists), `written`, `example` |
3556
3593
  | `joins` | `data.sounds.joins` | `meeting`, `rule`, `letters` (a list), `where` |
3557
- | `marks` | `data.sounds.marks` | `mark`, `letters` (a list), `kind`, `limit` |
3594
+ | `marks` | `data.sounds.marks` | `mark`, `letters` (a list), `kind`, `limit`; a spelling guide's rows too, keyed by the guide |
3558
3595
  | `skeleton` | `data.sounds.skeleton` | `second` (a list, `[any]` for every other), `between` |
3559
3596
  | `frames` | `data.sounds.frames` | `frame`, `shape`, `class` (a list), `makes`, `examples` (a list of `{ root, form }`) |
3560
3597
  | `read_past` | `data.sounds.readPast` | `written`, `readAs`, `what` |
@@ -3616,7 +3653,7 @@ including on an empty relation:
3616
3653
  | Column | SQL type | Meaning |
3617
3654
  | -------- | --------- | -------------------------------------------------------------------------------------------- |
3618
3655
  | `owner` | `VARCHAR` | Containing authored page's canonical NOTE Address, or `NULL` when the record has no Address. |
3619
- | `kind` | `VARCHAR` | `span`, `block` or `verse`. |
3656
+ | `kind` | `VARCHAR` | `span`, `block`, `verse` or `scroll`. |
3620
3657
  | `lang` | `VARCHAR` | The language as written, its own or inherited, or `NULL`. |
3621
3658
  | `tag` | `VARCHAR` | The BCP 47 tag `lang` resolves to, or `NULL` when it resolves to none. |
3622
3659
  | `font` | `VARCHAR` | The font as written, its own or inherited, or `NULL`. |
@@ -6181,12 +6218,13 @@ SoHL sets `system.quantity` to `1` for each compendium item.
6181
6218
  | `scope.types` | `string[]` | The note types covered; a note of another type is out of scope whatever else catches it |
6182
6219
  | `scope.skip` | `Address[]` | Notes out of scope whatever else catches them |
6183
6220
  | `sounds` | `{ letters?, edges?, clusters?, stress?, finals?, syllables?, joining?, joins?, marks?, skeleton?, frames?, readPast? }` | `language` only: the letters it writes and the rules its words keep |
6184
- | `sounds.letters` | `{ letters, kind, like?, place?, tongue? }[]` | The letters and the sounds they stand for |
6221
+ | `sounds.letters` | `{ letters, kind, like?, place?, ipa?, tongue? }[]` | The letters and the sounds they stand for |
6185
6222
  | `sounds.letters[].letters` | `string[]`, required | The letters or digraphs the row describes |
6186
6223
  | `sounds.letters[].kind` | `string`, required | What kind of sound they write, as `consonant` or `long vowel` |
6187
6224
  | `sounds.letters[].like` | `string` | What they sound like; absent where the row states only their kind and place |
6188
6225
  | `sounds.letters[].place` | `string` | Where in the mouth they are made, as `lips` or `tongue-tip` |
6189
- | `sounds.letters[].tongue` | `string` or `string[]` | The tongues that write them, as tags `tongues` declares; every one where absent |
6226
+ | `sounds.letters[].ipa` | `string` | The sounds they write, in the International Phonetic Alphabet, as `ʃ` |
6227
+ | `sounds.letters[].tongue` | `string` or `string[]` | The tongues that write them, each a tag `tongues` declares or a language note's Address; every one where absent |
6190
6228
  | `sounds.edges` | `{ edge, sounds }[]` | The sounds that may stand at each edge of a word, one entry per edge |
6191
6229
  | `sounds.edges[].edge` | `openConsonant`, `openCluster`, `closeConsonant`, `closeCluster`, `innerCluster`, `vowelPair`, `glide` or `syllabic`, required | Which edge the sounds stand at |
6192
6230
  | `sounds.edges[].sounds` | `string[]` or `any`, required | The sounds; `any` for every one, an empty list for none |
@@ -6198,11 +6236,12 @@ SoHL sets `system.quantity` to `1` for each compendium item.
6198
6236
  | `sounds.clusters.groups[].use` | `common` or `sparing`, required | How often the group's clusters stand inside a word |
6199
6237
  | `sounds.stress` | `{ two, longer, mark? }` | Where a word's stress falls, as a rule a program reads |
6200
6238
  | `sounds.stress.two` | `first` or `last`, required | The stressed syllable of a word of two syllables |
6201
- | `sounds.stress.longer` | `antepenultimate`, `penultimate` or `final`, required | The stressed syllable of a word of three or more, counted from its end |
6239
+ | `sounds.stress.longer` | `first`, `antepenultimate`, `penultimate` or `final`, required | The stressed syllable of a word of three or more: the first, or counted from its end |
6202
6240
  | `sounds.stress.mark` | `acute`, `grave` or `circumflex` | The diacritic that marks a stress the rule would not choose; it moves the stress to the syllable it sits on |
6203
- | `sounds.finals` | `{ final, like }[]` | The syllable finals, for a language whose syllables are parsed by them |
6241
+ | `sounds.finals` | `{ final, like, ipa? }[]` | The syllable finals, for a language whose syllables are parsed by them |
6204
6242
  | `sounds.finals[].final` | `string`, required | The final, as `ang` |
6205
6243
  | `sounds.finals[].like` | `string`, required | What it sounds like |
6244
+ | `sounds.finals[].ipa` | `string` | Its sound, in the International Phonetic Alphabet |
6206
6245
  | `sounds.syllables` | map of syllable rules | What a syllable and a word may open and close on |
6207
6246
  | `sounds.syllables.onsets` | `single` | What a syllable opens on: a single consonant |
6208
6247
  | `sounds.syllables.codas` | `string[]` or `any` | The consonants that may close a syllable |
@@ -6332,10 +6371,14 @@ SoHL sets `system.quantity` to `1` for each compendium item.
6332
6371
  | `affixes[].native[].font` | `string` | The one face the writing is for, one the map lists; unstated, every face it lists |
6333
6372
  | `affixes[].native[].text` | `string`, required | The affix as the script writes it |
6334
6373
  | `emphasis` | `words`, `rubric` or `overline` | `language` only: how the language marks a stressed word, over its script's; `words` makes `*…*` and `**…**` in its runs an error — see [script notes and emphasis](#script-notes-and-emphasis) |
6335
- | `script` | `{ fonts, emphasis, strongEmphasis? }` | `script` only: the faces the script is written in and how it marks emphasis — see [script notes and emphasis](#script-notes-and-emphasis) |
6374
+ | `writtenIn` | `{ map, font }` | `language` only: the script the language is written in, which a run marked with the language alone takes — see [script notes and emphasis](#script-notes-and-emphasis) |
6375
+ | `writtenIn.map` | `string`, required | The `data.map.name` of a mapping note |
6376
+ | `writtenIn.font` | `string`, required | A face the map lists |
6377
+ | `script` | `{ fonts, emphasis, strongEmphasis?, direction? }` | `script` only: the faces the script is written in, how it marks emphasis and its direction — see [script notes and emphasis](#script-notes-and-emphasis) |
6336
6378
  | `script.fonts` | `string[]`, required | Installed faces by the slug `font=` names them by; a face belongs to one script |
6337
6379
  | `script.emphasis` | `rubric` or `overline`, required | Sets `*…*` and `**…**` in a run in one of its faces |
6338
6380
  | `script.strongEmphasis` | `rubric` or `overline` | Sets `**…**` instead of `emphasis` |
6381
+ | `script.direction` | `vertical-rl` | Written in columns, top to bottom, read from the right, which a [`scroll` fence](../authoring/links-and-markup.md#scrolls) sets |
6339
6382
 
6340
6383
  #### A language's words
6341
6384
 
@@ -6815,8 +6858,11 @@ unless `types` is stated and leaves its type out, or `skip` names it.
6815
6858
 
6816
6859
  **`sounds` states the letters and the rules a word keeps.** `letters` gives
6817
6860
  each letter or group of letters, the kind of sound it writes, what it sounds
6818
- like, where in the mouth it is made and, in a language whose tongues write
6819
- differently, the tongues that write it. A row that states only a kind and a
6861
+ like, where in the mouth it is made, its sound in the International Phonetic
6862
+ Alphabet as `ipa` and, in a language whose tongues write differently, the
6863
+ tongues that write it. Each `tongue` is a tag `tongues` declares, or else the
6864
+ Address of a language note, so a row can name another language's note
6865
+ directly. A row that states only a kind and a
6820
6866
  place — one cell of a grid of consonants by manner and place — states no
6821
6867
  `like`. `edges` gives the sounds that may stand at each edge of a word, one
6822
6868
  entry per edge, the edge from a closed list:
@@ -6846,14 +6892,15 @@ closed list where its values are words:
6846
6892
 
6847
6893
  - `stress`: the rule a program reads, `{ two, longer, mark? }`. `two` is the
6848
6894
  stressed syllable of a word of two syllables, `first` or `last`; `longer` is
6849
- the stressed syllable of a word of three or more, counted from its end,
6850
- `antepenultimate`, `penultimate` or `final`; `mark` is the diacritic, `acute`,
6895
+ the stressed syllable of a word of three or more, `first`, or counted from its
6896
+ end, `antepenultimate`, `penultimate` or `final`; `mark` is the diacritic, `acute`,
6851
6897
  `grave` or `circumflex`, that marks a stress the rule would not choose and
6852
6898
  moves it to the syllable it sits on. Syllables are vowel groups, a pair listed
6853
6899
  in `syllables.vowelPairs` counting as one. A verse fence's `scan=` counts
6854
6900
  beats by this rule; see [metres](#metres).
6855
- - `finals`: the syllable finals, each with what it sounds like, for a language
6856
- whose syllables are parsed by them.
6901
+ - `finals`: the syllable finals, each with what it sounds like and, as `ipa`,
6902
+ its sound in the International Phonetic Alphabet, for a language whose
6903
+ syllables are parsed by them.
6857
6904
  - `syllables`: what a syllable opens on (`single`, a single consonant), the
6858
6905
  `codas` that close a syllable and the `finals` that close a word (a list, or
6859
6906
  `any`), the `doubled` consonants and `vowelPairs` a word may hold (none where
@@ -7040,6 +7087,40 @@ FROM edges WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
7040
7087
  `cognates` read the same way; [content tables](#content-tables) gives every
7041
7088
  relation's columns.
7042
7089
 
7090
+ #### A spelling guide's sounds
7091
+
7092
+ One spelling guide can state the letters every tongue of a setting is written
7093
+ by. A `doc` note of any subType may state `data.sounds` with `letters` and
7094
+ `marks` alone, each row with a language note's keys, `ipa` included:
7095
+
7096
+ ```yaml
7097
+ type: doc
7098
+ subType: reference
7099
+ data:
7100
+ sounds:
7101
+ letters:
7102
+ - { letters: [sh], kind: consonant, like: ship, ipa: ʃ }
7103
+ - {
7104
+ letters: [ui],
7105
+ kind: vowel pair,
7106
+ like: gooey,
7107
+ ipa: ui,
7108
+ tongue: [skill-tantsoulng, skill-jurthatlng],
7109
+ }
7110
+ marks:
7111
+ - { mark: diaeresis, letters: [ë], kind: length, limit: any }
7112
+ ```
7113
+
7114
+ A guide declares no tags, so a letter row's `tongue` names language notes by
7115
+ their Addresses, and each must resolve to a `skill` of `subType: language`. Any
7116
+ other key of `sounds` is an error at the key, since the rules of a word belong
7117
+ to its language. The rows are rows of the `letters` and `marks` relations, with
7118
+ the guide's Address as `language`. Each of these is an error at the value:
7119
+
7120
+ > `` `data.sounds.letters[1].tongue` names `vylari`, which is no language note's Address; a spelling guide names each tongue by its language note ``
7121
+
7122
+ > `` `data.sounds.letters[1].tongue[1]` names thalorna-note-skill-riding, which is not a skill whose subType is language ``
7123
+
7043
7124
  if a `sohl` property is present, a SoHL item of type "skill" is created.
7044
7125
 
7045
7126
  If an `hm3` property is present, an HM3 item of type "skill" is created.
@@ -8190,35 +8271,48 @@ Content prepared to be played — a situation with its cast, places, and possibl
8190
8271
  - settingguide: A culture's guide to the setting, which names its culture in `data.culture`. It orients a reader to a setting or region, bringing its places, peoples, institutions, and daily life into one usable frame with links to detailed notes.
8191
8272
  - post: A blog post, which states the day it was published in `data.date` and may name its writer in `data.author`. A site whose `site.feed` names a section lists its posts there, newest first, and feeds them as Atom.
8192
8273
 
8193
- | `data` property | Values | Description |
8194
- | --------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
8195
- | `culture` | `Address` | `settingguide` only, and required there: the culture the guide introduces, naming a lore note with `subType: culture` |
8196
- | `concepts` | list of `{ id, gloss, group }` | A core vocabulary's concept list, any subType. See [the core vocabulary](#the-core-vocabulary) |
8197
- | `date` | `YYYY-MM-DD` | `post` only, and required there: the day the post was published |
8198
- | `author` | string | `post` only: who wrote the post; a post naming none carries the site's byline, the first entry of `authors` |
8199
- | `concepts[].id` | string | Required: lowercase letters, digits and `-`, unique in the package |
8200
- | `concepts[].gloss` | string | Required: what the concept means, in brief |
8201
- | `concepts[].group` | string | Required: the group the report lists the concept under |
8202
- | `map` | `{ name, vowels?, fonts, rows }` | A mapping, which text marked `map=` with its `name` is rewritten by; any subType. See [mapping notes](#mapping-notes) |
8203
- | `map.name` | string | Required: what `map=` names it by, lowercase letters, digits and `-`, unique in the index |
8204
- | `map.vowels` | string | The characters `before: vowel` reads as vowels |
8205
- | `map.rows` | list of `[from, to]` or `{ from, to, before?, at? }` | Required: the rewrites, in authored order |
8206
- | `map.rows[].from` | string of one or more characters | Required in a map row: the characters it matches |
8207
- | `map.rows[].to` | string, which may be empty | Required in a map row: what it writes in their place |
8208
- | `map.rows[].before` | `vowel \| consonant` | What must follow the match |
8209
- | `map.rows[].at` | `start \| end` | Where the match must sit |
8210
- | `map.fonts` | list of `{ font, rows? }` | Required, at least one: the faces the map is drawn in |
8211
- | `map.fonts[].font` | an installed face's slug | Required: the face, as `font=` names it; not `mono`, `serif` or `sans` |
8212
- | `map.fonts[].rows` | list of `[from, to]` or `{ from, to, before?, at? }` | Rows for this face alone, tried before the shared `rows` |
8213
- | `map.fonts[].rows[].from` | string of one or more characters | Required in a map row: the characters it matches |
8214
- | `map.fonts[].rows[].to` | string, which may be empty | Required in a map row: what it writes in their place |
8215
- | `map.fonts[].rows[].before` | `vowel \| consonant` | What must follow the match |
8216
- | `map.fonts[].rows[].at` | `start \| end` | Where the match must sit |
8217
- | `metres` | `{ name, beats, kind }[]` | The metres a verse fence's `scan=` names; any subType. See [metres](#metres) |
8218
- | `metres[].name` | string | Required: what `scan=` names it by, lowercase letters, digits and `-`, unique in the package |
8219
- | `metres[].beats` | `integer`, required | The beats of one line, above zero |
8220
- | `metres[].kind` | `accentual` | Required: how the beats are counted |
8221
- | `map.logographic` | `true` | The script writes meanings: a run's words are written by the lexicon alone, and the rows write only the text between them |
8274
+ | `data` property | Values | Description |
8275
+ | --------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
8276
+ | `culture` | `Address` | `settingguide` only, and required there: the culture the guide introduces, naming a lore note with `subType: culture` |
8277
+ | `concepts` | list of `{ id, gloss, group }` | A core vocabulary's concept list, any subType. See [the core vocabulary](#the-core-vocabulary) |
8278
+ | `date` | `YYYY-MM-DD` | `post` only, and required there: the day the post was published |
8279
+ | `author` | string | `post` only: who wrote the post; a post naming none carries the site's byline, the first entry of `authors` |
8280
+ | `concepts[].id` | string | Required: lowercase letters, digits and `-`, unique in the package |
8281
+ | `concepts[].gloss` | string | Required: what the concept means, in brief |
8282
+ | `concepts[].group` | string | Required: the group the report lists the concept under |
8283
+ | `map` | `{ name, vowels?, fonts, rows }` | A mapping, which text marked `map=` with its `name` is rewritten by; any subType. See [mapping notes](#mapping-notes) |
8284
+ | `map.name` | string | Required: what `map=` names it by, lowercase letters, digits and `-`, unique in the index |
8285
+ | `map.vowels` | string | The characters `before: vowel` reads as vowels |
8286
+ | `map.rows` | list of `[from, to]` or `{ from, to, before?, at? }` | Required: the rewrites, in authored order |
8287
+ | `map.rows[].from` | string of one or more characters | Required in a map row: the characters it matches |
8288
+ | `map.rows[].to` | string, which may be empty | Required in a map row: what it writes in their place |
8289
+ | `map.rows[].before` | `vowel \| consonant` | What must follow the match |
8290
+ | `map.rows[].at` | `start \| end` | Where the match must sit |
8291
+ | `map.fonts` | list of `{ font, rows? }` | Required, at least one: the faces the map is drawn in |
8292
+ | `map.fonts[].font` | an installed face's slug | Required: the face, as `font=` names it; not `mono`, `serif` or `sans` |
8293
+ | `map.fonts[].rows` | list of `[from, to]` or `{ from, to, before?, at? }` | Rows for this face alone, tried before the shared `rows` |
8294
+ | `map.fonts[].rows[].from` | string of one or more characters | Required in a map row: the characters it matches |
8295
+ | `map.fonts[].rows[].to` | string, which may be empty | Required in a map row: what it writes in their place |
8296
+ | `map.fonts[].rows[].before` | `vowel \| consonant` | What must follow the match |
8297
+ | `map.fonts[].rows[].at` | `start \| end` | Where the match must sit |
8298
+ | `metres` | `{ name, beats, kind }[]` | The metres a verse fence's `scan=` names; any subType. See [metres](#metres) |
8299
+ | `metres[].name` | string | Required: what `scan=` names it by, lowercase letters, digits and `-`, unique in the package |
8300
+ | `metres[].beats` | `integer`, required | The beats of one line, above zero |
8301
+ | `metres[].kind` | `accentual` | Required: how the beats are counted |
8302
+ | `map.logographic` | `true` | The script writes meanings: a run's words are written by the lexicon alone, and the rows write only the text between them |
8303
+ | `sounds` | `{ letters?, marks? }` | A spelling guide's letters and marks, for every tongue of the setting; any subType. See [a spelling guide's sounds](#a-spelling-guides-sounds) |
8304
+ | `sounds.letters` | `{ letters, kind, like?, place?, ipa?, tongue? }[]` | The letters, each row's keys as a language note's `sounds.letters` |
8305
+ | `sounds.letters[].letters` | `string[]`, required | The letters or digraphs the row describes |
8306
+ | `sounds.letters[].kind` | `string`, required | What kind of sound they write, as `consonant` or `vowel pair` |
8307
+ | `sounds.letters[].like` | `string` | What they sound like |
8308
+ | `sounds.letters[].place` | `string` | Where in the mouth they are made |
8309
+ | `sounds.letters[].ipa` | `string` | The sounds they write, in the International Phonetic Alphabet |
8310
+ | `sounds.letters[].tongue` | an Address, or a list of them | The language notes that write the letters; every tongue where absent |
8311
+ | `sounds.marks` | `{ mark, letters, kind, limit }[]` | The marks written on the letters, each row's keys as a language note's `sounds.marks` |
8312
+ | `sounds.marks[].mark` | `string`, required | The mark's name, as `acute` |
8313
+ | `sounds.marks[].letters` | `string[]`, required | The letters that carry it |
8314
+ | `sounds.marks[].kind` | `stress` or `length`, required | What it says of its letter |
8315
+ | `sounds.marks[].limit` | `one` or `any`, required | How many a word may carry |
8222
8316
 
8223
8317
  A setting guide introduces one culture's view of the setting, so it names that
8224
8318
  culture, and a `doc` of any other `subType` has no culture of its own to name.