@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.
Files changed (62) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +1 -1
  3. package/assets/styles/content-base.css +32 -0
  4. package/docs/api.md +30 -6
  5. package/docs/authoring/links-and-markup.md +143 -53
  6. package/docs/commands.md +8 -2
  7. package/docs/content-format.md +14 -6
  8. package/docs/diagnostics.md +12 -11
  9. package/docs/encoding-core.md +18 -4
  10. package/docs/guides/writing-in-invented-scripts.md +83 -37
  11. package/docs/reference/format-details.md +10 -11
  12. package/docs/reference/note-types.md +15 -15
  13. package/docs/reference/theme-pages.md +26 -18
  14. package/engine/anchors.mjs +14 -0
  15. package/engine/code-fences.mjs +15 -6
  16. package/engine/content-blocks.mjs +4 -2
  17. package/engine/content-figures.mjs +19 -5
  18. package/engine/content-footnotes.mjs +69 -1
  19. package/engine/content-index.mjs +1 -1
  20. package/engine/content-render.mjs +59 -43
  21. package/engine/content-scripts.mjs +301 -58
  22. package/engine/content-scroll.mjs +8 -3
  23. package/engine/content-spans.mjs +107 -6
  24. package/engine/content-verse.mjs +338 -198
  25. package/engine/encoding-standard.mjs +1 -0
  26. package/engine/encoding-template.mjs +5 -2
  27. package/engine/encoding.mjs +19 -14
  28. package/engine/first-use.mjs +43 -12
  29. package/engine/heading-attributes.mjs +2 -1
  30. package/engine/journals.mjs +8 -1
  31. package/engine/markdown-blocks.mjs +3 -2
  32. package/engine/markdownlint-run.mjs +190 -5
  33. package/engine/markup-validation.mjs +17 -0
  34. package/engine/name-markup.mjs +1 -0
  35. package/engine/note-vocabulary.mjs +2 -2
  36. package/engine/pdf-render.mjs +34 -23
  37. package/engine/prose-lint.mjs +14 -2
  38. package/engine/roman-characters.mjs +32 -10
  39. package/engine/roman-run.mjs +3 -0
  40. package/engine/roman-verse.mjs +1 -0
  41. package/engine/run-rows.mjs +1 -1
  42. package/engine/sql-tables.mjs +1 -1
  43. package/engine/verse-format.mjs +89 -0
  44. package/engine/verse-metre.mjs +18 -9
  45. package/engine/verse-regions.mjs +190 -0
  46. package/engine/wikilink-pattern.mjs +31 -0
  47. package/engine/wikilink-syntax.mjs +2 -16
  48. package/package.json +1 -1
  49. package/site-theme/static/css/style.css +24 -0
  50. package/types/engine/code-fences.d.mts +1 -3
  51. package/types/engine/content-footnotes.d.mts +23 -0
  52. package/types/engine/content-scripts.d.mts +4 -3
  53. package/types/engine/content-scroll.d.mts +1 -1
  54. package/types/engine/content-spans.d.mts +3 -1
  55. package/types/engine/content-verse.d.mts +75 -75
  56. package/types/engine/name-markup.d.mts +5 -0
  57. package/types/engine/roman-run.d.mts +3 -1
  58. package/types/engine/verse-format.d.mts +10 -0
  59. package/types/engine/verse-metre.d.mts +4 -4
  60. package/types/engine/verse-regions.d.mts +82 -0
  61. package/types/engine/wikilink-pattern.d.mts +17 -0
  62. package/types/engine/wikilink-syntax.d.mts +1 -41
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @heroiclands/package-build
2
2
 
