@heroiclands/package-build 25.2.1 → 25.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -1
  3. package/assets/styles/content-base.css +97 -116
  4. package/docs/api.md +30 -6
  5. package/docs/authoring/links-and-markup.md +214 -126
  6. package/docs/commands.md +2 -2
  7. package/docs/content-format.md +31 -6
  8. package/docs/diagnostics.md +27 -27
  9. package/docs/guides/writing-in-invented-scripts.md +89 -83
  10. package/docs/reference/format-details.md +6 -7
  11. package/docs/reference/note-types.md +15 -15
  12. package/docs/reference/theme-pages.md +38 -57
  13. package/engine/anchors.mjs +14 -0
  14. package/engine/code-fences.mjs +15 -6
  15. package/engine/content-blocks.mjs +7 -4
  16. package/engine/content-figures.mjs +19 -5
  17. package/engine/content-footnotes.mjs +60 -1
  18. package/engine/content-index.mjs +1 -1
  19. package/engine/content-render.mjs +66 -48
  20. package/engine/content-scripts.mjs +357 -101
  21. package/engine/content-spans.mjs +76 -10
  22. package/engine/content-verse.mjs +687 -358
  23. package/engine/first-use.mjs +43 -12
  24. package/engine/heading-attributes.mjs +2 -1
  25. package/engine/journals.mjs +8 -1
  26. package/engine/markdown-blocks.mjs +3 -2
  27. package/engine/markup-validation.mjs +17 -0
  28. package/engine/name-markup.mjs +1 -0
  29. package/engine/note-vocabulary.mjs +2 -2
  30. package/engine/pdf-render.mjs +89 -130
  31. package/engine/prose-lint.mjs +14 -2
  32. package/engine/roman-verse.mjs +68 -57
  33. package/engine/run-rows.mjs +1 -1
  34. package/engine/sql-tables.mjs +1 -1
  35. package/engine/verse-format.mjs +77 -0
  36. package/engine/verse-metre.mjs +49 -47
  37. package/engine/verse-regions.mjs +181 -0
  38. package/engine/wikilink-pattern.mjs +31 -0
  39. package/engine/wikilink-syntax.mjs +2 -16
  40. package/package.json +1 -1
  41. package/site-theme/static/css/style.css +68 -96
  42. package/types/engine/code-fences.d.mts +1 -3
  43. package/types/engine/content-blocks.d.mts +3 -1
  44. package/types/engine/content-footnotes.d.mts +23 -0
  45. package/types/engine/content-scripts.d.mts +12 -7
  46. package/types/engine/content-spans.d.mts +3 -1
  47. package/types/engine/content-verse.d.mts +263 -82
  48. package/types/engine/name-markup.d.mts +5 -0
  49. package/types/engine/roman-verse.d.mts +7 -6
  50. package/types/engine/verse-format.d.mts +9 -0
  51. package/types/engine/verse-metre.d.mts +4 -4
  52. package/types/engine/verse-regions.d.mts +78 -0
  53. package/types/engine/wikilink-pattern.d.mts +17 -0
  54. package/types/engine/wikilink-syntax.d.mts +1 -41
@@ -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,286 @@ 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 divs; 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 divs and findings.
28
+ */
29
+ export function scanVerse(source: string, { checkWorks }?: {
30
+ checkWorks?: boolean | undefined;
31
+ }): {
32
+ blocks: VerseBlock[];
33
+ errors: VerseDiagnostic[];
34
+ };
35
+ /**
36
+ * Parse logical verse lines, stanzas and cantos without losing authored offsets.
37
+ * Offsets are UTF-16 positions relative to body. Delimiters and indentation are
38
+ * layout ranges; source newlines inside a logical line contribute one space.
39
+ * @param {string} body - Authored verse body.
40
+ * @param {{inline?: boolean, footnotes?: ReadonlySet<string>}} [options] - Inline quotations have no cantos; footnotes are same-note definition labels.
41
+ * @returns {VerseModel} The shared structure with offsets relative to the body.
42
+ */
43
+ export function parseVerse(body: string, { inline, footnotes }?: {
44
+ inline?: boolean;
45
+ footnotes?: ReadonlySet<string>;
46
+ }): VerseModel;
15
47
  /**
16
- * Blank lines divide verse groups. A standalone `***` is its own group and
17
- * separates stanzas. Each text line carries its period-based indentation.
48
+ * Validate a quoted verse span using its original source coordinates.
49
+ * @param {{start: number, text: string, attrs: Array<[string,string]>}} span - Authored span.
50
+ * @param {string} source - Complete Markdown source.
51
+ * @returns {VerseDiagnostic[]} Located inline-only findings.
18
52
  */
