@heroiclands/package-build 25.3.0 → 25.5.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 +39 -0
- package/README.md +1 -1
- package/assets/styles/content-base.css +32 -0
- package/docs/api.md +30 -6
- package/docs/authoring/links-and-markup.md +143 -53
- package/docs/commands.md +8 -2
- package/docs/content-format.md +14 -6
- package/docs/diagnostics.md +12 -11
- package/docs/encoding-core.md +18 -4
- package/docs/guides/writing-in-invented-scripts.md +83 -37
- package/docs/reference/format-details.md +10 -11
- package/docs/reference/note-types.md +15 -15
- package/docs/reference/theme-pages.md +26 -18
- package/engine/anchors.mjs +14 -0
- package/engine/code-fences.mjs +15 -6
- package/engine/content-blocks.mjs +4 -2
- package/engine/content-figures.mjs +19 -5
- package/engine/content-footnotes.mjs +69 -1
- package/engine/content-index.mjs +1 -1
- package/engine/content-render.mjs +59 -43
- package/engine/content-scripts.mjs +301 -58
- package/engine/content-scroll.mjs +8 -3
- package/engine/content-spans.mjs +107 -6
- package/engine/content-verse.mjs +338 -198
- package/engine/encoding-standard.mjs +1 -0
- package/engine/encoding-template.mjs +5 -2
- package/engine/encoding.mjs +19 -14
- package/engine/first-use.mjs +43 -12
- package/engine/heading-attributes.mjs +2 -1
- package/engine/journals.mjs +8 -1
- package/engine/markdown-blocks.mjs +3 -2
- package/engine/markdownlint-run.mjs +190 -5
- package/engine/markup-validation.mjs +17 -0
- package/engine/name-markup.mjs +1 -0
- package/engine/note-vocabulary.mjs +2 -2
- package/engine/pdf-render.mjs +34 -23
- package/engine/prose-lint.mjs +14 -2
- package/engine/roman-characters.mjs +32 -10
- package/engine/roman-run.mjs +3 -0
- package/engine/roman-verse.mjs +1 -0
- package/engine/run-rows.mjs +1 -1
- package/engine/sql-tables.mjs +1 -1
- package/engine/verse-format.mjs +89 -0
- package/engine/verse-metre.mjs +18 -9
- package/engine/verse-regions.mjs +190 -0
- package/engine/wikilink-pattern.mjs +31 -0
- package/engine/wikilink-syntax.mjs +2 -16
- package/package.json +1 -1
- package/site-theme/static/css/style.css +24 -0
- package/types/engine/code-fences.d.mts +1 -3
- package/types/engine/content-footnotes.d.mts +23 -0
- package/types/engine/content-scripts.d.mts +4 -3
- package/types/engine/content-scroll.d.mts +1 -1
- package/types/engine/content-spans.d.mts +3 -1
- package/types/engine/content-verse.d.mts +75 -75
- package/types/engine/name-markup.d.mts +5 -0
- package/types/engine/roman-run.d.mts +3 -1
- package/types/engine/verse-format.d.mts +10 -0
- package/types/engine/verse-metre.d.mts +4 -4
- package/types/engine/verse-regions.d.mts +82 -0
- package/types/engine/wikilink-pattern.d.mts +17 -0
- package/types/engine/wikilink-syntax.d.mts +1 -41
package/docs/diagnostics.md
CHANGED
|
@@ -302,27 +302,28 @@ without collecting problems. The rules are under
|
|
|
302
302
|
[Versions of a work](authoring/links-and-markup.md#versions-and-stanza-labels)
|
|
303
303
|
share a page-local `work=` key and the same stanza shape. For example:
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
```markdown
|
|
306
|
+
::: {.verse work=watch lang=en}
|
|
307
307
|
The watch arrives.
|
|
308
308
|
|
|
309
309
|
The harbor wakes.
|
|
310
|
-
|
|
310
|
+
:::
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
::: {.verse work=watch lang=en}
|
|
313
313
|
Another telling has only one stanza.
|
|
314
|
+
:::
|
|
314
315
|
```
|
|
315
|
-
````
|
|
316
316
|
|
|
317
317
|
The opening lines receive findings naming canto 1 and its differing stanza
|
|
318
318
|
counts, two and one. The first version is included in the disagreement. A key
|
|
319
|
-
used by only one version is also a finding at that
|
|
319
|
+
used by only one version is also a finding at that div's opening line.
|
|
320
320
|
|
|
321
321
|
A concrete `enc=` creates its own script and Roman presentations from one
|
|
322
322
|
original; the display does not add a second authored version. Source newlines
|
|
323
|
-
join unless `/` ends the line. Blank lines and `//` end stanzas. A
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
join unless `/` ends the line. Blank lines and `//` end stanzas. A canto uses
|
|
324
|
+
`--- {.canto}` on its own line after a blank line. A leading, trailing or
|
|
325
|
+
consecutive canto separator without a stanza between is located at the break
|
|
326
|
+
itself. Authored `***` is a finding. Language and encoding findings retain their positions in the single
|
|
326
327
|
authored original, including text inside names, directions and speaker labels.
|
|
327
328
|
The content index records that original once in `runs`.
|
|
328
329
|
|
|
@@ -601,8 +602,8 @@ finding naming its `⟦U+XXXX⟧` spelling. Use that notation, or the chosen
|
|
|
601
602
|
encoding's codage name, inside the literal markers. The encoder checks the
|
|
602
603
|
codes; the Roman validator leaves their contents immutable.
|
|
603
604
|
|
|
604
|
-
A verse
|
|
605
|
-
stanzas, and
|
|
605
|
+
A verse div uses `/` for logical line endings, `//` or blank lines for
|
|
606
|
+
stanzas, and `--- {.canto}` after a blank line for cantos. A literal slash is written `\/`.
|
|
606
607
|
Visual indentation at a logical line boundary does not add periods to the
|
|
607
608
|
encoded text; a period on a joined continuation line remains text. Source positions survive Markdown escapes and nested
|
|
608
609
|
`.emph` or `.name` spans.
|
package/docs/encoding-core.md
CHANGED
|
@@ -136,9 +136,15 @@ encoding has its Roman forms checked against the lettered one only.
|
|
|
136
136
|
English names under a language's `data.names.en` are not encoded and are not
|
|
137
137
|
checked against any encoding.
|
|
138
138
|
|
|
139
|
-
Every encoding inherits the shared standard's
|
|
139
|
+
Every encoding inherits the shared standard's Roman punctuation
|
|
140
140
|
mappings, verse and name controls, and literal boundaries. `‼` marks an
|
|
141
|
-
imperative and `!` an exclamation.
|
|
141
|
+
imperative and `!` an exclamation. Configured language runs require sentence
|
|
142
|
+
text before each terminal (`.`, `?`, `‼`, `!`). Validation reports an opening
|
|
143
|
+
terminal at its original source position, including escaped marks. Whitespace,
|
|
144
|
+
indentation and verse boundaries preserve sentence state; opening quotations
|
|
145
|
+
start their own sentence, and closing quotations contribute their enclosed
|
|
146
|
+
text to the surrounding sentence. Names, literal codage and independent
|
|
147
|
+
language children count as text. An explicit mapping can give a standard
|
|
142
148
|
source its own font glyph. Other punctuation needs its own mapping.
|
|
143
149
|
|
|
144
150
|
## Conversion API
|
|
@@ -195,8 +201,16 @@ of the opening, closing or escape control are quoted with U+E0115; decoding
|
|
|
195
201
|
unquotes them before reading their codes. Unknown codes, malformed escapes,
|
|
196
202
|
nested markers and unmatched markers are errors.
|
|
197
203
|
|
|
198
|
-
|
|
199
|
-
|
|
204
|
+
The shared `\/` row writes the nonprinting U+E010F literal-slash mark and
|
|
205
|
+
decodes it to `\/`; `/` writes the distinct U+E010C line mark. Verse projection
|
|
206
|
+
retains the escape until encoding, including inside inline quotations. A row
|
|
207
|
+
program without a literal-slash row reports a source finding instead of
|
|
208
|
+
substituting a line control. Ordinary mappings cannot emit U+E010F.
|
|
209
|
+
|
|
210
|
+
`{verse: true}` handles line, stanza and canto structure. The encoder receives
|
|
211
|
+
`***` for a canto and decodes U+E010E back to `***`. Whitespace before the canto
|
|
212
|
+
still writes its stanza mark; following source whitespace adds no line mark.
|
|
213
|
+
The Markdown renderer additionally writes a boundary after every content line, including
|
|
200
214
|
the final line before a stanza or canto. Roman line layout is retained.
|
|
201
215
|
|
|
202
216
|
The internal row conformance fixtures cover their captured source programs;
|
|
@@ -72,9 +72,15 @@ keys makes a separate presentation choice. `enc=default` inside an encoded
|
|
|
72
72
|
parent keeps the inherited language but does not inherit its inferred script
|
|
73
73
|
face. An explicitly authored font remains a font choice.
|
|
74
74
|
|
|
75
|
+
Footnotes are not letters of the tongue. A defined `[^key]` in any encoded span
|
|
76
|
+
is removed before encoding and restored after the span, outside the script font.
|
|
77
|
+
In an encoded verse div, a reference appears only in the Roman column, beside
|
|
78
|
+
its authored word, with no duplicate number, definition or backlink. Footnotes
|
|
79
|
+
never change verse shape. See [footnotes in works and encoded spans](../authoring/links-and-markup.md#footnotes-in-works-and-encoded-spans).
|
|
80
|
+
|
|
75
81
|
A name's braces use the shared name controls. Resolved references encode only
|
|
76
82
|
their visible labels, retaining URLs and presentation cues. These keys apply
|
|
77
|
-
to spans, divs
|
|
83
|
+
to spans, divs and scroll fences. A scroll's selected font must
|
|
78
84
|
belong to a script whose note declares `direction: vertical-rl`.
|
|
79
85
|
|
|
80
86
|
## Roman source and literal characters
|
|
@@ -93,8 +99,11 @@ are supplied automatically. A language that lists uppercase letters accepts
|
|
|
93
99
|
them; the build changes no authored case.
|
|
94
100
|
|
|
95
101
|
The terminals are `.` for a statement, `?` for a question, `‼` for an imperative
|
|
96
|
-
and `!` for an exclamation. None is required. A
|
|
97
|
-
|
|
102
|
+
and `!` for an exclamation. None is required. A terminal needs preceding text
|
|
103
|
+
in its sentence; `! Vesun` is a finding at `!`, while `Vesun!` is valid.
|
|
104
|
+
Whitespace, indentation, verse boundaries and a preceding terminal do not
|
|
105
|
+
supply sentence text. A comma pauses within a sentence; use it instead of `;`
|
|
106
|
+
or `:`, and use a period between complete sentences.
|
|
98
107
|
Quotation pairs alternate `«…»`, `‹…›`, then `«…»` at successive depths.
|
|
99
108
|
English double quotes, `<<` and `>>` are findings. A closing quote is not a
|
|
100
109
|
terminal for the enclosing sentence.
|
|
@@ -106,11 +115,14 @@ escapes are removed before encoding, and diagnostics retain the source position.
|
|
|
106
115
|
|
|
107
116
|
Every `Zs` space separator and U+0009 through U+000D count as whitespace. A run
|
|
108
117
|
of them is one word separator, which the encoding writes by its own rule.
|
|
109
|
-
Newlines join as whitespace. In a verse
|
|
110
|
-
blank lines or `//` end stanzas, and
|
|
118
|
+
Newlines join as whitespace. In a verse div, `/` ends a logical line,
|
|
119
|
+
blank lines or `//` end stanzas, and `--- {.canto}` after a blank line ends a canto. A literal
|
|
111
120
|
slash is written `\/`. Indentation at a logical line boundary is layout,
|
|
112
121
|
not a punctuation character added to the encoded words.
|
|
113
122
|
|
|
123
|
+
An encoded literal slash has its own invisible mark, distinct from the verse
|
|
124
|
+
line mark, and decodes to `\/`. It never ends the logical line.
|
|
125
|
+
|
|
114
126
|
A `.name` child in a language run reaches the encoding with standard `{…}`
|
|
115
127
|
name boundaries. An `.emph` child contributes the same letters with emphasis
|
|
116
128
|
presentation. Both inherit the surrounding native writing when they state no
|
|
@@ -485,52 +497,86 @@ The keys are checked where they sit:
|
|
|
485
497
|
|
|
486
498
|
## Verse
|
|
487
499
|
|
|
488
|
-
### A poem in a verse
|
|
500
|
+
### A poem in a verse div
|
|
489
501
|
|
|
490
|
-
A
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
502
|
+
A `.verse` div holds inline Markdown and explicit verse structure. It is opaque
|
|
503
|
+
to lists, headings, quotes and code-block syntax. Its source newlines join unless
|
|
504
|
+
`/` ends a logical line. The authoring formatter preserves the div's text,
|
|
505
|
+
spacing and attributes, and also preserves inline `.verse` quotations. Quote
|
|
506
|
+
and list containers remain intact, table columns use the quotation's authored
|
|
507
|
+
width, and verse follows the same configured line endings as surrounding prose.
|
|
494
508
|
|
|
495
|
-
|
|
496
|
-
|
|
509
|
+
```markdown
|
|
510
|
+
::: {.verse lang=vyl font=semaron-kuriale enc=vylsemaronenc}
|
|
497
511
|
Lokazor lonak./
|
|
498
512
|
.lokamen zaron.
|
|
513
|
+
:::
|
|
499
514
|
```
|
|
500
|
-
|
|
515
|
+
|
|
516
|
+
Both `:::verse` and `::: {.verse}` inherit the enclosing div's language when
|
|
517
|
+
no `lang=` is stated. A link can select its label's language with trailing
|
|
518
|
+
attributes: `[[lore-longtunnel|Zebra Quartz]]{lang=en}`. This overrides the verse
|
|
519
|
+
language for the label while preserving the destination, including in an encoded
|
|
520
|
+
original's script and Roman columns.
|
|
521
|
+
|
|
522
|
+
Quoted verse is a span within prose, such as
|
|
523
|
+
`[Lokazor lonak zaron./..Lokamen lonak zaron.//]{.verse lang=vyl}`.
|
|
524
|
+
A concrete `enc=` sets a quotation in script only, continuously in the prose.
|
|
525
|
+
Its `/` and `//` become the encoding's verse marks; only a div has paired script
|
|
526
|
+
and Roman columns. Each stanza ending contributes its control, including
|
|
527
|
+
consecutive `//` marks and a final `//`. An unencoded quotation keeps Roman
|
|
528
|
+
line and stanza layout.
|
|
529
|
+
Quotations take no `work=`, `form=`, `scan=`, labels or canto breaks.
|
|
530
|
+
A div's canto separator can carry a heading and an anchor:
|
|
531
|
+
|
|
532
|
+
```markdown
|
|
533
|
+
::: {.verse lang=en}
|
|
534
|
+
The watch arrives.
|
|
535
|
+
|
|
536
|
+
--- {.canto #choosing title="The Choosing"}
|
|
537
|
+
The captain answers.
|
|
538
|
+
:::
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The title is shown once as heading text; the encoder receives its Roman `***`
|
|
542
|
+
canto control. Authored `***` inside verse is a finding. The canto stays within
|
|
543
|
+
the work and does not open a separate journal page.
|
|
544
|
+
|
|
545
|
+
The blank line before a canto retains its stanza mark in the encoded text.
|
|
546
|
+
Whitespace after the canto control adds no extra line mark.
|
|
501
547
|
|
|
502
548
|
### Versions of a work
|
|
503
549
|
|
|
504
550
|
`form=epic` records the author's literary form without inferring layout or metre.
|
|
505
551
|
|
|
506
|
-
A
|
|
552
|
+
A `.verse` div with a concrete `enc=` sets one original in its script on the
|
|
507
553
|
left and Roman on the right. The author writes the text once; the two
|
|
508
554
|
presentations align logical lines at full weight. `/` ends a logical line,
|
|
509
555
|
source newlines otherwise join, a blank line or `//` ends a stanza, and a line
|
|
510
|
-
of
|
|
556
|
+
of `--- {.canto}`, preceded by a blank line, ends a canto. Leading periods at a logical line boundary indent
|
|
511
557
|
that line. Use `\/` for a literal slash.
|
|
512
558
|
|
|
513
|
-
|
|
514
|
-
|
|
559
|
+
```markdown
|
|
560
|
+
::: {.verse work=walking lang=en}
|
|
515
561
|
He walks the oath road.
|
|
516
562
|
|
|
517
563
|
I walk the oath road.
|
|
518
|
-
|
|
564
|
+
:::
|
|
519
565
|
|
|
520
|
-
|
|
566
|
+
::: {.verse work=walking lang=vyl enc=vylsemaronenc}
|
|
521
567
|
Lokazor lonak zaron.
|
|
522
568
|
|
|
523
569
|
Lokamen lonak zaron.
|
|
570
|
+
:::
|
|
524
571
|
```
|
|
525
|
-
````
|
|
526
572
|
|
|
527
573
|
`work=` groups the versions within the page. Their stanza labels match, and the
|
|
528
574
|
build checks that their canto counts and stanza counts per canto agree. The
|
|
529
|
-
English
|
|
575
|
+
English div is one column, and `enc=default` also stays one Roman column.
|
|
530
576
|
The original's encoded and Roman presentations share one label per stanza.
|
|
531
577
|
Names, `⟦…⟧` codage, language gaps and other inline spans retain their meaning;
|
|
532
578
|
codage draws its glyphs on the left and appears as codage on the right. The
|
|
533
|
-
content index records the original once with its
|
|
579
|
+
content index records the original once with its div language and encoding.
|
|
534
580
|
See [versions and stanza labels](../authoring/links-and-markup.md#versions-and-stanza-labels)
|
|
535
581
|
for poetry and prose examples, and [directions and speakers](../authoring/links-and-markup.md#directions-and-speakers)
|
|
536
582
|
for plain semantic span hooks.
|
|
@@ -549,15 +595,15 @@ data:
|
|
|
549
595
|
`name` is lowercase letters, digits and `-`, unique in the package; `beats` is
|
|
550
596
|
the beats of one line, a whole number above zero; `kind` is `accentual`, the
|
|
551
597
|
only kind: a beat falls on a stressed syllable and the length of a syllable is
|
|
552
|
-
not counted. A
|
|
598
|
+
not counted. A div that states `scan=` with the declared name and a `lang=`
|
|
553
599
|
whose language note states `data.sounds.stress` is counted line by line:
|
|
554
600
|
|
|
555
|
-
|
|
556
|
-
|
|
601
|
+
```markdown
|
|
602
|
+
::: {.verse lang=vyl scan=trimeter}
|
|
557
603
|
Lokazor lonak zaron./
|
|
558
604
|
Lokamen lonak zaron.
|
|
605
|
+
:::
|
|
559
606
|
```
|
|
560
|
-
````
|
|
561
607
|
|
|
562
608
|
**The stress rule** is `data.sounds.stress`, `{ two, longer, mark }`. `two`
|
|
563
609
|
(`first` or `last`) places the stress in a word of two syllables; `longer`
|
|
@@ -587,14 +633,14 @@ the second beats and, in brackets, with all of them:
|
|
|
587
633
|
|
|
588
634
|
> ``this line has 4 beats (5 with secondary beats); the metre `hexameter` has 6``
|
|
589
635
|
|
|
590
|
-
**The check is author-side.** Readers see nothing of it: the rendered
|
|
591
|
-
carries `data-
|
|
636
|
+
**The check is author-side.** Readers see nothing of it: the rendered div
|
|
637
|
+
carries `data-scan` with the metre's name and nothing a reader sees. A div
|
|
592
638
|
without `scan=` is not counted. `scan=` is refused where it cannot mean
|
|
593
639
|
anything, each an error:
|
|
594
640
|
|
|
595
641
|
> `` `hexamter` is not a declared metre: `scan=` names the `name` of a `data.metres` entry of a `doc` note; did you mean `hexameter`? ``
|
|
596
642
|
|
|
597
|
-
> `` `scan=` counts beats by a language's stress rule: the
|
|
643
|
+
> `` `scan=` counts beats by a language's stress rule: the div needs a `lang=` ``
|
|
598
644
|
|
|
599
645
|
> ``the language `vyl` states no `data.sounds.stress`, which `scan=` counts beats by``
|
|
600
646
|
|
|
@@ -1144,11 +1190,11 @@ capital `L` of the rows, `zaron` is the exception's long vowel, and each period
|
|
|
1144
1190
|
writes the script's pause point.
|
|
1145
1191
|
|
|
1146
1192
|
A work's English and original versions sit on one note. Its original is written
|
|
1147
|
-
once and appears beside its Roman presentation; a separate
|
|
1193
|
+
once and appears beside its Roman presentation; a separate div checks metre.
|
|
1148
1194
|
|
|
1149
1195
|
**`assets/content/Lore/Walking.md`**
|
|
1150
1196
|
|
|
1151
|
-
|
|
1197
|
+
```markdown
|
|
1152
1198
|
---
|
|
1153
1199
|
shortcode: walking
|
|
1154
1200
|
name: { full: The Walking }
|
|
@@ -1159,23 +1205,23 @@ The walking of the oath road is sung in two settings. The first sets the poem
|
|
|
1159
1205
|
beside its translation, and the second keeps the metre that the court keeps, so
|
|
1160
1206
|
that a line with the wrong count is reported to the author who wrote it.
|
|
1161
1207
|
|
|
1162
|
-
|
|
1208
|
+
::: {.verse work=walking lang=en}
|
|
1163
1209
|
He walks the oath road.
|
|
1164
1210
|
|
|
1165
1211
|
I walk the oath road.
|
|
1166
|
-
|
|
1212
|
+
:::
|
|
1167
1213
|
|
|
1168
|
-
|
|
1214
|
+
::: {.verse work=walking lang=vyl enc=vylsemaronenc}
|
|
1169
1215
|
Lokazor lonak zaron.
|
|
1170
1216
|
|
|
1171
1217
|
Lokamen lonak zaron.
|
|
1172
|
-
|
|
1218
|
+
:::
|
|
1173
1219
|
|
|
1174
|
-
|
|
1220
|
+
::: {.verse lang=vyl scan=trimeter}
|
|
1175
1221
|
Lokazor lonak zaron./
|
|
1176
1222
|
Lokamen lonak zaron.
|
|
1223
|
+
:::
|
|
1177
1224
|
```
|
|
1178
|
-
````
|
|
1179
1225
|
|
|
1180
1226
|
A script note gives Semaron its emphasis convention, and a run with double stars then
|
|
1181
1227
|
sets them in red:
|
|
@@ -1994,9 +1994,9 @@ not.
|
|
|
1994
1994
|
|
|
1995
1995
|
##### Name-marking findings
|
|
1996
1996
|
|
|
1997
|
-
`package-build lint` reports
|
|
1998
|
-
|
|
1999
|
-
code, comments and embeds are outside
|
|
1997
|
+
`package-build lint` reports one name-marking warning in authored body prose.
|
|
1998
|
+
It leaves a valid package passing. Headings, frontmatter, tables, infoboxes,
|
|
1999
|
+
code, comments and embeds are outside this check.
|
|
2000
2000
|
|
|
2001
2001
|
1. A `.name` span without a `ref` whose whole text matches an indexed
|
|
2002
2002
|
`name.full` or a form its `name` lists, ignoring case, should be a link or
|
|
@@ -2025,8 +2025,7 @@ valid inside emphasis:
|
|
|
2025
2025
|
The name is `Joe Blow`; the surrounding phrase is emphasis.
|
|
2026
2026
|
|
|
2027
2027
|
Each finding is one warning at its authored `file:line:column`, naming the
|
|
2028
|
-
full name or explicit label.
|
|
2029
|
-
occurrence.
|
|
2028
|
+
full name or explicit label.
|
|
2030
2029
|
|
|
2031
2030
|
An optional `data-type` on a `.name` span states what the named thing is:
|
|
2032
2031
|
|
|
@@ -2107,7 +2106,7 @@ face. An explicitly authored font remains a font choice.
|
|
|
2107
2106
|
|
|
2108
2107
|
A name's braces use the shared name controls. Resolved references encode only
|
|
2109
2108
|
their visible labels, retaining URLs and presentation cues. These keys apply
|
|
2110
|
-
to spans, divs
|
|
2109
|
+
to spans, divs and scroll fences. A scroll's selected font must
|
|
2111
2110
|
belong to a script whose note declares `direction: vertical-rl`.
|
|
2112
2111
|
|
|
2113
2112
|
#### Encodings
|
|
@@ -2273,7 +2272,7 @@ keeps a lexicon to its exceptions.
|
|
|
2273
2272
|
|
|
2274
2273
|
#### Metres
|
|
2275
2274
|
|
|
2276
|
-
A verse
|
|
2275
|
+
A verse div that states `scan=` is counted against a metre declared in a
|
|
2277
2276
|
`doc` note's `data.metres`, each entry `{ name, beats, kind }`. `name` is
|
|
2278
2277
|
lowercase letters, digits and `-`, unique in the package, and a name declared
|
|
2279
2278
|
twice is an error at the second. `beats` is a whole number above zero. `kind` is
|
|
@@ -3592,7 +3591,7 @@ metadata supplies `names` in that package's SQL schema. Public queries exclude
|
|
|
3592
3591
|
GM-only owners; all/native contexts retain them. Only authored occurrences
|
|
3593
3592
|
contribute rows, so generated queries and sections add no further names.
|
|
3594
3593
|
|
|
3595
|
-
**`runs`** is one row per span, generic div and verse
|
|
3594
|
+
**`runs`** is one row per span, generic div and verse div an authored note
|
|
3596
3595
|
body marks with `lang=`, `font=` or `enc=`. Each row has these columns,
|
|
3597
3596
|
including on an empty relation:
|
|
3598
3597
|
|
|
@@ -4033,7 +4032,7 @@ The caption attaches to exactly the next supported block:
|
|
|
4033
4032
|
| Markdown table | `table` | Table |
|
|
4034
4033
|
| Image, Markdown or wikilink | `figure` | Figure |
|
|
4035
4034
|
| SQL fence, including backtick SQL | `table` | Table |
|
|
4036
|
-
| Verse
|
|
4035
|
+
| Verse div | `verse` | Poem |
|
|
4037
4036
|
| Any other code fence | `code` | Code |
|
|
4038
4037
|
| Paragraph, quote block or fenced div | `prose` | Prose |
|
|
4039
4038
|
|
|
@@ -6855,7 +6854,7 @@ closed list where its values are words:
|
|
|
6855
6854
|
end, `antepenultimate`, `penultimate` or `final`; `mark` is the diacritic, `acute`,
|
|
6856
6855
|
`grave` or `circumflex`, that marks a stress the rule would not choose and
|
|
6857
6856
|
moves it to the syllable it sits on. Syllables are vowel groups, a pair listed
|
|
6858
|
-
in `syllables.vowelPairs` counting as one. A verse
|
|
6857
|
+
in `syllables.vowelPairs` counting as one. A verse div's `scan=` counts
|
|
6859
6858
|
beats by this rule; see [metres](#metres).
|
|
6860
6859
|
- `finals`: the syllable finals, each with what it sounds like and, as `ipa`,
|
|
6861
6860
|
its sound in the International Phonetic Alphabet, for a language whose
|
|
@@ -8274,7 +8273,7 @@ Content prepared to be played — a situation with its cast, places, and possibl
|
|
|
8274
8273
|
| `concepts[].id` | string | Required: lowercase letters, digits and `-`, unique in the package |
|
|
8275
8274
|
| `concepts[].gloss` | string | Required: what the concept means, in brief |
|
|
8276
8275
|
| `concepts[].group` | string | Required: the group the report lists the concept under |
|
|
8277
|
-
| `metres` | `{ name, beats, kind }[]` | The metres a verse
|
|
8276
|
+
| `metres` | `{ name, beats, kind }[]` | The metres a verse div's `scan=` names; any subType. See [metres](#metres) |
|
|
8278
8277
|
| `metres[].name` | string | Required: what `scan=` names it by, lowercase letters, digits and `-`, unique in the package |
|
|
8279
8278
|
| `metres[].beats` | `integer`, required | The beats of one line, above zero |
|
|
8280
8279
|
| `metres[].kind` | `accentual` | Required: how the beats are counted |
|
|
@@ -997,20 +997,20 @@ Lore records in-world knowledge. A `culture` describes a people; a `custom` desc
|
|
|
997
997
|
|
|
998
998
|
**Subtypes:** `rules`, `userguide`, `reference`, `howto`, `concept`, `settingguide`, `post`.
|
|
999
999
|
|
|
1000
|
-
| Field | Shape | Meaning
|
|
1001
|
-
| --------------- | ------------------------------------ |
|
|
1002
|
-
| `data.language` | a configured language alias | The configured language alias an encoding document writes.
|
|
1003
|
-
| `data.font` | an installed font slug | The encoding's installed font, which supplies all glyph codes.
|
|
1004
|
-
| `data.accepts` | a list of characters or ranges | Accepted Roman letters and additions to standard punctuation.
|
|
1005
|
-
| `data.vowels` | a string | The letters a contextual vowel match reads as vowels.
|
|
1006
|
-
| `data.mappings` | Roman strings to glyph codes | Roman source strings mapped to codes published by the selected font.
|
|
1007
|
-
| `data.rules` | the closed encoding rules vocabulary | Executable normalization, matching, case, stress, vowel groups, accents and contextual mappings.
|
|
1008
|
-
| `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).
|
|
1009
|
-
| `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.
|
|
1010
|
-
| `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.
|
|
1011
|
-
| `data.culture` | an Address | The culture a setting guide introduces, as a culture lore note. Required on `settingguide`; no other subType states it.
|
|
1012
|
-
| `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.
|
|
1013
|
-
| `data.metres` | list of `{ name, beats, kind }` | The metres a verse
|
|
1000
|
+
| Field | Shape | Meaning |
|
|
1001
|
+
| --------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1002
|
+
| `data.language` | a configured language alias | The configured language alias an encoding document writes. |
|
|
1003
|
+
| `data.font` | an installed font slug | The encoding's installed font, which supplies all glyph codes. |
|
|
1004
|
+
| `data.accepts` | a list of characters or ranges | Accepted Roman letters and additions to standard punctuation. |
|
|
1005
|
+
| `data.vowels` | a string | The letters a contextual vowel match reads as vowels. |
|
|
1006
|
+
| `data.mappings` | Roman strings to glyph codes | Roman source strings mapped to codes published by the selected font. |
|
|
1007
|
+
| `data.rules` | the closed encoding rules vocabulary | Executable normalization, matching, case, stress, vowel groups, accents and contextual mappings. |
|
|
1008
|
+
| `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). |
|
|
1009
|
+
| `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. |
|
|
1010
|
+
| `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. |
|
|
1011
|
+
| `data.culture` | an Address | The culture a setting guide introduces, as a culture lore note. Required on `settingguide`; no other subType states it. |
|
|
1012
|
+
| `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. |
|
|
1013
|
+
| `data.metres` | list of `{ name, beats, kind }` | The metres a verse div's `scan=` names. A div that states one is warned at each line that cannot have its beats. See [metres](../authoring/links-and-markup.md#metre). |
|
|
1014
1014
|
|
|
1015
1015
|
**Inner keys** — a key a field's value does not declare is an error at its own line and column.
|
|
1016
1016
|
|
|
@@ -1065,7 +1065,7 @@ Lore records in-world knowledge. A `culture` describes a people; a `custom` desc
|
|
|
1065
1065
|
| `data.sounds.marks[].letters` | a list of letters | yes | The letters that carry it. |
|
|
1066
1066
|
| `data.sounds.marks[].kind` | one of stress, length, apart | yes | What the mark says of its letter. |
|
|
1067
1067
|
| `data.sounds.marks[].limit` | one of one, any | yes | How many a word may carry: `one` at most, or `any`. |
|
|
1068
|
-
| `data.metres[].name` | string | yes | What a verse
|
|
1068
|
+
| `data.metres[].name` | string | yes | What a verse div's `scan=` names the metre by: lowercase letters, digits and `-`, unique in the package. |
|
|
1069
1069
|
| `data.metres[].beats` | a whole number above zero | yes | The beats of one line. |
|
|
1070
1070
|
| `data.metres[].kind` | one of accentual | yes | How the beats are counted: `accentual`, one beat for each stressed syllable the language's stress rule and the beat convention give. |
|
|
1071
1071
|
|
|
@@ -333,32 +333,40 @@ Caption classes are unrestricted. The built-in `border` class draws the block as
|
|
|
333
333
|
|
|
334
334
|
## Verse
|
|
335
335
|
|
|
336
|
-
A
|
|
336
|
+
A `.verse` div reaches the page as `.verse`, with one `.verse-stanza` per
|
|
337
337
|
stanza and `.verse-line` per logical line. Indentation uses `i1` through `i8`;
|
|
338
338
|
deeper levels carry their complete `--verse-indent`. `.verse-canto-break`
|
|
339
|
-
separates cantos. A work-labelled
|
|
339
|
+
separates cantos. A work-labelled div adds `.verse-labelled`, and each stanza
|
|
340
340
|
opens with a small `.verse-label` shared across its presentations.
|
|
341
341
|
|
|
342
|
-
A concrete
|
|
342
|
+
A concrete div encoding adds `.verse-paired`. Each `.verse-row` aligns one
|
|
343
343
|
`.verse-native` cell with one `.verse-roman` cell at full weight. The script is
|
|
344
344
|
on the left; its direction applies within its cell. A narrow container stacks
|
|
345
|
-
the native presentation before the Roman presentation. An unencoded
|
|
345
|
+
the native presentation before the Roman presentation. An unencoded div or
|
|
346
346
|
`enc=default` is one Roman column. See [versions of a work](../authoring/links-and-markup.md#versions-and-stanza-labels).
|
|
347
347
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
| `.verse
|
|
357
|
-
| `.verse-
|
|
358
|
-
| `.verse-
|
|
359
|
-
| `.verse-
|
|
360
|
-
| `.
|
|
361
|
-
| `.
|
|
348
|
+
An unencoded quotation uses `.verse-inline` with inline-safe layout wrappers.
|
|
349
|
+
An encoded quotation is a script-only span flowing within prose, with no verse
|
|
350
|
+
grid or Roman companion. Its verse signs come from the encoding. Footnote
|
|
351
|
+
references follow encoded spans outside their script font. In a paired div,
|
|
352
|
+
references occur only in `.verse-roman`, beside their authored words.
|
|
353
|
+
|
|
354
|
+
| Class | Meaning |
|
|
355
|
+
| ---------------------- | ------------------------------------------------- |
|
|
356
|
+
| `.verse` | A block or unencoded quoted verse |
|
|
357
|
+
| `.verse-inline` | A quotation with inline-safe span wrappers |
|
|
358
|
+
| `.verse-canto-heading` | A canto title and optional anchor within the work |
|
|
359
|
+
| `.verse-stanza` | One stanza or prose paragraph |
|
|
360
|
+
| `.verse-line` | One logical line |
|
|
361
|
+
| `.verse-labelled` | A version carrying automatic stanza labels |
|
|
362
|
+
| `.verse-label` | The stanza number or canto:stanza label |
|
|
363
|
+
| `.verse-paired` | Script and Roman presentations of one original |
|
|
364
|
+
| `.verse-row` | Matching logical lines in both presentations |
|
|
365
|
+
| `.verse-native` | Encoded text on the left |
|
|
366
|
+
| `.verse-roman` | Roman text on the right |
|
|
367
|
+
| `.verse-canto-break` | A canto boundary |
|
|
368
|
+
| `.direction` | An instruction, inside or outside verse |
|
|
369
|
+
| `.speaker` | A speaker label, inside or outside verse |
|
|
362
370
|
|
|
363
371
|
Direction and speaker classes have plain defaults. The book preserves the same
|
|
364
372
|
classes through `book-span`, with plain `book-direction` and `book-speaker`
|
package/engine/anchors.mjs
CHANGED
|
@@ -124,6 +124,20 @@ export function collectAnchors(body, bodyLine = 1, resolveRole, syntax) {
|
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
126
|
for (const poem of scanVerse(body).blocks) {
|
|
127
|
+
for (const group of poem.model.groups)
|
|
128
|
+
if (group.cantoBreak && group.id)
|
|
129
|
+
anchors.push({
|
|
130
|
+
slug: slugify(group.id),
|
|
131
|
+
name: group.title || group.id,
|
|
132
|
+
level: 0,
|
|
133
|
+
line:
|
|
134
|
+
bodyLine +
|
|
135
|
+
String(body)
|
|
136
|
+
.slice(0, poem.bodyStart + group.from)
|
|
137
|
+
.split("\n").length -
|
|
138
|
+
1,
|
|
139
|
+
kind: "prose",
|
|
140
|
+
});
|
|
127
141
|
if (poem.id)
|
|
128
142
|
anchors.push({
|
|
129
143
|
slug: slugify(poem.id),
|
package/engine/code-fences.mjs
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
* prevent.
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
+
import { verseRegions } from "./verse-regions.mjs";
|
|
49
50
|
import { parseExtensionAttributes } from "./extension-attributes.mjs";
|
|
50
51
|
|
|
51
52
|
/** A fence line, capturing its indent, its marker, and its info string. */
|
|
@@ -104,11 +105,10 @@ function column(space) {
|
|
|
104
105
|
* @param {object} [options]
|
|
105
106
|
* @param {boolean} [options.spans=true] - Include inline code spans. Set false
|
|
106
107
|
* to consider only block-level code.
|
|
107
|
-
* @param {boolean} [options.verseAsProse=true] - Treat verse bodies as inline prose.
|
|
108
108
|
* @returns {Array<{start: number, end: number}>} Non-overlapping regions, in
|
|
109
109
|
* source order. `end` is exclusive.
|
|
110
110
|
*/
|
|
111
|
-
export function codeRegions(markdown, { spans = true
|
|
111
|
+
export function codeRegions(markdown, { spans = true } = {}) {
|
|
112
112
|
const src = String(markdown ?? "");
|
|
113
113
|
if (!src) return [];
|
|
114
114
|
const lines = src.split("\n");
|
|
@@ -127,6 +127,16 @@ export function codeRegions(markdown, { spans = true, verseAsProse = true } = {}
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
const regions = [];
|
|
130
|
+
const verses = verseRegions(src);
|
|
131
|
+
const verseLines = new Set(
|
|
132
|
+
verses.flatMap((region) =>
|
|
133
|
+
Array.from({ length: region.end - region.start + 1 }, (_, i) => region.start + i),
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
for (const verse of verses) {
|
|
137
|
+
regions.push(through(verse.start, verse.start));
|
|
138
|
+
if (verse.closed) regions.push(through(verse.end, verse.end));
|
|
139
|
+
}
|
|
130
140
|
// The content column of the innermost open list item: an indented block
|
|
131
141
|
// has to clear *that*, not column zero, or every list continuation would
|
|
132
142
|
// read as code.
|
|
@@ -137,6 +147,7 @@ export function codeRegions(markdown, { spans = true, verseAsProse = true } = {}
|
|
|
137
147
|
|
|
138
148
|
for (let i = 0; i < lines.length; i++) {
|
|
139
149
|
const line = lines[i];
|
|
150
|
+
if (verseLines.has(i)) continue;
|
|
140
151
|
|
|
141
152
|
const fence = FENCE_LINE.exec(line);
|
|
142
153
|
if (fence) {
|
|
@@ -145,10 +156,7 @@ export function codeRegions(markdown, { spans = true, verseAsProse = true } = {}
|
|
|
145
156
|
let close = i + 1;
|
|
146
157
|
while (close < lines.length && !closer.test(lines[close])) close++;
|
|
147
158
|
// An unclosed fence runs to the end of the document.
|
|
148
|
-
|
|
149
|
-
regions.push(through(i, i));
|
|
150
|
-
if (close < lines.length) regions.push(through(close, close));
|
|
151
|
-
} else regions.push(through(i, Math.min(close, lines.length - 1)));
|
|
159
|
+
regions.push(through(i, Math.min(close, lines.length - 1)));
|
|
152
160
|
i = close;
|
|
153
161
|
afterBlank = false;
|
|
154
162
|
continue;
|
|
@@ -186,6 +194,7 @@ export function codeRegions(markdown, { spans = true, verseAsProse = true } = {}
|
|
|
186
194
|
afterBlank = false;
|
|
187
195
|
}
|
|
188
196
|
|
|
197
|
+
regions.sort((a, b) => a.start - b.start);
|
|
189
198
|
if (spans) regions.push(...codeSpans(src, regions));
|
|
190
199
|
regions.sort((a, b) => a.start - b.start);
|
|
191
200
|
return regions;
|
|
@@ -111,7 +111,9 @@ export function scanBlocks(source) {
|
|
|
111
111
|
for (const token of blockTokens(source)) {
|
|
112
112
|
if (
|
|
113
113
|
!token.map ||
|
|
114
|
-
!["blockquote_open", "fence", "code_block", "html_block"].includes(
|
|
114
|
+
!["blockquote_open", "fence", "code_block", "html_block", "verse_div"].includes(
|
|
115
|
+
token.type,
|
|
116
|
+
)
|
|
115
117
|
)
|
|
116
118
|
continue;
|
|
117
119
|
for (let line = token.map[0]; line < token.map[1]; line++) literalLines.add(line);
|
|
@@ -277,7 +279,7 @@ export function renderBlocks(source, target, { renderInline, verses } = {}) {
|
|
|
277
279
|
// at every depth, never a rendered fragment.
|
|
278
280
|
const held =
|
|
279
281
|
BLOCK_CONTAINERS.includes(block.name) ?
|
|
280
|
-
renderBlocks(block.body, target, { renderInline }).markdown
|
|
282
|
+
renderBlocks(block.body, target, { renderInline, verses }).markdown
|
|
281
283
|
: block.body;
|
|
282
284
|
if (block.name === "div") {
|
|
283
285
|
output.push("", `<div ${attributes}>`, "", held, "", "</div>", "");
|