@heroiclands/package-build 25.2.1 → 25.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -1
  3. package/assets/styles/content-base.css +97 -116
  4. package/docs/api.md +30 -6
  5. package/docs/authoring/links-and-markup.md +214 -126
  6. package/docs/commands.md +2 -2
  7. package/docs/content-format.md +31 -6
  8. package/docs/diagnostics.md +27 -27
  9. package/docs/guides/writing-in-invented-scripts.md +89 -83
  10. package/docs/reference/format-details.md +6 -7
  11. package/docs/reference/note-types.md +15 -15
  12. package/docs/reference/theme-pages.md +38 -57
  13. package/engine/anchors.mjs +14 -0
  14. package/engine/code-fences.mjs +15 -6
  15. package/engine/content-blocks.mjs +7 -4
  16. package/engine/content-figures.mjs +19 -5
  17. package/engine/content-footnotes.mjs +60 -1
  18. package/engine/content-index.mjs +1 -1
  19. package/engine/content-render.mjs +66 -48
  20. package/engine/content-scripts.mjs +357 -101
  21. package/engine/content-spans.mjs +76 -10
  22. package/engine/content-verse.mjs +687 -358
  23. package/engine/first-use.mjs +43 -12
  24. package/engine/heading-attributes.mjs +2 -1
  25. package/engine/journals.mjs +8 -1
  26. package/engine/markdown-blocks.mjs +3 -2
  27. package/engine/markup-validation.mjs +17 -0
  28. package/engine/name-markup.mjs +1 -0
  29. package/engine/note-vocabulary.mjs +2 -2
  30. package/engine/pdf-render.mjs +89 -130
  31. package/engine/prose-lint.mjs +14 -2
  32. package/engine/roman-verse.mjs +68 -57
  33. package/engine/run-rows.mjs +1 -1
  34. package/engine/sql-tables.mjs +1 -1
  35. package/engine/verse-format.mjs +77 -0
  36. package/engine/verse-metre.mjs +49 -47
  37. package/engine/verse-regions.mjs +181 -0
  38. package/engine/wikilink-pattern.mjs +31 -0
  39. package/engine/wikilink-syntax.mjs +2 -16
  40. package/package.json +1 -1
  41. package/site-theme/static/css/style.css +68 -96
  42. package/types/engine/code-fences.d.mts +1 -3
  43. package/types/engine/content-blocks.d.mts +3 -1
  44. package/types/engine/content-footnotes.d.mts +23 -0
  45. package/types/engine/content-scripts.d.mts +12 -7
  46. package/types/engine/content-spans.d.mts +3 -1
  47. package/types/engine/content-verse.d.mts +263 -82
  48. package/types/engine/name-markup.d.mts +5 -0
  49. package/types/engine/roman-verse.d.mts +7 -6
  50. package/types/engine/verse-format.d.mts +9 -0
  51. package/types/engine/verse-metre.d.mts +4 -4
  52. package/types/engine/verse-regions.d.mts +78 -0
  53. package/types/engine/wikilink-pattern.d.mts +17 -0
  54. package/types/engine/wikilink-syntax.d.mts +1 -41
@@ -260,7 +260,7 @@ The caption attaches to exactly the next supported block:
260
260
  | Markdown table | `table` | Table |
261
261
  | Image, Markdown or wikilink | `figure` | Figure |
262
262
  | SQL fence, including backtick SQL | `table` | Table |
263
- | Verse fence | `verse` | Poem |
263
+ | Verse div | `verse` | Poem |
264
264
  | Any other code fence | `code` | Code |
265
265
  | Paragraph, quote block or fenced div | `prose` | Prose |
266
266
 
@@ -409,65 +409,48 @@ Foundry renders a secret section; the website renders an expandable spoiler, and
409
409
 
410
410
  ### Verse
411
411
 
412
- Use a code fence with the language `verse` to preserve verse lines and stanzas.
413
- Each nonblank source line is one verse line. A blank line separates verse units;
414
- `***` on a line by itself separates stanzas. Neither separator is numbered.
415
- The fence itself adds no title, caption or number.
412
+ A `.verse` div sets a version of a work, whether poetry or prose. `/` ends a
413
+ logical line. Source newlines otherwise join with whitespace, so prose can wrap
414
+ across source lines. A blank line or `//` ends a stanza (a paragraph); a line
415
+ of `--- {.canto}`, preceded by a blank line, ends a canto (a section). The last line before either
416
+ boundary needs no `/`. A literal slash in text is written `\/`; slashes inside
417
+ Markdown syntax, such as a link destination, remain syntax.
416
418
 