3
+ ## 25.5.0
4
+
5
+ **Languages and scripts**
6
+
7
+ - A `.`, `?`, `‼` or `!` placed at the start of a sentence in invented-language roman is reported at that mark.
8
+
9
+ **Verse**
10
+
11
+ - A `--- {.canto}` break keeps the stanza break before it and decodes back without adding an extra line ending.
12
+ - Inline `[…]{.verse}` keeps repeated and trailing `//` stanza marks alongside its `/` line marks and footnotes, including in files with CRLF line endings.
13
+ - A literal `\/` in verse stays inside its line and decodes with its backslash intact.
14
+ - A link inside verse is written in the link label's own language, not the verse's.
15
+ - A verse line that looks like a footnote definition or a code fence stays ordinary verse text instead of raising a footnote error or swallowing what follows.
16
+ - A scroll placed after verse renders and reports its own findings correctly, whichever line endings the file uses.
17
+ - A nested shorthand verse div takes the language of the verse around it and shows no stray attribute text on the page.
18
+ - Verse findings inside lists and block quotes point to the verse's opening mark, and leave out the column when the position is unknown.
19
+ - `package-build format` keeps block quotes that contain verse, aligns tables that quote verse, and gives each document one consistent line ending.
20
+ - `package-build markdown` leaves verse untouched while still checking and fixing the prose around it.
21
+ - The authoring guide describes verse scansion and the warnings for names as the build applies them.
22
+
23
+ **Upgrading**
24
+
25
+ - Move any `.`, `?`, `‼` or `!` that opens a sentence in invented-language roman to the end of that sentence.
26
+
27
+ ## 25.4.0
28
+
29
+ **Verse**
30
+
31
+ - Verse is written as a `.verse` div, or quoted inside prose as a `[…]{.verse}` span. An encoded div sets script beside Roman; an encoded quotation flows in the prose as script only.
32
+ - A canto break can carry a heading and an anchor.
33
+ - The formatter leaves verse untouched.
34
+ - Footnotes in an encoded work appear in its Roman column only, with one number and one definition each.
35
+ - A footnote inside any encoded passage appears after its script text, in the ordinary font.
36
+
37
+ **Upgrading**
38
+
39
+ - Rewrite each ```` ```verse ```` fence as `::: {.verse …}` (or `:::verse {…}`) with the same attributes, closed by `:::`. A verse fence is an error.
40
+ - Replace each typed `***` with `--- {.canto}` on its own line after a blank line, with a stanza on both sides. A typed `***` is an error.
41
+
3
42
  ## 25.3.0
4
43
 
5
44
  **Verse**
package/README.md CHANGED
@@ -92,7 +92,7 @@ Every icon and image is covered by a provenance record stating `attribution`, `l
92
92
 
93
93
  `package-build cdn publish --set <file> --name <display name>` uploads every icon and image the package has, shipped or not, to `<site.assets>/<contentPackage>/` in that flat layout, and writes the named set listing the pictures the package leaves out. It reads the bucket from `CDN_ENDPOINT`, `CDN_BUCKET`, `CDN_ACCESS_KEY_ID` and `CDN_SECRET_ACCESS_KEY`, in the environment or `.env.local`. See [publish pictures to the CDN](docs/guides/release-and-deploy.md#publish-pictures-to-the-cdn).
94
94
 
95
- Leading captions, generic fenced divs, inline spans, and verse code fences are described in [links and markup](docs/authoring/links-and-markup.md).
95
+ Leading captions, fenced divs, inline spans, and verse quotations are described in [links and markup](docs/authoring/links-and-markup.md).
96
96
 
97
97
  Cypress end-to-end suites use pinned Chrome for Testing 155.0.8059.84 by default
98
98
  on macOS arm64 and Linux x64, downloaded once into a reusable cache. Select an
@@ -131,6 +131,38 @@
131
131
  margin: 0;
132
132
  }
133
133
 
134
+ /* A quotation stays within its prose paragraph; canto titles retain heading type. */
135
+ :is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
136
+ .verse.verse-inline {
137
+ display: inline-block;
138
+ vertical-align: baseline;
139
+ max-inline-size: 100%;
140
+ margin: 0;
141
+ container-type: normal;
142
+ }
143
+ :is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
144
+ .verse.verse-inline
145
+ .verse-stanza {
146
+ display: block;
147
+ margin: 0;
148
+ }
149
+ :is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
150
+ .verse.verse-inline
151
+ .verse-stanza
152
+ + .verse-stanza {
153
+ margin-top: 0.5em;
154
+ }
155
+ :is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
156
+ .verse
157
+ .verse-canto-heading {
158
+ display: block;
159
+ margin: 0.5em 0;
160
+ font-family: sans-serif;
161
+ font-size: 1.1em;
162
+ font-weight: bold;
163
+ line-height: 1.3;
164
+ }
165
+
134
166
  /* Logical stanzas share labels across native and Roman presentations. */
