@hawkeyexl/manni 4.3.1 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/batch-DFRCLY77.js +36 -0
- package/dist/build-Q5C6SX5J.js +31 -0
- package/dist/calibrate-XQILKXS3.js +31 -0
- package/dist/capture-JQMOC3BW.js +32 -0
- package/dist/check-HYNGXYJV.js +18 -0
- package/dist/check-HYNGXYJV.js.map +1 -0
- package/dist/check-NFZQLJKN.js +27 -0
- package/dist/check-NFZQLJKN.js.map +1 -0
- package/dist/check-U54XV6BP.js +40 -0
- package/dist/check-U54XV6BP.js.map +1 -0
- package/dist/chunk-252LNOEG.js +622 -0
- package/dist/chunk-252LNOEG.js.map +1 -0
- package/dist/chunk-2H7UOFLK.js +11 -0
- package/dist/chunk-2H7UOFLK.js.map +1 -0
- package/dist/chunk-2U3ORT6D.js +230 -0
- package/dist/chunk-2U3ORT6D.js.map +1 -0
- package/dist/chunk-3AFUD75K.js +23 -0
- package/dist/chunk-3AFUD75K.js.map +1 -0
- package/dist/{chunk-3R23C5DT.js → chunk-4TSWU2SU.js} +2 -14
- package/dist/chunk-4TSWU2SU.js.map +1 -0
- package/dist/chunk-5KHIFVD2.js +1192 -0
- package/dist/chunk-5KHIFVD2.js.map +1 -0
- package/dist/chunk-5YXBLLAC.js +2165 -0
- package/dist/chunk-5YXBLLAC.js.map +1 -0
- package/dist/chunk-644JVKJ4.js +3872 -0
- package/dist/chunk-644JVKJ4.js.map +1 -0
- package/dist/chunk-6OYEI2VV.js +88 -0
- package/dist/chunk-6OYEI2VV.js.map +1 -0
- package/dist/chunk-77AINBYM.js +19 -0
- package/dist/chunk-77AINBYM.js.map +1 -0
- package/dist/chunk-77HX34KD.js +1287 -0
- package/dist/chunk-77HX34KD.js.map +1 -0
- package/dist/{chunk-CFDUZRM2.js → chunk-7QMCHA4N.js} +32 -240
- package/dist/chunk-7QMCHA4N.js.map +1 -0
- package/dist/chunk-BUXDLRDT.js +455 -0
- package/dist/chunk-BUXDLRDT.js.map +1 -0
- package/dist/chunk-C6OH6CNF.js +388 -0
- package/dist/chunk-C6OH6CNF.js.map +1 -0
- package/dist/chunk-CK7SKVHR.js +1042 -0
- package/dist/chunk-CK7SKVHR.js.map +1 -0
- package/dist/chunk-CYWHFSRT.js +6737 -0
- package/dist/chunk-CYWHFSRT.js.map +1 -0
- package/dist/chunk-ERMSO34F.js +17 -0
- package/dist/chunk-ERMSO34F.js.map +1 -0
- package/dist/{chunk-IOYXPBCL.js → chunk-G3T47CFV.js} +1 -7
- package/dist/{chunk-IOYXPBCL.js.map → chunk-G3T47CFV.js.map} +1 -1
- package/dist/chunk-G7NJSREW.js +979 -0
- package/dist/chunk-G7NJSREW.js.map +1 -0
- package/dist/chunk-GLP5PSXB.js +72 -0
- package/dist/chunk-GLP5PSXB.js.map +1 -0
- package/dist/chunk-H2DLH2JI.js +198 -0
- package/dist/chunk-H2DLH2JI.js.map +1 -0
- package/dist/chunk-H6FZ66XR.js +634 -0
- package/dist/chunk-H6FZ66XR.js.map +1 -0
- package/dist/{chunk-KJR7OVDX.js → chunk-IEQHSCZG.js} +56 -137
- package/dist/chunk-IEQHSCZG.js.map +1 -0
- package/dist/chunk-IKEWBMCN.js +98 -0
- package/dist/chunk-IKEWBMCN.js.map +1 -0
- package/dist/chunk-JOHKIAVH.js +5440 -0
- package/dist/chunk-JOHKIAVH.js.map +1 -0
- package/dist/chunk-JVTNMVYU.js +10921 -0
- package/dist/chunk-JVTNMVYU.js.map +1 -0
- package/dist/chunk-K3D6FPV6.js +164 -0
- package/dist/chunk-K3D6FPV6.js.map +1 -0
- package/dist/{chunk-UBMMXS2Y.js → chunk-KCGV52AM.js} +69 -48
- package/dist/{chunk-UBMMXS2Y.js.map → chunk-KCGV52AM.js.map} +1 -1
- package/dist/chunk-LAKAWRV5.js +1651 -0
- package/dist/chunk-LAKAWRV5.js.map +1 -0
- package/dist/chunk-LJ2RDH3F.js +49 -0
- package/dist/chunk-LJ2RDH3F.js.map +1 -0
- package/dist/chunk-M2JCK5F6.js +805 -0
- package/dist/chunk-M2JCK5F6.js.map +1 -0
- package/dist/chunk-MNH7QO4Z.js +15 -0
- package/dist/chunk-MNH7QO4Z.js.map +1 -0
- package/dist/{chunk-HAPTXWU2.js → chunk-MYC3O5EJ.js} +4 -4
- package/dist/chunk-MYMBCTDE.js +387 -0
- package/dist/chunk-MYMBCTDE.js.map +1 -0
- package/dist/chunk-NCPWXHDO.js +683 -0
- package/dist/chunk-NCPWXHDO.js.map +1 -0
- package/dist/chunk-NWZ2SLYL.js +2957 -0
- package/dist/chunk-NWZ2SLYL.js.map +1 -0
- package/dist/chunk-OBFENF3U.js +934 -0
- package/dist/chunk-OBFENF3U.js.map +1 -0
- package/dist/chunk-OWBRDNRZ.js +16 -0
- package/dist/chunk-OWBRDNRZ.js.map +1 -0
- package/dist/{chunk-KTSJ2ZHA.js → chunk-PAU352SV.js} +5 -3
- package/dist/{chunk-KTSJ2ZHA.js.map → chunk-PAU352SV.js.map} +1 -1
- package/dist/chunk-PCE7QHXJ.js +68 -0
- package/dist/chunk-PCE7QHXJ.js.map +1 -0
- package/dist/chunk-PCHZY2I7.js +299 -0
- package/dist/chunk-PCHZY2I7.js.map +1 -0
- package/dist/chunk-PHF3D7ER.js +1042 -0
- package/dist/chunk-PHF3D7ER.js.map +1 -0
- package/dist/chunk-Q35YIDBV.js +1202 -0
- package/dist/chunk-Q35YIDBV.js.map +1 -0
- package/dist/chunk-RLR4TKUZ.js +4398 -0
- package/dist/chunk-RLR4TKUZ.js.map +1 -0
- package/dist/chunk-RNVYGWIC.js +30 -0
- package/dist/chunk-RNVYGWIC.js.map +1 -0
- package/dist/chunk-SE4JN5XN.js +19 -0
- package/dist/chunk-SE4JN5XN.js.map +1 -0
- package/dist/chunk-TIUTIOFB.js +25 -0
- package/dist/chunk-TIUTIOFB.js.map +1 -0
- package/dist/chunk-TU2WUBVZ.js +2 -0
- package/dist/chunk-TU2WUBVZ.js.map +1 -0
- package/dist/chunk-TZOYZK2E.js +98 -0
- package/dist/chunk-TZOYZK2E.js.map +1 -0
- package/dist/chunk-UKZNLVJW.js +17 -0
- package/dist/chunk-UKZNLVJW.js.map +1 -0
- package/dist/chunk-UZC7LDAQ.js +178 -0
- package/dist/chunk-UZC7LDAQ.js.map +1 -0
- package/dist/chunk-V46OILVC.js +3090 -0
- package/dist/chunk-V46OILVC.js.map +1 -0
- package/dist/chunk-WQE54PNH.js +1975 -0
- package/dist/chunk-WQE54PNH.js.map +1 -0
- package/dist/chunk-X3BPBDGQ.js +52 -0
- package/dist/chunk-X3BPBDGQ.js.map +1 -0
- package/dist/chunk-XSLV76YK.js +54 -0
- package/dist/chunk-XSLV76YK.js.map +1 -0
- package/dist/{chunk-5HNHEUD5.js → chunk-XYLUCIKQ.js} +3 -3
- package/dist/chunk-YEUYKR62.js +72 -0
- package/dist/chunk-YEUYKR62.js.map +1 -0
- package/dist/{chunk-G5CM2VGQ.js → chunk-YFQBFNQS.js} +8 -94
- package/dist/chunk-YFQBFNQS.js.map +1 -0
- package/dist/chunk-YIL4XLLJ.js +1661 -0
- package/dist/chunk-YIL4XLLJ.js.map +1 -0
- package/dist/chunk-YNHZHSSM.js +41 -0
- package/dist/chunk-YNHZHSSM.js.map +1 -0
- package/dist/chunk-YTCZRLTU.js +96 -0
- package/dist/chunk-YTCZRLTU.js.map +1 -0
- package/dist/chunk-YYBFZLAJ.js +374 -0
- package/dist/chunk-YYBFZLAJ.js.map +1 -0
- package/dist/chunk-ZXRAE55H.js +31 -0
- package/dist/chunk-ZXRAE55H.js.map +1 -0
- package/dist/cli-2QPR2OZG.js +232 -0
- package/dist/cli-2QPR2OZG.js.map +1 -0
- package/dist/cli-4IOPGZHR.js +1203 -0
- package/dist/cli-4IOPGZHR.js.map +1 -0
- package/dist/cli-5FL73WHA.js +346 -0
- package/dist/cli-5FL73WHA.js.map +1 -0
- package/dist/cli-C262QOWM.js +739 -0
- package/dist/cli-C262QOWM.js.map +1 -0
- package/dist/cli-LJLLIQB2.js +423 -0
- package/dist/cli-LJLLIQB2.js.map +1 -0
- package/dist/cli-OFPZ5MAS.js +626 -0
- package/dist/cli-OFPZ5MAS.js.map +1 -0
- package/dist/cli-SHSMSRQY.js +28 -0
- package/dist/cli-SHSMSRQY.js.map +1 -0
- package/dist/cli-SRHFUZHA.js +473 -0
- package/dist/cli-SRHFUZHA.js.map +1 -0
- package/dist/cli-URZQXL4K.js +552 -0
- package/dist/cli-URZQXL4K.js.map +1 -0
- package/dist/cli.d.ts +12 -2
- package/dist/cli.js +109 -7661
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +15 -3
- package/dist/docmeta.js.map +1 -1
- package/dist/github-FE6KCNYJ.js +27 -0
- package/dist/github-FE6KCNYJ.js.map +1 -0
- package/dist/github-QXL3VMK2.js +32 -0
- package/dist/github-QXL3VMK2.js.map +1 -0
- package/dist/index.d.ts +65 -3
- package/dist/index.js +407 -337
- package/dist/index.js.map +1 -1
- package/dist/json-7WV7KL6H.js +17 -0
- package/dist/json-7WV7KL6H.js.map +1 -0
- package/dist/json-SGZ6ZRFD.js +35 -0
- package/dist/json-SGZ6ZRFD.js.map +1 -0
- package/dist/lint-DL4LJRAY.js +28 -0
- package/dist/lint-DL4LJRAY.js.map +1 -0
- package/dist/list-6BAXTZUM.js +29 -0
- package/dist/list-6BAXTZUM.js.map +1 -0
- package/dist/list-7BKNYPSB.js +31 -0
- package/dist/list-7BKNYPSB.js.map +1 -0
- package/dist/page-3U2GCFNE.js +41 -0
- package/dist/page-3U2GCFNE.js.map +1 -0
- package/dist/picker-3XF36MJF.js +14 -0
- package/dist/picker-3XF36MJF.js.map +1 -0
- package/dist/pretty-2H57QVTY.js +43 -0
- package/dist/pretty-2H57QVTY.js.map +1 -0
- package/dist/pretty-N6DO4OOL.js +37 -0
- package/dist/pretty-N6DO4OOL.js.map +1 -0
- package/dist/reporters-M6LJ2IYU.js +21 -0
- package/dist/reporters-M6LJ2IYU.js.map +1 -0
- package/dist/reporters-N6GHXSS7.js +42 -0
- package/dist/reporters-N6GHXSS7.js.map +1 -0
- package/dist/reporters-UCNEV7PH.js +71 -0
- package/dist/reporters-UCNEV7PH.js.map +1 -0
- package/dist/run-XZDAREJE.js +33 -0
- package/dist/run-XZDAREJE.js.map +1 -0
- package/dist/term-5ICGKPC3.js +1592 -0
- package/dist/term-5ICGKPC3.js.map +1 -0
- package/dist/types-Y6TXHM7M.js +10 -0
- package/dist/types-Y6TXHM7M.js.map +1 -0
- package/dist/validate-GQRM77YN.js +16 -0
- package/dist/validate-GQRM77YN.js.map +1 -0
- package/package.json +1 -1
- package/plugin/manni/.claude-plugin/plugin.json +9 -0
- package/plugin/manni/hooks/hooks.json +52 -0
- package/plugin/manni/skills/check/SKILL.md +20 -0
- package/plugin/manni/skills/evals/SKILL.md +27 -0
- package/plugin/manni/skills/fix/SKILL.md +56 -0
- package/plugin/manni/skills/setup/SKILL.md +41 -0
- package/dist/batch-A5HZKYIW.js +0 -18
- package/dist/calibrate-S5K6QHUY.js +0 -13
- package/dist/capture-OZEZDABQ.js +0 -15
- package/dist/chunk-3R23C5DT.js.map +0 -1
- package/dist/chunk-CFDUZRM2.js.map +0 -1
- package/dist/chunk-G5CM2VGQ.js.map +0 -1
- package/dist/chunk-KJR7OVDX.js.map +0 -1
- package/dist/chunk-V4KUVE47.js +0 -27170
- package/dist/chunk-V4KUVE47.js.map +0 -1
- package/dist/chunk-ZQBTK3DO.js +0 -26518
- package/dist/chunk-ZQBTK3DO.js.map +0 -1
- package/dist/picker-6HRMETE7.js +0 -12
- package/plugin/tracevals/.claude-plugin/plugin.json +0 -9
- package/plugin/tracevals/hooks/hooks.json +0 -17
- /package/dist/{batch-A5HZKYIW.js.map → batch-DFRCLY77.js.map} +0 -0
- /package/dist/{calibrate-S5K6QHUY.js.map → build-Q5C6SX5J.js.map} +0 -0
- /package/dist/{capture-OZEZDABQ.js.map → calibrate-XQILKXS3.js.map} +0 -0
- /package/dist/{picker-6HRMETE7.js.map → capture-JQMOC3BW.js.map} +0 -0
- /package/dist/{chunk-HAPTXWU2.js.map → chunk-MYC3O5EJ.js.map} +0 -0
- /package/dist/{chunk-5HNHEUD5.js.map → chunk-XYLUCIKQ.js.map} +0 -0
|
@@ -0,0 +1,979 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
codeEndAt,
|
|
4
|
+
codeRegions
|
|
5
|
+
} from "./chunk-IKEWBMCN.js";
|
|
6
|
+
import {
|
|
7
|
+
LineRangeError,
|
|
8
|
+
MAX_RANGE_LINES,
|
|
9
|
+
hashRange,
|
|
10
|
+
isKeyedPin,
|
|
11
|
+
lineSpec,
|
|
12
|
+
parseLines,
|
|
13
|
+
sliceLines
|
|
14
|
+
} from "./chunk-RLR4TKUZ.js";
|
|
15
|
+
import {
|
|
16
|
+
__default3 as __default,
|
|
17
|
+
extractorByName,
|
|
18
|
+
extractorForExtension,
|
|
19
|
+
hasFrontmatterFence,
|
|
20
|
+
locateFrontmatter,
|
|
21
|
+
supportedExtensions
|
|
22
|
+
} from "./chunk-JVTNMVYU.js";
|
|
23
|
+
import {
|
|
24
|
+
isEncryptedValue
|
|
25
|
+
} from "./chunk-Q35YIDBV.js";
|
|
26
|
+
import {
|
|
27
|
+
ToolError
|
|
28
|
+
} from "./chunk-G3T47CFV.js";
|
|
29
|
+
|
|
30
|
+
// src/cite/core/page.ts
|
|
31
|
+
import { extname } from "node:path";
|
|
32
|
+
import * as Ajv2020Ns from "ajv/dist/2020.js";
|
|
33
|
+
|
|
34
|
+
// src/cite/errors.ts
|
|
35
|
+
var CiteError = class extends ToolError {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = "CiteError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function asCiteError(call) {
|
|
42
|
+
try {
|
|
43
|
+
return call();
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error instanceof LineRangeError) throw new CiteError(error.message);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/cite/core/hash.ts
|
|
51
|
+
function sliceLines2(lines, range, label) {
|
|
52
|
+
return asCiteError(() => sliceLines(lines, range, label));
|
|
53
|
+
}
|
|
54
|
+
function hashRange2(text, range, key) {
|
|
55
|
+
return asCiteError(() => hashRange(text, range, key));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/cite/core/range.ts
|
|
59
|
+
var FILE_PATTERN = /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\.\.?(?:\/|$))[^/\\:\r\n\t]+)(?:\/(?:(?!\.\.?(?:\/|$))[^/\\:\r\n\t]+))*)$/;
|
|
60
|
+
var SRC_PATTERN = /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\.\.?(?:\/|:|$))[^/\\:\r\n\t]+)(?:\/(?:(?!\.\.?(?:\/|:|$))[^/\\:\r\n\t]+))*)(?::[1-9][0-9]*(?:-[1-9][0-9]*)?)?$/;
|
|
61
|
+
function parseSrc(src) {
|
|
62
|
+
if (!SRC_PATTERN.test(src)) {
|
|
63
|
+
throw new CiteError(
|
|
64
|
+
`Invalid src "${src}": expected path, path:L, path:L1-L2, or an encrypted source (~ and at least 82 base64url characters) with the same line forms; the path is repo-root-relative, posix, and free of . and .. segments.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const colon = src.indexOf(":");
|
|
68
|
+
const path = colon === -1 ? src : src.slice(0, colon);
|
|
69
|
+
const range = { path, encrypted: isEncryptedValue(path) };
|
|
70
|
+
if (colon === -1) return range;
|
|
71
|
+
const [startText, endText] = src.slice(colon + 1).split("-");
|
|
72
|
+
const start = Number(startText);
|
|
73
|
+
const end = endText === void 0 ? start : Number(endText);
|
|
74
|
+
if (end < start) {
|
|
75
|
+
throw new CiteError(`Invalid range "${src}": end line ${end} is before start line ${start}.`);
|
|
76
|
+
}
|
|
77
|
+
range.start = start;
|
|
78
|
+
range.end = end;
|
|
79
|
+
return range;
|
|
80
|
+
}
|
|
81
|
+
function tooWide(lines) {
|
|
82
|
+
const width = lines.end - lines.start + 1;
|
|
83
|
+
return width > MAX_RANGE_LINES ? `spans ${String(width)} lines, more than ${String(MAX_RANGE_LINES)}` : void 0;
|
|
84
|
+
}
|
|
85
|
+
function formatSrc(range) {
|
|
86
|
+
const { path, start, end } = range;
|
|
87
|
+
if (start === void 0) return path;
|
|
88
|
+
if (end === void 0 || end === start) return `${path}:${start}`;
|
|
89
|
+
return `${path}:${start}-${end}`;
|
|
90
|
+
}
|
|
91
|
+
function sourceRange(source) {
|
|
92
|
+
const range = { path: source.file, encrypted: isEncryptedValue(source.file) };
|
|
93
|
+
if (source.lines === void 0) return range;
|
|
94
|
+
const lines = parseLines(source.lines);
|
|
95
|
+
if (lines !== void 0) {
|
|
96
|
+
range.start = lines.start;
|
|
97
|
+
range.end = lines.end;
|
|
98
|
+
}
|
|
99
|
+
return range;
|
|
100
|
+
}
|
|
101
|
+
function spellSource(source) {
|
|
102
|
+
return formatSrc(sourceRange(source));
|
|
103
|
+
}
|
|
104
|
+
function rangeLines(range) {
|
|
105
|
+
if (range.start === void 0) return void 0;
|
|
106
|
+
return lineSpec({ start: range.start, end: range.end ?? range.start });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/cite/types.ts
|
|
110
|
+
var CITE_RULES = [
|
|
111
|
+
"source-moved",
|
|
112
|
+
"source-moved-ambiguous",
|
|
113
|
+
"source-changed",
|
|
114
|
+
"source-never-true",
|
|
115
|
+
"source-missing",
|
|
116
|
+
"claim-moved",
|
|
117
|
+
"claim-moved-ambiguous",
|
|
118
|
+
"claim-reanchored",
|
|
119
|
+
"claim-changed",
|
|
120
|
+
"marker-orphan",
|
|
121
|
+
"marker-invalid",
|
|
122
|
+
"marker-repeated",
|
|
123
|
+
"marker-misplaced",
|
|
124
|
+
"anchor-invalid",
|
|
125
|
+
"entry-invalid",
|
|
126
|
+
"quote-drift"
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
// src/cite/core/severity.ts
|
|
130
|
+
var DEFAULT_SEVERITY = {
|
|
131
|
+
"source-moved": "warning",
|
|
132
|
+
"source-moved-ambiguous": "error",
|
|
133
|
+
"source-changed": "error",
|
|
134
|
+
"source-never-true": "error",
|
|
135
|
+
"source-missing": "error",
|
|
136
|
+
"claim-moved": "notice",
|
|
137
|
+
"claim-moved-ambiguous": "warning",
|
|
138
|
+
"claim-reanchored": "notice",
|
|
139
|
+
"claim-changed": "warning",
|
|
140
|
+
"marker-orphan": "error",
|
|
141
|
+
"marker-invalid": "error",
|
|
142
|
+
"marker-repeated": "warning",
|
|
143
|
+
"marker-misplaced": "warning",
|
|
144
|
+
"anchor-invalid": "error",
|
|
145
|
+
"entry-invalid": "error",
|
|
146
|
+
"quote-drift": "error"
|
|
147
|
+
};
|
|
148
|
+
var RULE_ID_PREFIX = "manni:cite";
|
|
149
|
+
function ruleId(rule) {
|
|
150
|
+
return `${RULE_ID_PREFIX}/${rule}`;
|
|
151
|
+
}
|
|
152
|
+
function isCiteRule(value) {
|
|
153
|
+
return CITE_RULES.includes(value);
|
|
154
|
+
}
|
|
155
|
+
function resolveSeverity(overrides) {
|
|
156
|
+
return { ...DEFAULT_SEVERITY, ...overrides ?? {} };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/cite/core/statements.ts
|
|
160
|
+
var HTML_COMMENT = { open: "<!--", close: "-->" };
|
|
161
|
+
var JSX_COMMENT = { open: "{/*", close: "*/}" };
|
|
162
|
+
var LINK_REFERENCE = { open: "[comment]: # (", close: ")" };
|
|
163
|
+
var MARKDOWN_FORMS = [HTML_COMMENT, JSX_COMMENT, LINK_REFERENCE];
|
|
164
|
+
var MDX_FORMS = [JSX_COMMENT, HTML_COMMENT, LINK_REFERENCE];
|
|
165
|
+
var COMMENT_FORMS = [{ open: "<!--", close: "-->" }];
|
|
166
|
+
var ASCIIDOC_FORMS = [{ open: "// (", close: ")" }];
|
|
167
|
+
var RST_FORMS = [{ open: ".. (", close: ")" }];
|
|
168
|
+
var ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
169
|
+
var ANY_FENCE = /^(?:[ \t]*(?:`{3,}|~{3,})|-{4,})/;
|
|
170
|
+
var MARKDOWN_FENCE = /^(`{3,}|~{3,})/;
|
|
171
|
+
var ASCIIDOC_FENCE = /^(-{4,})/;
|
|
172
|
+
function statementForms(format) {
|
|
173
|
+
switch (format) {
|
|
174
|
+
case "markdown":
|
|
175
|
+
return MARKDOWN_FORMS;
|
|
176
|
+
case "mdx":
|
|
177
|
+
return MDX_FORMS;
|
|
178
|
+
case "html":
|
|
179
|
+
case "xml":
|
|
180
|
+
return COMMENT_FORMS;
|
|
181
|
+
case "asciidoc":
|
|
182
|
+
return ASCIIDOC_FORMS;
|
|
183
|
+
case "rst":
|
|
184
|
+
return RST_FORMS;
|
|
185
|
+
default:
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function fenceFor(format) {
|
|
190
|
+
switch (format) {
|
|
191
|
+
case "markdown":
|
|
192
|
+
case "mdx":
|
|
193
|
+
return MARKDOWN_FENCE;
|
|
194
|
+
case "asciidoc":
|
|
195
|
+
return ASCIIDOC_FENCE;
|
|
196
|
+
default:
|
|
197
|
+
return void 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function lineEnd(content, pos) {
|
|
201
|
+
const nl = content.indexOf("\n", pos);
|
|
202
|
+
return nl === -1 ? content.length : nl;
|
|
203
|
+
}
|
|
204
|
+
function lineText(content, pos, end) {
|
|
205
|
+
const text = content.slice(pos, end);
|
|
206
|
+
return text.endsWith("\r") ? text.slice(0, -1) : text;
|
|
207
|
+
}
|
|
208
|
+
function beforeCr(content, end) {
|
|
209
|
+
return end > 0 && content.charCodeAt(end - 1) === 13 ? end - 1 : end;
|
|
210
|
+
}
|
|
211
|
+
function nextLineStart(content, offset) {
|
|
212
|
+
if (offset === 0 || content.charCodeAt(offset - 1) === 10) return offset;
|
|
213
|
+
return lineEnd(content, offset) + 1;
|
|
214
|
+
}
|
|
215
|
+
var MAX_IDS_PER_MARKER = 25;
|
|
216
|
+
function payloadOf(payload) {
|
|
217
|
+
if (payload === "") return { kind: "bad", reason: "empty payload" };
|
|
218
|
+
if (/[\r\n]/.test(payload)) {
|
|
219
|
+
return { kind: "bad", reason: "a marker is one line; write two markers" };
|
|
220
|
+
}
|
|
221
|
+
const [head, ...rest] = payload.split(" ").filter((word) => word !== "");
|
|
222
|
+
if (head === void 0) return { kind: "bad", reason: "empty payload" };
|
|
223
|
+
const words = [head, ...rest];
|
|
224
|
+
if (words.some((word) => word.startsWith("{"))) {
|
|
225
|
+
return { kind: "bad", reason: "a JSON payload", json: true };
|
|
226
|
+
}
|
|
227
|
+
if (words.length > MAX_IDS_PER_MARKER) {
|
|
228
|
+
return {
|
|
229
|
+
kind: "bad",
|
|
230
|
+
reason: `more than ${String(MAX_IDS_PER_MARKER)} ids in one marker (${String(words.length)}); write a second marker`
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const bad = words.find((word) => !ID.test(word));
|
|
234
|
+
if (bad !== void 0) return { kind: "bad", reason: `"${bad}" is not an id` };
|
|
235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
236
|
+
for (const word of words) {
|
|
237
|
+
if (seen.has(word)) {
|
|
238
|
+
return { kind: "bad", reason: `"${word}" is named twice in one marker` };
|
|
239
|
+
}
|
|
240
|
+
seen.add(word);
|
|
241
|
+
}
|
|
242
|
+
return { kind: "ref", ids: words };
|
|
243
|
+
}
|
|
244
|
+
function isCite(inner) {
|
|
245
|
+
return inner === "cite" || inner.startsWith("cite") && /\s/.test(inner.charAt(4));
|
|
246
|
+
}
|
|
247
|
+
function isMarkerLine(line, format) {
|
|
248
|
+
const text = line.trim();
|
|
249
|
+
return statementForms(format).some((form) => {
|
|
250
|
+
if (text.length < form.open.length + form.close.length) return false;
|
|
251
|
+
if (!text.startsWith(form.open)) return false;
|
|
252
|
+
const closeAt = text.indexOf(form.close, form.open.length);
|
|
253
|
+
if (closeAt !== text.length - form.close.length) return false;
|
|
254
|
+
return isCite(text.slice(form.open.length, closeAt).trim());
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
var ATX_HEADING = /^[ \t]*#{1,6}([ \t]|$)/;
|
|
258
|
+
var ASCIIDOC_TITLE = /^={1,6}[ \t]/;
|
|
259
|
+
var ADORNMENT = /^[ \t]*([-=~^"'*+#_:<>])(?:[ \t]*\1){2,}[ \t]*$/;
|
|
260
|
+
var TAG_LINE = /^[ \t]*<\/?[A-Za-z][^<>]*>[ \t]*$/;
|
|
261
|
+
var TABLE_ROW = /^[ \t]*\|/;
|
|
262
|
+
function isTableRow(line) {
|
|
263
|
+
return TABLE_ROW.test(line);
|
|
264
|
+
}
|
|
265
|
+
var TABLE_RULE = /^(?=[^|]*\|)[ \t]*\|?(?:[ \t]*:?-+:?[ \t]*\|)*[ \t]*:?-+:?[ \t]*\|?[ \t]*$/;
|
|
266
|
+
function isTableSeparator(line) {
|
|
267
|
+
return TABLE_RULE.test(line);
|
|
268
|
+
}
|
|
269
|
+
function isBoundLine(line, format) {
|
|
270
|
+
if (ADORNMENT.test(line)) return true;
|
|
271
|
+
switch (format) {
|
|
272
|
+
case "markdown":
|
|
273
|
+
case "mdx":
|
|
274
|
+
return ATX_HEADING.test(line) || TAG_LINE.test(line);
|
|
275
|
+
case "html":
|
|
276
|
+
case "xml":
|
|
277
|
+
return TAG_LINE.test(line);
|
|
278
|
+
case "asciidoc":
|
|
279
|
+
return ASCIIDOC_TITLE.test(line);
|
|
280
|
+
default:
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function parseStatements(body, format, from = { offset: 0, line: 1 }) {
|
|
285
|
+
const out = [];
|
|
286
|
+
const fileLine = (bodyOffset) => from.line + lineAt(body, bodyOffset) - 1;
|
|
287
|
+
const code = codeRegions(body, format);
|
|
288
|
+
for (const form of statementForms(format)) {
|
|
289
|
+
let cursor = 0;
|
|
290
|
+
for (; ; ) {
|
|
291
|
+
const at = body.indexOf(form.open, cursor);
|
|
292
|
+
if (at === -1) break;
|
|
293
|
+
const codeEnd = codeEndAt(code, at);
|
|
294
|
+
if (codeEnd !== void 0) {
|
|
295
|
+
cursor = codeEnd;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const closeAt = body.indexOf(form.close, at + form.open.length);
|
|
299
|
+
if (closeAt === -1) break;
|
|
300
|
+
const end = closeAt + form.close.length;
|
|
301
|
+
cursor = end;
|
|
302
|
+
const inner = body.slice(at + form.open.length, closeAt).trim();
|
|
303
|
+
if (!isCite(inner)) continue;
|
|
304
|
+
const payload = inner.slice(4).trim();
|
|
305
|
+
const unit = anchoredLines(body, end, format);
|
|
306
|
+
const anchorLine = unit === void 0 ? void 0 : from.line + unit.start - 1;
|
|
307
|
+
const statement = {
|
|
308
|
+
line: fileLine(at),
|
|
309
|
+
payload: payloadOf(payload),
|
|
310
|
+
raw: inner,
|
|
311
|
+
start: from.offset + at,
|
|
312
|
+
end: from.offset + end
|
|
313
|
+
};
|
|
314
|
+
if (anchorLine !== void 0) statement.anchorLine = anchorLine;
|
|
315
|
+
out.push(statement);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return out.sort((a, b) => a.start - b.start);
|
|
319
|
+
}
|
|
320
|
+
function detectEol(text) {
|
|
321
|
+
const nl = text.indexOf("\n");
|
|
322
|
+
return nl > 0 && text.charCodeAt(nl - 1) === 13 ? "\r\n" : "\n";
|
|
323
|
+
}
|
|
324
|
+
function paragraphAfter(content, offset, format) {
|
|
325
|
+
const marker = (text) => format !== void 0 && isMarkerLine(text, format);
|
|
326
|
+
const bound = (text) => format !== void 0 && isBoundLine(text, format);
|
|
327
|
+
let pos = offset;
|
|
328
|
+
const firstEnd = lineEnd(content, pos);
|
|
329
|
+
if (lineText(content, pos, firstEnd).trim() === "") pos = firstEnd + 1;
|
|
330
|
+
while (pos < content.length) {
|
|
331
|
+
const end = lineEnd(content, pos);
|
|
332
|
+
const text = lineText(content, pos, end);
|
|
333
|
+
if (text.trim() === "" || marker(text)) {
|
|
334
|
+
pos = end + 1;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (ANY_FENCE.test(text)) return void 0;
|
|
338
|
+
const start = pos;
|
|
339
|
+
let last = end;
|
|
340
|
+
let cursor = bound(text) ? content.length : end + 1;
|
|
341
|
+
while (cursor < content.length) {
|
|
342
|
+
const e = lineEnd(content, cursor);
|
|
343
|
+
const t = lineText(content, cursor, e);
|
|
344
|
+
if (t.trim() === "" || ANY_FENCE.test(t) || marker(t) || bound(t)) break;
|
|
345
|
+
last = e;
|
|
346
|
+
cursor = e + 1;
|
|
347
|
+
}
|
|
348
|
+
return { start, end: beforeCr(content, last), line: lineAt(content, start) };
|
|
349
|
+
}
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
function scanFence(content, offset, fence) {
|
|
353
|
+
let pos = nextLineStart(content, offset);
|
|
354
|
+
while (pos < content.length) {
|
|
355
|
+
const end = lineEnd(content, pos);
|
|
356
|
+
const text = lineText(content, pos, end);
|
|
357
|
+
const opener = fence.exec(text)?.[1];
|
|
358
|
+
if (opener === void 0) {
|
|
359
|
+
pos = end + 1;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const line = lineAt(content, pos);
|
|
363
|
+
const start = Math.min(end + 1, content.length);
|
|
364
|
+
let cursor = start;
|
|
365
|
+
while (cursor < content.length) {
|
|
366
|
+
const e = lineEnd(content, cursor);
|
|
367
|
+
if (lineText(content, cursor, e).startsWith(opener)) {
|
|
368
|
+
return {
|
|
369
|
+
start,
|
|
370
|
+
end: cursor,
|
|
371
|
+
line,
|
|
372
|
+
text: content.slice(start, cursor),
|
|
373
|
+
next: e + 1
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
cursor = e + 1;
|
|
377
|
+
}
|
|
378
|
+
return void 0;
|
|
379
|
+
}
|
|
380
|
+
return void 0;
|
|
381
|
+
}
|
|
382
|
+
function fencedBlockAfter(content, offset, format) {
|
|
383
|
+
const fence = fenceFor(format);
|
|
384
|
+
if (!fence) return void 0;
|
|
385
|
+
const block = scanFence(content, offset, fence);
|
|
386
|
+
if (!block) return void 0;
|
|
387
|
+
const { start, end, line, text } = block;
|
|
388
|
+
return { start, end, line, text };
|
|
389
|
+
}
|
|
390
|
+
function fencedBlockAt(content, offset) {
|
|
391
|
+
const pos = nextLineStart(content, offset);
|
|
392
|
+
if (!ANY_FENCE.test(lineText(content, pos, lineEnd(content, pos)))) {
|
|
393
|
+
return void 0;
|
|
394
|
+
}
|
|
395
|
+
const block = scanFence(content, pos, MARKDOWN_FENCE) ?? scanFence(content, pos, ASCIIDOC_FENCE);
|
|
396
|
+
if (!block || block.line !== lineAt(content, pos)) return void 0;
|
|
397
|
+
const { start, end, line, text } = block;
|
|
398
|
+
return { start, end, line, text };
|
|
399
|
+
}
|
|
400
|
+
function fencedBlocks(content, bodyOffset, format) {
|
|
401
|
+
const fence = fenceFor(format);
|
|
402
|
+
if (!fence) return [];
|
|
403
|
+
const out = [];
|
|
404
|
+
let pos = bodyOffset;
|
|
405
|
+
for (; ; ) {
|
|
406
|
+
const block = scanFence(content, pos, fence);
|
|
407
|
+
if (!block) return out;
|
|
408
|
+
const { start, end, line, text } = block;
|
|
409
|
+
out.push({ start, end, line, text });
|
|
410
|
+
pos = block.next;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function writtenForm(format) {
|
|
414
|
+
const form = statementForms(format)[0];
|
|
415
|
+
if (!form) {
|
|
416
|
+
throw new CiteError(`No marker syntax for format "${format}".`);
|
|
417
|
+
}
|
|
418
|
+
return form;
|
|
419
|
+
}
|
|
420
|
+
function formatStatement(format, payload) {
|
|
421
|
+
const form = writtenForm(format);
|
|
422
|
+
const pad = form.open.endsWith("(") ? "" : " ";
|
|
423
|
+
return `${form.open}${pad}cite ${payload.ids.join(" ")}${pad}${form.close}`;
|
|
424
|
+
}
|
|
425
|
+
function respellEdit(content, statement, ids) {
|
|
426
|
+
const text = content.slice(statement.start, statement.end);
|
|
427
|
+
const at = text.indexOf(statement.raw);
|
|
428
|
+
if (at === -1) return void 0;
|
|
429
|
+
return {
|
|
430
|
+
start: statement.start + at,
|
|
431
|
+
end: statement.start + at + statement.raw.length,
|
|
432
|
+
text: `cite ${ids.join(" ")}`
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
function respellStatement(content, statement, ids) {
|
|
436
|
+
const edit = respellEdit(content, statement, ids);
|
|
437
|
+
if (edit === void 0) return content;
|
|
438
|
+
return content.slice(0, edit.start) + edit.text + content.slice(edit.end);
|
|
439
|
+
}
|
|
440
|
+
function nextTextLine(text, offset, format) {
|
|
441
|
+
let pos = nextLineStart(text, offset);
|
|
442
|
+
while (pos < text.length) {
|
|
443
|
+
const end = lineEnd(text, pos);
|
|
444
|
+
const line = lineText(text, pos, end);
|
|
445
|
+
if (line.trim() !== "" && !isMarkerLine(line, format)) return lineAt(text, pos);
|
|
446
|
+
pos = end + 1;
|
|
447
|
+
}
|
|
448
|
+
return void 0;
|
|
449
|
+
}
|
|
450
|
+
function fenceSpanAt(text, line, format) {
|
|
451
|
+
const fence = fenceFor(format);
|
|
452
|
+
if (!fence) return void 0;
|
|
453
|
+
const block = scanFence(text, offsetOfLine(text, line), fence);
|
|
454
|
+
if (!block || block.line !== line) return void 0;
|
|
455
|
+
return { start: line, end: lineAt(text, block.end) };
|
|
456
|
+
}
|
|
457
|
+
function fenceAround(text, bodyOffset, line, format) {
|
|
458
|
+
const block = fencedBlocks(text, bodyOffset, format).find(
|
|
459
|
+
(b) => line > b.line && line <= lineAt(text, b.end)
|
|
460
|
+
);
|
|
461
|
+
return block === void 0 ? void 0 : { start: block.line, end: lineAt(text, block.end) };
|
|
462
|
+
}
|
|
463
|
+
function insideFence(text, bodyOffset, line, format) {
|
|
464
|
+
return fenceAround(text, bodyOffset, line, format) !== void 0;
|
|
465
|
+
}
|
|
466
|
+
function unitHolding(text, line, format, body) {
|
|
467
|
+
const textOf = (n) => lineText(text, offsetOfLine(text, n), lineEnd(text, offsetOfLine(text, n)));
|
|
468
|
+
const own = textOf(line);
|
|
469
|
+
if (own.trim() === "" || isMarkerLine(own, format)) return void 0;
|
|
470
|
+
const block = fencedBlocks(text, body.offset, format).find(
|
|
471
|
+
(b) => line >= b.line && line <= lineAt(text, b.end)
|
|
472
|
+
);
|
|
473
|
+
if (block !== void 0) {
|
|
474
|
+
return { start: block.line, end: lineAt(text, block.end), kind: "block" };
|
|
475
|
+
}
|
|
476
|
+
if (ANY_FENCE.test(own)) return void 0;
|
|
477
|
+
let start = line;
|
|
478
|
+
while (start - 1 >= body.line && !isBoundLine(own, format)) {
|
|
479
|
+
const above = textOf(start - 1);
|
|
480
|
+
if (above.trim() === "" || ANY_FENCE.test(above) || isMarkerLine(above, format) || isBoundLine(above, format)) {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
start--;
|
|
484
|
+
}
|
|
485
|
+
const paragraph = paragraphAfter(text, offsetOfLine(text, start), format);
|
|
486
|
+
if (paragraph?.line !== start) return void 0;
|
|
487
|
+
return { start, end: lineAt(text, paragraph.end), kind: "paragraph" };
|
|
488
|
+
}
|
|
489
|
+
var LIST_ITEM = /^([ \t]*)([-*+]|\d{1,9}[.)])([ \t]+|$)/;
|
|
490
|
+
var THEMATIC_BREAK = /^[ \t]*([-*_])(?:[ \t]*\1){2,}[ \t]*$/;
|
|
491
|
+
function textOfLine(text, n) {
|
|
492
|
+
const pos = offsetOfLine(text, n);
|
|
493
|
+
return lineText(text, pos, lineEnd(text, pos));
|
|
494
|
+
}
|
|
495
|
+
function indentOf(line) {
|
|
496
|
+
return /^[ \t]*/.exec(line)?.[0] ?? "";
|
|
497
|
+
}
|
|
498
|
+
function columnOf(indent) {
|
|
499
|
+
let column = 0;
|
|
500
|
+
for (const ch of indent) column = ch === " " ? column + 4 - column % 4 : column + 1;
|
|
501
|
+
return column;
|
|
502
|
+
}
|
|
503
|
+
function listItemOf(line) {
|
|
504
|
+
if (THEMATIC_BREAK.test(line)) return void 0;
|
|
505
|
+
const match = LIST_ITEM.exec(line);
|
|
506
|
+
if (match === null) return void 0;
|
|
507
|
+
const [, lead = "", bullet = "", gap = ""] = match;
|
|
508
|
+
return { lead, bullet, gap };
|
|
509
|
+
}
|
|
510
|
+
function continuesList(text, line, format, bodyLine, column) {
|
|
511
|
+
let n = line - 1;
|
|
512
|
+
while (n >= bodyLine) {
|
|
513
|
+
const above = textOfLine(text, n);
|
|
514
|
+
if (above.trim() !== "" && !isMarkerLine(above, format)) break;
|
|
515
|
+
n--;
|
|
516
|
+
}
|
|
517
|
+
if (n < bodyLine) return false;
|
|
518
|
+
if (columnOf(indentOf(textOfLine(text, n))) > column) return true;
|
|
519
|
+
for (; n >= bodyLine; n--) {
|
|
520
|
+
const above = textOfLine(text, n);
|
|
521
|
+
if (above.trim() === "" || ANY_FENCE.test(above) || isMarkerLine(above, format) || isBoundLine(above, format)) {
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
const item = listItemOf(above);
|
|
525
|
+
if (item !== void 0 && columnOf(item.lead) === column) return true;
|
|
526
|
+
}
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
function markerIndent(text, line, format, bodyLine) {
|
|
530
|
+
if (format === "asciidoc") return "";
|
|
531
|
+
const own = textOfLine(text, line);
|
|
532
|
+
const indent = indentOf(own);
|
|
533
|
+
if (format !== "markdown" && format !== "mdx") return indent;
|
|
534
|
+
const item = listItemOf(own);
|
|
535
|
+
if (item === void 0 || !continuesList(text, line, format, bodyLine, columnOf(item.lead))) {
|
|
536
|
+
return indent;
|
|
537
|
+
}
|
|
538
|
+
const gap = item.gap === "" || columnOf(item.gap) > 4 ? " " : item.gap;
|
|
539
|
+
return item.lead + " ".repeat(item.bullet.length) + gap;
|
|
540
|
+
}
|
|
541
|
+
function anchoredLines(text, after, format, quote = false) {
|
|
542
|
+
if (quote) {
|
|
543
|
+
const block = fencedBlockAfter(text, after, format);
|
|
544
|
+
return block === void 0 ? void 0 : { start: block.line, end: lineAt(text, block.end) };
|
|
545
|
+
}
|
|
546
|
+
const restEnd = lineEnd(text, after);
|
|
547
|
+
if (text.slice(after, restEnd).trim() !== "") {
|
|
548
|
+
const line2 = lineAt(text, after);
|
|
549
|
+
return { start: line2, end: line2 };
|
|
550
|
+
}
|
|
551
|
+
const paragraph = paragraphAfter(text, after, format);
|
|
552
|
+
if (paragraph !== void 0) {
|
|
553
|
+
return { start: paragraph.line, end: lineAt(text, paragraph.end) };
|
|
554
|
+
}
|
|
555
|
+
const line = nextTextLine(text, after, format);
|
|
556
|
+
return line === void 0 ? void 0 : fenceSpanAt(text, line, format);
|
|
557
|
+
}
|
|
558
|
+
var LINE_INDEX_SLOTS = 4;
|
|
559
|
+
var lineIndexes = [];
|
|
560
|
+
function newlinesOf(content) {
|
|
561
|
+
const hit = lineIndexes.findIndex((entry) => entry.text === content);
|
|
562
|
+
const found = hit === -1 ? void 0 : lineIndexes[hit];
|
|
563
|
+
if (found !== void 0) return found.newlines;
|
|
564
|
+
const newlines = [];
|
|
565
|
+
for (let at = content.indexOf("\n"); at !== -1; at = content.indexOf("\n", at + 1)) newlines.push(at);
|
|
566
|
+
lineIndexes.unshift({ text: content, newlines });
|
|
567
|
+
lineIndexes.length = Math.min(lineIndexes.length, LINE_INDEX_SLOTS);
|
|
568
|
+
return newlines;
|
|
569
|
+
}
|
|
570
|
+
function lineAt(content, offset) {
|
|
571
|
+
const stop = Math.min(offset, content.length);
|
|
572
|
+
const newlines = newlinesOf(content);
|
|
573
|
+
let low = 0;
|
|
574
|
+
let high = newlines.length;
|
|
575
|
+
while (low < high) {
|
|
576
|
+
const mid = low + high >>> 1;
|
|
577
|
+
if ((newlines[mid] ?? Infinity) < stop) low = mid + 1;
|
|
578
|
+
else high = mid;
|
|
579
|
+
}
|
|
580
|
+
return low + 1;
|
|
581
|
+
}
|
|
582
|
+
function offsetOfLine(content, line) {
|
|
583
|
+
if (line <= 1) return 0;
|
|
584
|
+
const before = newlinesOf(content)[line - 2];
|
|
585
|
+
return before === void 0 ? content.length : before + 1;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// src/cite/core/page.ts
|
|
589
|
+
var MAX_MARKERS_PER_PAGE = 500;
|
|
590
|
+
var ELEMENT_BACKED = /* @__PURE__ */ new Set(["html", "xml"]);
|
|
591
|
+
var FENCE_ONLY = /* @__PURE__ */ new Set(["markdown", "mdx"]);
|
|
592
|
+
var MARKER_JSON = "A marker names an entry by id. Write the entry in frontmatter or the sidecar.";
|
|
593
|
+
function ownedMessage(owner) {
|
|
594
|
+
return `"citations" is owned by manifest ${owner.file} (collection ${owner.collection}); remove it from the document`;
|
|
595
|
+
}
|
|
596
|
+
var Ajv2020 = Ajv2020Ns.default;
|
|
597
|
+
var entryValidator;
|
|
598
|
+
function compileEntryValidator() {
|
|
599
|
+
if (entryValidator) return entryValidator;
|
|
600
|
+
const ajv = new Ajv2020({ allErrors: false, strict: false });
|
|
601
|
+
ajv.addSchema(__default);
|
|
602
|
+
entryValidator = ajv.compile({
|
|
603
|
+
$ref: `${__default.$id}#/$defs/citationEntry`
|
|
604
|
+
});
|
|
605
|
+
return entryValidator;
|
|
606
|
+
}
|
|
607
|
+
function validateEntry(entry) {
|
|
608
|
+
const validate = compileEntryValidator();
|
|
609
|
+
if (validate(entry)) return void 0;
|
|
610
|
+
const first = validate.errors?.[0];
|
|
611
|
+
if (!first) return "invalid entry";
|
|
612
|
+
return `${first.instancePath} ${first.message ?? "is invalid"}`.trim();
|
|
613
|
+
}
|
|
614
|
+
function isRecord(value) {
|
|
615
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
616
|
+
}
|
|
617
|
+
function toCitation(entry) {
|
|
618
|
+
const source = isRecord(entry.source) ? entry.source : {};
|
|
619
|
+
const citation = {
|
|
620
|
+
source: {
|
|
621
|
+
file: String(source.file),
|
|
622
|
+
integrity: String(source.integrity)
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
if (typeof source.lines === "number" || typeof source.lines === "string") {
|
|
626
|
+
citation.source.lines = source.lines;
|
|
627
|
+
}
|
|
628
|
+
if (typeof source["commit-sha"] === "string") {
|
|
629
|
+
citation.source["commit-sha"] = source["commit-sha"];
|
|
630
|
+
}
|
|
631
|
+
if (typeof entry.id === "string") citation.id = entry.id;
|
|
632
|
+
if (isRecord(entry.claim)) {
|
|
633
|
+
const claim = entry.claim;
|
|
634
|
+
citation.claim = { integrity: String(claim.integrity) };
|
|
635
|
+
if (typeof claim.lines === "number" || typeof claim.lines === "string") {
|
|
636
|
+
citation.claim.lines = claim.lines;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (typeof entry.quote === "boolean") citation.quote = entry.quote;
|
|
640
|
+
return citation;
|
|
641
|
+
}
|
|
642
|
+
function finding(rule, message, extra) {
|
|
643
|
+
const level = DEFAULT_SEVERITY[rule];
|
|
644
|
+
const out = {
|
|
645
|
+
rule,
|
|
646
|
+
ruleId: ruleId(rule),
|
|
647
|
+
// The caller re-applies the configured severity table; no page-side rule
|
|
648
|
+
// defaults to `off`, so there is nothing to collapse.
|
|
649
|
+
severity: level === "off" ? "error" : level,
|
|
650
|
+
message
|
|
651
|
+
};
|
|
652
|
+
if (extra.line !== void 0) out.line = extra.line;
|
|
653
|
+
if (extra.file !== void 0) out.file = extra.file;
|
|
654
|
+
if (extra.id !== void 0) out.id = extra.id;
|
|
655
|
+
if (extra.src !== void 0) out.src = extra.src;
|
|
656
|
+
if (extra.index !== void 0) out.index = extra.index;
|
|
657
|
+
return out;
|
|
658
|
+
}
|
|
659
|
+
function named(id, text) {
|
|
660
|
+
return id === void 0 ? text : `${id}: ${text}`;
|
|
661
|
+
}
|
|
662
|
+
function subjectOf(entry) {
|
|
663
|
+
const out = {};
|
|
664
|
+
if (!isRecord(entry)) return out;
|
|
665
|
+
if (typeof entry.id === "string") out.id = entry.id;
|
|
666
|
+
if (isRecord(entry.source) && typeof entry.source.file === "string") out.src = entry.source.file;
|
|
667
|
+
return out;
|
|
668
|
+
}
|
|
669
|
+
function pickExtractor(file, format) {
|
|
670
|
+
if (format !== void 0) {
|
|
671
|
+
const forced = extractorByName(format);
|
|
672
|
+
if (forced === void 0) {
|
|
673
|
+
throw new CiteError(
|
|
674
|
+
`Unknown format "${format}". Supported extensions: ${supportedExtensions().join(", ")}.`
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
return forced;
|
|
678
|
+
}
|
|
679
|
+
const extension = extname(file);
|
|
680
|
+
const byExt = extractorForExtension(extension);
|
|
681
|
+
if (!byExt) {
|
|
682
|
+
throw new CiteError(
|
|
683
|
+
`Unsupported file type "${extension}" for "${file}". Supported: ${supportedExtensions().join(", ")}. Use --as to override.`
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
return byExt;
|
|
687
|
+
}
|
|
688
|
+
function byLine(a, b) {
|
|
689
|
+
return (a.line ?? Number.MAX_SAFE_INTEGER) - (b.line ?? Number.MAX_SAFE_INTEGER);
|
|
690
|
+
}
|
|
691
|
+
function bodyLineOf(content, bodyOffset) {
|
|
692
|
+
if (bodyOffset <= 0) return 1;
|
|
693
|
+
const line = lineAt(content, bodyOffset);
|
|
694
|
+
return content.charCodeAt(bodyOffset - 1) === 10 ? line : line + 1;
|
|
695
|
+
}
|
|
696
|
+
function citationInputs(file, extracted, injected) {
|
|
697
|
+
if (injected !== void 0) return [...injected];
|
|
698
|
+
const raw = extracted.data.citations;
|
|
699
|
+
const list = Array.isArray(raw) ? raw : [];
|
|
700
|
+
return list.map((entry, index) => {
|
|
701
|
+
const origin = { kind: "frontmatter", file };
|
|
702
|
+
const line = extracted.lineFor(`/citations/${String(index)}`);
|
|
703
|
+
if (line !== void 0) origin.line = line;
|
|
704
|
+
return { entry, origin };
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
function readPage(file, content, opts) {
|
|
708
|
+
const extractor = pickExtractor(file, opts?.format);
|
|
709
|
+
const format = extractor.name;
|
|
710
|
+
if (FENCE_ONLY.has(format) && hasFrontmatterFence(content) && locateFrontmatter(content) === null) {
|
|
711
|
+
throw new CiteError(
|
|
712
|
+
`${file}: Unterminated front matter fence: the opening fence has no matching close, so the page's citations cannot be read. Add a closing fence.`
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
const extracted = extractor.extract(content, file);
|
|
716
|
+
const data = extracted.data;
|
|
717
|
+
const bodyOffset = ELEMENT_BACKED.has(format) ? 0 : locateFrontmatter(content)?.closeEnd ?? 0;
|
|
718
|
+
const bodyLine = bodyLineOf(content, bodyOffset);
|
|
719
|
+
const findings = [];
|
|
720
|
+
const citations = [];
|
|
721
|
+
const byId = /* @__PURE__ */ new Map();
|
|
722
|
+
const ids = /* @__PURE__ */ new Set();
|
|
723
|
+
const markedAt = /* @__PURE__ */ new Map();
|
|
724
|
+
for (const key of Object.keys(data)) {
|
|
725
|
+
if (!key.startsWith("citation-")) continue;
|
|
726
|
+
findings.push(
|
|
727
|
+
finding(
|
|
728
|
+
"entry-invalid",
|
|
729
|
+
`"${key}" is not a citations key; the page root reserves the citation- prefix`,
|
|
730
|
+
{ line: extracted.lineFor(`/${key}`) }
|
|
731
|
+
)
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
const injected = opts?.citations;
|
|
735
|
+
const rawCitations = data.citations;
|
|
736
|
+
if (opts?.owned !== void 0 && rawCitations !== void 0) {
|
|
737
|
+
findings.push(
|
|
738
|
+
finding("entry-invalid", ownedMessage(opts.owned), {
|
|
739
|
+
line: extracted.lineFor("/citations")
|
|
740
|
+
})
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
if (injected === void 0 && rawCitations !== void 0 && !Array.isArray(rawCitations)) {
|
|
744
|
+
findings.push(
|
|
745
|
+
finding("entry-invalid", "citations must be an array of entries", {
|
|
746
|
+
line: extracted.lineFor("/citations")
|
|
747
|
+
})
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
const inputs = citationInputs(file, extracted, injected);
|
|
751
|
+
inputs.forEach((input, index) => {
|
|
752
|
+
const origin = { ...input.origin, index };
|
|
753
|
+
const where = { index };
|
|
754
|
+
if (origin.line !== void 0) where.line = origin.line;
|
|
755
|
+
if (origin.kind === "manifest") where.file = origin.file;
|
|
756
|
+
const entry = input.entry;
|
|
757
|
+
const error = validateEntry(entry);
|
|
758
|
+
if (error !== void 0 || !isRecord(entry)) {
|
|
759
|
+
findings.push(finding("entry-invalid", error ?? "must be object", { ...where, ...subjectOf(entry) }));
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
const citation = toCitation(entry);
|
|
763
|
+
const subject = { ...where, src: spellSource(citation.source) };
|
|
764
|
+
if (citation.id !== void 0) subject.id = citation.id;
|
|
765
|
+
const bad = ["claim", "source"].find((end) => {
|
|
766
|
+
const lines = end === "claim" ? citation.claim?.lines : citation.source.lines;
|
|
767
|
+
return lines !== void 0 && parseLines(lines) === void 0;
|
|
768
|
+
});
|
|
769
|
+
if (bad !== void 0) {
|
|
770
|
+
const lines = bad === "claim" ? citation.claim?.lines : citation.source.lines;
|
|
771
|
+
findings.push(
|
|
772
|
+
finding(
|
|
773
|
+
"entry-invalid",
|
|
774
|
+
named(citation.id, `${bad}.lines "${String(lines)}" ends before it starts`),
|
|
775
|
+
subject
|
|
776
|
+
)
|
|
777
|
+
);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
const wide = ["claim", "source"].map((end) => {
|
|
781
|
+
const lines = end === "claim" ? citation.claim?.lines : citation.source.lines;
|
|
782
|
+
const parsed = lines === void 0 ? void 0 : parseLines(lines);
|
|
783
|
+
const reason = parsed === void 0 ? void 0 : tooWide(parsed);
|
|
784
|
+
return reason === void 0 ? void 0 : `${end}.lines "${String(lines)}" ${reason}`;
|
|
785
|
+
}).find((message) => message !== void 0);
|
|
786
|
+
if (wide !== void 0) {
|
|
787
|
+
findings.push(finding("entry-invalid", named(citation.id, wide), subject));
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
const encrypted = isEncryptedValue(citation.source.file);
|
|
791
|
+
if (encrypted !== isKeyedPin(citation.source.integrity)) {
|
|
792
|
+
findings.push(
|
|
793
|
+
finding(
|
|
794
|
+
"entry-invalid",
|
|
795
|
+
named(
|
|
796
|
+
citation.id,
|
|
797
|
+
encrypted ? "an encrypted source is pinned with hmac-sha256-, not sha256-." : "a plain source is pinned with sha256-, not hmac-sha256-."
|
|
798
|
+
),
|
|
799
|
+
subject
|
|
800
|
+
)
|
|
801
|
+
);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
const page = { citation, origin };
|
|
805
|
+
citations.push(page);
|
|
806
|
+
if (citation.id !== void 0) {
|
|
807
|
+
if (ids.has(citation.id)) {
|
|
808
|
+
findings.push(finding("entry-invalid", `duplicate id "${citation.id}"`, subject));
|
|
809
|
+
} else {
|
|
810
|
+
ids.add(citation.id);
|
|
811
|
+
byId.set(citation.id, page);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
const body = content.slice(bodyOffset);
|
|
816
|
+
const statements = opts?.markers === false ? [] : parseStatements(body, format, { offset: bodyOffset, line: bodyLine });
|
|
817
|
+
if (statements.length > MAX_MARKERS_PER_PAGE) {
|
|
818
|
+
findings.push(
|
|
819
|
+
finding(
|
|
820
|
+
"marker-invalid",
|
|
821
|
+
`more than ${String(MAX_MARKERS_PER_PAGE)} markers on one page (${String(statements.length)}); the rest are not read`,
|
|
822
|
+
{ line: statements[MAX_MARKERS_PER_PAGE]?.line }
|
|
823
|
+
)
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
for (const statement of statements.slice(0, MAX_MARKERS_PER_PAGE)) {
|
|
827
|
+
const { payload } = statement;
|
|
828
|
+
if (payload.kind === "bad") {
|
|
829
|
+
findings.push(
|
|
830
|
+
finding(
|
|
831
|
+
"marker-invalid",
|
|
832
|
+
payload.json === true ? MARKER_JSON : `invalid marker: ${payload.reason}`,
|
|
833
|
+
{ line: statement.line }
|
|
834
|
+
)
|
|
835
|
+
);
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
const anchored = [];
|
|
839
|
+
for (const id of payload.ids) {
|
|
840
|
+
const target = byId.get(id);
|
|
841
|
+
if (target === void 0) {
|
|
842
|
+
findings.push(
|
|
843
|
+
finding("marker-orphan", `no entry has id "${id}"`, {
|
|
844
|
+
line: statement.line,
|
|
845
|
+
id
|
|
846
|
+
})
|
|
847
|
+
);
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
const first = markedAt.get(target);
|
|
851
|
+
if (first !== void 0) {
|
|
852
|
+
findings.push(
|
|
853
|
+
finding(
|
|
854
|
+
"marker-repeated",
|
|
855
|
+
`${id} is named by markers at lines ${String(first)} and ${String(statement.line)}; the first anchors it.`,
|
|
856
|
+
{
|
|
857
|
+
line: statement.line,
|
|
858
|
+
id,
|
|
859
|
+
index: target.origin.index,
|
|
860
|
+
src: spellSource(target.citation.source)
|
|
861
|
+
}
|
|
862
|
+
)
|
|
863
|
+
);
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
markedAt.set(target, statement.line);
|
|
867
|
+
target.marker = statement;
|
|
868
|
+
anchored.push(target);
|
|
869
|
+
}
|
|
870
|
+
const quoted = anchored.find((entry) => entry.citation.quote === true);
|
|
871
|
+
const plain = anchored.find((entry) => entry.citation.quote !== true);
|
|
872
|
+
if (quoted !== void 0 && plain !== void 0) {
|
|
873
|
+
const mixed = {
|
|
874
|
+
line: statement.line,
|
|
875
|
+
index: quoted.origin.index,
|
|
876
|
+
src: spellSource(quoted.citation.source)
|
|
877
|
+
};
|
|
878
|
+
if (quoted.citation.id !== void 0) mixed.id = quoted.citation.id;
|
|
879
|
+
findings.push(
|
|
880
|
+
finding(
|
|
881
|
+
"anchor-invalid",
|
|
882
|
+
named(
|
|
883
|
+
quoted.citation.id,
|
|
884
|
+
"a quote entry shares a marker with a non-quote entry. Give the quote its own marker."
|
|
885
|
+
),
|
|
886
|
+
mixed
|
|
887
|
+
)
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
for (const entry of citations) {
|
|
892
|
+
const { citation, origin, marker } = entry;
|
|
893
|
+
const subject = { index: origin.index, src: spellSource(citation.source) };
|
|
894
|
+
if (citation.id !== void 0) subject.id = citation.id;
|
|
895
|
+
if (origin.line !== void 0) subject.line = origin.line;
|
|
896
|
+
if (origin.kind === "manifest") subject.file = origin.file;
|
|
897
|
+
if (citation.claim?.lines !== void 0 && marker !== void 0) {
|
|
898
|
+
const onPage = { index: origin.index, line: marker.line, src: subject.src };
|
|
899
|
+
if (citation.id !== void 0) onPage.id = citation.id;
|
|
900
|
+
findings.push(
|
|
901
|
+
finding(
|
|
902
|
+
"anchor-invalid",
|
|
903
|
+
`${citation.id ?? "the entry"} has claim lines and a marker. Keep one.`,
|
|
904
|
+
onPage
|
|
905
|
+
)
|
|
906
|
+
);
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
if (citation.quote === true && citation.claim?.lines === void 0 && marker === void 0) {
|
|
910
|
+
findings.push(
|
|
911
|
+
finding("anchor-invalid", named(citation.id, "quote needs a claim or a marker."), subject)
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return {
|
|
916
|
+
file,
|
|
917
|
+
format,
|
|
918
|
+
content,
|
|
919
|
+
bodyOffset,
|
|
920
|
+
bodyLine,
|
|
921
|
+
citations,
|
|
922
|
+
statements,
|
|
923
|
+
findings: findings.sort(byLine)
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
export {
|
|
928
|
+
CiteError,
|
|
929
|
+
asCiteError,
|
|
930
|
+
sliceLines2 as sliceLines,
|
|
931
|
+
hashRange2 as hashRange,
|
|
932
|
+
FILE_PATTERN,
|
|
933
|
+
SRC_PATTERN,
|
|
934
|
+
parseSrc,
|
|
935
|
+
tooWide,
|
|
936
|
+
formatSrc,
|
|
937
|
+
sourceRange,
|
|
938
|
+
spellSource,
|
|
939
|
+
rangeLines,
|
|
940
|
+
CITE_RULES,
|
|
941
|
+
DEFAULT_SEVERITY,
|
|
942
|
+
RULE_ID_PREFIX,
|
|
943
|
+
ruleId,
|
|
944
|
+
isCiteRule,
|
|
945
|
+
resolveSeverity,
|
|
946
|
+
ANY_FENCE,
|
|
947
|
+
statementForms,
|
|
948
|
+
MAX_IDS_PER_MARKER,
|
|
949
|
+
isMarkerLine,
|
|
950
|
+
isTableRow,
|
|
951
|
+
isTableSeparator,
|
|
952
|
+
isBoundLine,
|
|
953
|
+
parseStatements,
|
|
954
|
+
detectEol,
|
|
955
|
+
paragraphAfter,
|
|
956
|
+
fencedBlockAfter,
|
|
957
|
+
fencedBlockAt,
|
|
958
|
+
fencedBlocks,
|
|
959
|
+
formatStatement,
|
|
960
|
+
respellEdit,
|
|
961
|
+
respellStatement,
|
|
962
|
+
fenceSpanAt,
|
|
963
|
+
fenceAround,
|
|
964
|
+
insideFence,
|
|
965
|
+
unitHolding,
|
|
966
|
+
markerIndent,
|
|
967
|
+
anchoredLines,
|
|
968
|
+
lineAt,
|
|
969
|
+
offsetOfLine,
|
|
970
|
+
MAX_MARKERS_PER_PAGE,
|
|
971
|
+
MARKER_JSON,
|
|
972
|
+
ownedMessage,
|
|
973
|
+
validateEntry,
|
|
974
|
+
pickExtractor,
|
|
975
|
+
bodyLineOf,
|
|
976
|
+
citationInputs,
|
|
977
|
+
readPage
|
|
978
|
+
};
|
|
979
|
+
//# sourceMappingURL=chunk-G7NJSREW.js.map
|