53
+ export function inlineVerseFindings(span: {
54
+ start: number;
55
+ text: string;
56
+ attrs: Array<[string, string]>;
57
+ }, source: string): VerseDiagnostic[];
58
+ /** Logical line text for consumers that do not need source locations. */
59
+ export function verseLines(body: any): string[];
60
+ /** Paragraph groups with separate canto gaps. */
19
61
  export function verseStanzas(body: any): {
20
62
  text: string;
21
63
  level: number;
22
64
  }[][];
23
- /** A verse is inline Markdown even when it starts with block syntax. */
24
- export function inlineVerse(text: any): string;
25
65
  /**
26
- * Keep blank-line verse groups as paragraphs and each text line a hard break.
27
- * A standalone `***` emits a separate stanza gap.
28
- * The surrounding renderer still sees the entire note, so links and footnote
29
- * definitions remain in scope. The span carries the indent for each line.
66
+ * Compare the stanza counts of each version of a page-local work.
67
+ * @param {VerseBlock[]} blocks - Divs belonging to one page.
68
+ * @returns {VerseDiagnostic[]} Findings at affected opening divs.
30
69
  */
31
- export function verseMarkdown(body: any, step?: number): string;
70
+ export function workShapeFindings(blocks: VerseBlock[]): VerseDiagnostic[];
32
71
  /**
33
- * The number a line shows: `undefined` when the verse is not numbered, `""`
34
- * when this line is not one of every `step`th.
35
- *
36
- * @param {number} line - The line's number, 1-based across the verse.
37
- * @param {number} step - The verse's `numstep`.
38
- * @returns {string|undefined} The number shown.
72
+ * Render a shared verse structure while preserving surrounding inline Markdown.
73
+ * @param {string} body - Authored verse body.
74
+ * @param {object} [options] - Shared structure and display choices.
75
+ * @param {boolean} [options.labelled] - Whether each stanza carries its label.
76
+ * @param {VerseModel} [options.model] - Parsed structure; defaults to parsing the body.
77
+ * @param {VersePresentation} [options.presentation] - Native-cell font and language.
78
+ * @param {boolean} [options.inline] - Whether wrappers must remain inline-safe.
79
+ * @returns {string} Markdown with verse layout wrappers.
39
80
  */
40
- export function lineNumber(line: number, step: number): string | undefined;
41
- /** Read verse code fences; start/end are inclusive zero-based source lines.
42
- * @param {string} source - Authored Markdown.
81
+ export function verseMarkdown(body: string, { labelled, model, presentation, inline }?: {
82
+ labelled?: boolean | undefined;
83
+ model?: VerseModel | undefined;
84
+ presentation?: VersePresentation | undefined;
85
+ inline?: boolean | undefined;
86
+ }): string;
87
+ /**
88
+ * Replace verse divs with wrappers whose bodies remain inline Markdown.
89
+ * @param {string} source - Markdown containing verse divs.
90
+ * @param {object} [options] - Encoded display models.
91
+ * @param {Map<string, VersePresentation>} [options.verses] - Presentations keyed by rewritten body.
43
92
  */
