@heroiclands/package-build 25.2.0 → 25.3.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 +18 -0
- package/assets/styles/content-base.css +65 -116
- package/docs/authoring/links-and-markup.md +114 -109
- package/docs/content-format.md +20 -3
- package/docs/diagnostics.md +25 -26
- package/docs/guides/writing-in-invented-scripts.md +41 -62
- package/docs/reference/format-details.md +0 -1
- package/docs/reference/theme-pages.md +30 -57
- package/docs/source-preview.md +2 -1
- package/engine/content-blocks.mjs +3 -2
- package/engine/content-render.mjs +31 -29
- package/engine/content-scripts.mjs +180 -86
- package/engine/content-spans.mjs +4 -6
- package/engine/content-verse.mjs +482 -281
- package/engine/journals.mjs +14 -14
- package/engine/pdf-render.mjs +65 -117
- package/engine/preview-source.mjs +15 -8
- package/engine/roman-verse.mjs +68 -57
- package/engine/verse-metre.mjs +33 -40
- package/package.json +1 -1
- package/site-theme/static/css/style.css +49 -101
- package/types/engine/content-blocks.d.mts +3 -1
- package/types/engine/content-scripts.d.mts +9 -5
- package/types/engine/content-verse.d.mts +269 -83
- package/types/engine/journals.d.mts +3 -3
- package/types/engine/roman-verse.d.mts +7 -6
|
@@ -1380,118 +1380,66 @@ a.tag:hover {
|
|
|
1380
1380
|
background: var(--bg-card);
|
|
1381
1381
|
}
|
|
1382
1382
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
margin: 1.5rem 0;
|
|
1386
|
-
line-height: 1.7;
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
.single-content .verse p {
|
|
1390
|
-
margin: 0;
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
.single-content .verse p + p {
|
|
1394
|
-
margin-top: 1em;
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
.single-content .verse .verse-line {
|
|
1398
|
-
display: inline-block;
|
|
1399
|
-
margin-inline-start: var(--verse-indent, 0em);
|
|
1400
|
-
white-space: pre-wrap;
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
.single-content .verse :is(.verse-line, .verse-part).i1 { --verse-indent: 1.25em; }
|
|
1404
|
-
.single-content .verse :is(.verse-line, .verse-part).i2 { --verse-indent: 2.5em; }
|
|
1405
|
-
.single-content .verse :is(.verse-line, .verse-part).i3 { --verse-indent: 3.75em; }
|
|
1406
|
-
.single-content .verse :is(.verse-line, .verse-part).i4 { --verse-indent: 5em; }
|
|
1407
|
-
.single-content .verse :is(.verse-line, .verse-part).i5 { --verse-indent: 6.25em; }
|
|
1408
|
-
.single-content .verse :is(.verse-line, .verse-part).i6 { --verse-indent: 7.5em; }
|
|
1409
|
-
.single-content .verse :is(.verse-line, .verse-part).i7 { --verse-indent: 8.75em; }
|
|
1410
|
-
.single-content .verse :is(.verse-line, .verse-part).i8 { --verse-indent: 10em; }
|
|
1411
|
-
|
|
1412
|
-
.single-content .verse .verse-stanza-break { display: block; height: 0.5em; }
|
|
1413
|
-
|
|
1414
|
-
/* Numbered verse carries its numbers in a margin. A verse in columns is one
|
|
1415
|
-
grid per verse line: its number, then each column's parts stacked, the
|
|
1416
|
-
first in the normal tone and the rest muted, every part in the body serif
|
|
1417
|
-
unless its face sets it. A narrow verse stacks the columns of each line. */
|
|
1418
|
-
.single-content .verse.verse-numbered {
|
|
1419
|
-
position: relative;
|
|
1420
|
-
padding-inline-start: 3em;
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
.single-content .verse .verse-number {
|
|
1424
|
-
color: var(--text-muted);
|
|
1425
|
-
font-size: 0.8em;
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
.single-content .verse-numbered .verse-line .verse-number {
|
|
1429
|
-
position: absolute;
|
|
1430
|
-
inset-inline-start: 0;
|
|
1431
|
-
width: 2.2em;
|
|
1432
|
-
text-align: end;
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
.single-content .verse.verse-columns {
|
|
1436
|
-
container-type: inline-size;
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
.single-content .verse-numbered.verse-columns {
|
|
1440
|
-
padding-inline-start: 0;
|
|
1383
|
+
.single-content .verse .verse-stanza p {
|
|
1384
|
+
margin: 0;
|
|
1441
1385
|
}
|
|
1442
1386
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
grid-template-columns: repeat(var(--verse-columns, 2), minmax(0, 1fr));
|
|
1449
|
-
column-gap: 1.5rem;
|
|
1450
|
-
margin-bottom: 0.5em;
|
|
1387
|
+
/* Logical stanzas share labels across native and Roman presentations. */
|
|
1388
|
+
.single-content .verse {
|
|
1389
|
+
margin: 1.5rem 0;
|
|
1390
|
+
line-height: 1.7;
|
|
1391
|
+
container-type: inline-size;
|
|
1451
1392
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1393
|
+
.single-content .verse .verse-stanza {
|
|
1394
|
+
position: relative;
|
|
1395
|
+
margin: 0 0 1em;
|
|
1455
1396
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
text-align: end;
|
|
1459
|
-
padding-top: 0.2em;
|
|
1397
|
+
.single-content .verse-labelled .verse-stanza {
|
|
1398
|
+
padding-inline-start: 3em;
|
|
1460
1399
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1400
|
+
.single-content .verse .verse-label {
|
|
1401
|
+
position: absolute;
|
|
1402
|
+
inset-inline-start: 0;
|
|
1403
|
+
width: 2.5em;
|
|
1404
|
+
text-align: end;
|
|
1405
|
+
font-size: 0.75em;
|
|
1406
|
+
color: color-mix(in srgb, currentColor 60%, transparent);
|
|
1465
1407
|
}
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1408
|
+
.single-content .verse .verse-line {
|
|
1409
|
+
display: inline-block;
|
|
1410
|
+
margin-inline-start: var(--verse-indent, 0em);
|
|
1411
|
+
white-space: pre-wrap;
|
|
1412
|
+
}
|
|
1413
|
+
.single-content .verse .verse-line.i1 { --verse-indent: 1.25em; }
|
|
1414
|
+
.single-content .verse .verse-line.i2 { --verse-indent: 2.5em; }
|
|
1415
|
+
.single-content .verse .verse-line.i3 { --verse-indent: 3.75em; }
|
|
1416
|
+
.single-content .verse .verse-line.i4 { --verse-indent: 5em; }
|
|
1417
|
+
.single-content .verse .verse-line.i5 { --verse-indent: 6.25em; }
|
|
1418
|
+
.single-content .verse .verse-line.i6 { --verse-indent: 7.5em; }
|
|
1419
|
+
.single-content .verse .verse-line.i7 { --verse-indent: 8.75em; }
|
|
1420
|
+
.single-content .verse .verse-line.i8 { --verse-indent: 10em; }
|
|
1421
|
+
.single-content .verse .verse-canto-break {
|
|
1422
|
+
display: block;
|
|
1423
|
+
height: 0.5em;
|
|
1470
1424
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1425
|
+
.single-content .verse-paired .verse-row {
|
|
1426
|
+
display: grid;
|
|
1427
|
+
direction: ltr;
|
|
1428
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
1429
|
+
column-gap: 1.5rem;
|
|
1430
|
+
align-items: start;
|
|
1474
1431
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1432
|
+
.single-content .verse-paired :is(.verse-native, .verse-roman) {
|
|
1433
|
+
min-width: 0;
|
|
1434
|
+
white-space: pre-wrap;
|
|
1478
1435
|
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
text-align: start;
|
|
1436
|
+
.single-content .verse-paired .verse-roman {
|
|
1437
|
+
font-family: serif;
|
|
1482
1438
|
}
|
|
1483
|
-
|
|
1484
1439
|
@container (max-width: 32rem) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
}
|
|
1489
|
-
.single-content .verse-numbered.verse-columns .verse-row {
|
|
1490
|
-
grid-template-columns: 2.5em 1fr;
|
|
1491
|
-
}
|
|
1492
|
-
.single-content .verse-numbered.verse-columns .verse-column {
|
|
1493
|
-
grid-column: 2;
|
|
1494
|
-
}
|
|
1440
|
+
.single-content .verse-paired .verse-row {
|
|
1441
|
+
grid-template-columns: 1fr;
|
|
1442
|
+
}
|
|
1495
1443
|
}
|
|
1496
1444
|
|
|
1497
1445
|
/* Ornamental horizontal rule: thin line flanking a centered gold
|
|
@@ -43,10 +43,12 @@ export function scanBlocks(source: string): {
|
|
|
43
43
|
* @param {object} [options]
|
|
44
44
|
* @param {(markdown: string) => string} [options.renderInline] - How a title
|
|
45
45
|
* is rendered; omitted, a title is plain inline Markdown.
|
|
46
|
+
* @param {Map<string, object>} [options.verses] - Shared encoded verse presentations.
|
|
46
47
|
* @returns {{markdown: string, errors: Array<{line: number, column: number, message: string}>}}
|
|
47
48
|
*/
|
|
48
|
-
export function renderBlocks(source: string, target: "foundry" | "web" | "preview", { renderInline }?: {
|
|
49
|
+
export function renderBlocks(source: string, target: "foundry" | "web" | "preview", { renderInline, verses }?: {
|
|
49
50
|
renderInline?: ((markdown: string) => string) | undefined;
|
|
51
|
+
verses?: Map<string, object> | undefined;
|
|
50
52
|
}): {
|
|
51
53
|
markdown: string;
|
|
52
54
|
errors: Array<{
|
|
@@ -50,11 +50,10 @@ export function scanRuns(source: string, ctx?: RunContext, syntax?: import("./co
|
|
|
50
50
|
};
|
|
51
51
|
/**
|
|
52
52
|
* Rewrite text marked with `lang=`, `font=` and `enc=` into the plain span,
|
|
53
|
-
* div and verse grammar the rest of each chain renders
|
|
53
|
+
* div and verse grammar the rest of each chain renders.
|
|
54
54
|
*
|
|
55
|
-
* - **
|
|
56
|
-
*
|
|
57
|
-
* lines and source positions remain unchanged.
|
|
55
|
+
* - **Verse layout markers** stay outside encoded text. A shared logical
|
|
56
|
+
* structure retains authored source positions and both presentations.
|
|
58
57
|
* - **The enc, if any, is applied first.** Characters Markdown would read are
|
|
59
58
|
* then backslash-escaped, so they reach every later pass as characters.
|
|
60
59
|
* - **Emphasis in a face** becomes an `<em>` or a `<strong>` carrying its
|
|
@@ -81,7 +80,7 @@ export function scanRuns(source: string, ctx?: RunContext, syntax?: import("./co
|
|
|
81
80
|
* scanner projections.
|
|
82
81
|
* @param {{target?: "site"|"foundry"|"book"}} [options] - The target the
|
|
83
82
|
* Markdown is rendered for; only `site` writes the search marker.
|
|
84
|
-
* @returns {{markdown: string, errors: Array<{file?: string, line: number, column: number, message: string}>, scrolls: Map<string, import("./content-scroll.mjs").ScrollLayout>}}
|
|
83
|
+
* @returns {{markdown: string, errors: Array<{file?: string, line: number, column: number, message: string}>, scrolls: Map<string, import("./content-scroll.mjs").ScrollLayout>, verses: Map<string, {model: ReturnType<typeof import("./content-verse.mjs").parseVerse>, classes: string[], attributes: Record<string, string>}>}}
|
|
85
84
|
* The rewritten Markdown, the findings of {@link scanRuns}, and each
|
|
86
85
|
* rewritten scroll fence's layout, by its rewritten body.
|
|
87
86
|
*/
|
|
@@ -96,6 +95,11 @@ export function renderRuns(source: string, ctx?: RunContext, syntax?: import("./
|
|
|
96
95
|
message: string;
|
|
97
96
|
}>;
|
|
98
97
|
scrolls: Map<string, import("./content-scroll.mjs").ScrollLayout>;
|
|
98
|
+
verses: Map<string, {
|
|
99
|
+
model: ReturnType<typeof import("./content-verse.mjs").parseVerse>;
|
|
100
|
+
classes: string[];
|
|
101
|
+
attributes: Record<string, string>;
|
|
102
|
+
}>;
|
|
99
103
|
};
|
|
100
104
|
/** The keys this module reads, which no construct passes through as written. */
|
|
101
105
|
export const RUN_KEYS: readonly string[];
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** The authored verse lines, excluding blank lines and stanza separators. */
|
|
2
|
-
export function verseLines(body: any): string[];
|
|
3
1
|
/**
|
|
4
2
|
* Read one verse line. Marker offsets are zero-based in the authored line;
|
|
5
3
|
* textColumn is the one-based column of its first non-space character.
|
|
@@ -12,103 +10,291 @@ export function verseLine(line: any): {
|
|
|
12
10
|
markerLength: number;
|
|
13
11
|
textColumn: number;
|
|
14
12
|
};
|
|
13
|
+
/** A verse is inline Markdown even when it starts with block syntax. */
|
|
14
|
+
export function inlineVerse(text: any): string;
|
|
15
|
+
/**
|
|
16
|
+
* Whether text runs right to left: its first letter is in a right-to-left
|
|
17
|
+
* block. A face's right-to-left code points sit in U+1E800–U+1EFFF.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} text - Text, after any map.
|
|
20
|
+
* @returns {boolean} Whether it starts right to left.
|
|
21
|
+
*/
|
|
22
|
+
export function rightToLeft(text: string): boolean;
|
|
23
|
+
/** Read verse code fences; start/end are inclusive zero-based source lines.
|
|
24
|
+
* @param {string} source - Authored Markdown.
|
|
25
|
+
* @param {object} [options] - Whole-page validation choices.
|
|
26
|
+
* @param {boolean} [options.checkWorks] - Whether to validate page-local versions.
|
|
27
|
+
* @returns {{blocks: VerseBlock[], errors: VerseDiagnostic[]}} Located fences and findings.
|
|
28
|
+
*/
|
|
29
|
+
export function scanVerse(source: string, { checkWorks }?: {
|
|
30
|
+
checkWorks?: boolean | undefined;
|
|
31
|
+
}): {
|
|
32
|
+
blocks: VerseBlock[];
|
|
33
|
+
errors: VerseDiagnostic[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A logical line with its authored UTF-16 coordinates.
|
|
37
|
+
* @typedef {object} VerseLine
|
|
38
|
+
* @property {string} text - Inline Markdown in this presentation.
|
|
39
|
+
* @property {number} level - Leading-period indentation depth.
|
|
40
|
+
* @property {number} from - First authored offset, including indentation.
|
|
41
|
+
* @property {number} to - Offset at the line ending.
|
|
42
|
+
* @property {number[]} offsets - Source offset for each UTF-16 text unit.
|
|
43
|
+
* @property {string} [romanText] - Roman text paired with an encoded line.
|
|
44
|
+
*/
|
|
15
45
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
46
|
+
* A stanza's logical lines and authored bounds.
|
|
47
|
+
* @typedef {object} VerseStanza
|
|
48
|
+
* @property {VerseLine[]} lines - Lines in reading order.
|
|
49
|
+
* @property {number} from - First authored offset.
|
|
50
|
+
* @property {number} to - Offset at the stanza ending.
|
|
18
51
|
*/
|
|
52
|
+
/**
|
|
53
|
+
* @typedef {VerseStanza & {canto: number, stanza: number, label: string, cantoBreak?: false}} VerseTextGroup
|
|
54
|
+
* @typedef {{cantoBreak: true, from: number, to: number, text?: string}} VerseCantoBreak
|
|
55
|
+
* @typedef {{kind: "line"|"stanza"|"canto", sourceOffset: number}} VerseBoundary
|
|
56
|
+
* @typedef {{offset: number, message: string}} VerseFinding
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Shared authored verse structure and source locations.
|
|
60
|
+
* @typedef {object} VerseModel
|
|
61
|
+
* @property {Array<{stanzas: VerseStanza[]}>} cantos - Cantos in reading order.
|
|
62
|
+
* @property {Array<VerseTextGroup|VerseCantoBreak>} groups - Stanzas and canto breaks.
|
|
63
|
+
* @property {VerseBoundary[]} boundaries - Explicit authored boundaries.
|
|
64
|
+
* @property {Array<[number, number]>} layout - Source ranges omitted from encoded letters.
|
|
65
|
+
* @property {VerseFinding[]} errors - Findings relative to the fence body.
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* An authored verse fence with its parsed logical structure.
|
|
69
|
+
* @typedef {object} VerseBlock
|
|
70
|
+
* @property {number} start - Opening fence's zero-based source line.
|
|
71
|
+
* @property {number} end - Closing fence's zero-based source line.
|
|
72
|
+
* @property {string} fence - Authored fence delimiter.
|
|
73
|
+
* @property {"verse"} name - Fence language.
|
|
74
|
+
* @property {Record<string, string>} attributes - Authored attribute values.
|
|
75
|
+
* @property {string} id - Authored anchor, or the empty string.
|
|
76
|
+
* @property {string[]} classes - Authored presentation classes.
|
|
77
|
+
* @property {string} indent - Opening fence's leading spaces.
|
|
78
|
+
* @property {string} body - Authored fence body.
|
|
79
|
+
* @property {VerseModel} model - Logical structure relative to the body.
|
|
80
|
+
*/
|
|
81
|
+
/** @typedef {{line: number, column: number, message: string}} VerseDiagnostic */
|
|
82
|
+
/**
|
|
83
|
+
* An encoded verse's shared display model and native-cell presentation.
|
|
84
|
+
* @typedef {object} VersePresentation
|
|
85
|
+
* @property {VerseModel} model - Logical structure with paired line text.
|
|
86
|
+
* @property {string[]} classes - Native script and font classes.
|
|
87
|
+
* @property {Record<string, string>} attributes - Native language, direction and search attributes.
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* Parse logical verse lines, stanzas and cantos without losing authored offsets.
|
|
91
|
+
* Offsets are UTF-16 positions relative to body. Delimiters and indentation are
|
|
92
|
+
* layout ranges; source newlines inside a logical line contribute one space.
|
|
93
|
+
* @param {string} body - Authored fence body.
|
|
94
|
+
* @returns {VerseModel} The shared structure with offsets relative to the body.
|
|
95
|
+
*/
|
|
96
|
+
export function parseVerse(body: string): VerseModel;
|
|
97
|
+
/** Logical line text for consumers that do not need source locations. */
|
|
98
|
+
export function verseLines(body: any): string[];
|
|
99
|
+
/** Paragraph groups with separate canto gaps. */
|
|
19
100
|
export function verseStanzas(body: any): {
|
|
20
101
|
text: string;
|
|
21
102
|
level: number;
|
|
22
103
|
}[][];
|
|
23
|
-
/** A verse is inline Markdown even when it starts with block syntax. */
|
|
24
|
-
export function inlineVerse(text: any): string;
|
|
25
104
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* definitions remain in scope. The span carries the indent for each line.
|
|
105
|
+
* Compare the stanza counts of each version of a page-local work.
|
|
106
|
+
* @param {VerseBlock[]} blocks - Fences belonging to one page.
|
|
107
|
+
* @returns {VerseDiagnostic[]} Findings at affected opening fences.
|
|
30
108
|
*/
|
|
31
|
-
export function
|
|
109
|
+
export function workShapeFindings(blocks: VerseBlock[]): VerseDiagnostic[];
|
|
32
110
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {
|
|
38
|
-
* @
|
|
111
|
+
* Render a shared verse structure while preserving surrounding inline Markdown.
|
|
112
|
+
* @param {string} body - Authored fence body.
|
|
113
|
+
* @param {object} [options] - Shared structure and display choices.
|
|
114
|
+
* @param {boolean} [options.labelled] - Whether each stanza carries its label.
|
|
115
|
+
* @param {VerseModel} [options.model] - Parsed structure; defaults to parsing the body.
|
|
116
|
+
* @param {VersePresentation} [options.presentation] - Native-cell font and language.
|
|
117
|
+
* @returns {string} Markdown with verse layout wrappers.
|
|
39
118
|
*/
|
|
40
|
-
export function
|
|
41
|
-
|
|
42
|
-
|
|
119
|
+
export function verseMarkdown(body: string, { labelled, model, presentation }?: {
|
|
120
|
+
labelled?: boolean | undefined;
|
|
121
|
+
model?: VerseModel | undefined;
|
|
122
|
+
presentation?: VersePresentation | undefined;
|
|
123
|
+
}): string;
|
|
124
|
+
/**
|
|
125
|
+
* Replace verse fences with wrappers whose bodies remain inline Markdown.
|
|
126
|
+
* @param {string} source - Markdown containing verse fences.
|
|
127
|
+
* @param {object} [options] - Encoded display models.
|
|
128
|
+
* @param {Map<string, VersePresentation>} [options.verses] - Presentations keyed by rewritten body.
|
|
43
129
|
*/
|
|
44
|
-
export function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
fence: string;
|
|
50
|
-
name: string;
|
|
51
|
-
attributes: {};
|
|
52
|
-
id: string;
|
|
53
|
-
classes: never[];
|
|
54
|
-
indent: string;
|
|
55
|
-
}[];
|
|
56
|
-
errors: any[];
|
|
130
|
+
export function renderVerse(source: string, { verses }?: {
|
|
131
|
+
verses?: Map<string, VersePresentation> | undefined;
|
|
132
|
+
}): {
|
|
133
|
+
markdown: string;
|
|
134
|
+
errors: VerseDiagnostic[];
|
|
57
135
|
};
|
|
58
|
-
/** The
|
|
59
|
-
export
|
|
60
|
-
/**
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
65
|
-
* offsets are measured before prefixes or indentation periods are removed.
|
|
66
|
-
*
|
|
67
|
-
* @param {object} block - A verse from scanVerse.
|
|
68
|
-
* @param {string[]} lines - The complete source, by line.
|
|
69
|
-
* @returns {Array<{stanzaBreak: true, line: number}|{stanzaBreak?: false, parts: Array<{column: number, line: number, sourceColumn: number, textColumn: number, text: string, indent: number, markerStart: number, markerLength: number, prefixLength: number}>}>}
|
|
136
|
+
/** The authored attributes of a verse fence. */
|
|
137
|
+
export const VERSE_KEYS: readonly string[];
|
|
138
|
+
/** A canto separator, including the escaped form produced by a native run. */
|
|
139
|
+
export const STANZA_BREAK: RegExp;
|
|
140
|
+
export function stanzaSeparator(group: any): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* A logical line with its authored UTF-16 coordinates.
|
|
70
143
|
*/
|
|
71
|
-
export
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
144
|
+
export type VerseLine = {
|
|
145
|
+
/**
|
|
146
|
+
* - Inline Markdown in this presentation.
|
|
147
|
+
*/
|
|
148
|
+
text: string;
|
|
149
|
+
/**
|
|
150
|
+
* - Leading-period indentation depth.
|
|
151
|
+
*/
|
|
152
|
+
level: number;
|
|
153
|
+
/**
|
|
154
|
+
* - First authored offset, including indentation.
|
|
155
|
+
*/
|
|
156
|
+
from: number;
|
|
157
|
+
/**
|
|
158
|
+
* - Offset at the line ending.
|
|
159
|
+
*/
|
|
160
|
+
to: number;
|
|
161
|
+
/**
|
|
162
|
+
* - Source offset for each UTF-16 text unit.
|
|
163
|
+
*/
|
|
164
|
+
offsets: number[];
|
|
165
|
+
/**
|
|
166
|
+
* - Roman text paired with an encoded line.
|
|
167
|
+
*/
|
|
168
|
+
romanText?: string | undefined;
|
|
169
|
+
};
|
|
88
170
|
/**
|
|
89
|
-
*
|
|
90
|
-
* block. A face's right-to-left code points sit in U+1E800–U+1EFFF.
|
|
91
|
-
*
|
|
92
|
-
* @param {string} text - Text, after any map.
|
|
93
|
-
* @returns {boolean} Whether it starts right to left.
|
|
171
|
+
* A stanza's logical lines and authored bounds.
|
|
94
172
|
*/
|
|
95
|
-
export
|
|
96
|
-
/**
|
|
97
|
-
|
|
173
|
+
export type VerseStanza = {
|
|
174
|
+
/**
|
|
175
|
+
* - Lines in reading order.
|
|
176
|
+
*/
|
|
177
|
+
lines: VerseLine[];
|
|
178
|
+
/**
|
|
179
|
+
* - First authored offset.
|
|
180
|
+
*/
|
|
181
|
+
from: number;
|
|
182
|
+
/**
|
|
183
|
+
* - Offset at the stanza ending.
|
|
184
|
+
*/
|
|
185
|
+
to: number;
|
|
186
|
+
};
|
|
187
|
+
export type VerseTextGroup = VerseStanza & {
|
|
188
|
+
canto: number;
|
|
189
|
+
stanza: number;
|
|
190
|
+
label: string;
|
|
191
|
+
cantoBreak?: false;
|
|
192
|
+
};
|
|
193
|
+
export type VerseCantoBreak = {
|
|
194
|
+
cantoBreak: true;
|
|
195
|
+
from: number;
|
|
196
|
+
to: number;
|
|
197
|
+
text?: string;
|
|
198
|
+
};
|
|
199
|
+
export type VerseBoundary = {
|
|
200
|
+
kind: "line" | "stanza" | "canto";
|
|
201
|
+
sourceOffset: number;
|
|
202
|
+
};
|
|
203
|
+
export type VerseFinding = {
|
|
204
|
+
offset: number;
|
|
205
|
+
message: string;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Shared authored verse structure and source locations.
|
|
98
209
|
*/
|
|
99
|
-
export
|
|
100
|
-
|
|
101
|
-
|
|
210
|
+
export type VerseModel = {
|
|
211
|
+
/**
|
|
212
|
+
* - Cantos in reading order.
|
|
213
|
+
*/
|
|
214
|
+
cantos: Array<{
|
|
215
|
+
stanzas: VerseStanza[];
|
|
216
|
+
}>;
|
|
217
|
+
/**
|
|
218
|
+
* - Stanzas and canto breaks.
|
|
219
|
+
*/
|
|
220
|
+
groups: Array<VerseTextGroup | VerseCantoBreak>;
|
|
221
|
+
/**
|
|
222
|
+
* - Explicit authored boundaries.
|
|
223
|
+
*/
|
|
224
|
+
boundaries: VerseBoundary[];
|
|
225
|
+
/**
|
|
226
|
+
* - Source ranges omitted from encoded letters.
|
|
227
|
+
*/
|
|
228
|
+
layout: Array<[number, number]>;
|
|
229
|
+
/**
|
|
230
|
+
* - Findings relative to the fence body.
|
|
231
|
+
*/
|
|
232
|
+
errors: VerseFinding[];
|
|
102
233
|
};
|
|
103
|
-
export function stanzaSeparator(group: any): boolean;
|
|
104
|
-
/** The layout class the build gives a verse whose cols count exceeds one. */
|
|
105
|
-
export const COLUMNS_CLASS: "verse-columns";
|
|
106
234
|
/**
|
|
107
|
-
*
|
|
108
|
-
* are read by `scanRuns` in content-scripts.mjs; `dir`, and on the site
|
|
109
|
-
* `data-pagefind-ignore`, are written by its rewrite of a fence set in one of
|
|
110
|
-
* the faces, and reach the element as they are written.
|
|
235
|
+
* An authored verse fence with its parsed logical structure.
|
|
111
236
|
*/
|
|
112
|
-
export
|
|
113
|
-
/**
|
|
114
|
-
|
|
237
|
+
export type VerseBlock = {
|
|
238
|
+
/**
|
|
239
|
+
* - Opening fence's zero-based source line.
|
|
240
|
+
*/
|
|
241
|
+
start: number;
|
|
242
|
+
/**
|
|
243
|
+
* - Closing fence's zero-based source line.
|
|
244
|
+
*/
|
|
245
|
+
end: number;
|
|
246
|
+
/**
|
|
247
|
+
* - Authored fence delimiter.
|
|
248
|
+
*/
|
|
249
|
+
fence: string;
|
|
250
|
+
/**
|
|
251
|
+
* - Fence language.
|
|
252
|
+
*/
|
|
253
|
+
name: "verse";
|
|
254
|
+
/**
|
|
255
|
+
* - Authored attribute values.
|
|
256
|
+
*/
|
|
257
|
+
attributes: Record<string, string>;
|
|
258
|
+
/**
|
|
259
|
+
* - Authored anchor, or the empty string.
|
|
260
|
+
*/
|
|
261
|
+
id: string;
|
|
262
|
+
/**
|
|
263
|
+
* - Authored presentation classes.
|
|
264
|
+
*/
|
|
265
|
+
classes: string[];
|
|
266
|
+
/**
|
|
267
|
+
* - Opening fence's leading spaces.
|
|
268
|
+
*/
|
|
269
|
+
indent: string;
|
|
270
|
+
/**
|
|
271
|
+
* - Authored fence body.
|
|
272
|
+
*/
|
|
273
|
+
body: string;
|
|
274
|
+
/**
|
|
275
|
+
* - Logical structure relative to the body.
|
|
276
|
+
*/
|
|
277
|
+
model: VerseModel;
|
|
278
|
+
};
|
|
279
|
+
export type VerseDiagnostic = {
|
|
280
|
+
line: number;
|
|
281
|
+
column: number;
|
|
282
|
+
message: string;
|
|
283
|
+
};
|
|
284
|
+
/**
|
|
285
|
+
* An encoded verse's shared display model and native-cell presentation.
|
|
286
|
+
*/
|
|
287
|
+
export type VersePresentation = {
|
|
288
|
+
/**
|
|
289
|
+
* - Logical structure with paired line text.
|
|
290
|
+
*/
|
|
291
|
+
model: VerseModel;
|
|
292
|
+
/**
|
|
293
|
+
* - Native script and font classes.
|
|
294
|
+
*/
|
|
295
|
+
classes: string[];
|
|
296
|
+
/**
|
|
297
|
+
* - Native language, direction and search attributes.
|
|
298
|
+
*/
|
|
299
|
+
attributes: Record<string, string>;
|
|
300
|
+
};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* code blocks are respected so `# foo` inside ``` or ~~~ blocks doesn't
|
|
4
4
|
* trigger a split. Content before the first H1 (if non-empty) becomes a
|
|
5
5
|
* leading page. Each H1 yields a page whose name is the heading
|
|
6
|
-
* text (with any `{#anchor-id}` suffix stripped out and
|
|
7
|
-
* `anchorSlug`). The classes the heading declares come along as
|
|
8
|
-
* a surface that honours one has it without reading the suffix again.
|
|
6
|
+
* text without inline markup (with any `{#anchor-id}` suffix stripped out and
|
|
7
|
+
* surfaced as `anchorSlug`). The classes the heading declares come along as
|
|
8
|
+
* `classes`, so a surface that honours one has it without reading the suffix again.
|
|
9
9
|
*
|
|
10
10
|
* `leadName` names that leading page. A journal note's is "Introduction",
|
|
11
11
|
* because it introduces the pages that follow. An item doc's is the item — a
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* The caller writes the boundaries through its selected encoding.
|
|
2
|
+
* Project verse text with explicit authored line, stanza and canto boundaries.
|
|
3
|
+
* Source newlines within a logical line are whitespace. Delimiters and visual
|
|
4
|
+
* indentation do not reach the encoder as letters.
|
|
6
5
|
* @param {string} source - Complete authored source.
|
|
7
|
-
* @param {Parameters<typeof plainRomanRun>[1] & {
|
|
6
|
+
* @param {Parameters<typeof plainRomanRun>[1] & {model?: ReturnType<typeof parseVerse>, modelOffset?: number}} [options] - Run bounds, spans and layout projection.
|
|
8
7
|
* @returns {ReturnType<typeof plainRomanRun> & {boundaries: Array<{kind: "line"|"stanza"|"canto", at: number, sourceOffset: number}>, errors: Array<{offset: number, message: string}>}} Visible text, positions and structural events.
|
|
9
8
|
*/
|
|
10
9
|
export function plainRomanVerse(source: string, options?: Parameters<typeof plainRomanRun>[1] & {
|
|
11
|
-
|
|
10
|
+
model?: ReturnType<typeof parseVerse>;
|
|
11
|
+
modelOffset?: number;
|
|
12
12
|
}): ReturnType<typeof plainRomanRun> & {
|
|
13
13
|
boundaries: Array<{
|
|
14
14
|
kind: "line" | "stanza" | "canto";
|
|
@@ -21,3 +21,4 @@ export function plainRomanVerse(source: string, options?: Parameters<typeof plai
|
|
|
21
21
|
}>;
|
|
22
22
|
};
|
|
23
23
|
import { plainRomanRun } from "./roman-run.mjs";
|
|
24
|
+
import { parseVerse } from "./content-verse.mjs";
|