135
167
  :is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) .verse {
136
168
  margin: 1.5rem 0;
package/docs/api.md CHANGED
@@ -1339,6 +1339,29 @@ index for checking page links.
1339
1339
 
1340
1340
  `createRenderer(target, options?)` builds the one markdown-it configuration every target renders through. `target` is `"foundry"`, `"web"`, `"preview"` or `"book"`. The renderer holds the configured parser (`md`), the names of the plugins installed (`plugins`), and three functions: `prepare` writes the constructs markdown-it has no syntax for — marked text, captioned items, named blocks, verse and alerts — as HTML between blank lines; `render` prepares and renders to HTML; `renderInline` renders one inline run. The `book` target parses only, and its Typst stage reads the tokens.
1341
1341
 
1342
+ Verse blocks are `::: {.verse ...}` or `:::verse {...}`; their raw bodies are
1343
+ parsed with inline Markdown through the shared verse structure. Inline
1344
+ `[text/..line//]{.verse}` quotations retain span wrappers inside prose. A blank
1345
+ line followed by `--- {.canto #id title="Heading"}` supplies a titled canto
1346
+ boundary without opening a journal page. `verseDivPlugin` from
1347
+ `engine/verse-regions.mjs` emits `verse_div` tokens before Markdown block
1348
+ interpretation. `renderVerseQuotes` emits inline-safe HTML from the same logical
1349
+ model; the book's `verse_inline` token parses quoted lines in the note's footnote
1350
+ environment. A canto title is heading metadata, while its encoder receives the
1351
+ standard Roman canto control. Encoded verse divs produce paired
1352
+ script and Roman presentations. Encoded verse spans produce ordinary script-only
1353
+ inline text with encoded verse controls, while unencoded quotations retain their
1354
+ Roman line and stanza layout. Defined footnote references are excluded before
1355
+ encoding: divs retain the references only in their Roman presentation; all
1356
+ encoded spans restore references after their script wrapper. Display generation
1357
+ adds no duplicate reference, number, definition or backlink.
1358
+
1359
+ `parseVerse(body, {footnotes})` accepts the same-note set of defined footnote
1360
+ labels when parsing a detached body; `scanVerse` obtains that context from the
1361
+ complete source. Reference-only positions contribute no work shape. A wholly
1362
+ reference-only body carries its references in `model.notes`, rendered once
1363
+ outside native-font wrappers without a verse row or label.
1364
+
1342
1365
  | Export | Signature | Returns | Use it when |
1343
1366
  | ---------------- | ---------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
1344
1367
  | `createRenderer` | `createRenderer(target, options?)` | `{ target, md, plugins, prepare, render, renderInline }` | Rendering a note body for one target with the rules every target shares. |
@@ -2497,12 +2520,13 @@ Not a JavaScript module — this subpath entry exists so tooling (bundlers, `imp
2497
2520
 
2498
2521
  The engine wildcard subpath also exposes the body parsers below. Their figure exports operate on leading captions.
2499
2522
 
2500
- | Module | Exports | Contract |
2501
- | ---------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2502
- | `engine/content-figures.mjs` | `FIGURE_NAMES`, `FIGURE_CLASSES`, `scanFigures`, `numberFigures`, `renderFigureBlocks` | Scan leading captions and their next supported blocks; `numbered` distinguishes `:` and `:@`. `type` may override inference; `example` is supported. `FIGURE_CLASSES` retains built-in styled classes, not a closed author vocabulary. |
2503
- | `engine/content-blocks.mjs` | `BLOCK_NAMES`, `BLOCK_CONTAINERS`, `scanBlocks`, `renderBlocks`, `renderWithheldSections` | Read div and secret fences; generic div records have `name: "div"` and no generated title. Scanning includes verse errors. |
2504
- | `engine/content-verse.mjs` | `verseLines`, `verseStanzas`, `inlineVerse`, `verseMarkdown`, `scanVerse`, `renderVerse` | Read `verse` code fences, validate authored metadata and tabs, and preserve relative indent levels and stanzas. |
2505
- | `engine/content-spans.mjs` | `spanMarkdownPlugin`, `scanSpans`, `renderSpans` | Parse bracket spans after recognized links. The scanner returns spans, the exact `.name` inventory and located errors, retaining visible text and attribute positions; rendering preserves inline Markdown and permitted attributes. |
2523
+ | Module | Exports | Contract |
2524
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2525
+ | `engine/content-figures.mjs` | `FIGURE_NAMES`, `FIGURE_CLASSES`, `scanFigures`, `numberFigures`, `renderFigureBlocks` | Scan leading captions and their next supported blocks; `numbered` distinguishes `:` and `:@`. `type` may override inference; `example` is supported. `FIGURE_CLASSES` retains built-in styled classes, not a closed author vocabulary. |
2526
+ | `engine/content-blocks.mjs` | `BLOCK_NAMES`, `BLOCK_CONTAINERS`, `scanBlocks`, `renderBlocks`, `renderWithheldSections` | Read div and secret fences; generic div records have `name: "div"` and no generated title. Scanning includes verse errors. |
2527
+ | `engine/content-verse.mjs` | `verseLines`, `verseStanzas`, `inlineVerse`, `parseVerse`, `verseMarkdown`, `scanVerse`, `renderVerse`, `renderVerseQuotes` | Read `.verse` divs and quotations, validate metadata and source positions, and share logical lines, stanza labels and titled canto headings across targets. |
2528
+ | `engine/verse-regions.mjs` | `verseRegions`, `verseDivPlugin` | Locate opaque raw verse div regions and install their block token rule before ordinary Markdown interpretation. |
2529
+ | `engine/content-spans.mjs` | `spanMarkdownPlugin`, `scanSpans`, `renderSpans` | Parse bracket spans after recognized links. The scanner returns spans, the exact `.name` inventory and located errors, retaining visible text and attribute positions; rendering preserves inline Markdown and permitted attributes. |
2506
2530
 
2507
2531
  Inline `.secret` spans preserve their inline content, name classes and
2508
2532
  attributes. Site rendering uses a separate show/hide button and content span,
@@ -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,10 +409,10 @@ Foundry renders a secret section; the website renders an expandable spoiler, and
409
409
 
410
410
  ### Verse
411
411
 
412
- A `verse` fence sets a version of a work, whether poetry or prose. `/` ends a
412
+ A `.verse` div sets a version of a work, whether poetry or prose. `/` ends a
413
413
  logical line. Source newlines otherwise join with whitespace, so prose can wrap
414
414
  across source lines. A blank line or `//` ends a stanza (a paragraph); a line
415
- containing only `***` ends a canto (a section). The last line before either
415
+ of `--- {.canto}`, preceded by a blank line, ends a canto (a section). The last line before either
416
416
  boundary needs no `/`. A literal slash in text is written `\/`; slashes inside
417
417
  Markdown syntax, such as a link destination, remain syntax.
418
418
 
@@ -421,33 +421,34 @@ level, and are removed from the display. They may follow `/` on the same source
421
421
  line. Leading spaces do not set indentation. A period beginning a continuation
422
422
  source line is literal text when the preceding text has no logical line ending.
423
423
  Periods inside the first inline span can set indentation; periods in later spans
424
- are literal. Tabs inside a verse fence are errors.
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.
425
426
 
426
427
  These two bodies have the same lines and indentation:
427
428
 
428
- ````markdown
429
- ```verse {lang=en}
429
+ ```markdown
430
+ ::: {.verse lang=en}
430
431
  To be or not to be,/
431
432
  ..that is the question!
432
- ```
433
+ :::
433
434
 
434
- ```verse {lang=en}
435
+ ::: {.verse lang=en}
435
436
  To be or not to be,/..that is the question!
437
+ :::
436
438
  ```
437
- ````
438
439
 
439
440
  Verse is upright by default. English text accepts Markdown emphasis; other
440
441
  languages use their declared [script emphasis](#emphasis-in-a-script). Inline
441
442
  links, names, language spans and footnotes keep their ordinary meanings.
442
443
  The optional `form=` records the author's literary form, `lang=` identifies the
443
444
  language, and `font=` selects a face. `enc=` selects an encoding document. An
444
- optional `#id` addresses the fence. `scan=` checks a declared metre.
445
+ optional `#id` addresses the div. `scan=` checks a declared metre.
445
446
 
446
- A concrete `enc=` draws the original in its script on the left and the same text
447
+ On a div, a concrete `enc=` draws the original in its script on the left and the same text
447
448
  in Roman on the right. Write the original once, with no column prefixes. Each
448
449
  logical line aligns with its counterpart at full weight; indentation and breaks
449
450
  match. `⟦…⟧` codage draws glyphs on the left and remains codage on the right.
450
- Names, nested language choices and `lang=zxx` gaps retain their scope. A fence
451
+ Names, nested language choices and `lang=zxx` gaps retain their scope. A div
451
452
  with no `enc=`, or with `enc=default`, has one Roman column. The content index's
452
453
  `runs` relation records the authored original once, in its language and encoding.
453
454
 
@@ -467,21 +468,21 @@ the beats of one line, a whole number above zero. `kind` is `accentual`, the
467
468
  only kind: a beat falls on a stressed syllable, and the length of a syllable
468
469
  is not counted.
469
470
 
470
- 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
471
472
  language whose `note` names a language note stating
472
473
  [`data.sounds.stress`](../reference/format-details.md#a-languages-register-sounds-and-history),
473
474
  is counted line by line. A line that cannot have the metre's beats is a warning
474
475
  at that line:
475
476
 
476
- ````markdown
477
- ```verse {form=epic scan=hexameter lang=vyl}
477
+ ```markdown
478
+ ::: {.verse form=epic scan=hexameter lang=vyl}
478
479
  Thiruthriman sorimamen, ul alathas kedis alatha valmazor,
480
+ :::
479
481
  ```
480
- ````
481
482
 
482
483
  > ``this line has 4 beats (5 with secondary beats); the metre `hexameter` has 6``
483
484
 
484
- `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
485
486
  a run in another language, the build does not scan that run with the fence
486
487
  language's stress rules; it reports an error at the line:
487
488
 
@@ -512,77 +513,166 @@ Beats are counted this way:
512
513
  - The caesura is not written.
513
514
 
514
515
  `scan=` is refused where it cannot mean anything: a name no `data.metres`
515
- declares, a fence with no `lang=`, a language without a stress rule. A fence with no `scan=` is not counted. Readers see nothing of the
516
- 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.
517
518
 
518
- 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:
519
520
 
520
- ````markdown
521
+ ```markdown
521
522
  :@ A song sung by the harbor watch. {#watch-song}
522
523
 
523
- ```verse {form=ballad}
524
+ ::: {.verse form=ballad}
524
525
  The watch has gone to sea,/
525
526
  The lantern marks the shore.
527
+ :::
526
528
  ```
527
- ````
528
529
 
529
530
  This uses the **Poem** counter, so `{{ref "#watch-song"}}` reads **Poem 1**. Use `:` for a caption without a number.
530
531
 
531
532
  #### Versions and stanza labels
532
533
 
533
- `work=<key>` names a work within the page. Every fence with that key is a version
534
+ `work=<key>` names a work within the page. Every div with that key is a version
534
535
  of the same work. Each stanza opens with its automatically counted label: `1`,
535
536
  `2`, and so on for a work with no canto break, or `1:1`, `1:2`, `2:1`, and so on
536
- when the fence contains cantos. Stanza numbering starts at one in each canto.
537
+ when the div contains cantos. Stanza numbering starts at one in each canto.
537
538
  The website, Foundry journals and book show the same labels. A paired original
538
- has one label shared by both presentations. A fence without `work=` has no label.
539
+ has one label shared by both presentations. A div without `work=` has no label.
539
540
 
540
541
  Versions must have the same number of cantos and the same number of stanzas in
541
542
  each canto. Their line counts can differ. A work with only one version is a
542
543
  finding. Shape disagreements are findings at the opening lines of the versions,
543
- naming the canto and the counts. A `***` at the edge of a fence, or beside another
544
+ naming the canto and the counts. A canto break at the edge of a div, or beside another
544
545
  canto break with no intervening stanza, is a finding at the break itself.
546
+ Authored `***` inside verse is a finding.
545
547
 
546
548
  This poem's English version and Sinale original share stanza `1`. The original
547
549
  is authored once and displays as script beside Roman:
548
550
 
549
- ````markdown
550
- ```verse {form=lay work=asking lang=en}
551
+ ```markdown
552
+ ::: {.verse form=lay work=asking lang=en}
551
553
  A child comes up the hill at night/
552
554
  .and leaves a loaf beneath the birch./
553
555
  .She does not wait. She does not search/
554
556
  the dark for us. We stand in sight.
555
- ```
557
+ :::
556
558
 
557
- ```verse {form=lay work=asking lang=sina enc=sinaveldikkoenc}
559
+ ::: {.verse form=lay work=asking lang=sina enc=sinaveldikkoenc}
558
560
  irtal nysse auldiho nalduho/
559
561
  .penvai onsa tarnevinu halpi polpeho/
560
562
  .ahi sennevi onsa ahi syltete onsa/
561
563
  ehii nalduho setty ehii nelkis yinserseho
564
+ :::
562
565
  ```
563
- ````
564
566
 
565
- Prose uses the same fence and omits line-ending marks. Source lines join into
567
+ Prose uses the same div and omits line-ending marks. Source lines join into
566
568
  paragraphs. Both versions below have stanzas `1` and `2`; the original's paragraphs
567
569
  also appear beside their Roman text:
568
570
 
569
- ````markdown
570
- ```verse {work=walking lang=en}
571
+ ```markdown
572
+ ::: {.verse work=walking lang=en}
571
573
  He walks the oath road.
572
574
 
573
575
  I walk the oath road.
574
- ```
576
+ :::
575
577
 
576
- ```verse {work=walking lang=vyl enc=vylsemaronenc}
578
+ ::: {.verse work=walking lang=vyl enc=vylsemaronenc}
577
579
  Lokazor lonak zaron.
578
580
 
579
581
  Lokamen lonak zaron.
582
+ :::
580
583
  ```
581
- ````
582
584
 
583
585
  See [work shape diagnostics](../diagnostics.md#a-worked-case-versions-of-a-work)
584
586
  for how findings locate a disagreement.
585
587
 
588
+ #### Inline quotations
589
+
590
+ Quoted verse inside a prose paragraph uses a `.verse` span:
591
+
592
+ ```markdown
593
+ The reply is [to be or not to be/..that is the question!//]{.verse} in the telling.
594
+ ```
595
+
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. Consecutive
602
+ stanza endings and a trailing stanza ending each retain their control. Only divs
603
+ have paired script and Roman columns.
604
+ Inline verse has no `work=`, `form=`, `scan=`, stanza labels or canto breaks.
605
+ Directions, speaker labels, links, names and shared note footnotes work inside it.
606
+
607
+ #### Footnotes in works and encoded spans
608
+
609
+ Footnote references are valid after a line or word inside verse. Their definitions
610
+ sit below the work, as ordinary note footnotes:
611
+
612
+ ```markdown
613
+ ::: {.verse work=walking lang=en}
614
+ He walks the oath road.[^image]
615
+ :::
616
+
617
+ ::: {.verse work=walking lang=vyl enc=vylsemaronenc}
618
+ Lokazor lonak[^oath] zaron.
619
+ :::
620
+
621
+ [^image]: The road names the obligation as well as the route.
622
+
623
+ [^oath]: This word carries the oath image in the original.
624
+ ```
625
+
626
+ The English reference renders normally. In the encoded original, the reference
627
+ appears only in the Roman column, beside the word it follows. The script column
628
+ has no marker. Displaying a line twice adds no duplicate number, definition or
629
+ backlink. References never add lines, stanzas or labels and never affect work
630
+ shape.
631
+
632
+ This rule also applies to every encoded span, whether or not it carries
633
+ `.verse`. A footnote marker is removed before encoding and restored after the
634
+ span's text, outside its script font, as an ordinary reference:
635
+
636
+ ```markdown
637
+ The inscription reads [Lokazor lonak[^word] zaron.]{lang=vyl enc=vylsemaronenc}.
638
+ The reply is [Lokazor lonak[^reply] zaron./Lokamen lonak zaron.//]{.verse lang=vyl enc=vylsemaronenc}.
639
+
640
+ [^word]: A note about the inscription's wording.
641
+
642
+ [^reply]: A note about the reply's wording.
643
+ ```
644
+
645
+ Markers never reach an encoder, draw a script glyph or cause an encoding finding.
646
+ The website, Foundry journals and book share the note's footnote numbering and
647
+ definitions.
648
+
649
+ #### Canto headings
650
+
651
+ A canto break stands alone after a blank line, with a stanza on both sides.
652
+ Its optional `title` appears as a heading and its optional `#id` is an anchor
653
+ within the work, without starting a separate Foundry journal page:
654
+
655
+ ```markdown
656
+ ::: {.verse lang=en}
657
+ The watch crosses the shore.
658
+
659
+ --- {.canto #choosing title="The Choosing"}
660
+ The captain raises the lamp.
661
+ :::
662
+ ```
663
+
664
+ The heading appears once across an encoded div's presentations. Its title is
665
+ heading text, separate from the letters passed to the encoder. A valid break
666
+ supplies the encoder's standard Roman `***` canto control. `package-build format`
667
+ preserves each verse div and quotation's text, spacing, delimiters and
668
+ attributes while formatting surrounding prose. Quote and list
669
+ containers remain intact, table columns use inline verse's authored width, and
670
+ verse follows the same configured line endings as surrounding prose.
671
+
672
+ The stanza mark before a canto is retained; whitespace after its encoded
673
+ control adds no extra line mark. An encoded literal `\/` uses a separate
674
+ invisible mark and decodes to `\/`, keeping it distinct from a line ending.
675
+
586
676
  #### Directions and speakers
587
677
 
588
678
  A `.direction` span identifies an instruction or stage direction; `.speaker`
@@ -591,29 +681,29 @@ Each version writes its own directions and speaker names in its own language.
591
681
  Write ordinary case; these classes do not rewrite the text. The classes are
592
682
  valid outside verse as well.
593
683
 
594
- ````markdown
595
- ```verse {form=rite work=weighing lang=en}
684
+ ```markdown
685
+ ::: {.verse form=rite work=weighing lang=en}
596
686
  Let the household enter. Let the creditor enter./
597
687
  [The reader names the year of the reign, the season, the day, and the dead.]{.direction}/
598
688
  One person of this household goes down to the West.
599
- ```
689
+ :::
600
690
 
601
- ```verse {form=rite work=weighing lang=khel enc=khelqalezuenc}
691
+ ::: {.verse form=rite work=weighing lang=khel enc=khelqalezuenc}
602
692
  galun garqen. galun zeqatar./
603
693
  [zethul nemar …]{.direction}/
604
694
  yarul genar lazen elu garqen nizar ez ithnar.
605
- ```
695
+ :::
606
696
 
607
- ```verse {form=roll work=thresholds lang=en}
697
+ ::: {.verse form=roll work=thresholds lang=en}
608
698
  [The Captain]{.speaker}/
609
699
  Is the stone here?
610
- ```
700
+ :::
611
701
 
612
- ```verse {form=roll work=thresholds lang=tarv enc=tarvsemaronenc}
702
+ ::: {.verse form=roll work=thresholds lang=tarv enc=tarvsemaronenc}
613
703
  [thrumar]{.speaker}/
614
704
  eza goitsa ared ir denon sedon.
705
+ :::
615
706
  ```
616
- ````
617
707
 
618
708
  Their text is encoded normally. The classes themselves are presentation hooks;
619
709
  they add no emphasis, encoding controls or stanza boundaries. A direction alone
@@ -645,7 +735,7 @@ A scroll fence is a real code fence, so Markdown never reformats its body.
645
735
  - **`rows=`** is the number of characters in a column, and **`cols=`** the
646
736
  number of columns in a panel. Each is a whole number above zero, and either
647
737
  may be left out.
648
- - **`lang=`, `font=` and `enc=`** work as they do on a verse fence. See
738
+ - **`lang=`, `font=` and `enc=`** work as they do on a verse div. See
649
739
  [marking language, font and encoding](#marking-language-font-and-encoding).
650
740
  The text is encoded before layout. Own and composed lexical spellings precede
651
741
  rows; a written separator follows the selected definition. An explicit `enc=`
@@ -733,7 +823,7 @@ Use the guillemet pairs instead of English double quotation marks or `<<` and
733
823
  Whitespace is every Unicode space-separator (`Zs`) and U+0009 through U+000D.
734
824
  A contiguous run of that whitespace is one word separator, written as the
735
825
  chosen encoding specifies. A source newline joins as whitespace. In verse,
736
- `/` ends a logical line, blank lines or `//` end stanzas, and standalone `***`
826
+ `/` ends a logical line, blank lines or `//` end stanzas, and `--- {.canto}` after a blank line
737
827
  ends a canto. Visual indentation at a logical line boundary stays layout,
738
828
  outside the encoded letters. Write `\/` for a literal slash.
739
829
 
@@ -774,7 +864,7 @@ face. An explicitly authored font remains a font choice.
774
864
 
775
865
  A name's braces use the shared name controls. Resolved references encode only
776
866
  their visible labels, retaining URLs and presentation cues. These keys apply
777
- to spans, divs, verse fences and scroll fences. A scroll's selected font must
867
+ to spans, divs and scroll fences. A scroll's selected font must
778
868
  belong to a script whose note declares `direction: vertical-rl`.
779
869
 
780
870
  ### A language's script
@@ -1162,7 +1252,7 @@ that `lint` reports and that fails nothing:
1162
1252
  | ``a span in non-English language `vyl` holds no bold or italic markup`` | Remove the markup, or escape its delimiter characters. |
1163
1253
  | `` `vyl` marks emphasis with a word, not a mark; write the word `` | Remove the emphasis marks and write the word the language stresses with. |
1164
1254
  | ``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. |
1165
- | `` `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. |
1255
+ | `` `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. |
1166
1256
  | `` `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. |
1167
1257
 
1168
1258
  A character the face does not draw is reported once per run, at its first
@@ -1319,7 +1409,7 @@ const lantern = "lit"; // the harbor light
1319
1409
  ```
1320
1410
  ````
1321
1411
 
1322
- A fence named `sql`, `pagelist` or `verse` is not a listing: a query is replaced by its table, and verse is set as a work.
1412
+ A fence named `sql` or `pagelist` is a query. Verse uses a `.verse` div or quotation.
1323
1413
 
1324
1414
  ## SQL generated tables
1325
1415
 
@@ -1341,7 +1431,7 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
1341
1431
  | `entries` | Every note, stubs included. |
1342
1432
  | `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
1343
1433
  | `names` | Each authored `.name` span, with its containing NOTE Address, visible text, optional type/subtype and source line/column. |
1344
- | `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). |
1434
+ | `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). |
1345
1435
  | `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). |
1346
1436
  | `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. |
1347
1437
  | `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**
@@ -2574,6 +2574,12 @@ overrides the rules and the ignore list; an option the file cannot mean is
2574
2574
  refused as `file:line:column: error:` and nothing is linted. See
2575
2575
  [Project setup](project-setup.md) for the accepted keys.
2576
2576
 
2577
+ Closed `.verse` div bodies and inline `.verse` quotation contents are excluded
2578
+ from Markdown rules and inline lint directives. Their authored bytes stay
2579
+ unchanged under `--fix`, including their line endings. The div's opening and
2580
+ closing lines and surrounding prose are still checked, with diagnostics at
2581
+ their original source locations. Verse markup validation remains active.
2582
+
2577
2583
  **OPTIONS**
2578
2584
 
2579
2585
  | Positional | Type | Default | Description |
@@ -2626,7 +2632,7 @@ with visible text, nullable type/subtype and original source line/column.
2626
2632
  Local and dependency SQL schemas expose them through `names`; they travel in
2627
2633
  the metadata artifact.
2628
2634
 
2629
- Metadata includes each own note's spans, divs and verse fences marked with
2635
+ Metadata includes each own note's spans, divs and verse divs marked with
2630
2636
  `lang=`, `font=` or `enc=` under `runs`, with the language as written, its
2631
2637
  resolved tag, font, encoding document Address and original source line/column.
2632
2638
  Roman runs use the default encoding and receive no inferred script face.
@@ -29,11 +29,11 @@ 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 `verse` fence sets poetry or prose. `/` ends a logical line; source newlines
33
- otherwise join. Blank lines or `//` end stanzas, and standalone `***` ends a canto.
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
34
  Leading periods indent a logical line, including after `/` within a source line;
35
35
  a period on a joined continuation line is text. `\/` writes a literal slash.
36
- A concrete `enc=` sets the original once in two presentations, script on the left
36
+ A concrete `enc=` on a div sets the original once in two presentations, script on the left
37
37
  and Roman on the right, aligned by logical line at full weight. No `enc=`, or
38
38
  `enc=default`, produces one Roman column. Inline names, codage, language gaps and
39
39
  footnotes retain their meaning. `work=<key>` groups versions within the page,
@@ -44,13 +44,21 @@ side is a finding at that separator. `.direction` and `.speaker` spans identify
44
44
  instructions and speakers inside or outside verse, retain plain presentation
45
45
  hooks in HTML and Typst, and change neither encoding nor shape. See
46
46
  [verse and worked examples](authoring/links-and-markup.md#verse). Its numbered
47
- caption uses the **Poem** label. Generic `:::` divs and `[inline spans]{.class}`
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}`
48
56
  accept attributes; see [fenced divs](authoring/links-and-markup.md#fenced-divs)
49
57
  and [inline spans](authoring/links-and-markup.md#inline-spans).
50
58
 
51
- 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).
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).
52
60
 
53
- A span, generic div, verse or scroll fence uses `enc=default` unless it selects
61
+ A span, generic div, verse div or scroll fence uses `enc=default` unless it selects
54
62
  an encoding document. `enc=` is an Address whose default type is `doc`; the
55
63
  document names its language and font, and explicit `lang=` or `font=` values
56
64
  must agree. Each encoding tries authored native writings, complete parts and