44
- export function scanVerse(source: string): {
45
- blocks: {
46
- end: number;
47
- body: string;
48
- start: number;
49
- fence: string;
50
- name: string;
51
- attributes: {};
52
- id: string;
53
- classes: never[];
54
- indent: string;
55
- }[];
56
- errors: any[];
93
+ export function renderVerse(source: string, { verses }?: {
94
+ verses?: Map<string, VersePresentation> | undefined;
95
+ }): {
96
+ markdown: string;
97
+ errors: VerseDiagnostic[];
57
98
  };
58
- /** The number of verse columns; an omitted or invalid count uses the ordinary layout. */
59
- export function verseColumnCount(block: any): number;
60
- /** Whether a verse uses the numbered multi-column protocol. */
61
- export function hasColumns(block: any): boolean;
62
99
  /**
63
- * Blank-separated multi-column rows with ordered physical parts. Text retains
64
- * its authored inline markup and spacing after the numeric prefix. All source
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}>}>}
100
+ * Render quoted verse with inline-safe wrappers and shared logical structure.
101
+ * @param {string} source - Markdown after block verse rendering.
102
+ * @returns {string} Markdown retaining surrounding prose.
70
103
  */
71
- export function verseGroups(block: object, lines: string[]): Array<{
72
- stanzaBreak: true;
73
- line: number;
74
- } | {
75
- stanzaBreak?: false;
76
- parts: Array<{
77
- column: number;
78
- line: number;
79
- sourceColumn: number;
80
- textColumn: number;
81
- text: string;
82
- indent: number;
83
- markerStart: number;
84
- markerLength: number;
85
- prefixLength: number;
86
- }>;
87
- }>;
104
+ export function renderVerseQuotes(source: string): string;
105
+ /** The authored attributes of a verse div. */
106
+ export const VERSE_KEYS: readonly string[];
107
+ /** A canto separator, including the escaped form produced by a native run. */
108
+ export const STANZA_BREAK: RegExp;
109
+ export function stanzaSeparator(group: any): boolean;
88
110
  /**
89
- * Whether text runs right to left: its first letter is in a right-to-left
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.
111
+ * A logical line with its authored UTF-16 coordinates.
94
112
  */
95
- export function rightToLeft(text: string): boolean;
96
- /** Replace verse fences with HTML wrappers whose body remains inline Markdown.
97
- * @param {string} source - Authored Markdown.
113
+ export type VerseLine = {
114
+ /**
115
+ * - Inline Markdown in this presentation.
116
+ */
117
+ text: string;
118
+ /**
119
+ * - Leading-period indentation depth.
120
+ */
121
+ level: number;
122
+ /**
123
+ * - First authored offset, including indentation.
124
+ */
125
+ from: number;
126
+ /**
127
+ * - Offset at the line ending.
128
+ */
129
+ to: number;
130
+ /**
131
+ * - Source offset for each UTF-16 text unit.
132
+ */
133
+ offsets: number[];
134
+ /**
135
+ * - Roman text paired with an encoded line.
136
+ */
137
+ romanText?: string | undefined;
138
+ };
139
+ /**
140
+ * A stanza's logical lines and authored bounds.
98
141
  */
