asciidoc-abundant-tree 0.2.0 → 0.2.1
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/README.md +23 -0
- package/dist/animation-yaml-export/cli.mjs +1 -1
- package/dist/browser.mjs +182 -78
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +18 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-CNTTQlPJ.mjs → src-DMOLXZbF.mjs} +330 -140
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -274,6 +274,29 @@ const ttl = projection.ttl;
|
|
|
274
274
|
const jsonLd = projection.jsonLd;
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
+
Book-entry callers can register include resolvers for includes that select by something other than a file path, such as a symbol in a TypeScript file. A resolver claims targets by prefix and returns whole consecutive lines of a source file inside `documentRoot`, plus the line they start at; the lines get coordinates in that file just like a file include:
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
const book = await parseAbundantTree({
|
|
281
|
+
sourcePath: "bookshelf/books/08-design/book.adoc",
|
|
282
|
+
mode: "book-entry",
|
|
283
|
+
documentRoot: ".",
|
|
284
|
+
includeResolvers: [
|
|
285
|
+
{
|
|
286
|
+
// include::docloom:examples/replay.ts[symbol=replay,part=source]
|
|
287
|
+
prefix: "docloom:",
|
|
288
|
+
resolve: ({ target, attributes }) => {
|
|
289
|
+
// Your own selector: find the declaration, widen it to whole lines.
|
|
290
|
+
const { text, startLine } = selectWholeLines(target, attributes);
|
|
291
|
+
return { text, origin: { path: target, startLine } };
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`attributes` are the include attributes as Asciidoctor parses them, the same an Asciidoctor include processor receives, so the bookshelf build and this parser can register the same selector. A resolver that throws fails construction with `include.resolver-failed`; returned text that does not match its source leaves those lines without coordinates and reports `origin-map.selection-mismatch`.
|
|
299
|
+
|
|
277
300
|
`parseAbundantTree` reads only the supplied source file. Interdocument xrefs keep their raw target and official href when Asciidoctor exposes one, but this package does not open the referenced `.adoc` file.
|
|
278
301
|
|
|
279
302
|
Browser tools that already hold AsciiDoc source text can use the browser-safe subpath:
|
package/dist/browser.mjs
CHANGED
|
@@ -944,8 +944,8 @@ function recoveryFailure(code, message, source) {
|
|
|
944
944
|
}
|
|
945
945
|
//#endregion
|
|
946
946
|
//#region src/official-block-policy.ts
|
|
947
|
-
function officialBlockPolicy(
|
|
948
|
-
switch (
|
|
947
|
+
function officialBlockPolicy(block) {
|
|
948
|
+
switch (block.getContext?.()) {
|
|
949
949
|
case "admonition":
|
|
950
950
|
case "dlist":
|
|
951
951
|
case "list_item":
|
|
@@ -953,12 +953,13 @@ function officialBlockPolicy(context) {
|
|
|
953
953
|
case "table":
|
|
954
954
|
case "verse": return "scan";
|
|
955
955
|
case "example":
|
|
956
|
-
case "olist":
|
|
957
956
|
case "quote":
|
|
958
|
-
case "section":
|
|
959
957
|
case "sidebar":
|
|
960
|
-
case "
|
|
961
|
-
case "
|
|
958
|
+
case "open": return block.getContentModel?.() === "simple" ? "scan" : "recurse";
|
|
959
|
+
case "olist":
|
|
960
|
+
case "preamble":
|
|
961
|
+
case "section":
|
|
962
|
+
case "ulist": return "recurse";
|
|
962
963
|
case "listing":
|
|
963
964
|
case "literal":
|
|
964
965
|
case "pass":
|
|
@@ -1017,7 +1018,6 @@ function projectOfficialDocument(options) {
|
|
|
1017
1018
|
usedAnchorKeys: /* @__PURE__ */ new Set(),
|
|
1018
1019
|
intervalByBlock: options.intervalByBlock,
|
|
1019
1020
|
projectableBlocks: options.projectableBlocks,
|
|
1020
|
-
containerFallbackBlocks: options.containerFallbackBlocks,
|
|
1021
1021
|
sectionByBlock: options.sectionByBlock,
|
|
1022
1022
|
bindingRequests,
|
|
1023
1023
|
targets,
|
|
@@ -1035,19 +1035,18 @@ function buildChildren(officialDocument, context) {
|
|
|
1035
1035
|
for (const block of childBlocksOf(officialDocument)) topLevel.push(...toNodes(buildNode(block, context)));
|
|
1036
1036
|
return topLevel;
|
|
1037
1037
|
}
|
|
1038
|
-
function buildNode(block, context
|
|
1038
|
+
function buildNode(block, context) {
|
|
1039
1039
|
const blockContext = block.getContext?.();
|
|
1040
1040
|
const officialLine = block.getSourceLocation?.()?.getLineNumber?.();
|
|
1041
|
-
const line = officialLine ?? fallbackLine;
|
|
1042
1041
|
const interval = context.intervalByBlock.get(block);
|
|
1043
|
-
if (!canProjectBlock(block, context
|
|
1042
|
+
if (!canProjectBlock(block, context)) return;
|
|
1044
1043
|
if (blockContext === "section" && officialLine !== void 0) return buildSection(block, context);
|
|
1045
|
-
if (blockContext === "paragraph" &&
|
|
1044
|
+
if (blockContext === "paragraph" && officialLine !== void 0) return buildParagraph(block, officialLine, context, interval);
|
|
1046
1045
|
if (blockContext === "listing" && officialLine !== void 0) return buildListing(block, officialLine, context, interval);
|
|
1047
1046
|
if (blockContext === "table" && officialLine !== void 0) return buildTable(block, officialLine, context, interval);
|
|
1048
1047
|
if (blockContext === "dlist" && officialLine !== void 0) return buildDescriptionList(block, officialLine, context, interval);
|
|
1049
|
-
if (blockContext === "open" &&
|
|
1050
|
-
if (officialBlockPolicy(
|
|
1048
|
+
if (blockContext === "open" && officialLine !== void 0) return childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
1049
|
+
if (officialBlockPolicy(block) === "diagnostic") return;
|
|
1051
1050
|
if (officialLine !== void 0) {
|
|
1052
1051
|
registerOfficialBlockTarget(context, block, {
|
|
1053
1052
|
targetType: "block",
|
|
@@ -1059,10 +1058,8 @@ function buildNode(block, context, fallbackLine) {
|
|
|
1059
1058
|
return childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
1060
1059
|
}
|
|
1061
1060
|
}
|
|
1062
|
-
function canProjectBlock(block, context
|
|
1063
|
-
|
|
1064
|
-
if (context.projectableBlocks.has(block)) return true;
|
|
1065
|
-
return officialLine === void 0 && fallbackLine !== void 0 && (context.containerFallbackBlocks?.has(block) ?? false);
|
|
1061
|
+
function canProjectBlock(block, context) {
|
|
1062
|
+
return context.projectableBlocks?.has(block) ?? true;
|
|
1066
1063
|
}
|
|
1067
1064
|
function buildSection(block, context) {
|
|
1068
1065
|
const section = context.sectionByBlock.get(block);
|
|
@@ -1088,16 +1085,6 @@ function buildSection(block, context) {
|
|
|
1088
1085
|
section.children = childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
1089
1086
|
return section;
|
|
1090
1087
|
}
|
|
1091
|
-
function buildOpenChildren(block, line, context) {
|
|
1092
|
-
const nodes = [];
|
|
1093
|
-
let cursor = line;
|
|
1094
|
-
for (const child of childBlocksOf(block)) {
|
|
1095
|
-
const built = toNodes(buildNode(child, context, child.getSourceLocation?.()?.getLineNumber?.() ?? findBlockSourceLine(context, child, cursor)));
|
|
1096
|
-
nodes.push(...built);
|
|
1097
|
-
cursor = Math.max(cursor, ...built.map(nodeEndLine).filter(isNumber)) + 1;
|
|
1098
|
-
}
|
|
1099
|
-
return nodes;
|
|
1100
|
-
}
|
|
1101
1088
|
function buildDescriptionList(block, startLine, context, interval) {
|
|
1102
1089
|
const metadata = interval?.metadata ?? [];
|
|
1103
1090
|
const span = interval?.span ?? {
|
|
@@ -1329,17 +1316,6 @@ function sourceSpanOf(node) {
|
|
|
1329
1316
|
function isLineSpan(value) {
|
|
1330
1317
|
return value !== void 0;
|
|
1331
1318
|
}
|
|
1332
|
-
function findBlockSourceLine(context, block, startLine) {
|
|
1333
|
-
const firstSourceLine = block.getSource?.()?.split(/\r?\n/u).find((line) => line.trim() !== "")?.trim();
|
|
1334
|
-
if (!firstSourceLine) return;
|
|
1335
|
-
for (let line = startLine; line <= context.lineTable.lines.length; line += 1) if (lineText(context.lineTable, line).trim() === firstSourceLine) return line;
|
|
1336
|
-
}
|
|
1337
|
-
function nodeEndLine(node) {
|
|
1338
|
-
return node.source?.span?.endLine ?? node.source?.line;
|
|
1339
|
-
}
|
|
1340
|
-
function isNumber(value) {
|
|
1341
|
-
return typeof value === "number";
|
|
1342
|
-
}
|
|
1343
1319
|
function buildParagraph(block, line, context, interval) {
|
|
1344
1320
|
const blockSpan = interval?.span ?? {
|
|
1345
1321
|
startLine: line,
|
|
@@ -1604,6 +1580,37 @@ function isRecord$1(value) {
|
|
|
1604
1580
|
return value !== null && typeof value === "object";
|
|
1605
1581
|
}
|
|
1606
1582
|
//#endregion
|
|
1583
|
+
//#region src/official-source-location.ts
|
|
1584
|
+
const takenFromParent = /* @__PURE__ */ new WeakSet();
|
|
1585
|
+
const borrowedFromChild = /* @__PURE__ */ new WeakSet();
|
|
1586
|
+
function completeSynthesizedSourceLocations(officialDocument) {
|
|
1587
|
+
for (const block of childBlocksOf(officialDocument)) complete(block, void 0);
|
|
1588
|
+
}
|
|
1589
|
+
function takesParentSourceLocation(block) {
|
|
1590
|
+
return takenFromParent.has(block);
|
|
1591
|
+
}
|
|
1592
|
+
function borrowsChildSourceLocation(block) {
|
|
1593
|
+
return borrowedFromChild.has(block);
|
|
1594
|
+
}
|
|
1595
|
+
function complete(block, parent) {
|
|
1596
|
+
if (!block.getSourceLocation?.() && block.getContext?.() === "paragraph" && parent?.getContext?.() === "open") {
|
|
1597
|
+
locate(block, parent.getSourceLocation?.());
|
|
1598
|
+
takenFromParent.add(block);
|
|
1599
|
+
}
|
|
1600
|
+
const children = childBlocksOf(block);
|
|
1601
|
+
for (const child of children) complete(child, block);
|
|
1602
|
+
if (!block.getSourceLocation?.() && block.getContext?.() === "open") {
|
|
1603
|
+
const location = children.find((child) => child.getSourceLocation?.())?.getSourceLocation?.();
|
|
1604
|
+
if (location) {
|
|
1605
|
+
locate(block, location);
|
|
1606
|
+
borrowedFromChild.add(block);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
function locate(block, location) {
|
|
1611
|
+
if (location) block.sourceLocation = location;
|
|
1612
|
+
}
|
|
1613
|
+
//#endregion
|
|
1607
1614
|
//#region src/book-entry/source-scope-index.ts
|
|
1608
1615
|
const sectionSourceScopeBySection = /* @__PURE__ */ new WeakMap();
|
|
1609
1616
|
function registerSectionSourceScope(section, scope) {
|
|
@@ -1673,7 +1680,7 @@ function scanInlineOccurrencesInOfficialBlocks(options) {
|
|
|
1673
1680
|
}
|
|
1674
1681
|
if (interval.metadataSpan) scanMetadataRange(options.lineTable, interval.metadataSpan.startLine, interval.metadataSpan.endLine, xrefOccurrences, anchorOccurrences);
|
|
1675
1682
|
const span = interval.contentSpan ?? interval.span;
|
|
1676
|
-
if (officialBlockPolicy(surface.
|
|
1683
|
+
if (officialBlockPolicy(surface.block) !== "scan") continue;
|
|
1677
1684
|
if (!scansMacroSubstitutedContent(surface)) continue;
|
|
1678
1685
|
if (surface.context === "table") scanTableInlineRange(options.lineTable, surface.block, span.startLine, span.endLine, xrefOccurrences, anchorOccurrences, headingInlineMetadataOccurrences, options.toolDiagnostics);
|
|
1679
1686
|
else scanInlineRange(options.lineTable, span.startLine, span.endLine, xrefOccurrences, anchorOccurrences, headingInlineMetadataOccurrences, options.toolDiagnostics, descendantUnscannableRanges(surface, options.intervalByBlock));
|
|
@@ -1721,7 +1728,7 @@ function recoverSourceAwareInlineOrigins(occurrences, sourceAwareDocument, toolD
|
|
|
1721
1728
|
function hasDiagnosticPolicyAncestor$1(surface) {
|
|
1722
1729
|
let current = surface.parent;
|
|
1723
1730
|
while (current) {
|
|
1724
|
-
if (officialBlockPolicy(current.
|
|
1731
|
+
if (officialBlockPolicy(current.block) === "diagnostic") return true;
|
|
1725
1732
|
current = current.parent;
|
|
1726
1733
|
}
|
|
1727
1734
|
return false;
|
|
@@ -1918,7 +1925,7 @@ function descendantUnscannableRanges(surface, intervalByBlock) {
|
|
|
1918
1925
|
return mergeLineSpans(ranges);
|
|
1919
1926
|
}
|
|
1920
1927
|
function collectUnscannableRanges(surface, intervalByBlock, ranges) {
|
|
1921
|
-
const policy = officialBlockPolicy(surface.
|
|
1928
|
+
const policy = officialBlockPolicy(surface.block);
|
|
1922
1929
|
const interval = intervalByBlock.get(surface.block);
|
|
1923
1930
|
if (policy === "skip" || policy === "diagnostic") {
|
|
1924
1931
|
if (interval) ranges.push(interval.span);
|
|
@@ -2203,6 +2210,85 @@ function parseStyleIdRoles(part) {
|
|
|
2203
2210
|
});
|
|
2204
2211
|
}
|
|
2205
2212
|
//#endregion
|
|
2213
|
+
//#region src/official-delimiter.ts
|
|
2214
|
+
const DELIMITED_BLOCKS = {
|
|
2215
|
+
"--": ["open", new Set([
|
|
2216
|
+
"comment",
|
|
2217
|
+
"example",
|
|
2218
|
+
"literal",
|
|
2219
|
+
"listing",
|
|
2220
|
+
"pass",
|
|
2221
|
+
"quote",
|
|
2222
|
+
"sidebar",
|
|
2223
|
+
"source",
|
|
2224
|
+
"verse",
|
|
2225
|
+
"admonition",
|
|
2226
|
+
"abstract",
|
|
2227
|
+
"partintro"
|
|
2228
|
+
])],
|
|
2229
|
+
"----": ["listing", new Set(["literal", "source"])],
|
|
2230
|
+
"....": ["literal", new Set(["listing", "source"])],
|
|
2231
|
+
"====": ["example", new Set(["admonition"])],
|
|
2232
|
+
"****": ["sidebar", /* @__PURE__ */ new Set()],
|
|
2233
|
+
____: ["quote", new Set(["verse"])],
|
|
2234
|
+
"++++": ["pass", new Set([
|
|
2235
|
+
"stem",
|
|
2236
|
+
"latexmath",
|
|
2237
|
+
"asciimath"
|
|
2238
|
+
])],
|
|
2239
|
+
"|===": ["table", /* @__PURE__ */ new Set()],
|
|
2240
|
+
",===": ["table", /* @__PURE__ */ new Set()],
|
|
2241
|
+
":===": ["table", /* @__PURE__ */ new Set()],
|
|
2242
|
+
"!===": ["table", /* @__PURE__ */ new Set()],
|
|
2243
|
+
"~~~~": ["open", new Set(["abstract", "partintro"])],
|
|
2244
|
+
"////": ["comment", /* @__PURE__ */ new Set()],
|
|
2245
|
+
"```": ["fenced_code", /* @__PURE__ */ new Set()]
|
|
2246
|
+
};
|
|
2247
|
+
const DELIMITED_BLOCK_HEADS = new Set(Object.keys(DELIMITED_BLOCKS).map((delimiter) => delimiter.slice(0, 2)));
|
|
2248
|
+
const DELIMITED_BLOCK_TAILS = Object.fromEntries(Object.keys(DELIMITED_BLOCKS).filter((delimiter) => delimiter.length === 4).map((delimiter) => [delimiter, delimiter.slice(-1)]));
|
|
2249
|
+
function officialDelimiter(line) {
|
|
2250
|
+
let candidate = line;
|
|
2251
|
+
let lineLength = candidate.length;
|
|
2252
|
+
if (lineLength < 2 || !DELIMITED_BLOCK_HEADS.has(candidate.slice(0, 2))) return;
|
|
2253
|
+
let tip;
|
|
2254
|
+
let tipLength;
|
|
2255
|
+
if (lineLength === 2) {
|
|
2256
|
+
tip = candidate;
|
|
2257
|
+
tipLength = 2;
|
|
2258
|
+
} else {
|
|
2259
|
+
tipLength = lineLength < 5 ? lineLength : 4;
|
|
2260
|
+
tip = candidate.slice(0, tipLength);
|
|
2261
|
+
if (tip.startsWith("`")) {
|
|
2262
|
+
if (tipLength === 4) {
|
|
2263
|
+
if (tip === "````") return;
|
|
2264
|
+
tip = tip.slice(0, 3);
|
|
2265
|
+
if (tip !== "```") return;
|
|
2266
|
+
candidate = tip;
|
|
2267
|
+
lineLength = 3;
|
|
2268
|
+
tipLength = 3;
|
|
2269
|
+
} else if (tip !== "```") return;
|
|
2270
|
+
} else if (tipLength === 3) return;
|
|
2271
|
+
}
|
|
2272
|
+
const entry = DELIMITED_BLOCKS[tip];
|
|
2273
|
+
if (!entry) return;
|
|
2274
|
+
const tail = DELIMITED_BLOCK_TAILS[tip];
|
|
2275
|
+
if (!(lineLength === tipLength || tail !== void 0 && isUniform(candidate.slice(1), tail))) return;
|
|
2276
|
+
const [context, masq] = entry;
|
|
2277
|
+
return {
|
|
2278
|
+
context,
|
|
2279
|
+
masq,
|
|
2280
|
+
terminator: candidate
|
|
2281
|
+
};
|
|
2282
|
+
}
|
|
2283
|
+
function delimiterOpens(delimiter, context, style) {
|
|
2284
|
+
if (context === void 0) return false;
|
|
2285
|
+
if (delimiter.context === "fenced_code") return context === "listing";
|
|
2286
|
+
return delimiter.context === context || delimiter.masq.has(context) || style !== null && style !== void 0 && delimiter.masq.has(style);
|
|
2287
|
+
}
|
|
2288
|
+
function isUniform(text, character) {
|
|
2289
|
+
return [...text].every((each) => each === character);
|
|
2290
|
+
}
|
|
2291
|
+
//#endregion
|
|
2206
2292
|
//#region src/source-interval-resolver.ts
|
|
2207
2293
|
function resolveSourceInterval(surface, lineTable) {
|
|
2208
2294
|
if (surface.sourceLine === void 0) return;
|
|
@@ -2210,11 +2296,14 @@ function resolveSourceInterval(surface, lineTable) {
|
|
|
2210
2296
|
const metadata = metadataForSurface(surface, lineTable, blockStartLine);
|
|
2211
2297
|
const startLine = metadata.at(0)?.line ?? blockStartLine;
|
|
2212
2298
|
const diagnostics = [];
|
|
2213
|
-
const
|
|
2214
|
-
const
|
|
2299
|
+
const delimitedContext = isDelimitedContext(surface.context);
|
|
2300
|
+
const synthesized = borrowsChildSourceLocation(surface.block);
|
|
2301
|
+
const delimited = delimitedContext ? resolveDelimitedBlockSpan(lineTable, blockStartLine, surface) : void 0;
|
|
2302
|
+
const undelimited = delimitedContext && delimited === void 0 && !synthesized ? resolveUndelimitedBlockSpan(lineTable, blockStartLine, surface) : void 0;
|
|
2303
|
+
const sourceContentSpan = sourceContentSpanForContext(surface, lineTable, blockStartLine);
|
|
2215
2304
|
const nextSiblingStart = nextSiblingStartLine(surface, lineTable);
|
|
2216
2305
|
const childEndLine = surface.context === "dlist" ? lastChildEndLine(surface, lineTable) : void 0;
|
|
2217
|
-
const endLine = delimited?.span.endLine ?? sourceContentSpan?.endLine ?? childEndLine ?? (nextSiblingStart !== void 0 ? nextSiblingStart - 1 : void 0) ?? parentEndLine(surface, lineTable) ?? lineTable.lines.length;
|
|
2306
|
+
const endLine = delimited?.span.endLine ?? undelimited?.endLine ?? sourceContentSpan?.endLine ?? childEndLine ?? (nextSiblingStart !== void 0 ? nextSiblingStart - 1 : void 0) ?? parentEndLine(surface, lineTable) ?? lineTable.lines.length;
|
|
2218
2307
|
const span = normalizeLineSpan({
|
|
2219
2308
|
startLine,
|
|
2220
2309
|
endLine: Math.max(startLine, endLine)
|
|
@@ -2223,13 +2312,13 @@ function resolveSourceInterval(surface, lineTable) {
|
|
|
2223
2312
|
startLine,
|
|
2224
2313
|
endLine: blockStartLine - 1
|
|
2225
2314
|
} : void 0;
|
|
2226
|
-
if (delimited === void 0 &&
|
|
2315
|
+
if (delimitedContext && delimited === void 0 && undelimited === void 0 && !synthesized && blockStartLine <= lineTable.lines.length) diagnostics.push({
|
|
2227
2316
|
level: "warning",
|
|
2228
2317
|
code: "source-interval.delimiter-not-found",
|
|
2229
2318
|
message: `Could not locate ${surface.context} block delimiter from official source line ${blockStartLine}.`,
|
|
2230
2319
|
source: spanForLineText(lineTable, blockStartLine, 1)
|
|
2231
2320
|
});
|
|
2232
|
-
const contentSpan = delimited?.contentSpan ?? sourceContentSpan ?? contentSpanForContext(surface, span);
|
|
2321
|
+
const contentSpan = delimited?.contentSpan ?? undelimited ?? sourceContentSpan ?? contentSpanForContext(surface, span);
|
|
2233
2322
|
const sourceSpan = sourceSpanFromLineSpan(lineTable, span);
|
|
2234
2323
|
const titleSpan = titleSpanForSurface(surface, lineTable);
|
|
2235
2324
|
return {
|
|
@@ -2251,6 +2340,7 @@ function nextSiblingStartLine(surface, lineTable) {
|
|
|
2251
2340
|
}
|
|
2252
2341
|
function metadataForSurface(surface, lineTable, blockStartLine) {
|
|
2253
2342
|
if (surface.context === "list_item") return [];
|
|
2343
|
+
if (takesParentSourceLocation(surface.block)) return [];
|
|
2254
2344
|
return collectPrecedingMetadata(lineTable, blockStartLine);
|
|
2255
2345
|
}
|
|
2256
2346
|
function lastChildEndLine(surface, lineTable) {
|
|
@@ -2266,25 +2356,10 @@ function parentEndLine(surface, lineTable) {
|
|
|
2266
2356
|
if (!parent) return lineTable.lines.length;
|
|
2267
2357
|
return resolveSourceInterval(parent, lineTable)?.span.endLine;
|
|
2268
2358
|
}
|
|
2269
|
-
function
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
case "literal": return resolveDelimitedBlockSpan(lineTable, startLine, ["...."]);
|
|
2274
|
-
case "pass": return resolveDelimitedBlockSpan(lineTable, startLine, ["++++"]);
|
|
2275
|
-
case "open": return resolveDelimitedBlockSpan(lineTable, startLine, ["--"]);
|
|
2276
|
-
case "quote":
|
|
2277
|
-
case "verse": return resolveDelimitedBlockSpan(lineTable, startLine, ["____"]);
|
|
2278
|
-
case "sidebar": return resolveDelimitedBlockSpan(lineTable, startLine, ["****"]);
|
|
2279
|
-
case "stem": return resolveDelimitedBlockSpan(lineTable, startLine, ["++++"]);
|
|
2280
|
-
case "table": return resolveDelimitedBlockSpan(lineTable, startLine, ["|==="]);
|
|
2281
|
-
default: return;
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
function resolveDelimitedBlockSpan(lineTable, startLine, allowedDelimiters) {
|
|
2285
|
-
const opening = lineText(lineTable, startLine).trim();
|
|
2286
|
-
if (!allowedDelimiters.includes(opening)) return;
|
|
2287
|
-
for (let line = startLine + 1; line <= lineTable.lines.length; line += 1) if (lineText(lineTable, line).trim() === opening) return {
|
|
2359
|
+
function resolveDelimitedBlockSpan(lineTable, startLine, surface) {
|
|
2360
|
+
const delimiter = officialDelimiter(lineText(lineTable, startLine).trimEnd());
|
|
2361
|
+
if (!delimiter || !delimiterOpens(delimiter, surface.context, surface.block.getStyle?.())) return;
|
|
2362
|
+
for (let line = startLine + 1; line <= lineTable.lines.length; line += 1) if (lineText(lineTable, line).trimEnd() === delimiter.terminator) return {
|
|
2288
2363
|
span: {
|
|
2289
2364
|
startLine,
|
|
2290
2365
|
endLine: line
|
|
@@ -2295,6 +2370,42 @@ function resolveDelimitedBlockSpan(lineTable, startLine, allowedDelimiters) {
|
|
|
2295
2370
|
}
|
|
2296
2371
|
};
|
|
2297
2372
|
}
|
|
2373
|
+
function resolveUndelimitedBlockSpan(lineTable, startLine, surface) {
|
|
2374
|
+
const firstLine = firstSourceLine(surface);
|
|
2375
|
+
if (firstLine === void 0 || withoutWhitespace(lineText(lineTable, startLine)) !== withoutWhitespace(firstLine)) return;
|
|
2376
|
+
if (surface.children.length > 0) {
|
|
2377
|
+
const childEnds = surface.children.map((child) => resolveSourceInterval(child, lineTable)?.span.endLine).filter((line) => line !== void 0);
|
|
2378
|
+
return {
|
|
2379
|
+
startLine,
|
|
2380
|
+
endLine: Math.max(startLine, ...childEnds)
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
return {
|
|
2384
|
+
startLine,
|
|
2385
|
+
endLine: lastSourceLine(lineTable, startLine, surface.block)
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
function withoutWhitespace(text) {
|
|
2389
|
+
return text.replace(/\s+/gu, "");
|
|
2390
|
+
}
|
|
2391
|
+
function lastSourceLine(lineTable, startLine, block) {
|
|
2392
|
+
const count = Math.max(1, block.getSourceLines?.().length ?? block.getSource?.().split(/\r?\n/u).length ?? 1);
|
|
2393
|
+
const skipsLineComments = block.getContentModel?.() !== "verbatim";
|
|
2394
|
+
let counted = 0;
|
|
2395
|
+
for (let line = startLine; line <= lineTable.lines.length; line += 1) {
|
|
2396
|
+
const text = lineText(lineTable, line);
|
|
2397
|
+
if (skipsLineComments && text.startsWith("//") && !text.startsWith("///")) continue;
|
|
2398
|
+
counted += 1;
|
|
2399
|
+
if (counted === count) return line;
|
|
2400
|
+
}
|
|
2401
|
+
return Math.max(startLine, lineTable.lines.length);
|
|
2402
|
+
}
|
|
2403
|
+
function firstSourceLine(surface) {
|
|
2404
|
+
const own = surface.block.getSourceLines?.()[0];
|
|
2405
|
+
if (own !== void 0) return own;
|
|
2406
|
+
const firstChild = surface.children[0];
|
|
2407
|
+
return firstChild ? firstSourceLine(firstChild) : void 0;
|
|
2408
|
+
}
|
|
2298
2409
|
function contentSpanForContext(surface, span) {
|
|
2299
2410
|
if (surface.context === "paragraph") return {
|
|
2300
2411
|
startLine: surface.sourceLine ?? span.startLine,
|
|
@@ -2308,13 +2419,12 @@ function contentSpanForContext(surface, span) {
|
|
|
2308
2419
|
};
|
|
2309
2420
|
}
|
|
2310
2421
|
}
|
|
2311
|
-
function sourceContentSpanForContext(surface, startLine) {
|
|
2422
|
+
function sourceContentSpanForContext(surface, lineTable, startLine) {
|
|
2312
2423
|
if (surface.context !== "paragraph" && surface.context !== "admonition") return;
|
|
2313
|
-
|
|
2314
|
-
if (source === void 0) return;
|
|
2424
|
+
if (surface.block.getSourceLines === void 0 && surface.block.getSource === void 0) return;
|
|
2315
2425
|
return {
|
|
2316
2426
|
startLine,
|
|
2317
|
-
endLine:
|
|
2427
|
+
endLine: lastSourceLine(lineTable, startLine, surface.block)
|
|
2318
2428
|
};
|
|
2319
2429
|
}
|
|
2320
2430
|
function titleSpanForSurface(surface, lineTable) {
|
|
@@ -2357,13 +2467,12 @@ function projectSourceSurfaces(options) {
|
|
|
2357
2467
|
const blockSurfaces = walkOfficialBlocks(options.officialDocument);
|
|
2358
2468
|
const intervalByBlock = /* @__PURE__ */ new WeakMap();
|
|
2359
2469
|
const projectableBlocks = /* @__PURE__ */ new WeakSet();
|
|
2360
|
-
const containerFallbackBlocks = /* @__PURE__ */ new WeakSet();
|
|
2361
2470
|
const toolDiagnostics = [];
|
|
2362
2471
|
const mainSourcePath = options.sourcePath ? options.sourceIdentity.normalize(options.sourceIdentity.resolve(options.sourcePath)) : void 0;
|
|
2363
2472
|
const sourceAwareDocument = sourceAwareDocumentForLineTable(options.lineTable);
|
|
2364
2473
|
const logicalSource = logicalSourceForLineTable(options.lineTable);
|
|
2365
2474
|
for (const surface of blockSurfaces) {
|
|
2366
|
-
const policy = officialBlockPolicy(surface.
|
|
2475
|
+
const policy = officialBlockPolicy(surface.block);
|
|
2367
2476
|
if (isExternalSourceSurface(surface, mainSourcePath, options.sourceIdentity)) {
|
|
2368
2477
|
if (policy === "diagnostic") toolDiagnostics.push(unknownContextDiagnostic(surface));
|
|
2369
2478
|
toolDiagnostics.push({
|
|
@@ -2380,7 +2489,6 @@ function projectSourceSurfaces(options) {
|
|
|
2380
2489
|
code: "source-location.missing",
|
|
2381
2490
|
message: `Official block source location is missing for context '${surface.context ?? "undefined"}' node '${surface.nodeName ?? "undefined"}'.`
|
|
2382
2491
|
});
|
|
2383
|
-
if (canUseContainerFallbackSurface(surface, policy)) containerFallbackBlocks.add(surface.block);
|
|
2384
2492
|
continue;
|
|
2385
2493
|
}
|
|
2386
2494
|
const interval = resolveSourceInterval(surface, options.lineTable);
|
|
@@ -2424,7 +2532,6 @@ function projectSourceSurfaces(options) {
|
|
|
2424
2532
|
blockSurfaces,
|
|
2425
2533
|
intervalByBlock,
|
|
2426
2534
|
projectableBlocks,
|
|
2427
|
-
containerFallbackBlocks,
|
|
2428
2535
|
sectionByBlock,
|
|
2429
2536
|
sections,
|
|
2430
2537
|
xrefOccurrences,
|
|
@@ -2457,9 +2564,6 @@ function unknownContextDiagnostic(surface, interval) {
|
|
|
2457
2564
|
source: interval?.sourceSpan
|
|
2458
2565
|
});
|
|
2459
2566
|
}
|
|
2460
|
-
function canUseContainerFallbackSurface(surface, policy) {
|
|
2461
|
-
return surface.context === "paragraph" && policy === "scan" && !hasDiagnosticPolicyAncestor(surface);
|
|
2462
|
-
}
|
|
2463
2567
|
function buildSectionSurfaces(blockSurfaces, intervalByBlock, lineTable, toolDiagnostics, logicalSource, sourceAwareDocument) {
|
|
2464
2568
|
const sections = [];
|
|
2465
2569
|
const sectionByBlock = /* @__PURE__ */ new WeakMap();
|
|
@@ -2577,7 +2681,7 @@ function sourceAwareOriginForLine(document, logicalLine) {
|
|
|
2577
2681
|
function hasDiagnosticPolicyAncestor(surface) {
|
|
2578
2682
|
let current = surface.parent;
|
|
2579
2683
|
while (current) {
|
|
2580
|
-
if (officialBlockPolicy(current.
|
|
2684
|
+
if (officialBlockPolicy(current.block) === "diagnostic") return true;
|
|
2581
2685
|
current = current.parent;
|
|
2582
2686
|
}
|
|
2583
2687
|
return false;
|
|
@@ -2594,6 +2698,7 @@ function mapSectionScope(sections, totalLines) {
|
|
|
2594
2698
|
//#endregion
|
|
2595
2699
|
//#region src/parser-core.ts
|
|
2596
2700
|
async function parseAsciidoctorDocument(input) {
|
|
2701
|
+
completeSynthesizedSourceLocations(input.officialDocument);
|
|
2597
2702
|
const sourceSurfaces = projectSourceSurfaces({
|
|
2598
2703
|
officialDocument: input.officialDocument,
|
|
2599
2704
|
lineTable: input.lineTable,
|
|
@@ -2610,7 +2715,6 @@ async function parseAsciidoctorDocument(input) {
|
|
|
2610
2715
|
headingInlineMetadataOccurrences: sourceSurfaces.headingInlineMetadataOccurrences,
|
|
2611
2716
|
intervalByBlock: sourceSurfaces.intervalByBlock,
|
|
2612
2717
|
projectableBlocks: sourceSurfaces.projectableBlocks,
|
|
2613
|
-
containerFallbackBlocks: sourceSurfaces.containerFallbackBlocks,
|
|
2614
2718
|
sectionByBlock: sourceSurfaces.sectionByBlock
|
|
2615
2719
|
});
|
|
2616
2720
|
await resolveOfficialBindings(officialProjection.bindingRequests, input.officialDocument, input.adapter);
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as parseAbundantTree, i as serializeAbundantTreeToJson, n as formatAbundantTree, t as rdf12 } from "./src-
|
|
2
|
+
import { a as parseAbundantTree, i as serializeAbundantTreeToJson, n as formatAbundantTree, t as rdf12 } from "./src-DMOLXZbF.mjs";
|
|
3
3
|
import { relative, resolve, sep } from "node:path";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import process from "node:process";
|
package/dist/index.d.mts
CHANGED
|
@@ -213,6 +213,23 @@ type ParseAbundantTreeOptions = {
|
|
|
213
213
|
sourcePath: string;
|
|
214
214
|
mode: "book-entry";
|
|
215
215
|
documentRoot: string;
|
|
216
|
+
includeResolvers?: readonly IncludeResolver[];
|
|
217
|
+
};
|
|
218
|
+
type IncludeResolver = {
|
|
219
|
+
readonly prefix: string;
|
|
220
|
+
resolve(request: IncludeResolverRequest): IncludeResolution | Promise<IncludeResolution>;
|
|
221
|
+
};
|
|
222
|
+
type IncludeResolverRequest = {
|
|
223
|
+
readonly target: string;
|
|
224
|
+
readonly attributes: Readonly<Record<string, string>>;
|
|
225
|
+
readonly sourcePath: string;
|
|
226
|
+
};
|
|
227
|
+
type IncludeResolution = {
|
|
228
|
+
readonly text: string;
|
|
229
|
+
readonly origin: {
|
|
230
|
+
readonly path: string;
|
|
231
|
+
readonly startLine: number;
|
|
232
|
+
};
|
|
216
233
|
};
|
|
217
234
|
//#endregion
|
|
218
235
|
//#region src/rdf12-projection/options.d.ts
|
|
@@ -354,4 +371,4 @@ type Rdf12Result = Rdf12Projection & {
|
|
|
354
371
|
};
|
|
355
372
|
declare function rdf12(document: AbundantDocument, options: Rdf12Options): Rdf12Result;
|
|
356
373
|
//#endregion
|
|
357
|
-
export { type AbundantDocument, type AbundantNode, type AnchorOccurrenceNode, type AsciidoctorLayer, type ExportAnimationYamlOptions, type ExportAnimationYamlResult, type LineSpan, type ListingNode, type MetadataNode, type OutputFormat, type ParagraphNode, type ParseAbundantTreeOptions, type ParserInfo, Rdf12Result, type SectionNode, type SourceFileNode, type SourceLayer, type SourcePosition, type SourceSpan, type TableNode, type TargetNode, type TargetType, type TextNode, type TitleNode, type ToolDiagnostic, type XrefOccurrenceNode, exportAnimationYaml, formatAbundantTree, parseAbundantTree, rdf12, serializeAbundantTree, serializeAbundantTreeToJson };
|
|
374
|
+
export { type AbundantDocument, type AbundantNode, type AnchorOccurrenceNode, type AsciidoctorLayer, type ExportAnimationYamlOptions, type ExportAnimationYamlResult, type IncludeResolution, type IncludeResolver, type IncludeResolverRequest, type LineSpan, type ListingNode, type MetadataNode, type OutputFormat, type ParagraphNode, type ParseAbundantTreeOptions, type ParserInfo, Rdf12Result, type SectionNode, type SourceFileNode, type SourceLayer, type SourcePosition, type SourceSpan, type TableNode, type TargetNode, type TargetType, type TextNode, type TitleNode, type ToolDiagnostic, type XrefOccurrenceNode, exportAnimationYaml, formatAbundantTree, parseAbundantTree, rdf12, serializeAbundantTree, serializeAbundantTreeToJson };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseAbundantTree, i as serializeAbundantTreeToJson, n as formatAbundantTree, o as exportAnimationYaml, r as serializeAbundantTree, t as rdf12 } from "./src-
|
|
1
|
+
import { a as parseAbundantTree, i as serializeAbundantTreeToJson, n as formatAbundantTree, o as exportAnimationYaml, r as serializeAbundantTree, t as rdf12 } from "./src-DMOLXZbF.mjs";
|
|
2
2
|
export { exportAnimationYaml, formatAbundantTree, parseAbundantTree, rdf12, serializeAbundantTree, serializeAbundantTreeToJson };
|
|
@@ -2544,6 +2544,90 @@ function isElement(node) {
|
|
|
2544
2544
|
return "tagName" in node;
|
|
2545
2545
|
}
|
|
2546
2546
|
//#endregion
|
|
2547
|
+
//#region src/book-entry/diagnostics.ts
|
|
2548
|
+
var BookEntryConstructionError = class extends Error {
|
|
2549
|
+
code;
|
|
2550
|
+
diagnostic;
|
|
2551
|
+
constructor(diagnostic) {
|
|
2552
|
+
super(`${diagnostic.code}: ${diagnostic.message}`);
|
|
2553
|
+
this.name = "BookEntryConstructionError";
|
|
2554
|
+
this.code = diagnostic.code;
|
|
2555
|
+
this.diagnostic = diagnostic;
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
function constructionError(code, message, source) {
|
|
2559
|
+
return new BookEntryConstructionError({
|
|
2560
|
+
level: "error",
|
|
2561
|
+
code,
|
|
2562
|
+
message,
|
|
2563
|
+
...source ? { source } : {}
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
//#endregion
|
|
2567
|
+
//#region src/book-entry/path-boundary.ts
|
|
2568
|
+
function normalizeDocumentRoot(documentRoot) {
|
|
2569
|
+
return resolve(documentRoot);
|
|
2570
|
+
}
|
|
2571
|
+
function resolveEntryPath(sourcePath) {
|
|
2572
|
+
return resolve(sourcePath);
|
|
2573
|
+
}
|
|
2574
|
+
function resolveIncludeTarget(containingFilePath, targetPath) {
|
|
2575
|
+
return resolve(containingFilePath, "..", targetPath);
|
|
2576
|
+
}
|
|
2577
|
+
function relativePathWithinDocumentRoot(documentRoot, absolutePath) {
|
|
2578
|
+
const normalizedRoot = normalizeDocumentRoot(documentRoot);
|
|
2579
|
+
const normalizedPath = resolve(absolutePath);
|
|
2580
|
+
const relativePath = relative(normalizedRoot, normalizedPath);
|
|
2581
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep}`) || relativePath.includes(`${sep}..${sep}`) || relativePath.startsWith(`${sep}`)) throw constructionError("include.outside-document-root", `Resolved include path is outside documentRoot: ${normalizedPath}.`);
|
|
2582
|
+
return toPortableRelativePath(relativePath);
|
|
2583
|
+
}
|
|
2584
|
+
function toPortableRelativePath(value) {
|
|
2585
|
+
return value.split(sep).join("/");
|
|
2586
|
+
}
|
|
2587
|
+
//#endregion
|
|
2588
|
+
//#region src/book-entry/include-resolvers.ts
|
|
2589
|
+
function claimingResolver(resolvers, target) {
|
|
2590
|
+
return resolvers.find((resolver) => target.startsWith(resolver.prefix));
|
|
2591
|
+
}
|
|
2592
|
+
function registerIncludeResolvers(registry, resolvers, documentRoot, resolutions) {
|
|
2593
|
+
registry.includeProcessor(function() {
|
|
2594
|
+
this.handles((target) => claimingResolver(resolvers, target) !== void 0);
|
|
2595
|
+
this.process(async (_document, reader, target, attributes) => {
|
|
2596
|
+
const resolver = claimingResolver(resolvers, target);
|
|
2597
|
+
if (!resolver) return;
|
|
2598
|
+
const sourcePath = reader.getCursor().getFile() ?? "";
|
|
2599
|
+
const resolution = await resolveOrFail(resolver, target, attributes, sourcePath);
|
|
2600
|
+
const absolutePath = resolve(documentRoot, resolution.origin.path);
|
|
2601
|
+
let relativePath;
|
|
2602
|
+
try {
|
|
2603
|
+
relativePath = relativePathWithinDocumentRoot(documentRoot, absolutePath);
|
|
2604
|
+
} catch {
|
|
2605
|
+
throw constructionError("include.outside-document-root", `Include resolver '${resolver.prefix}' returned a source outside documentRoot for include::${target}[] in ${sourcePath}: ${absolutePath}.`);
|
|
2606
|
+
}
|
|
2607
|
+
const text = resolution.text.replace(/\r?\n$/u, "");
|
|
2608
|
+
reader.pushInclude(text, absolutePath, relativePath, resolution.origin.startLine, attributes);
|
|
2609
|
+
const frame = reader.includeStack.at(-1);
|
|
2610
|
+
if (frame && text !== "") resolutions.set(frame, {
|
|
2611
|
+
target,
|
|
2612
|
+
absolutePath,
|
|
2613
|
+
startLine: resolution.origin.startLine,
|
|
2614
|
+
lineCount: text.split(/\r?\n/u).length
|
|
2615
|
+
});
|
|
2616
|
+
});
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
async function resolveOrFail(resolver, target, attributes, sourcePath) {
|
|
2620
|
+
try {
|
|
2621
|
+
return await resolver.resolve({
|
|
2622
|
+
target: target.slice(resolver.prefix.length),
|
|
2623
|
+
attributes,
|
|
2624
|
+
sourcePath
|
|
2625
|
+
});
|
|
2626
|
+
} catch (error) {
|
|
2627
|
+
throw constructionError("include.resolver-failed", `Include resolver '${resolver.prefix}' failed for include::${target}[] in ${sourcePath}: ${error instanceof Error ? error.message : String(error)}.`);
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
//#endregion
|
|
2547
2631
|
//#region src/asciidoctor-file-adapter.ts
|
|
2548
2632
|
function createAsciidoctorFileAdapter() {
|
|
2549
2633
|
const extensionRegistry = createExtensionRegistry();
|
|
@@ -2558,6 +2642,9 @@ function createAsciidoctorFileAdapter() {
|
|
|
2558
2642
|
});
|
|
2559
2643
|
},
|
|
2560
2644
|
async readPreprocessedLines(options) {
|
|
2645
|
+
const resolutions = /* @__PURE__ */ new WeakMap();
|
|
2646
|
+
const registry = Extensions.create();
|
|
2647
|
+
if (options.includeResolution) registerIncludeResolvers(registry, options.includeResolution.resolvers, options.includeResolution.documentRoot, resolutions);
|
|
2561
2648
|
const reader = (await loadFile(options.sourcePath, {
|
|
2562
2649
|
safe: "unsafe",
|
|
2563
2650
|
base_dir: options.baseDir,
|
|
@@ -2565,7 +2652,7 @@ function createAsciidoctorFileAdapter() {
|
|
|
2565
2652
|
parse: false,
|
|
2566
2653
|
to_file: false,
|
|
2567
2654
|
attributes: options.attributes ?? {},
|
|
2568
|
-
extension_registry:
|
|
2655
|
+
extension_registry: registry
|
|
2569
2656
|
})).getReader();
|
|
2570
2657
|
const lines = [];
|
|
2571
2658
|
const pushIds = /* @__PURE__ */ new WeakMap();
|
|
@@ -2581,12 +2668,14 @@ function createAsciidoctorFileAdapter() {
|
|
|
2581
2668
|
pushes += 1;
|
|
2582
2669
|
pushIds.set(frame, pushes);
|
|
2583
2670
|
}
|
|
2671
|
+
const resolved = frame ? resolutions.get(frame) : void 0;
|
|
2584
2672
|
lines.push({
|
|
2585
2673
|
text,
|
|
2586
2674
|
cursor: cursorForReturnedReaderLine(before, after),
|
|
2587
2675
|
push: {
|
|
2588
2676
|
id: frame ? pushIds.get(frame) ?? 0 : 0,
|
|
2589
|
-
depth: stack.length
|
|
2677
|
+
depth: stack.length,
|
|
2678
|
+
...resolved ? { resolved } : {}
|
|
2590
2679
|
}
|
|
2591
2680
|
});
|
|
2592
2681
|
}
|
|
@@ -2619,26 +2708,6 @@ function cursorForReturnedReaderLine(before, after) {
|
|
|
2619
2708
|
return before;
|
|
2620
2709
|
}
|
|
2621
2710
|
//#endregion
|
|
2622
|
-
//#region src/book-entry/diagnostics.ts
|
|
2623
|
-
var BookEntryConstructionError = class extends Error {
|
|
2624
|
-
code;
|
|
2625
|
-
diagnostic;
|
|
2626
|
-
constructor(diagnostic) {
|
|
2627
|
-
super(`${diagnostic.code}: ${diagnostic.message}`);
|
|
2628
|
-
this.name = "BookEntryConstructionError";
|
|
2629
|
-
this.code = diagnostic.code;
|
|
2630
|
-
this.diagnostic = diagnostic;
|
|
2631
|
-
}
|
|
2632
|
-
};
|
|
2633
|
-
function constructionError(code, message, source) {
|
|
2634
|
-
return new BookEntryConstructionError({
|
|
2635
|
-
level: "error",
|
|
2636
|
-
code,
|
|
2637
|
-
message,
|
|
2638
|
-
...source ? { source } : {}
|
|
2639
|
-
});
|
|
2640
|
-
}
|
|
2641
|
-
//#endregion
|
|
2642
2711
|
//#region src/book-entry/include-attribute-model.ts
|
|
2643
2712
|
const mappedAttributeNames = new Set([
|
|
2644
2713
|
"tag",
|
|
@@ -2919,27 +2988,6 @@ function buildParserSafeLogicalText(lineRecords) {
|
|
|
2919
2988
|
};
|
|
2920
2989
|
}
|
|
2921
2990
|
//#endregion
|
|
2922
|
-
//#region src/book-entry/path-boundary.ts
|
|
2923
|
-
function normalizeDocumentRoot(documentRoot) {
|
|
2924
|
-
return resolve(documentRoot);
|
|
2925
|
-
}
|
|
2926
|
-
function resolveEntryPath(sourcePath) {
|
|
2927
|
-
return resolve(sourcePath);
|
|
2928
|
-
}
|
|
2929
|
-
function resolveIncludeTarget(containingFilePath, targetPath) {
|
|
2930
|
-
return resolve(containingFilePath, "..", targetPath);
|
|
2931
|
-
}
|
|
2932
|
-
function relativePathWithinDocumentRoot(documentRoot, absolutePath) {
|
|
2933
|
-
const normalizedRoot = normalizeDocumentRoot(documentRoot);
|
|
2934
|
-
const normalizedPath = resolve(absolutePath);
|
|
2935
|
-
const relativePath = relative(normalizedRoot, normalizedPath);
|
|
2936
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep}`) || relativePath.includes(`${sep}..${sep}`) || relativePath.startsWith(`${sep}`)) throw constructionError("include.outside-document-root", `Resolved include path is outside documentRoot: ${normalizedPath}.`);
|
|
2937
|
-
return toPortableRelativePath(relativePath);
|
|
2938
|
-
}
|
|
2939
|
-
function toPortableRelativePath(value) {
|
|
2940
|
-
return value.split(sep).join("/");
|
|
2941
|
-
}
|
|
2942
|
-
//#endregion
|
|
2943
2991
|
//#region src/book-entry/reader-boundary-policy.ts
|
|
2944
2992
|
function readerPreprocessingOptions(options) {
|
|
2945
2993
|
const sourcePath = resolve(options.sourcePath);
|
|
@@ -3025,13 +3073,14 @@ function createSourceSet(options) {
|
|
|
3025
3073
|
//#endregion
|
|
3026
3074
|
//#region src/book-entry/official-reader-preprocessor.ts
|
|
3027
3075
|
const asciidocExtensionPattern = /\.(?:adoc|asciidoc|asc|ad|txt)$/u;
|
|
3028
|
-
function validateIncludeGraph(absolutePath, documentRoot, stack) {
|
|
3076
|
+
function validateIncludeGraph(absolutePath, documentRoot, stack, includeResolvers) {
|
|
3029
3077
|
const cycleStart = stack.indexOf(absolutePath);
|
|
3030
3078
|
if (cycleStart !== -1) throw constructionError("include.cycle", `Include graph contains a cycle: ${[...stack.slice(cycleStart), absolutePath].join(" -> ")}.`);
|
|
3031
3079
|
const nextStack = [...stack, absolutePath];
|
|
3032
3080
|
for (const line of authoredTextLines(readFileSync(absolutePath, "utf8"))) {
|
|
3033
3081
|
const directive = parseReaderIncludeDirective(line);
|
|
3034
3082
|
if (!directive || directive.escaped) continue;
|
|
3083
|
+
if (claimingResolver(includeResolvers, directive.target)) continue;
|
|
3035
3084
|
const attributes = parseIncludeAttributes(directive.attrlist);
|
|
3036
3085
|
if (attributes.classification === "unmapped") continue;
|
|
3037
3086
|
if (isUriTarget(directive.target) || directive.target.includes("{")) throwDiagnostic(classifyReaderBoundaryDiagnostic({
|
|
@@ -3064,7 +3113,7 @@ function validateIncludeGraph(absolutePath, documentRoot, stack) {
|
|
|
3064
3113
|
}));
|
|
3065
3114
|
}
|
|
3066
3115
|
if (selectionSurface(attributes) || !asciidocExtensionPattern.test(includePath)) continue;
|
|
3067
|
-
validateIncludeGraph(includePath, documentRoot, nextStack);
|
|
3116
|
+
validateIncludeGraph(includePath, documentRoot, nextStack, includeResolvers);
|
|
3068
3117
|
}
|
|
3069
3118
|
}
|
|
3070
3119
|
async function preprocessBookEntryWithOfficialReader(options) {
|
|
@@ -3072,13 +3121,21 @@ async function preprocessBookEntryWithOfficialReader(options) {
|
|
|
3072
3121
|
const documentRoot = normalizeDocumentRoot(options.documentRoot);
|
|
3073
3122
|
relativePathWithinDocumentRoot(documentRoot, entryPath);
|
|
3074
3123
|
if (!existsSync(entryPath)) throw constructionError("entry.missing-source", `Entry source file does not exist: ${entryPath}.`);
|
|
3075
|
-
|
|
3124
|
+
const includeResolvers = options.includeResolvers ?? [];
|
|
3125
|
+
validateIncludeGraph(entryPath, documentRoot, [], includeResolvers);
|
|
3076
3126
|
const state = {
|
|
3077
3127
|
documentRoot,
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3128
|
+
includeResolvers,
|
|
3129
|
+
officialLines: await options.adapter.readPreprocessedLines({
|
|
3130
|
+
...readerPreprocessingOptions({
|
|
3131
|
+
sourcePath: entryPath,
|
|
3132
|
+
attributes: options.attributes
|
|
3133
|
+
}),
|
|
3134
|
+
includeResolution: {
|
|
3135
|
+
resolvers: includeResolvers,
|
|
3136
|
+
documentRoot
|
|
3137
|
+
}
|
|
3138
|
+
}),
|
|
3082
3139
|
sourceSet: createSourceSet({ documentRoot }),
|
|
3083
3140
|
records: [],
|
|
3084
3141
|
diagnostics: [],
|
|
@@ -3128,6 +3185,10 @@ function appendSourceFile(absolutePath, state) {
|
|
|
3128
3185
|
}
|
|
3129
3186
|
}
|
|
3130
3187
|
function appendIncludeDirective(containingFile, line, directive, state) {
|
|
3188
|
+
if (claimingResolver(state.includeResolvers, directive.target)) {
|
|
3189
|
+
appendResolvedInclude(containingFile, line, directive, state);
|
|
3190
|
+
return;
|
|
3191
|
+
}
|
|
3131
3192
|
const attributes = parseIncludeAttributes(directive.attrlist);
|
|
3132
3193
|
state.diagnostics.push(...attributes.diagnostics);
|
|
3133
3194
|
if (attributes.classification === "unmapped") {
|
|
@@ -3166,18 +3227,40 @@ function appendIncludeDirective(containingFile, line, directive, state) {
|
|
|
3166
3227
|
}
|
|
3167
3228
|
const targetFile = state.sourceSet.registerFile(includePath);
|
|
3168
3229
|
const selector = selectionSurface(attributes);
|
|
3230
|
+
appendPushedInclude(containingFile, line, targetFile, attributes, selector ? {
|
|
3231
|
+
selector,
|
|
3232
|
+
selection: mapIncludeSelection(targetFile.text, selector)
|
|
3233
|
+
} : void 0, state);
|
|
3234
|
+
}
|
|
3235
|
+
function appendResolvedInclude(containingFile, line, directive, state) {
|
|
3236
|
+
const first = state.officialLines[state.officialIndex];
|
|
3237
|
+
const resolved = first && first.push.depth === state.currentPush.depth + 1 ? first.push.resolved : void 0;
|
|
3238
|
+
if (!resolved || resolved.target !== directive.target) return;
|
|
3239
|
+
appendPushedInclude(containingFile, line, state.sourceSet.registerFile(resolved.absolutePath), parseIncludeAttributes(directive.attrlist), {
|
|
3240
|
+
selector: {
|
|
3241
|
+
kind: "resolver",
|
|
3242
|
+
target: directive.target
|
|
3243
|
+
},
|
|
3244
|
+
selection: {
|
|
3245
|
+
ok: true,
|
|
3246
|
+
lines: Array.from({ length: resolved.lineCount }, (_, index) => resolved.startLine + index)
|
|
3247
|
+
}
|
|
3248
|
+
}, state);
|
|
3249
|
+
}
|
|
3250
|
+
function appendPushedInclude(containingFile, line, targetFile, attributes, selected, state) {
|
|
3251
|
+
const includePath = targetFile.absolutePath;
|
|
3169
3252
|
const leveloffset = hasLeveloffsetSurface(attributes);
|
|
3170
3253
|
const parent = state.currentPush;
|
|
3171
3254
|
const first = state.officialLines[state.officialIndex];
|
|
3172
|
-
const selection =
|
|
3255
|
+
const selection = selected?.selection;
|
|
3173
3256
|
const candidate = first && first.push.depth === parent.depth + 1 && selection?.ok !== false ? first.push : void 0;
|
|
3174
3257
|
const own = candidate && state.officialLines.slice(state.officialIndex, pushEnd(candidate, state)).some((official) => official.push.id === candidate.id && official.cursor.file === includePath) ? candidate : void 0;
|
|
3175
3258
|
const end = own ? pushEnd(own, state) : state.officialIndex;
|
|
3176
3259
|
state.currentPush = own ?? parent;
|
|
3177
3260
|
consumeGeneratedPreludeForInclude(leveloffset, own, state);
|
|
3178
|
-
if (
|
|
3261
|
+
if (selected) appendSelectedInclude(targetFile, selected.selector, indentSurface(attributes), state, `${containingFile.relativePath}:${line.number}`, selected.selection, own, leveloffset ? generatedTailStart(end, state) : end);
|
|
3179
3262
|
else appendFullFileInclude(targetFile, indentSurface(attributes), state);
|
|
3180
|
-
if (leveloffset && own) consumeGeneratedTailForInclude(state);
|
|
3263
|
+
if (leveloffset && own) consumeGeneratedTailForInclude(own, state);
|
|
3181
3264
|
state.currentPush = parent;
|
|
3182
3265
|
}
|
|
3183
3266
|
function pushEnd(own, state) {
|
|
@@ -3265,7 +3348,11 @@ function degradeRestOfPush(targetFile, selector, includeSite, bodyEnd, state) {
|
|
|
3265
3348
|
});
|
|
3266
3349
|
}
|
|
3267
3350
|
function selectorSurface(selector) {
|
|
3268
|
-
|
|
3351
|
+
switch (selector.kind) {
|
|
3352
|
+
case "tag": return `tag=${selector.name}`;
|
|
3353
|
+
case "resolver": return `the resolver for ${selector.target}`;
|
|
3354
|
+
default: return `${selector.kind}=${selector.expression}`;
|
|
3355
|
+
}
|
|
3269
3356
|
}
|
|
3270
3357
|
function sameLine(officialText, sourceText, indent) {
|
|
3271
3358
|
const official = officialText.trimEnd();
|
|
@@ -3348,15 +3435,13 @@ function consumeGeneratedPreludeForInclude(hasLeveloffset, own, state) {
|
|
|
3348
3435
|
const blank = state.officialLines[state.officialIndex];
|
|
3349
3436
|
if (blank?.push.id === own.id && blank.text === "") appendGeneratedControl(consumeOfficialLine(state)?.text ?? "", state);
|
|
3350
3437
|
}
|
|
3351
|
-
function consumeGeneratedTailForInclude(state) {
|
|
3438
|
+
function consumeGeneratedTailForInclude(own, state) {
|
|
3352
3439
|
while (state.officialIndex < state.officialLines.length) {
|
|
3353
3440
|
const next = state.officialLines[state.officialIndex];
|
|
3354
|
-
if (!next || !(next.text === "" || next.text.startsWith(":leveloffset"))) break;
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
break;
|
|
3359
|
-
}
|
|
3441
|
+
if (!next || next.push.id !== own.id || !(next.text === "" || next.text.startsWith(":leveloffset"))) break;
|
|
3442
|
+
consumeOfficialLine(state);
|
|
3443
|
+
appendGeneratedControl(next.text, state);
|
|
3444
|
+
if (next.text.startsWith(":leveloffset")) break;
|
|
3360
3445
|
}
|
|
3361
3446
|
}
|
|
3362
3447
|
function consumeUnmappedOfficialTail(state) {
|
|
@@ -3853,8 +3938,8 @@ function recoveryFailure(code, message, source) {
|
|
|
3853
3938
|
}
|
|
3854
3939
|
//#endregion
|
|
3855
3940
|
//#region src/official-block-policy.ts
|
|
3856
|
-
function officialBlockPolicy(
|
|
3857
|
-
switch (
|
|
3941
|
+
function officialBlockPolicy(block) {
|
|
3942
|
+
switch (block.getContext?.()) {
|
|
3858
3943
|
case "admonition":
|
|
3859
3944
|
case "dlist":
|
|
3860
3945
|
case "list_item":
|
|
@@ -3862,12 +3947,13 @@ function officialBlockPolicy(context) {
|
|
|
3862
3947
|
case "table":
|
|
3863
3948
|
case "verse": return "scan";
|
|
3864
3949
|
case "example":
|
|
3865
|
-
case "olist":
|
|
3866
3950
|
case "quote":
|
|
3867
|
-
case "section":
|
|
3868
3951
|
case "sidebar":
|
|
3869
|
-
case "
|
|
3870
|
-
case "
|
|
3952
|
+
case "open": return block.getContentModel?.() === "simple" ? "scan" : "recurse";
|
|
3953
|
+
case "olist":
|
|
3954
|
+
case "preamble":
|
|
3955
|
+
case "section":
|
|
3956
|
+
case "ulist": return "recurse";
|
|
3871
3957
|
case "listing":
|
|
3872
3958
|
case "literal":
|
|
3873
3959
|
case "pass":
|
|
@@ -3926,7 +4012,6 @@ function projectOfficialDocument(options) {
|
|
|
3926
4012
|
usedAnchorKeys: /* @__PURE__ */ new Set(),
|
|
3927
4013
|
intervalByBlock: options.intervalByBlock,
|
|
3928
4014
|
projectableBlocks: options.projectableBlocks,
|
|
3929
|
-
containerFallbackBlocks: options.containerFallbackBlocks,
|
|
3930
4015
|
sectionByBlock: options.sectionByBlock,
|
|
3931
4016
|
bindingRequests,
|
|
3932
4017
|
targets,
|
|
@@ -3944,19 +4029,18 @@ function buildChildren(officialDocument, context) {
|
|
|
3944
4029
|
for (const block of childBlocksOf(officialDocument)) topLevel.push(...toNodes(buildNode(block, context)));
|
|
3945
4030
|
return topLevel;
|
|
3946
4031
|
}
|
|
3947
|
-
function buildNode(block, context
|
|
4032
|
+
function buildNode(block, context) {
|
|
3948
4033
|
const blockContext = block.getContext?.();
|
|
3949
4034
|
const officialLine = block.getSourceLocation?.()?.getLineNumber?.();
|
|
3950
|
-
const line = officialLine ?? fallbackLine;
|
|
3951
4035
|
const interval = context.intervalByBlock.get(block);
|
|
3952
|
-
if (!canProjectBlock(block, context
|
|
4036
|
+
if (!canProjectBlock(block, context)) return;
|
|
3953
4037
|
if (blockContext === "section" && officialLine !== void 0) return buildSection(block, context);
|
|
3954
|
-
if (blockContext === "paragraph" &&
|
|
4038
|
+
if (blockContext === "paragraph" && officialLine !== void 0) return buildParagraph(block, officialLine, context, interval);
|
|
3955
4039
|
if (blockContext === "listing" && officialLine !== void 0) return buildListing(block, officialLine, context, interval);
|
|
3956
4040
|
if (blockContext === "table" && officialLine !== void 0) return buildTable(block, officialLine, context, interval);
|
|
3957
4041
|
if (blockContext === "dlist" && officialLine !== void 0) return buildDescriptionList(block, officialLine, context, interval);
|
|
3958
|
-
if (blockContext === "open" &&
|
|
3959
|
-
if (officialBlockPolicy(
|
|
4042
|
+
if (blockContext === "open" && officialLine !== void 0) return childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
4043
|
+
if (officialBlockPolicy(block) === "diagnostic") return;
|
|
3960
4044
|
if (officialLine !== void 0) {
|
|
3961
4045
|
registerOfficialBlockTarget(context, block, {
|
|
3962
4046
|
targetType: "block",
|
|
@@ -3968,10 +4052,8 @@ function buildNode(block, context, fallbackLine) {
|
|
|
3968
4052
|
return childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
3969
4053
|
}
|
|
3970
4054
|
}
|
|
3971
|
-
function canProjectBlock(block, context
|
|
3972
|
-
|
|
3973
|
-
if (context.projectableBlocks.has(block)) return true;
|
|
3974
|
-
return officialLine === void 0 && fallbackLine !== void 0 && (context.containerFallbackBlocks?.has(block) ?? false);
|
|
4055
|
+
function canProjectBlock(block, context) {
|
|
4056
|
+
return context.projectableBlocks?.has(block) ?? true;
|
|
3975
4057
|
}
|
|
3976
4058
|
function buildSection(block, context) {
|
|
3977
4059
|
const section = context.sectionByBlock.get(block);
|
|
@@ -3997,16 +4079,6 @@ function buildSection(block, context) {
|
|
|
3997
4079
|
section.children = childBlocksOf(block).flatMap((child) => toNodes(buildNode(child, context)));
|
|
3998
4080
|
return section;
|
|
3999
4081
|
}
|
|
4000
|
-
function buildOpenChildren(block, line, context) {
|
|
4001
|
-
const nodes = [];
|
|
4002
|
-
let cursor = line;
|
|
4003
|
-
for (const child of childBlocksOf(block)) {
|
|
4004
|
-
const built = toNodes(buildNode(child, context, child.getSourceLocation?.()?.getLineNumber?.() ?? findBlockSourceLine(context, child, cursor)));
|
|
4005
|
-
nodes.push(...built);
|
|
4006
|
-
cursor = Math.max(cursor, ...built.map(nodeEndLine).filter(isNumber)) + 1;
|
|
4007
|
-
}
|
|
4008
|
-
return nodes;
|
|
4009
|
-
}
|
|
4010
4082
|
function buildDescriptionList(block, startLine, context, interval) {
|
|
4011
4083
|
const metadata = interval?.metadata ?? [];
|
|
4012
4084
|
const span = interval?.span ?? {
|
|
@@ -4238,17 +4310,6 @@ function sourceSpanOf(node) {
|
|
|
4238
4310
|
function isLineSpan(value) {
|
|
4239
4311
|
return value !== void 0;
|
|
4240
4312
|
}
|
|
4241
|
-
function findBlockSourceLine(context, block, startLine) {
|
|
4242
|
-
const firstSourceLine = block.getSource?.()?.split(/\r?\n/u).find((line) => line.trim() !== "")?.trim();
|
|
4243
|
-
if (!firstSourceLine) return;
|
|
4244
|
-
for (let line = startLine; line <= context.lineTable.lines.length; line += 1) if (lineText(context.lineTable, line).trim() === firstSourceLine) return line;
|
|
4245
|
-
}
|
|
4246
|
-
function nodeEndLine(node) {
|
|
4247
|
-
return node.source?.span?.endLine ?? node.source?.line;
|
|
4248
|
-
}
|
|
4249
|
-
function isNumber(value) {
|
|
4250
|
-
return typeof value === "number";
|
|
4251
|
-
}
|
|
4252
4313
|
function buildParagraph(block, line, context, interval) {
|
|
4253
4314
|
const blockSpan = interval?.span ?? {
|
|
4254
4315
|
startLine: line,
|
|
@@ -4513,6 +4574,37 @@ function isRecord$1(value) {
|
|
|
4513
4574
|
return value !== null && typeof value === "object";
|
|
4514
4575
|
}
|
|
4515
4576
|
//#endregion
|
|
4577
|
+
//#region src/official-source-location.ts
|
|
4578
|
+
const takenFromParent = /* @__PURE__ */ new WeakSet();
|
|
4579
|
+
const borrowedFromChild = /* @__PURE__ */ new WeakSet();
|
|
4580
|
+
function completeSynthesizedSourceLocations(officialDocument) {
|
|
4581
|
+
for (const block of childBlocksOf(officialDocument)) complete(block, void 0);
|
|
4582
|
+
}
|
|
4583
|
+
function takesParentSourceLocation(block) {
|
|
4584
|
+
return takenFromParent.has(block);
|
|
4585
|
+
}
|
|
4586
|
+
function borrowsChildSourceLocation(block) {
|
|
4587
|
+
return borrowedFromChild.has(block);
|
|
4588
|
+
}
|
|
4589
|
+
function complete(block, parent) {
|
|
4590
|
+
if (!block.getSourceLocation?.() && block.getContext?.() === "paragraph" && parent?.getContext?.() === "open") {
|
|
4591
|
+
locate(block, parent.getSourceLocation?.());
|
|
4592
|
+
takenFromParent.add(block);
|
|
4593
|
+
}
|
|
4594
|
+
const children = childBlocksOf(block);
|
|
4595
|
+
for (const child of children) complete(child, block);
|
|
4596
|
+
if (!block.getSourceLocation?.() && block.getContext?.() === "open") {
|
|
4597
|
+
const location = children.find((child) => child.getSourceLocation?.())?.getSourceLocation?.();
|
|
4598
|
+
if (location) {
|
|
4599
|
+
locate(block, location);
|
|
4600
|
+
borrowedFromChild.add(block);
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4604
|
+
function locate(block, location) {
|
|
4605
|
+
if (location) block.sourceLocation = location;
|
|
4606
|
+
}
|
|
4607
|
+
//#endregion
|
|
4516
4608
|
//#region src/book-entry/source-scope-index.ts
|
|
4517
4609
|
const sectionSourceScopeBySection = /* @__PURE__ */ new WeakMap();
|
|
4518
4610
|
function registerSectionSourceScope(section, scope) {
|
|
@@ -4582,7 +4674,7 @@ function scanInlineOccurrencesInOfficialBlocks(options) {
|
|
|
4582
4674
|
}
|
|
4583
4675
|
if (interval.metadataSpan) scanMetadataRange(options.lineTable, interval.metadataSpan.startLine, interval.metadataSpan.endLine, xrefOccurrences, anchorOccurrences);
|
|
4584
4676
|
const span = interval.contentSpan ?? interval.span;
|
|
4585
|
-
if (officialBlockPolicy(surface.
|
|
4677
|
+
if (officialBlockPolicy(surface.block) !== "scan") continue;
|
|
4586
4678
|
if (!scansMacroSubstitutedContent(surface)) continue;
|
|
4587
4679
|
if (surface.context === "table") scanTableInlineRange(options.lineTable, surface.block, span.startLine, span.endLine, xrefOccurrences, anchorOccurrences, headingInlineMetadataOccurrences, options.toolDiagnostics);
|
|
4588
4680
|
else scanInlineRange(options.lineTable, span.startLine, span.endLine, xrefOccurrences, anchorOccurrences, headingInlineMetadataOccurrences, options.toolDiagnostics, descendantUnscannableRanges(surface, options.intervalByBlock));
|
|
@@ -4630,7 +4722,7 @@ function recoverSourceAwareInlineOrigins(occurrences, sourceAwareDocument, toolD
|
|
|
4630
4722
|
function hasDiagnosticPolicyAncestor$1(surface) {
|
|
4631
4723
|
let current = surface.parent;
|
|
4632
4724
|
while (current) {
|
|
4633
|
-
if (officialBlockPolicy(current.
|
|
4725
|
+
if (officialBlockPolicy(current.block) === "diagnostic") return true;
|
|
4634
4726
|
current = current.parent;
|
|
4635
4727
|
}
|
|
4636
4728
|
return false;
|
|
@@ -4827,7 +4919,7 @@ function descendantUnscannableRanges(surface, intervalByBlock) {
|
|
|
4827
4919
|
return mergeLineSpans(ranges);
|
|
4828
4920
|
}
|
|
4829
4921
|
function collectUnscannableRanges(surface, intervalByBlock, ranges) {
|
|
4830
|
-
const policy = officialBlockPolicy(surface.
|
|
4922
|
+
const policy = officialBlockPolicy(surface.block);
|
|
4831
4923
|
const interval = intervalByBlock.get(surface.block);
|
|
4832
4924
|
if (policy === "skip" || policy === "diagnostic") {
|
|
4833
4925
|
if (interval) ranges.push(interval.span);
|
|
@@ -5112,6 +5204,85 @@ function parseStyleIdRoles(part) {
|
|
|
5112
5204
|
});
|
|
5113
5205
|
}
|
|
5114
5206
|
//#endregion
|
|
5207
|
+
//#region src/official-delimiter.ts
|
|
5208
|
+
const DELIMITED_BLOCKS = {
|
|
5209
|
+
"--": ["open", new Set([
|
|
5210
|
+
"comment",
|
|
5211
|
+
"example",
|
|
5212
|
+
"literal",
|
|
5213
|
+
"listing",
|
|
5214
|
+
"pass",
|
|
5215
|
+
"quote",
|
|
5216
|
+
"sidebar",
|
|
5217
|
+
"source",
|
|
5218
|
+
"verse",
|
|
5219
|
+
"admonition",
|
|
5220
|
+
"abstract",
|
|
5221
|
+
"partintro"
|
|
5222
|
+
])],
|
|
5223
|
+
"----": ["listing", new Set(["literal", "source"])],
|
|
5224
|
+
"....": ["literal", new Set(["listing", "source"])],
|
|
5225
|
+
"====": ["example", new Set(["admonition"])],
|
|
5226
|
+
"****": ["sidebar", /* @__PURE__ */ new Set()],
|
|
5227
|
+
____: ["quote", new Set(["verse"])],
|
|
5228
|
+
"++++": ["pass", new Set([
|
|
5229
|
+
"stem",
|
|
5230
|
+
"latexmath",
|
|
5231
|
+
"asciimath"
|
|
5232
|
+
])],
|
|
5233
|
+
"|===": ["table", /* @__PURE__ */ new Set()],
|
|
5234
|
+
",===": ["table", /* @__PURE__ */ new Set()],
|
|
5235
|
+
":===": ["table", /* @__PURE__ */ new Set()],
|
|
5236
|
+
"!===": ["table", /* @__PURE__ */ new Set()],
|
|
5237
|
+
"~~~~": ["open", new Set(["abstract", "partintro"])],
|
|
5238
|
+
"////": ["comment", /* @__PURE__ */ new Set()],
|
|
5239
|
+
"```": ["fenced_code", /* @__PURE__ */ new Set()]
|
|
5240
|
+
};
|
|
5241
|
+
const DELIMITED_BLOCK_HEADS = new Set(Object.keys(DELIMITED_BLOCKS).map((delimiter) => delimiter.slice(0, 2)));
|
|
5242
|
+
const DELIMITED_BLOCK_TAILS = Object.fromEntries(Object.keys(DELIMITED_BLOCKS).filter((delimiter) => delimiter.length === 4).map((delimiter) => [delimiter, delimiter.slice(-1)]));
|
|
5243
|
+
function officialDelimiter(line) {
|
|
5244
|
+
let candidate = line;
|
|
5245
|
+
let lineLength = candidate.length;
|
|
5246
|
+
if (lineLength < 2 || !DELIMITED_BLOCK_HEADS.has(candidate.slice(0, 2))) return;
|
|
5247
|
+
let tip;
|
|
5248
|
+
let tipLength;
|
|
5249
|
+
if (lineLength === 2) {
|
|
5250
|
+
tip = candidate;
|
|
5251
|
+
tipLength = 2;
|
|
5252
|
+
} else {
|
|
5253
|
+
tipLength = lineLength < 5 ? lineLength : 4;
|
|
5254
|
+
tip = candidate.slice(0, tipLength);
|
|
5255
|
+
if (tip.startsWith("`")) {
|
|
5256
|
+
if (tipLength === 4) {
|
|
5257
|
+
if (tip === "````") return;
|
|
5258
|
+
tip = tip.slice(0, 3);
|
|
5259
|
+
if (tip !== "```") return;
|
|
5260
|
+
candidate = tip;
|
|
5261
|
+
lineLength = 3;
|
|
5262
|
+
tipLength = 3;
|
|
5263
|
+
} else if (tip !== "```") return;
|
|
5264
|
+
} else if (tipLength === 3) return;
|
|
5265
|
+
}
|
|
5266
|
+
const entry = DELIMITED_BLOCKS[tip];
|
|
5267
|
+
if (!entry) return;
|
|
5268
|
+
const tail = DELIMITED_BLOCK_TAILS[tip];
|
|
5269
|
+
if (!(lineLength === tipLength || tail !== void 0 && isUniform(candidate.slice(1), tail))) return;
|
|
5270
|
+
const [context, masq] = entry;
|
|
5271
|
+
return {
|
|
5272
|
+
context,
|
|
5273
|
+
masq,
|
|
5274
|
+
terminator: candidate
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5277
|
+
function delimiterOpens(delimiter, context, style) {
|
|
5278
|
+
if (context === void 0) return false;
|
|
5279
|
+
if (delimiter.context === "fenced_code") return context === "listing";
|
|
5280
|
+
return delimiter.context === context || delimiter.masq.has(context) || style !== null && style !== void 0 && delimiter.masq.has(style);
|
|
5281
|
+
}
|
|
5282
|
+
function isUniform(text, character) {
|
|
5283
|
+
return [...text].every((each) => each === character);
|
|
5284
|
+
}
|
|
5285
|
+
//#endregion
|
|
5115
5286
|
//#region src/source-interval-resolver.ts
|
|
5116
5287
|
function resolveSourceInterval(surface, lineTable) {
|
|
5117
5288
|
if (surface.sourceLine === void 0) return;
|
|
@@ -5119,11 +5290,14 @@ function resolveSourceInterval(surface, lineTable) {
|
|
|
5119
5290
|
const metadata = metadataForSurface(surface, lineTable, blockStartLine);
|
|
5120
5291
|
const startLine = metadata.at(0)?.line ?? blockStartLine;
|
|
5121
5292
|
const diagnostics = [];
|
|
5122
|
-
const
|
|
5123
|
-
const
|
|
5293
|
+
const delimitedContext = isDelimitedContext(surface.context);
|
|
5294
|
+
const synthesized = borrowsChildSourceLocation(surface.block);
|
|
5295
|
+
const delimited = delimitedContext ? resolveDelimitedBlockSpan(lineTable, blockStartLine, surface) : void 0;
|
|
5296
|
+
const undelimited = delimitedContext && delimited === void 0 && !synthesized ? resolveUndelimitedBlockSpan(lineTable, blockStartLine, surface) : void 0;
|
|
5297
|
+
const sourceContentSpan = sourceContentSpanForContext(surface, lineTable, blockStartLine);
|
|
5124
5298
|
const nextSiblingStart = nextSiblingStartLine(surface, lineTable);
|
|
5125
5299
|
const childEndLine = surface.context === "dlist" ? lastChildEndLine(surface, lineTable) : void 0;
|
|
5126
|
-
const endLine = delimited?.span.endLine ?? sourceContentSpan?.endLine ?? childEndLine ?? (nextSiblingStart !== void 0 ? nextSiblingStart - 1 : void 0) ?? parentEndLine(surface, lineTable) ?? lineTable.lines.length;
|
|
5300
|
+
const endLine = delimited?.span.endLine ?? undelimited?.endLine ?? sourceContentSpan?.endLine ?? childEndLine ?? (nextSiblingStart !== void 0 ? nextSiblingStart - 1 : void 0) ?? parentEndLine(surface, lineTable) ?? lineTable.lines.length;
|
|
5127
5301
|
const span = normalizeLineSpan({
|
|
5128
5302
|
startLine,
|
|
5129
5303
|
endLine: Math.max(startLine, endLine)
|
|
@@ -5132,13 +5306,13 @@ function resolveSourceInterval(surface, lineTable) {
|
|
|
5132
5306
|
startLine,
|
|
5133
5307
|
endLine: blockStartLine - 1
|
|
5134
5308
|
} : void 0;
|
|
5135
|
-
if (delimited === void 0 &&
|
|
5309
|
+
if (delimitedContext && delimited === void 0 && undelimited === void 0 && !synthesized && blockStartLine <= lineTable.lines.length) diagnostics.push({
|
|
5136
5310
|
level: "warning",
|
|
5137
5311
|
code: "source-interval.delimiter-not-found",
|
|
5138
5312
|
message: `Could not locate ${surface.context} block delimiter from official source line ${blockStartLine}.`,
|
|
5139
5313
|
source: spanForLineText(lineTable, blockStartLine, 1)
|
|
5140
5314
|
});
|
|
5141
|
-
const contentSpan = delimited?.contentSpan ?? sourceContentSpan ?? contentSpanForContext(surface, span);
|
|
5315
|
+
const contentSpan = delimited?.contentSpan ?? undelimited ?? sourceContentSpan ?? contentSpanForContext(surface, span);
|
|
5142
5316
|
const sourceSpan = sourceSpanFromLineSpan(lineTable, span);
|
|
5143
5317
|
const titleSpan = titleSpanForSurface(surface, lineTable);
|
|
5144
5318
|
return {
|
|
@@ -5160,6 +5334,7 @@ function nextSiblingStartLine(surface, lineTable) {
|
|
|
5160
5334
|
}
|
|
5161
5335
|
function metadataForSurface(surface, lineTable, blockStartLine) {
|
|
5162
5336
|
if (surface.context === "list_item") return [];
|
|
5337
|
+
if (takesParentSourceLocation(surface.block)) return [];
|
|
5163
5338
|
return collectPrecedingMetadata(lineTable, blockStartLine);
|
|
5164
5339
|
}
|
|
5165
5340
|
function lastChildEndLine(surface, lineTable) {
|
|
@@ -5175,25 +5350,10 @@ function parentEndLine(surface, lineTable) {
|
|
|
5175
5350
|
if (!parent) return lineTable.lines.length;
|
|
5176
5351
|
return resolveSourceInterval(parent, lineTable)?.span.endLine;
|
|
5177
5352
|
}
|
|
5178
|
-
function
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
case "literal": return resolveDelimitedBlockSpan(lineTable, startLine, ["...."]);
|
|
5183
|
-
case "pass": return resolveDelimitedBlockSpan(lineTable, startLine, ["++++"]);
|
|
5184
|
-
case "open": return resolveDelimitedBlockSpan(lineTable, startLine, ["--"]);
|
|
5185
|
-
case "quote":
|
|
5186
|
-
case "verse": return resolveDelimitedBlockSpan(lineTable, startLine, ["____"]);
|
|
5187
|
-
case "sidebar": return resolveDelimitedBlockSpan(lineTable, startLine, ["****"]);
|
|
5188
|
-
case "stem": return resolveDelimitedBlockSpan(lineTable, startLine, ["++++"]);
|
|
5189
|
-
case "table": return resolveDelimitedBlockSpan(lineTable, startLine, ["|==="]);
|
|
5190
|
-
default: return;
|
|
5191
|
-
}
|
|
5192
|
-
}
|
|
5193
|
-
function resolveDelimitedBlockSpan(lineTable, startLine, allowedDelimiters) {
|
|
5194
|
-
const opening = lineText(lineTable, startLine).trim();
|
|
5195
|
-
if (!allowedDelimiters.includes(opening)) return;
|
|
5196
|
-
for (let line = startLine + 1; line <= lineTable.lines.length; line += 1) if (lineText(lineTable, line).trim() === opening) return {
|
|
5353
|
+
function resolveDelimitedBlockSpan(lineTable, startLine, surface) {
|
|
5354
|
+
const delimiter = officialDelimiter(lineText(lineTable, startLine).trimEnd());
|
|
5355
|
+
if (!delimiter || !delimiterOpens(delimiter, surface.context, surface.block.getStyle?.())) return;
|
|
5356
|
+
for (let line = startLine + 1; line <= lineTable.lines.length; line += 1) if (lineText(lineTable, line).trimEnd() === delimiter.terminator) return {
|
|
5197
5357
|
span: {
|
|
5198
5358
|
startLine,
|
|
5199
5359
|
endLine: line
|
|
@@ -5204,6 +5364,42 @@ function resolveDelimitedBlockSpan(lineTable, startLine, allowedDelimiters) {
|
|
|
5204
5364
|
}
|
|
5205
5365
|
};
|
|
5206
5366
|
}
|
|
5367
|
+
function resolveUndelimitedBlockSpan(lineTable, startLine, surface) {
|
|
5368
|
+
const firstLine = firstSourceLine(surface);
|
|
5369
|
+
if (firstLine === void 0 || withoutWhitespace(lineText(lineTable, startLine)) !== withoutWhitespace(firstLine)) return;
|
|
5370
|
+
if (surface.children.length > 0) {
|
|
5371
|
+
const childEnds = surface.children.map((child) => resolveSourceInterval(child, lineTable)?.span.endLine).filter((line) => line !== void 0);
|
|
5372
|
+
return {
|
|
5373
|
+
startLine,
|
|
5374
|
+
endLine: Math.max(startLine, ...childEnds)
|
|
5375
|
+
};
|
|
5376
|
+
}
|
|
5377
|
+
return {
|
|
5378
|
+
startLine,
|
|
5379
|
+
endLine: lastSourceLine(lineTable, startLine, surface.block)
|
|
5380
|
+
};
|
|
5381
|
+
}
|
|
5382
|
+
function withoutWhitespace(text) {
|
|
5383
|
+
return text.replace(/\s+/gu, "");
|
|
5384
|
+
}
|
|
5385
|
+
function lastSourceLine(lineTable, startLine, block) {
|
|
5386
|
+
const count = Math.max(1, block.getSourceLines?.().length ?? block.getSource?.().split(/\r?\n/u).length ?? 1);
|
|
5387
|
+
const skipsLineComments = block.getContentModel?.() !== "verbatim";
|
|
5388
|
+
let counted = 0;
|
|
5389
|
+
for (let line = startLine; line <= lineTable.lines.length; line += 1) {
|
|
5390
|
+
const text = lineText(lineTable, line);
|
|
5391
|
+
if (skipsLineComments && text.startsWith("//") && !text.startsWith("///")) continue;
|
|
5392
|
+
counted += 1;
|
|
5393
|
+
if (counted === count) return line;
|
|
5394
|
+
}
|
|
5395
|
+
return Math.max(startLine, lineTable.lines.length);
|
|
5396
|
+
}
|
|
5397
|
+
function firstSourceLine(surface) {
|
|
5398
|
+
const own = surface.block.getSourceLines?.()[0];
|
|
5399
|
+
if (own !== void 0) return own;
|
|
5400
|
+
const firstChild = surface.children[0];
|
|
5401
|
+
return firstChild ? firstSourceLine(firstChild) : void 0;
|
|
5402
|
+
}
|
|
5207
5403
|
function contentSpanForContext(surface, span) {
|
|
5208
5404
|
if (surface.context === "paragraph") return {
|
|
5209
5405
|
startLine: surface.sourceLine ?? span.startLine,
|
|
@@ -5217,13 +5413,12 @@ function contentSpanForContext(surface, span) {
|
|
|
5217
5413
|
};
|
|
5218
5414
|
}
|
|
5219
5415
|
}
|
|
5220
|
-
function sourceContentSpanForContext(surface, startLine) {
|
|
5416
|
+
function sourceContentSpanForContext(surface, lineTable, startLine) {
|
|
5221
5417
|
if (surface.context !== "paragraph" && surface.context !== "admonition") return;
|
|
5222
|
-
|
|
5223
|
-
if (source === void 0) return;
|
|
5418
|
+
if (surface.block.getSourceLines === void 0 && surface.block.getSource === void 0) return;
|
|
5224
5419
|
return {
|
|
5225
5420
|
startLine,
|
|
5226
|
-
endLine:
|
|
5421
|
+
endLine: lastSourceLine(lineTable, startLine, surface.block)
|
|
5227
5422
|
};
|
|
5228
5423
|
}
|
|
5229
5424
|
function titleSpanForSurface(surface, lineTable) {
|
|
@@ -5266,13 +5461,12 @@ function projectSourceSurfaces(options) {
|
|
|
5266
5461
|
const blockSurfaces = walkOfficialBlocks(options.officialDocument);
|
|
5267
5462
|
const intervalByBlock = /* @__PURE__ */ new WeakMap();
|
|
5268
5463
|
const projectableBlocks = /* @__PURE__ */ new WeakSet();
|
|
5269
|
-
const containerFallbackBlocks = /* @__PURE__ */ new WeakSet();
|
|
5270
5464
|
const toolDiagnostics = [];
|
|
5271
5465
|
const mainSourcePath = options.sourcePath ? options.sourceIdentity.normalize(options.sourceIdentity.resolve(options.sourcePath)) : void 0;
|
|
5272
5466
|
const sourceAwareDocument = sourceAwareDocumentForLineTable(options.lineTable);
|
|
5273
5467
|
const logicalSource = logicalSourceForLineTable(options.lineTable);
|
|
5274
5468
|
for (const surface of blockSurfaces) {
|
|
5275
|
-
const policy = officialBlockPolicy(surface.
|
|
5469
|
+
const policy = officialBlockPolicy(surface.block);
|
|
5276
5470
|
if (isExternalSourceSurface(surface, mainSourcePath, options.sourceIdentity)) {
|
|
5277
5471
|
if (policy === "diagnostic") toolDiagnostics.push(unknownContextDiagnostic(surface));
|
|
5278
5472
|
toolDiagnostics.push({
|
|
@@ -5289,7 +5483,6 @@ function projectSourceSurfaces(options) {
|
|
|
5289
5483
|
code: "source-location.missing",
|
|
5290
5484
|
message: `Official block source location is missing for context '${surface.context ?? "undefined"}' node '${surface.nodeName ?? "undefined"}'.`
|
|
5291
5485
|
});
|
|
5292
|
-
if (canUseContainerFallbackSurface(surface, policy)) containerFallbackBlocks.add(surface.block);
|
|
5293
5486
|
continue;
|
|
5294
5487
|
}
|
|
5295
5488
|
const interval = resolveSourceInterval(surface, options.lineTable);
|
|
@@ -5333,7 +5526,6 @@ function projectSourceSurfaces(options) {
|
|
|
5333
5526
|
blockSurfaces,
|
|
5334
5527
|
intervalByBlock,
|
|
5335
5528
|
projectableBlocks,
|
|
5336
|
-
containerFallbackBlocks,
|
|
5337
5529
|
sectionByBlock,
|
|
5338
5530
|
sections,
|
|
5339
5531
|
xrefOccurrences,
|
|
@@ -5366,9 +5558,6 @@ function unknownContextDiagnostic(surface, interval) {
|
|
|
5366
5558
|
source: interval?.sourceSpan
|
|
5367
5559
|
});
|
|
5368
5560
|
}
|
|
5369
|
-
function canUseContainerFallbackSurface(surface, policy) {
|
|
5370
|
-
return surface.context === "paragraph" && policy === "scan" && !hasDiagnosticPolicyAncestor(surface);
|
|
5371
|
-
}
|
|
5372
5561
|
function buildSectionSurfaces(blockSurfaces, intervalByBlock, lineTable, toolDiagnostics, logicalSource, sourceAwareDocument) {
|
|
5373
5562
|
const sections = [];
|
|
5374
5563
|
const sectionByBlock = /* @__PURE__ */ new WeakMap();
|
|
@@ -5486,7 +5675,7 @@ function sourceAwareOriginForLine(document, logicalLine) {
|
|
|
5486
5675
|
function hasDiagnosticPolicyAncestor(surface) {
|
|
5487
5676
|
let current = surface.parent;
|
|
5488
5677
|
while (current) {
|
|
5489
|
-
if (officialBlockPolicy(current.
|
|
5678
|
+
if (officialBlockPolicy(current.block) === "diagnostic") return true;
|
|
5490
5679
|
current = current.parent;
|
|
5491
5680
|
}
|
|
5492
5681
|
return false;
|
|
@@ -5503,6 +5692,7 @@ function mapSectionScope(sections, totalLines) {
|
|
|
5503
5692
|
//#endregion
|
|
5504
5693
|
//#region src/parser-core.ts
|
|
5505
5694
|
async function parseAsciidoctorDocument(input) {
|
|
5695
|
+
completeSynthesizedSourceLocations(input.officialDocument);
|
|
5506
5696
|
const sourceSurfaces = projectSourceSurfaces({
|
|
5507
5697
|
officialDocument: input.officialDocument,
|
|
5508
5698
|
lineTable: input.lineTable,
|
|
@@ -5519,7 +5709,6 @@ async function parseAsciidoctorDocument(input) {
|
|
|
5519
5709
|
headingInlineMetadataOccurrences: sourceSurfaces.headingInlineMetadataOccurrences,
|
|
5520
5710
|
intervalByBlock: sourceSurfaces.intervalByBlock,
|
|
5521
5711
|
projectableBlocks: sourceSurfaces.projectableBlocks,
|
|
5522
|
-
containerFallbackBlocks: sourceSurfaces.containerFallbackBlocks,
|
|
5523
5712
|
sectionByBlock: sourceSurfaces.sectionByBlock
|
|
5524
5713
|
});
|
|
5525
5714
|
await resolveOfficialBindings(officialProjection.bindingRequests, input.officialDocument, input.adapter);
|
|
@@ -5587,7 +5776,8 @@ async function parseAbundantTree(options) {
|
|
|
5587
5776
|
const sourceAwareDocument = await preprocessBookEntryWithOfficialReader({
|
|
5588
5777
|
adapter,
|
|
5589
5778
|
sourcePath,
|
|
5590
|
-
documentRoot: options.documentRoot
|
|
5779
|
+
documentRoot: options.documentRoot,
|
|
5780
|
+
includeResolvers: options.includeResolvers
|
|
5591
5781
|
});
|
|
5592
5782
|
const constructionDiagnostic = sourceAwareDocument.diagnostics.find((diagnostic) => diagnostic.level === "error");
|
|
5593
5783
|
if (constructionDiagnostic) throw constructionError(constructionDiagnostic.code, constructionDiagnostic.message, constructionDiagnostic.source);
|
package/package.json
CHANGED