@heroiclands/package-build 24.0.4 → 24.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +6 -0
- package/assets/styles/content-base.css +25 -10
- package/docs/authoring/links-and-markup.md +215 -179
- package/docs/commands.md +5 -2
- package/docs/configuration.md +6 -3
- package/docs/content-format.md +4 -3
- package/docs/diagnostics.md +57 -29
- package/docs/guides/book.md +1 -1
- package/docs/guides/module-project.md +2 -2
- package/docs/guides/site.md +2 -2
- package/docs/guides/writing-in-invented-scripts.md +175 -125
- package/docs/reference/format-details.md +53 -35
- package/docs/reference/note-types.md +10 -10
- package/docs/reference/theme-pages.md +18 -9
- package/engine/content-render.mjs +23 -2
- package/engine/content-scripts.mjs +348 -140
- package/engine/content-spans.mjs +13 -1
- package/engine/content-verse.mjs +158 -373
- package/engine/note-vocabulary.mjs +5 -5
- package/engine/pdf-render.mjs +63 -44
- package/engine/run-rows.mjs +18 -20
- package/engine/verse-metre.mjs +36 -8
- package/engine/written-in.mjs +9 -13
- package/package.json +1 -1
- package/site-theme/static/css/style.css +19 -10
- package/types/engine/content-scripts.d.mts +18 -7
- package/types/engine/content-verse.d.mts +37 -163
- package/types/engine/run-rows.d.mts +16 -9
- package/types/engine/verse-metre.d.mts +4 -3
|
@@ -1962,32 +1962,45 @@ exit status. Supplied-value errors prevent publication and compilation.
|
|
|
1962
1962
|
|
|
1963
1963
|
#### Text marked with a language, a font or a map
|
|
1964
1964
|
|
|
1965
|
-
`lang
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
errors.
|
|
1965
|
+
`lang=` identifies a span, generic div, verse fence or scroll fence's
|
|
1966
|
+
language while retaining authored spelling and the surrounding prose font.
|
|
1967
|
+
`.nativefont` explicitly requests native presentation and requires `lang=` on
|
|
1968
|
+
that same construct; an inherited language does not satisfy the requirement.
|
|
1969
|
+
On a named block the language, font and map keys are errors.
|
|
1970
1970
|
|
|
1971
1971
|
- **`lang=`** is a name declared in [`languages`](../configuration.md#languages),
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1972
|
+
otherwise a BCP 47 tag checked for its form alone. Language identification
|
|
1973
|
+
and its existing validation do not depend on native presentation.
|
|
1974
|
+
- **`.nativefont`** selects that language's `data.writtenIn` map and font.
|
|
1975
|
+
A native run needs an effective font; a missing default reports the
|
|
1976
|
+
required `font=` override. The map is optional when the language supplies
|
|
1977
|
+
none, so directly typed script code points can be set without mapping. The
|
|
1978
|
+
build does not guess a font from a map's list of faces.
|
|
1979
|
+
- **`font=`** overrides the native font independently. Without `.nativefont`,
|
|
1980
|
+
only `mono`, `serif` and `sans` are permitted.
|
|
1981
|
+
- **`map=`** overrides the native map independently and requires `.nativefont`.
|
|
1982
|
+
It names a [mapping note](#mapping-notes). With a configured language note,
|
|
1983
|
+
mapping reads that language's lexicon first; see
|
|
1984
|
+
[a map reads the dictionary first](#a-map-reads-the-dictionary-first).
|
|
1985
|
+
|
|
1986
|
+
Unmarked text follows its passage. Each marked child chooses its presentation:
|
|
1987
|
+
a language-only child stays Roman, even inside a native passage of that same
|
|
1988
|
+
language. A native child requires its own explicit `lang=` and `.nativefont`,
|
|
1989
|
+
uses its own language's defaults and applies only its own overrides.
|
|
1990
|
+
|
|
1991
|
+
Standalone wikilinks accept the same attributes. `[[address|Name]]{lang=vyl}`
|
|
1992
|
+
stays Roman, while `[[address|Name]]{lang=vyl .nativefont}` applies native
|
|
1993
|
+
mapping and font to the displayed name alone. Targets, spoilers, `.show`,
|
|
1994
|
+
draft annotations and book page cues retain their behavior. Adjacent prose
|
|
1995
|
+
belongs in sibling spans; an embedded link inside a longer native run is an error.
|
|
1996
|
+
Parallel verse uses `cols=N`, a positive whole number defaulting to one.
|
|
1997
|
+
With multiple columns, each content line starts with its column number and
|
|
1998
|
+
one or more spaces. Blank-separated logical rows accept nondecreasing
|
|
1999
|
+
numbers in `1..cols`, preserving omitted cells and any number of repeated
|
|
2000
|
+
readings. The first reading in each column is foreground and all later ones
|
|
2001
|
+
in that column are grey; each row resets that choice. `numstep` counts logical
|
|
2002
|
+
rows, and `***` separates stanzas. Language and native script choices remain
|
|
2003
|
+
on the authored inline runs, independently for every reading.
|
|
1991
2004
|
|
|
1992
2005
|
**A face draws the code points its `fonts.json` entry lists in `codepoints`,
|
|
1993
2006
|
and whitespace.** After the map, any other character in a run set in a face is
|
|
@@ -2007,13 +2020,15 @@ with a real language's tag alone keeps its Markdown. See
|
|
|
2007
2020
|
[marking language, font and mapping](../authoring/links-and-markup.md#marking-language-font-and-mapping).
|
|
2008
2021
|
|
|
2009
2022
|
Each own-note metadata record carries `runs` in source order, an empty array
|
|
2010
|
-
when the body marks nothing. Every entry has
|
|
2023
|
+
when the body marks nothing. Every entry has `kind` (`span`, `block`, `scroll` or
|
|
2011
2024
|
`verse`), `lang`, `tag`, `font`, `map`, `line` and `column`: `lang`, `font` and
|
|
2012
|
-
`map` as written,
|
|
2013
|
-
|
|
2025
|
+
`map` as written, or its language's `data.writtenIn` defaults only for an
|
|
2026
|
+
explicit `.nativefont` run, `tag` the BCP 47 tag `lang` resolves
|
|
2014
2027
|
to, each `null` when absent, and the position of the span's `[`, the div's
|
|
2015
|
-
`:::` or the fence's opening.
|
|
2016
|
-
|
|
2028
|
+
`:::` or the fence's opening. An opted-in run also carries optional `nativefont: true`; Roman runs omit
|
|
2029
|
+
that flag and leave unused script defaults null. The `runs` SQL relation
|
|
2030
|
+
retains its existing columns and projects no flag column. Tags differing
|
|
2031
|
+
only in case remain separate values. This is derived
|
|
2017
2032
|
metadata, not frontmatter. The [`runs` relation](#content-tables) flattens
|
|
2018
2033
|
these entries with their containing NOTE Address.
|
|
2019
2034
|
|
|
@@ -2167,7 +2182,7 @@ is written word by word:
|
|
|
2167
2182
|
plural or a verb ending of an exception word is a different word, and the
|
|
2168
2183
|
rows spell it.
|
|
2169
2184
|
|
|
2170
|
-
A run with
|
|
2185
|
+
A native run with an explicit bare BCP 47 `lang=` tag, and a
|
|
2171
2186
|
declared language with no `note` are spelled by the rows alone. A character the
|
|
2172
2187
|
face does not draw inside a word written by its native form is an error at the
|
|
2173
2188
|
word's start:
|
|
@@ -2176,7 +2191,9 @@ word's start:
|
|
|
2176
2191
|
|
|
2177
2192
|
> `` `zaron` is written U+F024F by the lexicon of `vyl` for the map `semaron`, which the font `semaron-kuriale` does not draw ``
|
|
2178
2193
|
|
|
2179
|
-
**
|
|
2194
|
+
**Language word-book validation applies to Roman and native runs alike**,
|
|
2195
|
+
independently of `.nativefont` or mapping. Every word is a word of the
|
|
2196
|
+
language, case folded: a
|
|
2180
2197
|
`data.words[].form`, a word of a name the language note's own `data.register`
|
|
2181
2198
|
lists under a `tongue` other than `translation`, or a form one rule derives from a lexicon form —
|
|
2182
2199
|
the `data.grammar.plural` plural of a noun or its own `plural`, a verb's form
|
|
@@ -2383,7 +2400,8 @@ data:
|
|
|
2383
2400
|
writtenIn: { map: semaron, font: semaron-kuriale }
|
|
2384
2401
|
```
|
|
2385
2402
|
|
|
2386
|
-
A run marked with the language
|
|
2403
|
+
A run explicitly marked with the language and `.nativefont` is mapped by
|
|
2404
|
+
`map` and set in `font`, as
|
|
2387
2405
|
[text marked with a language, a font or a map](#text-marked-with-a-language-a-font-or-a-map)
|
|
2388
2406
|
describes. A face a language's `writtenIn` names counts as used, so the
|
|
2389
2407
|
package's fonts are delivered for it.
|
|
@@ -3602,8 +3620,8 @@ including on an empty relation:
|
|
|
3602
3620
|
| `kind` | `VARCHAR` | `span`, `block`, `verse` or `scroll`. |
|
|
3603
3621
|
| `lang` | `VARCHAR` | The language as written, its own or inherited, or `NULL`. |
|
|
3604
3622
|
| `tag` | `VARCHAR` | The BCP 47 tag `lang` resolves to, or `NULL` when it resolves to none. |
|
|
3605
|
-
| `font` | `VARCHAR` | The font
|
|
3606
|
-
| `map` | `VARCHAR` | The map
|
|
3623
|
+
| `font` | `VARCHAR` | The selected font; language defaults apply only to native runs, else `NULL`. |
|
|
3624
|
+
| `map` | `VARCHAR` | The selected map; language defaults apply only to native runs, else `NULL`. |
|
|
3607
3625
|
| `line` | `BIGINT` | Original 1-based source line of the span's `[`, the div's `:::` or the fence's opening. |
|
|
3608
3626
|
| `column` | `BIGINT` | Original 1-based UTF-16 source column there. |
|
|
3609
3627
|
|
|
@@ -6318,7 +6336,7 @@ SoHL sets `system.quantity` to `1` for each compendium item.
|
|
|
6318
6336
|
| `affixes[].native[].font` | `string` | The one face the writing is for, one the map lists; unstated, every face it lists |
|
|
6319
6337
|
| `affixes[].native[].text` | `string`, required | The affix as the script writes it |
|
|
6320
6338
|
| `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) |
|
|
6321
|
-
| `writtenIn` | `{ map, font }` | `language` only: the script the language is written in, which a run marked with the language
|
|
6339
|
+
| `writtenIn` | `{ map, font }` | `language` only: the script the language is written in, which a run explicitly marked with the language and `.nativefont` takes — see [script notes and emphasis](#script-notes-and-emphasis) |
|
|
6322
6340
|
| `writtenIn.map` | `string`, required | The `data.map.name` of a mapping note |
|
|
6323
6341
|
| `writtenIn.font` | `string`, required | A face the map lists |
|
|
6324
6342
|
| `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) |
|
|
@@ -483,7 +483,7 @@ These fields are accepted by every note type. A field's value can still be irrel
|
|
|
483
483
|
| `data.negation` | a map — `{ particle, mutation? }` | How a verb is negated. A language skill note only. |
|
|
484
484
|
| `data.naming` | a map — `{ shapes?, edges?, draws?, heldFrom?, nearName? }` | The shapes, edges and sources the language's names keep beyond its words' rules. A language skill note only. |
|
|
485
485
|
| `data.emphasis` | `words`, `rubric` or `overline` | How the language marks a stressed word, over its script's `emphasis`: `rubric` or `overline` sets `*…*` and `**…**` so in a run of the language, and `words` marks it with a word, so either is a finding. Only a skill of `subType: language` states it. |
|
|
486
|
-
| `data.writtenIn` | a map — `{ map, font }` | The script the language is written in, as the map and
|
|
486
|
+
| `data.writtenIn` | a map — `{ map, font }` | The script the language is written in, as the default map and face selected by a run with explicit `lang=` and `.nativefont`; a run's own `map=` or `font=` overrides its half. Only a skill of `subType: language` states it. |
|
|
487
487
|
| `data.script` | a map — `{ fonts, emphasis, strongEmphasis?, direction? }` | A script note's faces, how it marks emphasis and the direction it is written in. Only a skill of `subType: script` states it. |
|
|
488
488
|
|
|
489
489
|
**Inner keys** — a key a field's value does not declare is an error at its own line and column.
|
|
@@ -1000,15 +1000,15 @@ Lore records in-world knowledge. A `culture` describes a people; a `custom` desc
|
|
|
1000
1000
|
|
|
1001
1001
|
**Subtypes:** `rules`, `userguide`, `reference`, `howto`, `concept`, `settingguide`, `post`.
|
|
1002
1002
|
|
|
1003
|
-
| Field | Shape | Meaning
|
|
1004
|
-
| --------------- | ------------------------------------------------------ |
|
|
1005
|
-
| `data.concepts` | list of `{ id, gloss, group }` | The concepts of a core vocabulary, in the order the report lists them. See [the core vocabulary](format-details.md#the-core-vocabulary).
|
|
1006
|
-
| `data.date` | string | The day a post was published, as `YYYY-MM-DD`. Required on a `post`; no other subType states it. Posts are listed and fed newest first by it.
|
|
1007
|
-
| `data.author` | string | Who wrote a post, as the byline prints them. A post that names none carries the site's byline, the first entry of `authors`; no other subType states it.
|
|
1008
|
-
| `data.culture` | an Address | The culture a setting guide introduces, as a culture lore note. Required on `settingguide`; no other subType states it.
|
|
1009
|
-
| `data.sounds` | a map — `{ letters?, marks? }` | A spelling guide's letters and the marks written on them, for every tongue of the setting: each letter row's `tongue` names the language notes that write it.
|
|
1010
|
-
| `data.map` | a map — `{ name, logographic?, vowels?, fonts, rows }` | A mapping, which text marked `
|
|
1011
|
-
| `data.metres` | list of `{ name, beats, kind }` | The metres a verse fence's `scan=` names. A fence that states one is warned at each line that cannot have its beats. See [metres](../authoring/links-and-markup.md#metre).
|
|
1003
|
+
| Field | Shape | Meaning |
|
|
1004
|
+
| --------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1005
|
+
| `data.concepts` | list of `{ id, gloss, group }` | The concepts of a core vocabulary, in the order the report lists them. See [the core vocabulary](format-details.md#the-core-vocabulary). |
|
|
1006
|
+
| `data.date` | string | The day a post was published, as `YYYY-MM-DD`. Required on a `post`; no other subType states it. Posts are listed and fed newest first by it. |
|
|
1007
|
+
| `data.author` | string | Who wrote a post, as the byline prints them. A post that names none carries the site's byline, the first entry of `authors`; no other subType states it. |
|
|
1008
|
+
| `data.culture` | an Address | The culture a setting guide introduces, as a culture lore note. Required on `settingguide`; no other subType states it. |
|
|
1009
|
+
| `data.sounds` | a map — `{ letters?, marks? }` | A spelling guide's letters and the marks written on them, for every tongue of the setting: each letter row's `tongue` names the language notes that write it. |
|
|
1010
|
+
| `data.map` | a map — `{ name, logographic?, vowels?, fonts, rows }` | A mapping, which native text marked with `lang=`, `.nativefont` and its `map=` name is rewritten by before it is set. See [mapping notes](format-details.md#mapping-notes). |
|
|
1011
|
+
| `data.metres` | list of `{ name, beats, kind }` | The metres a verse fence's `scan=` names. A fence that states one is warned at each line that cannot have its beats. See [metres](../authoring/links-and-markup.md#metre). |
|
|
1012
1012
|
|
|
1013
1013
|
**Inner keys** — a key a field's value does not declare is an error at its own line and column.
|
|
1014
1014
|
|
|
@@ -340,10 +340,18 @@ keys reach the block as written, `lang` as its language and the rest as
|
|
|
340
340
|
numbered line starts with its `.verse-number`.
|
|
341
341
|
|
|
342
342
|
A [verse in columns](../authoring/links-and-markup.md#verse-in-columns) also
|
|
343
|
-
carries `.verse-columns`, and each
|
|
343
|
+
carries `.verse-columns`, and each logical row is one `.verse-row`. The
|
|
344
|
+
block carries `data-cols` and `--verse-columns` with its positive column
|
|
345
|
+
count. Every row contains that many `.verse-column` cells, including empty
|
|
346
|
+
ones:
|
|
344
347
|
|
|
345
348
|
```html
|
|
346
|
-
<div
|
|
349
|
+
<div
|
|
350
|
+
class="verse verse-columns verse-numbered"
|
|
351
|
+
lang="art-x-vyl"
|
|
352
|
+
data-numstep="5"
|
|
353
|
+
data-cols="3"
|
|
354
|
+
style="--verse-columns: 3">
|
|
347
355
|
<p>
|
|
348
356
|
<span class="verse-row"
|
|
349
357
|
><span class="verse-number"></span
|
|
@@ -351,6 +359,7 @@ carries `.verse-columns`, and each verse line is one `.verse-row`:
|
|
|
351
359
|
><span class="verse-part"
|
|
352
360
|
><span class="script hl-semaron-kuriale" lang="art-x-vyl">…</span></span
|
|
353
361
|
></span
|
|
362
|
+
><span class="verse-column"></span
|
|
354
363
|
><span class="verse-column"
|
|
355
364
|
><span class="verse-part"><span lang="en">The hallowed boundary I sing,</span></span
|
|
356
365
|
><span class="verse-part verse-secondary"
|
|
@@ -363,10 +372,10 @@ carries `.verse-columns`, and each verse line is one `.verse-row`:
|
|
|
363
372
|
</div>
|
|
364
373
|
```
|
|
365
374
|
|
|
366
|
-
A numbered verse in columns gives every row a `.verse-number`, empty
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
375
|
+
A numbered verse in columns gives every logical row a `.verse-number`, empty
|
|
376
|
+
on rows it does not number, so repeated readings do not advance the counter.
|
|
377
|
+
The grid remains left to right while inline text follows its own script
|
|
378
|
+
direction. Each row has its own grid and aligns all its cells at the top. Below a block width of `32rem` a row stacks
|
|
370
379
|
its columns in order; it is a container query, so a narrow journal window
|
|
371
380
|
stacks as well. The Foundry stylesheet draws the same.
|
|
372
381
|
|
|
@@ -377,10 +386,10 @@ stacks as well. The Foundry stylesheet draws the same.
|
|
|
377
386
|
| `.verse-numbered` | a numbered poem, with a margin for its numbers |
|
|
378
387
|
| `.verse-number` | a line's number, muted |
|
|
379
388
|
| `.verse-columns` | a poem in columns, and the container its rows are measured by |
|
|
380
|
-
| `.verse-row` | one verse
|
|
381
|
-
| `.verse-column` | one
|
|
389
|
+
| `.verse-row` | one logical verse row: its number and its cells |
|
|
390
|
+
| `.verse-column` | one numbered cell, possibly empty, with its readings stacked |
|
|
382
391
|
| `.verse-part` | one entry's text, in the body serif unless its face sets it |
|
|
383
|
-
| `.verse-secondary` | every
|
|
392
|
+
| `.verse-secondary` | every reading after a column's first in that row, grey |
|
|
384
393
|
|
|
385
394
|
## Emphasis in a script
|
|
386
395
|
|
|
@@ -77,7 +77,7 @@ import { imagePlugin } from "./content-images.mjs";
|
|
|
77
77
|
import { renderRuns } from "./content-scripts.mjs";
|
|
78
78
|
import { renderSpans, spanMarkdownPlugin } from "./content-spans.mjs";
|
|
79
79
|
import { cartoucheFigures, renderSymbolSpans } from "./content-symbols.mjs";
|
|
80
|
-
import { inlineVerse, verseStanzas } from "./content-verse.mjs";
|
|
80
|
+
import { hasColumns, inlineVerse, scanVerse, verseGroups, verseStanzas } from "./content-verse.mjs";
|
|
81
81
|
import { replaceOutsideCode } from "./code-fences.mjs";
|
|
82
82
|
import { dictionaryEntryPlugin } from "./dictionary-layout.mjs";
|
|
83
83
|
import { headingAttributesPlugin, headingIdsPlugin } from "./heading-attributes.mjs";
|
|
@@ -129,11 +129,32 @@ function verseInlinePlugin(md) {
|
|
|
129
129
|
if (token.type !== "fence" || !/^verse(?:\s|$)/.test(token.info?.trim() || ""))
|
|
130
130
|
continue;
|
|
131
131
|
token.meta ??= {};
|
|
132
|
+
const source = `${token.markup}${token.info}\n${token.content}${token.markup}`;
|
|
133
|
+
const poem = scanVerse(source).blocks[0];
|
|
134
|
+
if (hasColumns(poem)) {
|
|
135
|
+
token.meta.verseGroups = verseGroups(poem, source.split("\n")).map((group) => {
|
|
136
|
+
if (group.stanzaBreak) return group;
|
|
137
|
+
return {
|
|
138
|
+
...group,
|
|
139
|
+
parts: group.parts.map((part) => {
|
|
140
|
+
const children = [];
|
|
141
|
+
state.md.inline.parse(
|
|
142
|
+
inlineVerse(part.text),
|
|
143
|
+
state.md,
|
|
144
|
+
state.env,
|
|
145
|
+
children,
|
|
146
|
+
);
|
|
147
|
+
return { ...part, children };
|
|
148
|
+
}),
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
132
153
|
token.meta.verseStanzas = verseStanzas(token.content).map((stanza) =>
|
|
133
154
|
stanza.map(({ text, level }) => {
|
|
134
155
|
const children = [];
|
|
135
156
|
state.md.inline.parse(inlineVerse(text), state.md, state.env, children);
|
|
136
|
-
return { children, level };
|
|
157
|
+
return { children, level, stanzaBreak: /^\*{3}$/.test(text) };
|
|
137
158
|
}),
|
|
138
159
|
);
|
|
139
160
|
}
|