99
- export function renderVerse(source: string): {
100
- markdown: string;
101
- errors: any[];
142
+ export type VerseStanza = {
143
+ /**
144
+ * - Lines in reading order.
145
+ */
146
+ lines: VerseLine[];
147
+ /**
148
+ * - First authored offset.
149
+ */
150
+ from: number;
151
+ /**
152
+ * - Offset at the stanza ending.
153
+ */
154
+ to: number;
155
+ };
156
+ export type VerseTextGroup = VerseStanza & {
157
+ canto: number;
158
+ stanza: number;
159
+ label: string;
160
+ cantoBreak?: false;
161
+ };
162
+ export type VerseCantoBreak = {
163
+ cantoBreak: true;
164
+ from: number;
165
+ to: number;
166
+ text?: string;
167
+ id?: string;
168
+ title?: string;
169
+ };
170
+ export type VerseBoundary = {
171
+ kind: "line" | "stanza" | "canto";
172
+ sourceOffset: number;
173
+ };
174
+ export type VerseFinding = {
175
+ offset: number;
176
+ message: string;
102
177
  };
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
178
  /**
107
- * The keys a verse fence's attribute block takes. `lang`, `font` and `map`
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.
179
+ * Shared authored verse structure and source locations.
111
180
  */
112
- export const VERSE_KEYS: readonly string[];
113
- /** A line separating stanzas, including escaped output from a native run. */
114
- export const STANZA_BREAK: RegExp;
181
+ export type VerseModel = {
182
+ /**
183
+ * - Cantos in reading order.
184
+ */
185
+ cantos: Array<{
186
+ stanzas: VerseStanza[];
187
+ }>;
188
+ /**
189
+ * - Stanzas and canto breaks.
190
+ */
191
+ groups: Array<VerseTextGroup | VerseCantoBreak>;
192
+ /**
193
+ * - Explicit authored boundaries.
194
+ */
195
+ boundaries: VerseBoundary[];
196
+ /**
197
+ * - Source ranges omitted from encoded letters.
198
+ */
199
+ layout: Array<[number, number]>;
200
+ /**
201
+ * - Findings relative to the verse body.
202
+ */
203
+ errors: VerseFinding[];
204
+ /**
205
+ * - Defined references without substantive verse text.
206
+ */
207
+ notes: VerseLine[];
208
+ };
209
+ /**
210
+ * An authored verse div with its parsed logical structure.
211
+ */
212
+ export type VerseBlock = {
213
+ /**
214
+ * - Opening div's zero-based source line.
215
+ */
216
+ start: number;
217
+ /**
218
+ * - Closing div's zero-based source line.
219
+ */
220
+ end: number;
221
+ /**
222
+ * - Complete div first offset.
223
+ */
224
+ from: number;
225
+ /**
226
+ * - Offset past complete div.
227
+ */
228
+ to: number;
229
+ /**
230
+ * - First body offset.
231
+ */
232
+ bodyStart: number;
233
+ /**
234
+ * - Offset past body text.
235
+ */
236
+ bodyEnd: number;
237
+ /**
238
+ * - Whether the closing delimiter exists.
239
+ */
240
+ closed: boolean;
241
+ /**
242
+ * - Attribute syntax findings.
243
+ */
244
+ problems: string[];
245
+ /**
246
+ * - Region name.
247
+ */
248
+ name: "verse";
249
+ /**
250
+ * - Authored attribute values.
251
+ */
252
+ attributes: Record<string, string>;
253
+ /**
254
+ * - Authored anchor, or the empty string.
255
+ */
256
+ id: string;
257
+ /**
258
+ * - Authored presentation classes.
259
+ */
260
+ classes: string[];
261
+ /**
262
+ * - Opening div's leading spaces.
263
+ */
264
+ indent: string;
265
+ /**
266
+ * - Authored verse body.
267
+ */
268
+ body: string;
269
+ /**
270
+ * - Logical structure relative to the body.
271
+ */
272
+ model: VerseModel;
273
+ };
274
+ export type VerseDiagnostic = {
275
+ line: number;
276
+ column: number;
277
+ message: string;
278
+ };
279
+ /**
280
+ * An encoded verse's shared display model and native-cell presentation.
281
+ */
282
+ export type VersePresentation = {
283
+ /**
284
+ * - Logical structure with paired line text.
285
+ */
286
+ model: VerseModel;
287
+ /**
288
+ * - Native script and font classes.
289
+ */
290
+ classes: string[];
291
+ /**
292
+ * - Native language, direction and search attributes.
293
+ */
294
+ attributes: Record<string, string>;
295
+ };
@@ -26,6 +26,7 @@
26
26
  * @property {string} visible - Visible text from the actual parsed children.
27
27
  * @property {ReadonlyArray<readonly [string, string]>} attrs - Retained permitted HTML attributes.
28
28
  * @property {Record<string, SpanAttributePosition>} attributePositions - Authored key/value sites by retained attribute name.
29
+ * @property {ReturnType<typeof import("./content-verse.mjs").parseVerse>} [verseModel] - Logical model of an inline verse quotation.
29
30
  */
30
31
  /**
31
32
  * One located span-grammar or refused-attribute finding.
@@ -139,6 +140,10 @@ export type ContentSpan = {
139
140
  * - Authored key/value sites by retained attribute name.
140
141
  */
141
142
  attributePositions: Record<string, SpanAttributePosition>;
143
+ /**
144
+ * - Logical model of an inline verse quotation.
145
+ */
146
+ verseModel?: import("./content-verse.mjs").VerseModel | undefined;
142
147
  };
