@heroiclands/package-build 25.5.1 → 25.5.2
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 +6 -0
- package/docs/api.md +8 -6
- package/engine/content-scripts.mjs +147 -36
- package/engine/roman-characters.mjs +45 -8
- package/package.json +1 -1
- package/types/engine/roman-characters.d.mts +60 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 25.5.2
|
|
4
|
+
|
|
5
|
+
**Languages and scripts**
|
|
6
|
+
|
|
7
|
+
- A sentence that runs across several spans and links in one language is checked as one sentence, so the period that ends it is not reported as opening the next.
|
|
8
|
+
|
|
3
9
|
## 25.5.1
|
|
4
10
|
|
|
5
11
|
**Builds and commands**
|
package/docs/api.md
CHANGED
|
@@ -1449,12 +1449,14 @@ The charset authored content is held to, so a book can choose its face. The pack
|
|
|
1449
1449
|
Exact permitted Roman source characters for configured languages, before script
|
|
1450
1450
|
encoding. Inventories come from `data.roman` on each language's own note.
|
|
1451
1451
|
|
|
1452
|
-
| Export
|
|
1453
|
-
|
|
|
1454
|
-
| `isRomanWhitespace`
|
|
1455
|
-
| `romanInventoryProblems`
|
|
1456
|
-
| `romanInventoriesOf`
|
|
1457
|
-
| `romanTextProblems`
|
|
1452
|
+
| Export | Signature | Returns | Use it when |
|
|
1453
|
+
| ------------------------- | -------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1454
|
+
| `isRomanWhitespace` | `isRomanWhitespace(char)` | `boolean` | recognizing standard spaces and ASCII tab or line whitespace |
|
|
1455
|
+
| `romanInventoryProblems` | `romanInventoryProblems(value)` | `string[]` | checking NFC, repeated characters and forbidden whitespace or controls in a literal inventory |
|
|
1456
|
+
| `romanInventoriesOf` | `romanInventoriesOf(records, languages)` | `Map<string, RomanInventory>` | looking up a configured language's own inventory by name or BCP 47 tag |
|
|
1457
|
+
| `romanTextProblems` | `romanTextProblems(text, inventory, stream)` | `{offset, message}[]` | validating standard Roman punctuation and language additions with exact UTF-16 offsets; pass a `stream` state to continue sentences and quotations from earlier runs |
|
|
1458
|
+
| `romanPunctuationState` | `romanPunctuationState()` | `{sentenceStart, quotes}` | starting a stream of runs whose sentences and quotations continue from one run to the next |
|
|
1459
|
+
| `romanUnclosedQuotations` | `romanUnclosedQuotations(quotes)` | `{offset, message}[]` | reporting the quotations still open where a stream of runs ends |
|
|
1458
1460
|
|
|
1459
1461
|
### `engine.pathCharset`
|
|
1460
1462
|
|
|
@@ -63,7 +63,12 @@ import { unknownWordMessage, unknownWords, wordBooksFromRecords } from "./run-wo
|
|
|
63
63
|
import { metreBooksFromRecords, metreFindings, metresFromRecords } from "./verse-metre.mjs";
|
|
64
64
|
import { encodeWithLanguage } from "./encoding-language.mjs";
|
|
65
65
|
import { encodingsFromRecords, encodingAddress } from "./encoding-notes.mjs";
|
|
66
|
-
import {
|
|
66
|
+
import {
|
|
67
|
+
romanInventoriesOf,
|
|
68
|
+
romanPunctuationState,
|
|
69
|
+
romanTextProblems,
|
|
70
|
+
romanUnclosedQuotations,
|
|
71
|
+
} from "./roman-characters.mjs";
|
|
67
72
|
import { plainRomanRun } from "./roman-run.mjs";
|
|
68
73
|
import { plainRomanVerse } from "./roman-verse.mjs";
|
|
69
74
|
import { encodeText } from "./encoding.mjs";
|
|
@@ -1175,6 +1180,7 @@ function analyseRuns(source, ctx, syntax) {
|
|
|
1175
1180
|
rawReferences.push({
|
|
1176
1181
|
lang: keys.lang,
|
|
1177
1182
|
font: keys.font,
|
|
1183
|
+
enc: keys.enc,
|
|
1178
1184
|
from: match.index + 2 + bar + 1,
|
|
1179
1185
|
to: match.index + close - 1,
|
|
1180
1186
|
where: construct.where,
|
|
@@ -1363,24 +1369,6 @@ function analyseRuns(source, ctx, syntax) {
|
|
|
1363
1369
|
(ctx.romanInventories?.get(lang) ?? ctx.romanInventories?.get(lang.toLowerCase()))
|
|
1364
1370
|
);
|
|
1365
1371
|
|
|
1366
|
-
/** Check visible source before selection or lexicon-native replacement. */
|
|
1367
|
-
const roman = (parts, detail) => {
|
|
1368
|
-
const inventory = inventoryOf(detail.run.lang);
|
|
1369
|
-
if (!inventory) return;
|
|
1370
|
-
if (!inventory.characters) {
|
|
1371
|
-
report(
|
|
1372
|
-
{ line: detail.run.line, column: detail.run.column },
|
|
1373
|
-
`the language note for \`${inventory.language}\` must declare \`data.roman\``,
|
|
1374
|
-
);
|
|
1375
|
-
return;
|
|
1376
|
-
}
|
|
1377
|
-
for (const [from, to] of parts) {
|
|
1378
|
-
const plain = plainRomanRun(text, { from, to });
|
|
1379
|
-
for (const problem of romanTextProblems(plain.text, inventory))
|
|
1380
|
-
report(positionOf(starts, plain.offsets[problem.offset] ?? from), problem.message);
|
|
1381
|
-
}
|
|
1382
|
-
};
|
|
1383
|
-
|
|
1384
1372
|
/**
|
|
1385
1373
|
* Give a scroll fence the face it is set in, and report a fence that names
|
|
1386
1374
|
* none or whose script is written in lines. A fence that names no face
|
|
@@ -1646,7 +1634,128 @@ function analyseRuns(source, ctx, syntax) {
|
|
|
1646
1634
|
.filter((detail) => detail.run.kind === "span")
|
|
1647
1635
|
.map((detail) => [detail.run.start, detail]),
|
|
1648
1636
|
);
|
|
1649
|
-
|
|
1637
|
+
// Inline runs, spans and labelled links, of one resolved language and
|
|
1638
|
+
// encoding separated only by whitespace form one punctuation stream: a
|
|
1639
|
+
// sentence or a quotation may run through several of them. Each run opens
|
|
1640
|
+
// in the state its predecessor in the stream closed in, and quotations
|
|
1641
|
+
// still open are reported once, where the stream ends. A block (a div,
|
|
1642
|
+
// verse or scroll) is a stream of its own and never joins an inline run,
|
|
1643
|
+
// as a paragraph does not continue a sentence from outside it; it still
|
|
1644
|
+
// separates the runs on either side of it.
|
|
1645
|
+
const ownerDetails = details
|
|
1646
|
+
.filter((detail) => ownerOf(detail) === detail)
|
|
1647
|
+
.sort((a, b) => a.run.start - b.run.start);
|
|
1648
|
+
const streamEntry = (where, lang, enc, checkable, inline) => {
|
|
1649
|
+
const inventory = inventoryOf(lang);
|
|
1650
|
+
// A block's bounds are its opening and closing line indices.
|
|
1651
|
+
const end = Math.min(where.end, lines.length - 1);
|
|
1652
|
+
return {
|
|
1653
|
+
inline,
|
|
1654
|
+
start: inline ? where.start : starts[where.start],
|
|
1655
|
+
end: inline ? where.end : starts[end] + lines[end].length,
|
|
1656
|
+
line: where.line,
|
|
1657
|
+
column: where.column,
|
|
1658
|
+
lang,
|
|
1659
|
+
language: tagOf(lang)?.toLowerCase() ?? lang,
|
|
1660
|
+
enc,
|
|
1661
|
+
inventory,
|
|
1662
|
+
checked: checkable && Boolean(inventory?.characters),
|
|
1663
|
+
previous: undefined,
|
|
1664
|
+
continued: false,
|
|
1665
|
+
state: undefined,
|
|
1666
|
+
problems: undefined,
|
|
1667
|
+
};
|
|
1668
|
+
};
|
|
1669
|
+
const streamRuns = [
|
|
1670
|
+
...ownerDetails.map((detail) => ({
|
|
1671
|
+
...streamEntry(
|
|
1672
|
+
detail.run,
|
|
1673
|
+
detail.run.lang,
|
|
1674
|
+
detail.run.enc,
|
|
1675
|
+
Boolean(boundsOf(detail) && detail.checkRoman),
|
|
1676
|
+
detail.run.kind === "span",
|
|
1677
|
+
),
|
|
1678
|
+
detail,
|
|
1679
|
+
})),
|
|
1680
|
+
...rawReferences.map((reference) => ({
|
|
1681
|
+
...streamEntry(reference.where, reference.lang, reference.enc, true, true),
|
|
1682
|
+
reference,
|
|
1683
|
+
})),
|
|
1684
|
+
].sort((a, b) => a.start - b.start);
|
|
1685
|
+
for (const entry of streamRuns) {
|
|
1686
|
+
if (!entry.checked || !entry.inline) continue;
|
|
1687
|
+
const previous = streamRuns
|
|
1688
|
+
.filter((other) => other.end <= entry.start)
|
|
1689
|
+
.reduce((last, other) => (last && last.end >= other.end ? last : other), undefined);
|
|
1690
|
+
if (
|
|
1691
|
+
previous?.checked &&
|
|
1692
|
+
previous.inline &&
|
|
1693
|
+
previous.inventory === entry.inventory &&
|
|
1694
|
+
previous.language === entry.language &&
|
|
1695
|
+
previous.enc === entry.enc &&
|
|
1696
|
+
/^[\p{Zs}\t\r\n]*$/u.test(text.slice(previous.end, entry.start))
|
|
1697
|
+
) {
|
|
1698
|
+
entry.previous = previous;
|
|
1699
|
+
previous.continued = true;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
const streamRunOf = new Map(
|
|
1703
|
+
streamRuns.filter((entry) => entry.detail).map((entry) => [entry.detail, entry]),
|
|
1704
|
+
);
|
|
1705
|
+
/** The punctuation state a run opens in, a copy of its predecessor's. */
|
|
1706
|
+
const openingState = (entry) => {
|
|
1707
|
+
const previous = entry.previous && closingState(entry.previous);
|
|
1708
|
+
return previous ?
|
|
1709
|
+
{
|
|
1710
|
+
sentenceStart: previous.sentenceStart,
|
|
1711
|
+
quotes: previous.quotes.map((quote) => ({ ...quote })),
|
|
1712
|
+
}
|
|
1713
|
+
: romanPunctuationState();
|
|
1714
|
+
};
|
|
1715
|
+
/** A run's closing punctuation state, checking a labelled link on demand. */
|
|
1716
|
+
const closingState = (entry) => {
|
|
1717
|
+
if (entry.reference) checkReference(entry);
|
|
1718
|
+
return entry.state;
|
|
1719
|
+
};
|
|
1720
|
+
/**
|
|
1721
|
+
* Check a run's Roman text in its stream, giving findings by source offset.
|
|
1722
|
+
*
|
|
1723
|
+
* @param {any} entry - The run.
|
|
1724
|
+
* @param {string} roman - Its projected Roman text.
|
|
1725
|
+
* @param {(offset: number) => number} source - A text offset's source offset.
|
|
1726
|
+
*/
|
|
1727
|
+
const checkStream = (entry, roman, source) => {
|
|
1728
|
+
const state = openingState(entry);
|
|
1729
|
+
const problems = romanTextProblems(roman, entry.inventory, state).map((problem) => ({
|
|
1730
|
+
...problem,
|
|
1731
|
+
offset: source(problem.offset),
|
|
1732
|
+
}));
|
|
1733
|
+
for (const quote of state.quotes) quote.source ??= source(quote.offset);
|
|
1734
|
+
if (!entry.continued)
|
|
1735
|
+
problems.push(
|
|
1736
|
+
...romanUnclosedQuotations(
|
|
1737
|
+
state.quotes.map((quote) => ({ ...quote, offset: quote.source })),
|
|
1738
|
+
),
|
|
1739
|
+
);
|
|
1740
|
+
entry.state = state;
|
|
1741
|
+
return problems;
|
|
1742
|
+
};
|
|
1743
|
+
/** Check a labelled link's Roman source once, in its stream. */
|
|
1744
|
+
const checkReference = (entry) => {
|
|
1745
|
+
if (entry.problems) return entry.problems;
|
|
1746
|
+
entry.problems = [];
|
|
1747
|
+
if (!entry.checked) return entry.problems;
|
|
1748
|
+
const { reference } = entry;
|
|
1749
|
+
const plain = plainRomanRun(text, { from: reference.from, to: reference.to });
|
|
1750
|
+
entry.problems = checkStream(
|
|
1751
|
+
entry,
|
|
1752
|
+
plain.text,
|
|
1753
|
+
(offset) => plain.offsets[offset] ?? reference.from,
|
|
1754
|
+
);
|
|
1755
|
+
return entry.problems;
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
for (const owner of ownerDetails) {
|
|
1650
1759
|
const bounds = boundsOf(owner);
|
|
1651
1760
|
if (!bounds || !owner.checkRoman) continue;
|
|
1652
1761
|
const owned = details.filter((detail) => ownerOf(detail) === owner);
|
|
@@ -1703,12 +1812,15 @@ function analyseRuns(source, ctx, syntax) {
|
|
|
1703
1812
|
{ line: owner.run.line, column: owner.run.column },
|
|
1704
1813
|
`the language note for \`${inventory.language}\` must declare \`data.roman\``,
|
|
1705
1814
|
);
|
|
1706
|
-
else if (inventory)
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
)
|
|
1815
|
+
else if (inventory) {
|
|
1816
|
+
const entry = streamRunOf.get(owner);
|
|
1817
|
+
for (const problem of checkStream(
|
|
1818
|
+
entry,
|
|
1819
|
+
projection.text,
|
|
1820
|
+
(offset) => projection.offsets[offset] ?? bounds[0],
|
|
1821
|
+
))
|
|
1822
|
+
report(positionOf(starts, problem.offset), problem.message);
|
|
1823
|
+
}
|
|
1712
1824
|
for (const problem of projection.errors ?? [])
|
|
1713
1825
|
report(positionOf(starts, problem.offset), problem.message);
|
|
1714
1826
|
|
|
@@ -1830,16 +1942,15 @@ function analyseRuns(source, ctx, syntax) {
|
|
|
1830
1942
|
for (const detail of owned) detail.plan = plan;
|
|
1831
1943
|
}
|
|
1832
1944
|
|
|
1833
|
-
for (const
|
|
1834
|
-
const
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
});
|
|
1945
|
+
for (const entry of streamRuns.filter((entry) => entry.reference)) {
|
|
1946
|
+
const inventory = inventoryOf(entry.lang);
|
|
1947
|
+
if (inventory && !inventory.characters)
|
|
1948
|
+
report(
|
|
1949
|
+
{ line: entry.line, column: entry.column },
|
|
1950
|
+
`the language note for \`${inventory.language}\` must declare \`data.roman\``,
|
|
1951
|
+
);
|
|
1952
|
+
for (const problem of checkReference(entry))
|
|
1953
|
+
report(positionOf(starts, problem.offset), problem.message);
|
|
1843
1954
|
}
|
|
1844
1955
|
|
|
1845
1956
|
for (const reference of independentReferences) {
|
|
@@ -109,9 +109,14 @@ export function romanInventoriesOf(records, languages = {}) {
|
|
|
109
109
|
* No punctuation, case or normalization repair is performed.
|
|
110
110
|
* @param {string} text - Visible Roman source.
|
|
111
111
|
* @param {RomanInventory} inventory - Its language's declared characters.
|
|
112
|
+
* @param {RomanPunctuationState} [stream] - The punctuation state of a stream
|
|
113
|
+
* of runs the text continues, from {@link romanPunctuationState}; updated to
|
|
114
|
+
* the state the text closes in. Its unclosed quotations are left for
|
|
115
|
+
* {@link romanUnclosedQuotations} at the end of the stream. Without it the
|
|
116
|
+
* text is a stream of its own and its unclosed quotations are reported.
|
|
112
117
|
* @returns {Array<{offset: number, message: string}>}
|
|
113
118
|
*/
|
|
114
|
-
export function romanTextProblems(text, inventory) {
|
|
119
|
+
export function romanTextProblems(text, inventory, stream) {
|
|
115
120
|
const out = [];
|
|
116
121
|
if (!inventory.characters) return out;
|
|
117
122
|
const decomposed = new Map(
|
|
@@ -119,8 +124,9 @@ export function romanTextProblems(text, inventory) {
|
|
|
119
124
|
.filter(({ segment }) => segment !== segment.normalize("NFC"))
|
|
120
125
|
.map(({ segment, index }) => [index, segment]),
|
|
121
126
|
);
|
|
122
|
-
const
|
|
123
|
-
|
|
127
|
+
const state = stream ?? romanPunctuationState();
|
|
128
|
+
const { quotes } = state;
|
|
129
|
+
let sentenceStart = state.sentenceStart;
|
|
124
130
|
const sentenceText = () => {
|
|
125
131
|
sentenceStart = false;
|
|
126
132
|
if (quotes.length) quotes.at(-1).hasText = true;
|
|
@@ -245,10 +251,41 @@ export function romanTextProblems(text, inventory) {
|
|
|
245
251
|
} else sentenceText();
|
|
246
252
|
offset += char.length;
|
|
247
253
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
opening.offset,
|
|
251
|
-
`quotation \`${opening.char}\` needs its closing \`${opening.char === "«" ? "»" : "›"}\``,
|
|
252
|
-
);
|
|
254
|
+
state.sentenceStart = sentenceStart;
|
|
255
|
+
if (!stream) out.push(...romanUnclosedQuotations(quotes));
|
|
253
256
|
return out.sort((a, b) => a.offset - b.offset);
|
|
254
257
|
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @typedef {object} RomanQuotation
|
|
261
|
+
* @property {string} char - The opening mark, `«` or `‹`.
|
|
262
|
+
* @property {number} offset - Its offset in the text that opened it.
|
|
263
|
+
* @property {boolean} sentenceStart - Whether its sentence had text before it.
|
|
264
|
+
* @property {boolean} hasText - Whether it holds sentence text.
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @typedef {object} RomanPunctuationState
|
|
269
|
+
* @property {boolean} sentenceStart - Whether no sentence text precedes the next mark.
|
|
270
|
+
* @property {RomanQuotation[]} quotes - Open quotations, outermost first.
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* The punctuation state at the start of a stream of runs.
|
|
275
|
+
* @returns {RomanPunctuationState}
|
|
276
|
+
*/
|
|
277
|
+
export function romanPunctuationState() {
|
|
278
|
+
return { sentenceStart: true, quotes: [] };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Findings for quotations still open at the end of a stream.
|
|
283
|
+
* @param {ReadonlyArray<RomanQuotation>} quotes - The open quotations.
|
|
284
|
+
* @returns {Array<{offset: number, message: string}>} At each opening's `offset`.
|
|
285
|
+
*/
|
|
286
|
+
export function romanUnclosedQuotations(quotes) {
|
|
287
|
+
return quotes.map((opening) => ({
|
|
288
|
+
offset: opening.offset,
|
|
289
|
+
message: `quotation \`${opening.char}\` needs its closing \`${opening.char === "«" ? "»" : "›"}\``,
|
|
290
|
+
}));
|
|
291
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "25.5.
|
|
3
|
+
"version": "25.5.2",
|
|
4
4
|
"description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package \u2014 content compilation, manifest, localization, staging, bundle, release and deployment.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -26,9 +26,40 @@ export function romanInventoriesOf(records: ReadonlyMap<string, Record<string, a
|
|
|
26
26
|
* No punctuation, case or normalization repair is performed.
|
|
27
27
|
* @param {string} text - Visible Roman source.
|
|
28
28
|
* @param {RomanInventory} inventory - Its language's declared characters.
|
|
29
|
+
* @param {RomanPunctuationState} [stream] - The punctuation state of a stream
|
|
30
|
+
* of runs the text continues, from {@link romanPunctuationState}; updated to
|
|
31
|
+
* the state the text closes in. Its unclosed quotations are left for
|
|
32
|
+
* {@link romanUnclosedQuotations} at the end of the stream. Without it the
|
|
33
|
+
* text is a stream of its own and its unclosed quotations are reported.
|
|
29
34
|
* @returns {Array<{offset: number, message: string}>}
|
|
30
35
|
*/
|
|
31
|
-
export function romanTextProblems(text: string, inventory: RomanInventory): Array<{
|
|
36
|
+
export function romanTextProblems(text: string, inventory: RomanInventory, stream?: RomanPunctuationState): Array<{
|
|
37
|
+
offset: number;
|
|
38
|
+
message: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {object} RomanQuotation
|
|
42
|
+
* @property {string} char - The opening mark, `«` or `‹`.
|
|
43
|
+
* @property {number} offset - Its offset in the text that opened it.
|
|
44
|
+
* @property {boolean} sentenceStart - Whether its sentence had text before it.
|
|
45
|
+
* @property {boolean} hasText - Whether it holds sentence text.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {object} RomanPunctuationState
|
|
49
|
+
* @property {boolean} sentenceStart - Whether no sentence text precedes the next mark.
|
|
50
|
+
* @property {RomanQuotation[]} quotes - Open quotations, outermost first.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* The punctuation state at the start of a stream of runs.
|
|
54
|
+
* @returns {RomanPunctuationState}
|
|
55
|
+
*/
|
|
56
|
+
export function romanPunctuationState(): RomanPunctuationState;
|
|
57
|
+
/**
|
|
58
|
+
* Findings for quotations still open at the end of a stream.
|
|
59
|
+
* @param {ReadonlyArray<RomanQuotation>} quotes - The open quotations.
|
|
60
|
+
* @returns {Array<{offset: number, message: string}>} At each opening's `offset`.
|
|
61
|
+
*/
|
|
62
|
+
export function romanUnclosedQuotations(quotes: ReadonlyArray<RomanQuotation>): Array<{
|
|
32
63
|
offset: number;
|
|
33
64
|
message: string;
|
|
34
65
|
}>;
|
|
@@ -43,3 +74,31 @@ export type RomanInventory = {
|
|
|
43
74
|
*/
|
|
44
75
|
characters: ReadonlySet<string> | undefined;
|
|
45
76
|
};
|
|
77
|
+
export type RomanQuotation = {
|
|
78
|
+
/**
|
|
79
|
+
* - The opening mark, `«` or `‹`.
|
|
80
|
+
*/
|
|
81
|
+
char: string;
|
|
82
|
+
/**
|
|
83
|
+
* - Its offset in the text that opened it.
|
|
84
|
+
*/
|
|
85
|
+
offset: number;
|
|
86
|
+
/**
|
|
87
|
+
* - Whether its sentence had text before it.
|
|
88
|
+
*/
|
|
89
|
+
sentenceStart: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* - Whether it holds sentence text.
|
|
92
|
+
*/
|
|
93
|
+
hasText: boolean;
|
|
94
|
+
};
|
|
95
|
+
export type RomanPunctuationState = {
|
|
96
|
+
/**
|
|
97
|
+
* - Whether no sentence text precedes the next mark.
|
|
98
|
+
*/
|
|
99
|
+
sentenceStart: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* - Open quotations, outermost first.
|
|
102
|
+
*/
|
|
103
|
+
quotes: RomanQuotation[];
|
|
104
|
+
};
|