417
- Leading periods set indentation: one `.` per level. They are removed
418
- from the displayed line. Leading spaces are ignored and do not set indentation.
419
- Periods inside the first inline span also set indentation when that span begins
420
- the line; periods in later spans are literal text. Interior spaces between text
421
- and spans are preserved. Tabs anywhere in the poem are an error. Each medium
422
- sets the actual width of an indent level, with every higher level wider than the
423
- preceding one.
419
+ Leading periods at the beginning of a logical line set indentation, one `.` per
420
+ level, and are removed from the display. They may follow `/` on the same source
421
+ line. Leading spaces do not set indentation. A period beginning a continuation
422
+ source line is literal text when the preceding text has no logical line ending.
423
+ Periods inside the first inline span can set indentation; periods in later spans
424
+ are literal. Tabs inside a verse div are errors. The div body is opaque to Markdown block syntax:
425
+ lines beginning `- `, `1. `, `# `, `> ` or four spaces stay verse text.
424
426
 
425
- Levels 1 through 8 use the `i1`–`i8` indent classes. Deeper levels retain
426
- their full depth in the generated indent width.
427
+ These two bodies have the same lines and indentation:
427
428
 
428
- For example, `.A line` is indented one level, while ` ..A line` is indented
429
- two levels: the spaces do not count. Verse is upright by default. English text
430
- can use Markdown emphasis; emphasis inside a span whose effective language is
431
- not English is an error. See [emphasis in a script](#emphasis-in-a-script).
432
-
433
- A verse line can mix plain English, language-marked spans and more English on
434
- one authored line. Spaces are kept exactly as written between those runs; the
435
- spans add no spaces of their own. A period at the start of the first span also
436
- sets that line's indentation:
429
+ ```markdown
430
+ ::: {.verse lang=en}
431
+ To be or not to be,/
432
+ ..that is the question!
433
+ :::
437
434
 
438
- ````markdown
439
- ```verse {lang=en}
440
- ..The [boundary]{lang=en} is [thiruthriman]{lang=vyl} again.
441
- [.The boundary]{lang=en} is [thiruthriman]{lang=vyl} again.
435
+ ::: {.verse lang=en}
436
+ To be or not to be,/..that is the question!
437
+ :::
442
438
  ```
443
- ````
444
-
445
- Both lines have one verse number apiece when numbering is enabled. In the
446
- second, the leading period inside the first span is removed and indents the
447
- whole line.
448
-
449
- ````markdown
450
- ```verse {form=ballad lang=en}
451
- The lantern burns beside the gate,
452
- The harbor sleeps below.
453
439
 
454
- ***
440
+ Verse is upright by default. English text accepts Markdown emphasis; other
441
+ languages use their declared [script emphasis](#emphasis-in-a-script). Inline
442
+ links, names, language spans and footnotes keep their ordinary meanings.
443
+ The optional `form=` records the author's literary form, `lang=` identifies the
444
+ language, and `font=` selects a face. `enc=` selects an encoding document. An
445
+ optional `#id` addresses the div. `scan=` checks a declared metre.
455
446
 
456
- The keeper guards the road till dawn,
457
- And keeps a light aglow.
458
- ```
459
- ````
460
-
461
- The optional `form` attribute records the author's intent; the build does not
462
- infer stress, rhyme or pronunciation. `numstep` numbers the logical rows, and `cols`
463
- sets the poem's column count; see below. `lang` names the poem's language,
464
- `font` the font it is set in and `map` the mapping its text is rewritten by; see
465
- [marking language, font and encoding](#marking-language-font-and-encoding). An optional `#id`
466
- addresses the poem itself. There are no `title` or `lines` attributes, and no
467
- special punctuation for stress, pauses or refrains. A poem's metre, rhyme or
468
- syllable pattern is described in the note's prose. `scan` names a metre the
469
- package declares, and the build counts the poem's beats against it, as the next
470
- section describes.
447
+ On a div, a concrete `enc=` draws the original in its script on the left and the same text
448
+ in Roman on the right. Write the original once, with no column prefixes. Each
449
+ logical line aligns with its counterpart at full weight; indentation and breaks
450
+ match. `⟦…⟧` codage draws glyphs on the left and remains codage on the right.
451
+ Names, nested language choices and `lang=zxx` gaps retain their scope. A div
452
+ with no `enc=`, or with `enc=default`, has one Roman column. The content index's
453
+ `runs` relation records the authored original once, in its language and encoding.
471
454
 
472
455
  #### Metre
473
456
 
@@ -485,21 +468,21 @@ the beats of one line, a whole number above zero. `kind` is `accentual`, the
485
468
  only kind: a beat falls on a stressed syllable, and the length of a syllable
486
469
  is not counted.
487
470
 
488
- A verse fence that states `scan=` with the declared name, and `lang=` with a
471
+ A verse div that states `scan=` with the declared name, and `lang=` with a
489
472
  language whose `note` names a language note stating
490
473
  [`data.sounds.stress`](../reference/format-details.md#a-languages-register-sounds-and-history),
491
474
  is counted line by line. A line that cannot have the metre's beats is a warning
492
475
  at that line:
493
476
 
494
- ````markdown
495
- ```verse {form=epic scan=hexameter lang=vyl}
477
+ ```markdown
478
+ ::: {.verse form=epic scan=hexameter lang=vyl}
496
479
  Thiruthriman sorimamen, ul alathas kedis alatha valmazor,
480
+ :::
497
481
  ```
498
- ````
499
482
 
500
483
  > ``this line has 4 beats (5 with secondary beats); the metre `hexameter` has 6``
501
484
 
502
- `scan=` uses the fence's one language to count beats. If a verse line contains
485
+ `scan=` uses the div's one language to count beats. If a verse line contains
503
486
  a run in another language, the build does not scan that run with the fence
504
487
  language's stress rules; it reports an error at the line:
505
488
 
@@ -530,91 +513,196 @@ Beats are counted this way:
530
513
  - The caesura is not written.
531
514
 
532
515
  `scan=` is refused where it cannot mean anything: a name no `data.metres`
533
- declares, a fence with no `lang=`, a language without a stress rule, and a verse
534
- in columns. A fence with no `scan=` is not counted. Readers see nothing of the
535
- count; the fence carries `data-scan` with the metre's name.
516
+ declares, a div with no `lang=`, a language without a stress rule. A div with no `scan=` is not counted. Readers see nothing of the
517
+ count; the div carries `data-scan` with the metre's name.
536
518
 
537
- To number and caption a poem, put a leading numbered caption before the verse fence:
519
+ To number and caption a poem, put a leading numbered caption before the verse div:
538
520
 
539
- ````markdown
521
+ ```markdown
540
522
  :@ A song sung by the harbor watch. {#watch-song}
541
523
 
542
- ```verse {form=ballad}
543
- The watch has gone to sea,
524
+ ::: {.verse form=ballad}
525
+ The watch has gone to sea,/
544
526
  The lantern marks the shore.
527
+ :::
545
528
  ```
546
- ````
547
529
 
548
530
  This uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. Use `:` for a caption without a number.
549
531
 
550
- #### Line numbers
532
+ #### Versions and stanza labels
551
533
 
552
- `numstep=N` numbers the poem's lines, counting every verse line from the first
553
- to the last across stanzas. `numstep=1` numbers every line, `numstep=5` every
554
- fifth line, and `numstep=0`, the default, numbers none. The numbers sit in a
555
- margin beside the lines, in a muted tone.
534
+ `work=<key>` names a work within the page. Every div with that key is a version
535
+ of the same work. Each stanza opens with its automatically counted label: `1`,
536
+ `2`, and so on for a work with no canto break, or `1:1`, `1:2`, `2:1`, and so on
537
+ when the div contains cantos. Stanza numbering starts at one in each canto.
538
+ The website, Foundry journals and book show the same labels. A paired original
539
+ has one label shared by both presentations. A div without `work=` has no label.
556
540
 
557
- ````markdown
558
- ```verse {numstep=5 lang=en}
559
- The lantern burns beside the gate,
560
- …
541
+ Versions must have the same number of cantos and the same number of stanzas in
542
+ each canto. Their line counts can differ. A work with only one version is a
543
+ finding. Shape disagreements are findings at the opening lines of the versions,
544
+ naming the canto and the counts. A canto break at the edge of a div, or beside another
545
+ canto break with no intervening stanza, is a finding at the break itself.
546
+ Authored `***` inside verse is a finding.
547
+
548
+ This poem's English version and Sinale original share stanza `1`. The original
549
+ is authored once and displays as script beside Roman:
550
+
551
+ ```markdown
552
+ ::: {.verse form=lay work=asking lang=en}
553
+ A child comes up the hill at night/
554
+ .and leaves a loaf beneath the birch./
555
+ .She does not wait. She does not search/
556
+ the dark for us. We stand in sight.
557
+ :::
558
+
559
+ ::: {.verse form=lay work=asking lang=sina enc=sinaveldikkoenc}
560
+ irtal nysse auldiho nalduho/
561
+ .penvai onsa tarnevinu halpi polpeho/
562
+ .ahi sennevi onsa ahi syltete onsa/
563
+ ehii nalduho setty ehii nelkis yinserseho
564
+ :::
561
565
  ```
562
- ````
563
566
 
564
- #### Verse in columns
567
+ Prose uses the same div and omits line-ending marks. Source lines join into
568
+ paragraphs. Both versions below have stanzas `1` and `2`; the original's paragraphs
569
+ also appear beside their Roman text:
565
570
 
566
- `cols=N` sets a positive whole number of columns and defaults to `1`. A
567
- single-column poem keeps its physical lines without column prefixes. For
568
- `cols` above one, every content line starts with its column number and one
569
- or more spaces. The prefix selects its cell and is not displayed.
571
+ ```markdown
572
+ ::: {.verse work=walking lang=en}
573
+ He walks the oath road.
570
574
 
571
- A blank line ends a **logical verse row**. Within that row, numbers must be
572
- in `1..cols` and nondecreasing: finish one column before starting a higher
573
- one. Any column may be omitted; its empty cell remains in the grid. A column
574
- may hold any number of readings. Its first line uses the foreground color,
575
- and every subsequent line in that same column is grey. Each column starts
576
- its own foreground line, and the choice resets in the next row.
575
+ I walk the oath road.
576
+ :::
577
577
 
578
- This sparse three-column poem leaves the middle cell empty in its first row:
578
+ ::: {.verse work=walking lang=vyl enc=vylsemaronenc}
579
+ Lokazor lonak zaron.
579
580
 
580
- ````markdown
581
- ```verse {form=epic lang=en numstep=5 cols=3}
582
- 1 [Thiruthriman sorimamen,]{lang=vyl}
583
- 3 [The hallowed boundary I sing,]{lang=en}
584
- 3 [Thiruthriman sorimamen,]{lang=vyl}
581
+ Lokamen lonak zaron.
582
+ :::
583
+ ```
584
+
585
+ See [work shape diagnostics](../diagnostics.md#a-worked-case-versions-of-a-work)
586
+ for how findings locate a disagreement.
587
+
588
+ #### Inline quotations
589
+
590
+ Quoted verse inside a prose paragraph uses a `.verse` span:
585
591
 
586
- 1 [ul alathas kedis alatha valmazor, ul talothoi]{lang=vyl}
587
- 2 [Nothing to say]{lang=en}
588
- 3 [and the one who walked it, and the stones]{lang=en}
589
- 3 [ul alathas kedis alatha valmazor, ul talothoi]{lang=vyl}
592
+ ```markdown
593
+ The reply is [to be or not to be/..that is the question!//]{.verse} in the telling.
590
594
  ```
591
- ````
592
595
 
593
- The left cell uses Vylari's configured native script. The third cell contains
594
- an English reading in foreground and a separately authored Roman Vylari
595
- reading in grey. Language labels identify words; column numbers alone place
596
- them. `lang=`, `font=` and `enc=` are written on the actual
597
- runs, so a Roman repeat makes its own presentation choice. Inline links and
598
- mixed-language spans stay in their authored order with their spaces intact.
596
+ A quotation uses `/` for line endings and `//` for stanza endings, with the same
597
+ indentation and source-line joining as a div. It takes ordinary span attributes,
598
+ including `lang=` and `enc=`. An unencoded quotation draws Roman text with its
599
+ line and stanza layout. A concrete encoding draws only its script, continuously
600
+ inside the surrounding prose, like any encoded span. Its `/` and `//` reach the
601
+ encoder as verse controls, so a script with verse signs draws them. Only divs
602
+ have paired script and Roman columns.
603
+ Inline verse has no `work=`, `form=`, `scan=`, stanza labels or canto breaks.
604
+ Directions, speaker labels, links, names and shared note footnotes work inside it.
605
+
606
+ #### Footnotes in works and encoded spans
607
+
608
+ Footnote references are valid after a line or word inside verse. Their definitions
609
+ sit below the work, as ordinary note footnotes:
610
+
611
+ ```markdown
612
+ ::: {.verse work=walking lang=en}
613
+ He walks the oath road.[^image]
614
+ :::
615
+
616
+ ::: {.verse work=walking lang=vyl enc=vylsemaronenc}
617
+ Lokazor lonak[^oath] zaron.
618
+ :::
619
+
620
+ [^image]: The road names the obligation as well as the route.
621
+
622
+ [^oath]: This word carries the oath image in the original.
623
+ ```
599
624
 
600
- `numstep=N` counts logical rows, not their individual readings. A standalone
601
- `***` separates stanzas, and column order resets after it as after a blank
602
- line. Leading periods after the number and its separating spaces set a
603
- reading's indent. Periods at the start of its first span also count; periods
604
- inside later spans remain text. For example:
625
+ The English reference renders normally. In the encoded original, the reference
626
+ appears only in the Roman column, beside the word it follows. The script column
627
+ has no marker. Displaying a line twice adds no duplicate number, definition or
628
+ backlink. References never add lines, stanzas or labels and never affect work
629
+ shape.
630
+
631
+ This rule also applies to every encoded span, whether or not it carries
632
+ `.verse`. A footnote marker is removed before encoding and restored after the
633
+ span's text, outside its script font, as an ordinary reference:
605
634
 
606
635
  ```markdown
607
- 1 [.Thiruthriman [the boundary]{lang=en} sorimamen]{lang=vyl}
608
- 3 [The hallowed boundary I sing,]{lang=en}
636
+ The inscription reads [Lokazor lonak[^word] zaron.]{lang=vyl enc=vylsemaronenc}.
637
+ The reply is [Lokazor lonak[^reply] zaron./Lokamen lonak zaron.//]{.verse lang=vyl enc=vylsemaronenc}.
638
+
639
+ [^word]: A note about the inscription's wording.
640
+
641
+ [^reply]: A note about the reply's wording.
609
642
  ```
610
643
 
611
- Every target aligns a logical row's cells at the top, including empty ones.
612
- On a narrow screen or journal, cells stack in their numbered order. A reading
613
- in a right-to-left face stays in its chosen cell and runs right to left
614
- within it. The book uses the same row and cell order.
644
+ Markers never reach an encoder, draw a script glyph or cause an encoding finding.
645
+ The website, Foundry journals and book share the note's footnote numbering and
646
+ definitions.
647
+
648
+ #### Canto headings
649
+
650
+ A canto break stands alone after a blank line, with a stanza on both sides.
651
+ Its optional `title` appears as a heading and its optional `#id` is an anchor
652
+ within the work, without starting a separate Foundry journal page:
653
+
654
+ ```markdown
655
+ ::: {.verse lang=en}
656
+ The watch crosses the shore.
657
+
658
+ --- {.canto #choosing title="The Choosing"}
659
+ The captain raises the lamp.
660
+ :::
661
+ ```
662
+
663
+ The heading appears once across an encoded div's presentations. Its title is
664
+ heading text, separate from the letters passed to the encoder. A valid break
665
+ supplies the encoder's standard Roman `***` canto control. `package-build format`
666
+ leaves each complete verse div and quotation byte for byte, including its
667
+ delimiters and attributes, while formatting surrounding prose.
668
+
669
+ #### Directions and speakers
670
+
671
+ A `.direction` span identifies an instruction or stage direction; `.speaker`
672
+ identifies the person speaking. Either can fill a logical line or sit within it.
673
+ Each version writes its own directions and speaker names in its own language.
674
+ Write ordinary case; these classes do not rewrite the text. The classes are
675
+ valid outside verse as well.
676
+
677
+ ```markdown
678
+ ::: {.verse form=rite work=weighing lang=en}
679
+ Let the household enter. Let the creditor enter./
680
+ [The reader names the year of the reign, the season, the day, and the dead.]{.direction}/
681
+ One person of this household goes down to the West.
682
+ :::
683
+
684
+ ::: {.verse form=rite work=weighing lang=khel enc=khelqalezuenc}
685
+ galun garqen. galun zeqatar./
686
+ [zethul nemar …]{.direction}/
687
+ yarul genar lazen elu garqen nizar ez ithnar.
688
+ :::
689
+
690
+ ::: {.verse form=roll work=thresholds lang=en}
691
+ [The Captain]{.speaker}/
692
+ Is the stone here?
693
+ :::
694
+
695
+ ::: {.verse form=roll work=thresholds lang=tarv enc=tarvsemaronenc}
696
+ [thrumar]{.speaker}/
697
+ eza goitsa ared ir denon sedon.
698
+ :::
699
+ ```
615
700
 
616
- Findings point to the authored `cols` value, column prefix or inline run;
617
- see [a verse in columns](../diagnostics.md#a-worked-case-a-verse-in-columns).
701
+ Their text is encoded normally. The classes themselves are presentation hooks;
702
+ they add no emphasis, encoding controls or stanza boundaries. A direction alone
703
+ between blank lines is a stanza like any other. HTML preserves `direction` and
704
+ `speaker` classes. Typst preserves those classes through `book-span` and provides
705
+ plain `book-direction` and `book-speaker` hooks. The default appearance is plain.
618
706
 
619
707
  ### Scrolls
620
708
 
@@ -640,7 +728,7 @@ A scroll fence is a real code fence, so Markdown never reformats its body.
640
728
  - **`rows=`** is the number of characters in a column, and **`cols=`** the
641
729
  number of columns in a panel. Each is a whole number above zero, and either
642
730
  may be left out.
643
- - **`lang=`, `font=` and `enc=`** work as they do on a verse fence. See
731
+ - **`lang=`, `font=` and `enc=`** work as they do on a verse div. See
644
732
  [marking language, font and encoding](#marking-language-font-and-encoding).
645
733
  The text is encoded before layout. Own and composed lexical spellings precede
646
734
  rows; a written separator follows the selected definition. An explicit `enc=`
@@ -727,10 +815,10 @@ Use the guillemet pairs instead of English double quotation marks or `<<` and
727
815
 
728
816
  Whitespace is every Unicode space-separator (`Zs`) and U+0009 through U+000D.
729
817
  A contiguous run of that whitespace is one word separator, written as the
730
- chosen encoding specifies. A newline in prose is whitespace. In verse, line
731
- endings and blank lines supply line and stanza boundaries; a line of only
732
- `--- {.canto}` supplies a canto boundary. Visual verse indentation stays
733
- layout, outside the encoded letters. Do not type `/` inside a verse fence.
818
+ chosen encoding specifies. A source newline joins as whitespace. In verse,
819
+ `/` ends a logical line, blank lines or `//` end stanzas, and `--- {.canto}` after a blank line
820
+ ends a canto. Visual indentation at a logical line boundary stays layout,
821
+ outside the encoded letters. Write `\/` for a literal slash.
734
822
 
735
823
  Native characters in a language run are written through literal codage:
736
824
  `⟦U+F0230⟧`, or a name the encoding defines between `⟦` and `⟧`. Directly
@@ -769,7 +857,7 @@ face. An explicitly authored font remains a font choice.
769
857
 
770
858
  A name's braces use the shared name controls. Resolved references encode only
771
859
  their visible labels, retaining URLs and presentation cues. These keys apply
772
- to spans, divs, verse fences and scroll fences. A scroll's selected font must
860
+ to spans, divs and scroll fences. A scroll's selected font must
773
861
  belong to a script whose note declares `direction: vertical-rl`.
774
862
 
775
863
  ### A language's script
@@ -1157,7 +1245,7 @@ that `lint` reports and that fails nothing:
1157
1245
  | ``a span in non-English language `vyl` holds no bold or italic markup`` | Remove the markup, or escape its delimiter characters. |
1158
1246
  | `` `vyl` marks emphasis with a word, not a mark; write the word `` | Remove the emphasis marks and write the word the language stresses with. |
1159
1247
  | ``a div marked `lang=vyl font=semaron-kuriale enc=vylsemaronenc` holds paragraphs and line breaks only, not a list`` | Move the list out of the div. |
1160
- | `` `font=` is read on a span, a div or a verse fence, not on a secret block `` | Put a marked div inside the secret block. |
1248
+ | `` `font=` is read on a span, a div or a verse div, not on a secret block `` | Put a marked div inside the secret block. |
1161
1249
  | `` `vly` is read as a BCP 47 tag; did you mean the declared language `vyl`? `` (a warning) | Write the declared name, or ignore it when the tag is meant. |
1162
1250
 
1163
1251
  A character the face does not draw is reported once per run, at its first
@@ -1314,7 +1402,7 @@ const lantern = "lit"; // the harbor light
1314
1402
  ```
1315
1403
  ````
1316
1404
 
1317
- A fence named `sql`, `pagelist` or `verse` is not a listing: a query is replaced by its table, and verse is set as a poem.
1405
+ A fence named `sql` or `pagelist` is a query. Verse uses a `.verse` div or quotation.
1318
1406
 
1319
1407
  ## SQL generated tables
1320
1408
 
@@ -1336,7 +1424,7 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
1336
1424
  | `entries` | Every note, stubs included. |
1337
1425
  | `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
1338
1426
  | `names` | Each authored `.name` span, with its containing NOTE Address, visible text, optional type/subtype and source line/column. |
1339
- | `runs` | Each span, div and verse fence marked with `lang=`, `font=` or `enc=`, with its containing NOTE Address, its `kind`, `lang` as written, the `tag` it resolves to, the `font` and `enc` it is set with (its own, inherited, or its language's [script](#a-languages-script)), and source line/column. See [marking language, font and encoding](#marking-language-font-and-encoding). |
1427
+ | `runs` | Each span, div and verse div marked with `lang=`, `font=` or `enc=`, with its containing NOTE Address, its `kind`, `lang` as written, the `tag` it resolves to, the `font` and `enc` it is set with (its own, inherited, or its language's [script](#a-languages-script)), and source line/column. See [marking language, font and encoding](#marking-language-font-and-encoding). |
1340
1428
  | `natives` | One row per native form a language note's word states in `native`, with that note as its `language`, the word's place as `word`, its `form`, the entry's place as `native`, and its `enc`, `font` and `"text"`. See [what `enc=` takes](#what-enc-takes). |
1341
1429
  | `words` | One row per word a language note writes in `data.words`, with that note as its `language`, its `position` and what it is built from. |
1342
1430
  | `affixes` | One row per affix a language note writes in `data.affixes`, with that note as its `language`, its `position`, and each key the affix states: `form` (`NULL` on a zero affix), `zero`, `kind`, `given`, `"where"`, `gloss`, `attaches`, `replaces`, `attachesTo`, `lengthens`, `front`, `examples`, `barredAfter` and `tones`, then `written`, the form as a table prints it, `∅` for a zero affix. |
package/docs/commands.md CHANGED
@@ -1097,7 +1097,7 @@ and `**Rendering**`, and `### Patch Changes` holding `**Miscellaneous**` and
1097
1097
 
1098
1098
  **Verse**
1099
1099
 
1100
- - A verse fence keeps its line breaks.
1100
+ - A verse div keeps its line breaks.
1101
1101
  - A stanza break renders as a blank line.
1102
1102
 
1103
1103
  **Rendering**
@@ -2626,7 +2626,7 @@ with visible text, nullable type/subtype and original source line/column.
2626
2626
  Local and dependency SQL schemas expose them through `names`; they travel in
2627
2627
  the metadata artifact.
2628
2628
 
2629
- Metadata includes each own note's spans, divs and verse fences marked with
2629
+ Metadata includes each own note's spans, divs and verse divs marked with
2630
2630
  `lang=`, `font=` or `enc=` under `runs`, with the language as written, its
2631
2631
  resolved tag, font, encoding document Address and original source line/column.
2632
2632
  Roman runs use the default encoding and receive no inferred script face.
@@ -29,11 +29,36 @@ A nonempty note body creates one system-agnostic Foundry JournalEntry. Content b
29
29
 
30
30
  Leading `:` captions describe the next supported block; `:@` captions also number it. The optional type accepts `figure`, `table`, `verse`, `code`, `prose`, and `example`. Captions support identifiers, classes and named attributes; unsupported following blocks are errors. See [captions and numbered references](authoring/links-and-markup.md#captions-and-numbered-references).
31
31
 
32
- A code fence with language `verse` keeps verse lines, stanza breaks and relative indentation. Leading periods set indent levels and are removed from the text; leading spaces do not count. Blank lines separate verse units and `***` separates stanzas. Its numbered caption uses the **Poem** label. Generic `:::` divs and `[inline spans]{.class}` accept attributes. See [verse](authoring/links-and-markup.md#verse), [fenced divs](authoring/links-and-markup.md#fenced-divs) and [inline spans](authoring/links-and-markup.md#inline-spans). `numstep=N` numbers every Nth line. `cols=N` sets a positive whole number of columns and defaults to one. With `cols` above one, each content line starts with an integer and one or more spaces; numbers lie in `1..cols` and are nondecreasing within each blank-separated logical row. Any column may be omitted and keeps an empty cell. A column may repeat without limit: its first reading is foreground and its later readings are grey, independently for every column and row. Number prefixes are not displayed; `numstep` counts logical rows. `***` separates stanzas. Inline language and native presentation are explicit on each authored run. See [verse in columns](authoring/links-and-markup.md#verse-in-columns).
33
-
34
- A code fence with language `scroll` sets text in a script whose script note states `direction: vertical-rl` as columns, top to bottom, read from the right. The lines of a paragraph are joined, and each paragraph starts a fresh column. `rows=N` is the characters in a column and `cols=M` the columns in a panel, each a whole number above zero; `lang=`, `font=` and `enc=` mark the text as on a verse fence, an explicit `enc=` selects an encoding document and its language and font. The site, the preview and Foundry set it with `writing-mode: vertical-rl` in a panel that scrolls sideways from the right; the book draws its panels as images from the face's outlines, each with its roman text as alt text. A scroll fence in a script written in lines is an error. See [scrolls](authoring/links-and-markup.md#scrolls).
35
-
36
- A span, generic div, verse or scroll fence uses `enc=default` unless it selects
32
+ A `.verse` div (`::: {.verse ...}` or `:::verse {...}`) sets poetry or prose. `/` ends a logical line; source newlines
33
+ otherwise join. Blank lines or `//` end stanzas, and a standalone `--- {.canto}` after a blank line ends a canto.
34
+ Leading periods indent a logical line, including after `/` within a source line;
35
+ a period on a joined continuation line is text. `\/` writes a literal slash.
36
+ A concrete `enc=` on a div sets the original once in two presentations, script on the left
37
+ and Roman on the right, aligned by logical line at full weight. No `enc=`, or
38
+ `enc=default`, produces one Roman column. Inline names, codage, language gaps and
39
+ footnotes retain their meaning. `work=<key>` groups versions within the page,
40
+ labels each stanza with its number (or canto:stanza), and requires matching canto
41
+ and per-canto stanza counts; line counts may differ. Singleton work keys and
42
+ shape disagreements are findings. A canto separator with no stanza on either
43
+ side is a finding at that separator. `.direction` and `.speaker` spans identify
44
+ instructions and speakers inside or outside verse, retain plain presentation
45
+ hooks in HTML and Typst, and change neither encoding nor shape. See
46
+ [verse and worked examples](authoring/links-and-markup.md#verse). Its numbered
47
+ caption uses the **Poem** label. Inline quotations use `[text/..line//]{.verse}` with span presentation
48
+ attributes and no work, form, scan, canto or labels. An encoded quotation is
49
+ script-only and flows inside prose, with `/` and `//` drawn through its encoding;
50
+ an unencoded quotation retains Roman verse layout. Footnotes are excluded from
51
+ encoding: an encoded div shows each reference only beside its Roman word, and
52
+ every encoded span restores its references after the span, outside the script
53
+ font. A reference adds no line or stanza and creates no display duplicate. `--- {.canto #id title="Heading"}`
54
+ adds a visible canto heading and anchor inside its work. Authored `***` is a
55
+ finding. The formatter preserves complete verse divs and spans byte for byte. Generic `:::` divs and `[inline spans]{.class}`
56
+ accept attributes; see [fenced divs](authoring/links-and-markup.md#fenced-divs)
57
+ and [inline spans](authoring/links-and-markup.md#inline-spans).
58
+
59
+ A code fence with language `scroll` sets text in a script whose script note states `direction: vertical-rl` as columns, top to bottom, read from the right. The lines of a paragraph are joined, and each paragraph starts a fresh column. `rows=N` is the characters in a column and `cols=M` the columns in a panel, each a whole number above zero; `lang=`, `font=` and `enc=` mark the text as on a verse div, an explicit `enc=` selects an encoding document and its language and font. The site, the preview and Foundry set it with `writing-mode: vertical-rl` in a panel that scrolls sideways from the right; the book draws its panels as images from the face's outlines, each with its roman text as alt text. A scroll fence in a script written in lines is an error. See [scrolls](authoring/links-and-markup.md#scrolls).
60
+
61
+ A span, generic div, verse div or scroll fence uses `enc=default` unless it selects
37
62
  an encoding document. `enc=` is an Address whose default type is `doc`; the
38
63
  document names its language and font, and explicit `lang=` or `font=` values
39
64
  must agree. Each encoding tries authored native writings, complete parts and
@@ -41,7 +66,7 @@ then its mappings. Unknown characters, undefined glyph codes and conflicting
41
66
  selections are located errors. `⟦…⟧` reads the selected font's glyph codes or
42
67
  strict Unicode scalars. See [encodings](reference/format-details.md#encodings).
43
68
  Language word-book validation applies to both Roman and native runs. Parallel
44
- verse retains independent authored readings and their column numbers.
69
+ verse keeps one authored original with its language and selected encoding.
45
70
 
46
71
  Mark a name without a note as `[Name]{.name data-type="being"}`; the optional
47
72
  classification uses the declared note vocabulary. The [name-marking
@@ -297,36 +297,35 @@ Like a culture conflict, each fails the index and every command that reads it
297
297
  without collecting problems. The rules are under
298
298
  [a note's language](reference/format-details.md#a-notes-language).
299
299
 
300
- ## A worked case: a verse in columns
300
+ ## A worked case: versions of a work
301
301
 
302
- A [verse in columns](authoring/links-and-markup.md#verse-in-columns) has a
303
- positive whole-number `cols` value. Invalid counts are located at their
304
- value. With multiple columns, every content line needs a numeric prefix and
305
- one or more spaces. Missing prefixes point to the line's first content
306
- character; out-of-range or decreasing numbers point to the authored number.
302
+ [Versions of a work](authoring/links-and-markup.md#versions-and-stanza-labels)
303
+ share a page-local `work=` key and the same stanza shape. For example:
307
304
 
308
- This row has a decreasing column number on its third content line:
305
+ ```markdown
306
+ ::: {.verse work=watch lang=en}
307
+ The watch arrives.
309
308
 
310
- ````markdown
311
- ```verse {cols=3 lang=en}
312
- 1 The first reading.
313
- 3 A later column.
314
- 2 Out of order within this row.
309
+ The harbor wakes.
310
+ :::
311
+
312
+ ::: {.verse work=watch lang=en}
313
+ Another telling has only one stanza.
314
+ :::
315
315
  ```
316
- ````
317
316
 
318
- The finding points to `2`. A blank line before it would start another row,
319
- where the column order begins again. A number above three or below one is
320
- out of bounds. Skipping a column is valid and leaves an empty cell; repeating
321
- a number is valid and adds another reading to that column. The first reading
322
- in every column is foreground and its later readings are grey.
317
+ The opening lines receive findings naming canto 1 and its differing stanza
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 div's opening line.
323
320
 
324
- Language and native-font findings retain their authored locations inside a
325
- reading, including the column prefix and indentation before it. An unknown
326
- mapping or face points to that run's attribute; an unknown word or a character
327
- the face cannot draw points to the original word or character. A language-only
328
- Roman repeat is checked in its own language, independently of a native run.
329
- The build reports invalid input rather than publishing an inferred layout.
321
+ A concrete `enc=` creates its own script and Roman presentations from one
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 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
327
+ authored original, including text inside names, directions and speaker labels.
328
+ The content index records that original once in `runs`.
330
329
 
331
330
  ## Emphasis in non-English spans
332
331
 
@@ -603,9 +602,10 @@ finding naming its `⟦U+XXXX⟧` spelling. Use that notation, or the chosen
603
602
  encoding's codage name, inside the literal markers. The encoder checks the
604
603
  codes; the Roman validator leaves their contents immutable.
605
604
 
606
- A verse fence uses its authored line endings for boundaries. A literal `/`
607
- inside it is an error at that slash. Visual indentation does not add periods
608
- to the encoded text. Source positions survive Markdown escapes and nested
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 `\/`.
607
+ Visual indentation at a logical line boundary does not add periods to the
608
+ encoded text; a period on a joined continuation line remains text. Source positions survive Markdown escapes and nested
609
609
  `.emph` or `.name` spans.
610
610
 
611
611
  Language-run diagnostic columns count Unicode code points, so a supplementary