143
148
  /**
144
149
  * One located span-grammar or refused-attribute finding.
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Remove visual indentation before checking or encoding Roman verse. Each
3
- * content line keeps its own boundary, including the last line before a stanza
4
- * or canto; those extra structural controls do not consume its line boundary.
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] & {isCantoLine?: (line: string) => boolean}} [options] - Run bounds, spans and layout projection.
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
- isCantoLine?: (line: string) => boolean;
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";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Replace verse markup with opaque placeholders and restore its original bytes.
3
+ * @param {string} source - Complete Markdown source.
4
+ * @returns {{markdown: string, restore: (formatted: string) => string}} Protected source and exact restoration.
5
+ */
6
+ export function protectVerseSource(source: string): {
7
+ markdown: string;
8
+ restore: (formatted: string) => string;
9
+ };
@@ -60,7 +60,7 @@ export function lineBeats(text: string, book: MetreBook): {
60
60
  * The warning for a line that cannot have its metre's beats.
61
61
  *
62
62
  * @param {{min: number, max: number}} beats - The line's beats.
63
- * @param {import("./metre-declaration.mjs").Metre} metre - The fence's metre.
63
+ * @param {import("./metre-declaration.mjs").Metre} metre - The div's metre.
64
64
  * @returns {string} The message.
65
65
  */
66
66
  export function metreMessage({ min, max }: {
@@ -68,13 +68,13 @@ export function metreMessage({ min, max }: {
68
68
  max: number;
69
69
  }, metre: import("./metre-declaration.mjs").Metre): string;
70
70
  /**
71
- * Check the verse fences that state `scan=`.
71
+ * Check the verse divs that state `scan=`.
72
72
  *
73
73
  * @param {ReadonlyArray<{start: number, end: number, indent: string, attributes: Record<string, string>, classes: string[]}>} blocks -
74
- * The fences, from {@link module:engine/content-verse.scanVerse}.
74
+ * The divs, from {@link module:engine/content-verse.scanVerse}.
75
75
  * @param {string[]} lines - The source's lines.
76
76
  * @param {{languages?: Readonly<Record<string, {tag: string}>>, metres?: ReadonlyMap<string, import("./metre-declaration.mjs").Metre>, metreBooks?: ReadonlyMap<string, MetreBook>, lexicons?: ReadonlyMap<string, unknown>, attributeColumns: (line: string, key: string) => {key: number, value: number}}} ctx -
77
- * The metres and books, and how the fence says its columns and where its
77
+ * The metres and books, and how the div says its columns and where its
78
78
  * keys sit.
79
79
  * @returns {{errors: object[], warnings: object[]}} The findings at 1-based
80
80
  * positions.
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Install the opaque verse-div block rule. Tokens carry raw source regions.
3
+ * @param {import("markdown-it")} md - Markdown parser.
4
+ */
5
+ export function verseDivPlugin(md: typeof import("markdown-it")): void;
6
+ /**
7
+ * Locate complete raw verse divs while leaving literal examples untouched.
8
+ * @param {string} source - Authored Markdown.
9
+ * @returns {VerseRegion[]} Regions in source order, including unclosed divs.
10
+ */
11
+ export function verseRegions(source: string): VerseRegion[];
12
+ /**
13
+ * Source ranges belonging to inline syntax rather than visible verse text.
14
+ * @param {string} source - Inline Markdown.
15
+ * @returns {Array<[number,number]>} Protected UTF-16 ranges.
16
+ */
17
+ export function inlineSyntaxRanges(source: string): Array<[number, number]>;
18
+ /**
19
+ * A raw verse div, opaque to ordinary Markdown block syntax.
20
+ */
21
+ export type VerseRegion = {
22
+ /**
23
+ * - Opening line, zero based.
24
+ */
25
+ start: number;
26
+ /**
27
+ * - Closing line, zero based and inclusive.
28
+ */
29
+ end: number;
30
+ /**
31
+ * - First offset of the complete region.
32
+ */
33
+ from: number;
34
+ /**
35
+ * - Offset past the complete region.
36
+ */
37
+ to: number;
38
+ /**
39
+ * - First body offset.
40
+ */
41
+ bodyStart: number;
42
+ /**
43
+ * - Offset past body text, excluding its final newline.
44
+ */
45
+ bodyEnd: number;
46
+ /**
47
+ * - Authored body bytes.
48
+ */
49
+ body: string;
50
+ /**
51
+ * - Authored values.
52
+ */
53
+ attributes: Record<string, string>;
54
+ /**
55
+ * - Anchor or empty string.
56
+ */
57
+ id: string;
58
+ /**
59
+ * - Authored classes including verse.
60
+ */
61
+ classes: string[];
62
+ /**
63
+ * - Opening indentation.
64
+ */
65
+ indent: string;
66
+ /**
67
+ * - Region kind.
68
+ */
69
+ name: "verse";
70
+ /**
71
+ * - Whether a closing delimiter is present.
72
+ */
73
+ closed: boolean;
74
+ /**
75
+ * - Attribute syntax findings.
76
+ */
77
+ problems: string[];
78
+ };
@@ -0,0 +1,17 @@
1
+ /** The dependency-free lexical wikilink pattern. @module */
2
+ /**
3
+ * A wikilink, as authored.
4
+ *
5
+ * **Newlines are excluded deliberately.** A link is written on one line; an
6
+ * unclosed `[[` is a typo, and the alternative is letting it swallow arbitrary
7
+ * prose in search of a closer. Erring towards "not a link" leaves the author's
8
+ * text as written, which is the safe direction for a rewriter.
9
+ *
10
+ * **A leading `!` makes it an embed, not a link**, and the lookbehind is what
11
+ * keeps every reader from seeing one as the other. Stated here rather than in
12
+ * each reader for the reason the rest of this module exists: the checker, the
13
+ * resolver and the embed reader all match on this pattern, and a copy of the
14
+ * exclusion in each is a place for it to be forgotten. An embed's
15
+ * own grammar is {@link module:engine/content-embeds}.
16
+ */
17
+ export const WIKILINK: RegExp;
@@ -206,47 +206,7 @@ export function secretDestination(destination: object, anchor?: string): boolean
206
206
  * @returns {string} Inline spoiler or visible reference.
207
207
  */
208
208
  export function presentWikilink(reference: string, parsed: object, destination: object): string;
209
- /**
210
- * What a `[[…]]` **is**, before anything decides where it points.
211
- *
212
- * One authored link is written three ways — a Foundry `@UUID` content link for
213
- * the packs, a URL for the web, a cross-reference for the book — and those
214
- * forms are the *only* thing that legitimately differs. The syntax is the
215
- * author's, and it is the same syntax whichever build is reading it.
216
- *
217
- * So the parse lives here, once, and two readers take it: the link checker
218
- * (`content-links.mjs`) and the resolver (`wikilinks.mjs`). Each receives the
219
- * parts and decides only what it is for: which document the address names.
220
- *
221
- * The one rule about a link's *shape* also lives here — **a link carries a
222
- * label** ({@link unlabelledLinkMessage}) — because every build states it
223
- * through one message and the author reads the same words whichever ran
224
- * first.
225
- *
226
- * For the same reason, so does the **vocabulary of link findings**
227
- * ({@link LINK_FINDING_REASONS}) and the message each one reports through
228
- * ({@link linkFindingMessage}). Every build reads one authored link; an author
229
- * meets whichever ran first, and a consumer switching on a `reason` should not
230
- * be switching on which build produced it.
231
- *
232
- * @module
233
- */
234
- /**
235
- * A wikilink, as authored.
236
- *
237
- * **Newlines are excluded deliberately.** A link is written on one line; an
238
- * unclosed `[[` is a typo, and the alternative is letting it swallow arbitrary
239
- * prose in search of a closer. Erring towards "not a link" leaves the author's
240
- * text as written, which is the safe direction for a rewriter.
241
- *
242
- * **A leading `!` makes it an embed, not a link**, and the lookbehind is what
243
- * keeps every reader from seeing one as the other. Stated here rather than in
244
- * each reader for the reason the rest of this module exists: the checker, the
245
- * resolver and the embed reader all match on this pattern, and a copy of the
246
- * exclusion in each is a place for it to be forgotten. An embed's
247
- * own grammar is {@link module:engine/content-embeds}.
248
- */
249
- export const WIKILINK: RegExp;
209
+ export { WIKILINK } from "./wikilink-pattern.mjs";
250
210
  /**
251
211
  * Every way a link can fail, named once for every reader of a link.
252
212
  *