@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.
- package/CHANGELOG.md +26 -0
- package/README.md +1 -1
- package/assets/styles/content-base.css +97 -116
- package/docs/api.md +30 -6
- package/docs/authoring/links-and-markup.md +214 -126
- package/docs/commands.md +2 -2
- package/docs/content-format.md +31 -6
- package/docs/diagnostics.md +27 -27
- package/docs/guides/writing-in-invented-scripts.md +89 -83
- package/docs/reference/format-details.md +6 -7
- package/docs/reference/note-types.md +15 -15
- package/docs/reference/theme-pages.md +38 -57
- package/engine/anchors.mjs +14 -0
- package/engine/code-fences.mjs +15 -6
- package/engine/content-blocks.mjs +7 -4
- package/engine/content-figures.mjs +19 -5
- package/engine/content-footnotes.mjs +60 -1
- package/engine/content-index.mjs +1 -1
- package/engine/content-render.mjs +66 -48
- package/engine/content-scripts.mjs +357 -101
- package/engine/content-spans.mjs +76 -10
- package/engine/content-verse.mjs +687 -358
- 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/markup-validation.mjs +17 -0
- package/engine/name-markup.mjs +1 -0
- package/engine/note-vocabulary.mjs +2 -2
- package/engine/pdf-render.mjs +89 -130
- package/engine/prose-lint.mjs +14 -2
- package/engine/roman-verse.mjs +68 -57
- package/engine/run-rows.mjs +1 -1
- package/engine/sql-tables.mjs +1 -1
- package/engine/verse-format.mjs +77 -0
- package/engine/verse-metre.mjs +49 -47
- package/engine/verse-regions.mjs +181 -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 +68 -96
- package/types/engine/code-fences.d.mts +1 -3
- package/types/engine/content-blocks.d.mts +3 -1
- package/types/engine/content-footnotes.d.mts +23 -0
- package/types/engine/content-scripts.d.mts +12 -7
- package/types/engine/content-spans.d.mts +3 -1
- package/types/engine/content-verse.d.mts +263 -82
- package/types/engine/name-markup.d.mts +5 -0
- package/types/engine/roman-verse.d.mts +7 -6
- package/types/engine/verse-format.d.mts +9 -0
- package/types/engine/verse-metre.d.mts +4 -4
- package/types/engine/verse-regions.d.mts +78 -0
- package/types/engine/wikilink-pattern.d.mts +17 -0
- package/types/engine/wikilink-syntax.d.mts +1 -41
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 25.4.0
|
|
4
|
+
|
|
5
|
+
**Verse**
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
- A canto break can carry a heading and an anchor.
|
|
9
|
+
- The formatter leaves verse untouched.
|
|
10
|
+
- Footnotes in an encoded work appear in its Roman column only, with one number and one definition each.
|
|
11
|
+
- A footnote inside any encoded passage appears after its script text, in the ordinary font.
|
|
12
|
+
|
|
13
|
+
**Upgrading**
|
|
14
|
+
|
|
15
|
+
- Rewrite each ```` ```verse ```` fence as `::: {.verse …}` (or `:::verse {…}`) with the same attributes, closed by `:::`. A verse fence is an error.
|
|
16
|
+
- Replace each typed `***` with `--- {.canto}` on its own line after a blank line, with a stanza on both sides. A typed `***` is an error.
|
|
17
|
+
|
|
18
|
+
## 25.3.0
|
|
19
|
+
|
|
20
|
+
**Verse**
|
|
21
|
+
|
|
22
|
+
- Versions of a work share automatic stanza labels and a check that their stanza shapes agree. An encoded original is written once and appears as aligned script and Roman text. Directions and speaker labels carry plain presentation hooks.
|
|
23
|
+
|
|
24
|
+
**Upgrading**
|
|
25
|
+
|
|
26
|
+
- Verse fences join source newlines: add `/` at intended line endings. Blank lines or `//` end stanzas, and standalone `***` ends a canto.
|
|
27
|
+
- Remove `numstep=` and `cols=` from verse fences and remove column prefixes. Write each original once with its fence-level `lang=` and `enc=`; update the package and convert its content together.
|
|
28
|
+
|
|
3
29
|
## 25.2.1
|
|
4
30
|
|
|
5
31
|
**Rendering and sites**
|
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,
|
|
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
|
|
@@ -124,168 +124,149 @@
|
|
|
124
124
|
* the two markers are also the editor preview's stylesheet, with the content
|
|
125
125
|
* roots replaced by the preview's own. */
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
128
|
+
.verse
|
|
129
|
+
.verse-stanza
|
|
130
|
+
p {
|
|
131
|
+
margin: 0;
|
|
131
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%;
|
|
134
140
|
margin: 0;
|
|
141
|
+
container-type: normal;
|
|
135
142
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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;
|
|
139
164
|
}
|
|
140
165
|
|
|
141
|
-
|
|
166
|
+
/* Logical stanzas share labels across native and Roman presentations. */
|
|
167
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) .verse {
|
|
168
|
+
margin: 1.5rem 0;
|
|
169
|
+
line-height: 1.7;
|
|
170
|
+
container-type: inline-size;
|
|
171
|
+
}
|
|
172
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
173
|
+
.verse
|
|
174
|
+
.verse-stanza {
|
|
175
|
+
position: relative;
|
|
176
|
+
margin: 0 0 1em;
|
|
177
|
+
}
|
|
178
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
179
|
+
.verse-labelled
|
|
180
|
+
.verse-stanza {
|
|
181
|
+
padding-inline-start: 3em;
|
|
182
|
+
}
|
|
183
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
184
|
+
.verse
|
|
185
|
+
.verse-label {
|
|
186
|
+
position: absolute;
|
|
187
|
+
inset-inline-start: 0;
|
|
188
|
+
width: 2.5em;
|
|
189
|
+
text-align: end;
|
|
190
|
+
font-size: 0.75em;
|
|
191
|
+
color: color-mix(in srgb, currentColor 60%, transparent);
|
|
192
|
+
}
|
|
193
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) .verse .verse-line {
|
|
142
194
|
display: inline-block;
|
|
143
195
|
margin-inline-start: var(--verse-indent, 0em);
|
|
144
196
|
white-space: pre-wrap;
|
|
145
197
|
}
|
|
146
|
-
|
|
147
|
-
.verse
|
|
198
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
199
|
+
.verse
|
|
200
|
+
.verse-line.i1 {
|
|
148
201
|
--verse-indent: 1.25em;
|
|
149
202
|
}
|
|
150
|
-
|
|
203
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
204
|
+
.verse
|
|
205
|
+
.verse-line.i2 {
|
|
151
206
|
--verse-indent: 2.5em;
|
|
152
207
|
}
|
|
153
|
-
|
|
208
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
209
|
+
.verse
|
|
210
|
+
.verse-line.i3 {
|
|
154
211
|
--verse-indent: 3.75em;
|
|
155
212
|
}
|
|
156
|
-
|
|
213
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
214
|
+
.verse
|
|
215
|
+
.verse-line.i4 {
|
|
157
216
|
--verse-indent: 5em;
|
|
158
217
|
}
|
|
159
|
-
.verse :is(.verse-line, .verse-part).i5 {
|
|
160
|
-
--verse-indent: 6.25em;
|
|
161
|
-
}
|
|
162
|
-
.verse :is(.verse-line, .verse-part).i6 {
|
|
163
|
-
--verse-indent: 7.5em;
|
|
164
|
-
}
|
|
165
|
-
.verse :is(.verse-line, .verse-part).i7 {
|
|
166
|
-
--verse-indent: 8.75em;
|
|
167
|
-
}
|
|
168
|
-
.verse :is(.verse-line, .verse-part).i8 {
|
|
169
|
-
--verse-indent: 10em;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.verse .verse-stanza-break {
|
|
173
|
-
display: block;
|
|
174
|
-
height: 0.5em;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/* Numbered verse carries its numbers in a margin. A verse in columns is one
|
|
178
|
-
* grid per verse line: its number, then each column's parts stacked, the
|
|
179
|
-
* first in the normal tone and the rest muted, every part in the serif unless
|
|
180
|
-
* its face sets it. A narrow journal stacks the columns of each line. */
|
|
181
218
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
182
|
-
.verse
|
|
183
|
-
|
|
184
|
-
|
|
219
|
+
.verse
|
|
220
|
+
.verse-line.i5 {
|
|
221
|
+
--verse-indent: 6.25em;
|
|
185
222
|
}
|
|
186
|
-
|
|
187
223
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
188
224
|
.verse
|
|
189
|
-
.verse-
|
|
190
|
-
|
|
191
|
-
font-size: 0.8em;
|
|
225
|
+
.verse-line.i6 {
|
|
226
|
+
--verse-indent: 7.5em;
|
|
192
227
|
}
|
|
193
|
-
|
|
194
228
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
195
|
-
.verse
|
|
196
|
-
.verse-line
|
|
197
|
-
|
|
198
|
-
position: absolute;
|
|
199
|
-
inset-inline-start: 0;
|
|
200
|
-
width: 2.2em;
|
|
201
|
-
text-align: end;
|
|
229
|
+
.verse
|
|
230
|
+
.verse-line.i7 {
|
|
231
|
+
--verse-indent: 8.75em;
|
|
202
232
|
}
|
|
203
|
-
|
|
204
233
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
205
|
-
.verse
|
|
206
|
-
|
|
234
|
+
.verse
|
|
235
|
+
.verse-line.i8 {
|
|
236
|
+
--verse-indent: 10em;
|
|
207
237
|
}
|
|
208
|
-
|
|
209
238
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
210
|
-
.verse
|
|
211
|
-
|
|
239
|
+
.verse
|
|
240
|
+
.verse-canto-break {
|
|
241
|
+
display: block;
|
|
242
|
+
height: 0.5em;
|
|
212
243
|
}
|
|
213
|
-
|
|
214
244
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
215
|
-
.verse-
|
|
245
|
+
.verse-paired
|
|
216
246
|
.verse-row {
|
|
217
247
|
display: grid;
|
|
218
|
-
grid-auto-flow: column;
|
|
219
|
-
grid-auto-columns: 1fr;
|
|
220
248
|
direction: ltr;
|
|
221
|
-
grid-template-columns: repeat(
|
|
249
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
222
250
|
column-gap: 1.5rem;
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
227
|
-
.verse-numbered.verse-columns
|
|
228
|
-
.verse-row {
|
|
229
|
-
grid-template-columns: 2.5em repeat(var(--verse-columns, 2), minmax(0, 1fr));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
233
|
-
.verse-columns
|
|
234
|
-
.verse-number {
|
|
235
|
-
text-align: end;
|
|
236
|
-
padding-top: 0.2em;
|
|
251
|
+
align-items: start;
|
|
237
252
|
}
|
|
238
|
-
|
|
239
253
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
240
|
-
.verse-
|
|
241
|
-
:is(.verse-
|
|
242
|
-
|
|
254
|
+
.verse-paired
|
|
255
|
+
:is(.verse-native, .verse-roman) {
|
|
256
|
+
min-width: 0;
|
|
243
257
|
white-space: pre-wrap;
|
|
244
258
|
}
|
|
245
|
-
|
|
246
259
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
247
|
-
.verse-
|
|
248
|
-
.verse-
|
|
260
|
+
.verse-paired
|
|
261
|
+
.verse-roman {
|
|
249
262
|
font-family: serif;
|
|
250
|
-
padding-inline-start: var(--verse-indent, 0em);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
254
|
-
.verse-columns
|
|
255
|
-
.verse-secondary {
|
|
256
|
-
color: color-mix(in srgb, currentColor 60%, transparent);
|
|
257
263
|
}
|
|
258
|
-
|
|
259
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
260
|
-
.verse-columns
|
|
261
|
-
.verse-secondary
|
|
262
|
-
* {
|
|
263
|
-
color: inherit;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
267
|
-
.verse-columns
|
|
268
|
-
.verse-part[dir="rtl"] {
|
|
269
|
-
text-align: start;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
264
|
@container (max-width: 32rem) {
|
|
273
265
|
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
274
|
-
.verse-
|
|
266
|
+
.verse-paired
|
|
275
267
|
.verse-row {
|
|
276
|
-
grid-auto-flow: row;
|
|
277
268
|
grid-template-columns: 1fr;
|
|
278
269
|
}
|
|
279
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
280
|
-
.verse-numbered.verse-columns
|
|
281
|
-
.verse-row {
|
|
282
|
-
grid-template-columns: 2.5em 1fr;
|
|
283
|
-
}
|
|
284
|
-
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
285
|
-
.verse-numbered.verse-columns
|
|
286
|
-
.verse-column {
|
|
287
|
-
grid-column: 2;
|
|
288
|
-
}
|
|
289
270
|
}
|
|
290
271
|
|
|
291
272
|
/* Text set in one of the faces. The font family and features come from the
|
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
|
|
2501
|
-
| ---------------------------- |
|
|
2502
|
-
| `engine/content-figures.mjs` | `FIGURE_NAMES`, `FIGURE_CLASSES`, `scanFigures`, `numberFigures`, `renderFigureBlocks`
|
|
2503
|
-
| `engine/content-blocks.mjs` | `BLOCK_NAMES`, `BLOCK_CONTAINERS`, `scanBlocks`, `renderBlocks`, `renderWithheldSections`
|
|
2504
|
-
| `engine/content-verse.mjs` | `verseLines`, `verseStanzas`, `inlineVerse`, `verseMarkdown`, `scanVerse`, `renderVerse`
|
|
2505
|
-
| `engine/
|
|
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,
|