@hawkeyexl/manni 2.0.0 → 2.1.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 +4 -4
- package/dist/{chunk-XU2QTJQQ.js → chunk-2DC2GSRH.js} +2079 -312
- package/dist/chunk-2DC2GSRH.js.map +1 -0
- package/dist/{chunk-GGVNTB7W.js → chunk-HNPRXGD7.js} +16 -58
- package/dist/chunk-HNPRXGD7.js.map +1 -0
- package/dist/{chunk-7ZN43F3Y.js → chunk-UTXTVCBV.js} +156 -547
- package/dist/chunk-UTXTVCBV.js.map +1 -0
- package/dist/cli.js +10 -18
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +4 -3
- package/dist/docmeta.js.map +1 -1
- package/dist/index.d.ts +257 -68
- package/dist/index.js +2 -2
- package/package.json +3 -1
- package/dist/chunk-7ZN43F3Y.js.map +0 -1
- package/dist/chunk-GGVNTB7W.js.map +0 -1
- package/dist/chunk-XU2QTJQQ.js.map +0 -1
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
DocmetaError,
|
|
4
4
|
ENCRYPTION_KEY_ENV,
|
|
5
|
-
FILE_SCHEMA_KEY,
|
|
6
|
-
KEYED_PIN_PREFIX,
|
|
7
5
|
LEGACY_CONFIG_NAMES,
|
|
6
|
+
LineRangeError,
|
|
7
|
+
MAX_RANGE_LINES,
|
|
8
8
|
META_CONTEXT,
|
|
9
|
+
MOVE_BUDGET_BYTES,
|
|
10
|
+
MOVE_WINDOW_LINES,
|
|
9
11
|
PATH_JOIN,
|
|
10
12
|
STDIN_LABEL,
|
|
11
13
|
STDIN_TOKEN,
|
|
@@ -15,7 +17,6 @@ import {
|
|
|
15
17
|
classifyRef,
|
|
16
18
|
committedKeyWarning,
|
|
17
19
|
decryptValue,
|
|
18
|
-
deepEqual,
|
|
19
20
|
encryptValue,
|
|
20
21
|
ensureEncryptionKey,
|
|
21
22
|
errorMessage,
|
|
@@ -28,23 +29,29 @@ import {
|
|
|
28
29
|
findConfigFile,
|
|
29
30
|
findFamilyConfigFile,
|
|
30
31
|
findGitRoot,
|
|
32
|
+
findWindows,
|
|
31
33
|
generateEncryptionKey,
|
|
32
34
|
gitignoreOptions,
|
|
33
|
-
|
|
35
|
+
hashLines,
|
|
36
|
+
hashRange,
|
|
34
37
|
isEncryptedValue,
|
|
35
38
|
isErrorSeverity,
|
|
36
39
|
isIgnoredByGit,
|
|
40
|
+
isKeyedPin,
|
|
37
41
|
isMember,
|
|
38
42
|
isValidEncryptionKey,
|
|
39
|
-
|
|
43
|
+
lineSpec,
|
|
40
44
|
loadExternalMetadata,
|
|
41
45
|
locateFrontmatter,
|
|
42
46
|
memberOf,
|
|
43
47
|
mergeExternalMetadata,
|
|
48
|
+
normalizeText,
|
|
44
49
|
orphanEntries,
|
|
45
50
|
orphanError,
|
|
46
51
|
orphanJoins,
|
|
47
52
|
palette,
|
|
53
|
+
parseLines,
|
|
54
|
+
pinOfLines,
|
|
48
55
|
readConfigFile,
|
|
49
56
|
readFamilyConfigFile,
|
|
50
57
|
resolveBaselineRequest,
|
|
@@ -52,11 +59,17 @@ import {
|
|
|
52
59
|
resolveTargetSet,
|
|
53
60
|
selectCollections,
|
|
54
61
|
settleBaseline,
|
|
62
|
+
sliceLines,
|
|
63
|
+
spellLines,
|
|
64
|
+
spliceManifestValue,
|
|
65
|
+
splitLines,
|
|
55
66
|
supportedExtensions,
|
|
67
|
+
toBodyLines,
|
|
68
|
+
toFileLines,
|
|
56
69
|
withValueAt,
|
|
57
70
|
writeEncryptionKey,
|
|
58
71
|
writeFileAtomic
|
|
59
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-2DC2GSRH.js";
|
|
60
73
|
|
|
61
74
|
// src/meta/core/reencrypt.ts
|
|
62
75
|
import { extname } from "node:path";
|
|
@@ -200,7 +213,7 @@ __export(cite_exports, {
|
|
|
200
213
|
formatStatement: () => formatStatement,
|
|
201
214
|
gitClient: () => gitClient,
|
|
202
215
|
hashLines: () => hashLines,
|
|
203
|
-
hashRange: () =>
|
|
216
|
+
hashRange: () => hashRange2,
|
|
204
217
|
historyOf: () => historyOf,
|
|
205
218
|
insertStatementBefore: () => insertStatementBefore,
|
|
206
219
|
insideFence: () => insideFence,
|
|
@@ -249,7 +262,7 @@ __export(cite_exports, {
|
|
|
249
262
|
shortPin: () => shortPin,
|
|
250
263
|
shortSrc: () => shortSrc,
|
|
251
264
|
sidecarsFor: () => sidecarsFor,
|
|
252
|
-
sliceLines: () =>
|
|
265
|
+
sliceLines: () => sliceLines2,
|
|
253
266
|
sourceRange: () => sourceRange,
|
|
254
267
|
spellLines: () => spellLines,
|
|
255
268
|
spellSource: () => spellSource,
|
|
@@ -292,6 +305,14 @@ var CiteError = class extends ToolError {
|
|
|
292
305
|
this.name = "CiteError";
|
|
293
306
|
}
|
|
294
307
|
};
|
|
308
|
+
function asCiteError(call) {
|
|
309
|
+
try {
|
|
310
|
+
return call();
|
|
311
|
+
} catch (error) {
|
|
312
|
+
if (error instanceof LineRangeError) throw new CiteError(error.message);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
295
316
|
|
|
296
317
|
// src/cite/core/severity.ts
|
|
297
318
|
var DEFAULT_SEVERITY = {
|
|
@@ -324,7 +345,6 @@ function resolveSeverity(overrides) {
|
|
|
324
345
|
// src/cite/core/range.ts
|
|
325
346
|
var FILE_PATTERN = /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\.\.?(?:\/|$))[^/\\:\r\n\t]+)(?:\/(?:(?!\.\.?(?:\/|$))[^/\\:\r\n\t]+))*)$/;
|
|
326
347
|
var SRC_PATTERN = /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\.\.?(?:\/|:|$))[^/\\:\r\n\t]+)(?:\/(?:(?!\.\.?(?:\/|:|$))[^/\\:\r\n\t]+))*)(?::[1-9][0-9]*(?:-[1-9][0-9]*)?)?$/;
|
|
327
|
-
var RANGE_SPEC = /^([1-9][0-9]*)(?:-([1-9][0-9]*))?$/;
|
|
328
348
|
function parseSrc(src) {
|
|
329
349
|
if (!SRC_PATTERN.test(src)) {
|
|
330
350
|
throw new CiteError(
|
|
@@ -351,24 +371,6 @@ function formatSrc(range) {
|
|
|
351
371
|
if (end === void 0 || end === start) return `${path}:${start}`;
|
|
352
372
|
return `${path}:${start}-${end}`;
|
|
353
373
|
}
|
|
354
|
-
function parseLines(spec) {
|
|
355
|
-
if (typeof spec === "number") {
|
|
356
|
-
return Number.isInteger(spec) && spec >= 1 ? { start: spec, end: spec } : void 0;
|
|
357
|
-
}
|
|
358
|
-
const m = RANGE_SPEC.exec(spec);
|
|
359
|
-
const startText = m?.[1];
|
|
360
|
-
if (startText === void 0) return void 0;
|
|
361
|
-
const start = Number(startText);
|
|
362
|
-
const endText = m?.[2];
|
|
363
|
-
const end = endText === void 0 ? start : Number(endText);
|
|
364
|
-
return end < start ? void 0 : { start, end };
|
|
365
|
-
}
|
|
366
|
-
function lineSpec(lines) {
|
|
367
|
-
return lines.start === lines.end ? lines.start : `${String(lines.start)}-${String(lines.end)}`;
|
|
368
|
-
}
|
|
369
|
-
function spellLines(lines) {
|
|
370
|
-
return String(lineSpec(lines));
|
|
371
|
-
}
|
|
372
374
|
function sourceRange(source) {
|
|
373
375
|
const range = { path: source.file, encrypted: isEncryptedValue(source.file) };
|
|
374
376
|
if (source.lines === void 0) return range;
|
|
@@ -388,33 +390,11 @@ function rangeLines(range) {
|
|
|
388
390
|
}
|
|
389
391
|
|
|
390
392
|
// src/cite/core/hash.ts
|
|
391
|
-
function
|
|
392
|
-
|
|
393
|
-
return body.replace(/\r\n/g, "\n");
|
|
394
|
-
}
|
|
395
|
-
function splitLines(text) {
|
|
396
|
-
const parts = normalizeText(text).split("\n");
|
|
397
|
-
if (parts.length > 0 && parts[parts.length - 1] === "") parts.pop();
|
|
398
|
-
return parts;
|
|
399
|
-
}
|
|
400
|
-
function sliceLines(lines, range, label) {
|
|
401
|
-
const start = range?.start;
|
|
402
|
-
if (start === void 0) return lines.join("\n");
|
|
403
|
-
const end = range?.end ?? start;
|
|
404
|
-
if (start > lines.length || end > lines.length) {
|
|
405
|
-
const first = start > lines.length ? start : end;
|
|
406
|
-
throw new CiteError(`${label ?? "the source"} has ${lines.length} lines; line ${first} is out of range.`);
|
|
407
|
-
}
|
|
408
|
-
return lines.slice(start - 1, end).join("\n");
|
|
393
|
+
function sliceLines2(lines, range, label) {
|
|
394
|
+
return asCiteError(() => sliceLines(lines, range, label));
|
|
409
395
|
}
|
|
410
|
-
function
|
|
411
|
-
return
|
|
412
|
-
}
|
|
413
|
-
function hashLines(joined, key) {
|
|
414
|
-
return key === void 0 ? integrityOf(Buffer.from(joined, "utf8")) : keyedPin(joined, key);
|
|
415
|
-
}
|
|
416
|
-
function isKeyedPin(pin) {
|
|
417
|
-
return pin.startsWith(KEYED_PIN_PREFIX);
|
|
396
|
+
function hashRange2(text, range, key) {
|
|
397
|
+
return asCiteError(() => hashRange(text, range, key));
|
|
418
398
|
}
|
|
419
399
|
|
|
420
400
|
// src/cite/core/spell.ts
|
|
@@ -855,141 +835,6 @@ function offsetOfLine(content, line) {
|
|
|
855
835
|
return pos;
|
|
856
836
|
}
|
|
857
837
|
|
|
858
|
-
// src/cite/core/classify.ts
|
|
859
|
-
var MOVE_WINDOW_LINES = 2e3;
|
|
860
|
-
var MOVE_BUDGET_BYTES = 64 * 1024 * 1024;
|
|
861
|
-
var MAX_RANGE_LINES = 5e3;
|
|
862
|
-
function findWindows(lines, length, pin, key, opts) {
|
|
863
|
-
const starts = [];
|
|
864
|
-
const lastStart = lines.length - length + 1;
|
|
865
|
-
if (length < 1 || lastStart < 1) return { starts, truncated: false };
|
|
866
|
-
const joined = (start) => lines.slice(start - 1, start - 1 + length).join("\n");
|
|
867
|
-
const original = opts?.original;
|
|
868
|
-
if (original !== void 0) {
|
|
869
|
-
const first = original[0];
|
|
870
|
-
for (let start = 1; start <= lastStart; start++) {
|
|
871
|
-
if (lines[start - 1] !== first) continue;
|
|
872
|
-
let same = true;
|
|
873
|
-
for (let i = 1; i < length; i++) {
|
|
874
|
-
if (lines[start - 1 + i] !== original[i]) {
|
|
875
|
-
same = false;
|
|
876
|
-
break;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
if (same && hashLines(joined(start), key) === pin) starts.push(start);
|
|
880
|
-
}
|
|
881
|
-
return { starts, truncated: false };
|
|
882
|
-
}
|
|
883
|
-
const budget = opts?.budget ?? MOVE_BUDGET_BYTES;
|
|
884
|
-
const around = opts?.around ?? 1;
|
|
885
|
-
const bandStart = Math.max(1, around - MOVE_WINDOW_LINES);
|
|
886
|
-
const bandEnd = Math.min(lastStart, around + MOVE_WINDOW_LINES);
|
|
887
|
-
const order = [];
|
|
888
|
-
for (let start = bandStart; start <= bandEnd; start++) order.push(start);
|
|
889
|
-
for (let start = 1; start < bandStart; start++) order.push(start);
|
|
890
|
-
for (let start = bandEnd + 1; start <= lastStart; start++) order.push(start);
|
|
891
|
-
let spent = 0;
|
|
892
|
-
for (const start of order) {
|
|
893
|
-
const text = joined(start);
|
|
894
|
-
const bytes = Buffer.byteLength(text, "utf8");
|
|
895
|
-
if (spent + bytes > budget) return { starts, truncated: true };
|
|
896
|
-
spent += bytes;
|
|
897
|
-
if (hashLines(text, key) === pin) starts.push(start);
|
|
898
|
-
}
|
|
899
|
-
return { starts, truncated: false };
|
|
900
|
-
}
|
|
901
|
-
async function historyOf(git, commit, path, range, pin, key, budget) {
|
|
902
|
-
const shown = await git.showFile(commit, path);
|
|
903
|
-
if ("missing" in shown) {
|
|
904
|
-
return shown.missing === "commit" ? { kind: "unavailable" } : { kind: "never-true" };
|
|
905
|
-
}
|
|
906
|
-
const then = splitLines(shown.text);
|
|
907
|
-
let joined;
|
|
908
|
-
try {
|
|
909
|
-
joined = sliceLines(then, range);
|
|
910
|
-
} catch {
|
|
911
|
-
joined = void 0;
|
|
912
|
-
}
|
|
913
|
-
if (joined !== void 0 && hashLines(joined, key) === pin) {
|
|
914
|
-
return { kind: "original", lines: joined.split("\n") };
|
|
915
|
-
}
|
|
916
|
-
if (range.start === void 0) return { kind: "never-true" };
|
|
917
|
-
const length = (range.end ?? range.start) - range.start + 1;
|
|
918
|
-
const search = { around: range.start };
|
|
919
|
-
if (budget !== void 0) search.budget = budget;
|
|
920
|
-
const found = findWindows(then, length, pin, key, search);
|
|
921
|
-
const [first] = found.starts;
|
|
922
|
-
if (first !== void 0) {
|
|
923
|
-
return { kind: "original", lines: then.slice(first - 1, first - 1 + length) };
|
|
924
|
-
}
|
|
925
|
-
return found.truncated ? { kind: "unknown" } : { kind: "never-true" };
|
|
926
|
-
}
|
|
927
|
-
async function classifyCitation(entry, opts) {
|
|
928
|
-
const { citation } = entry;
|
|
929
|
-
const range = sourceRange(citation.source);
|
|
930
|
-
const commit = citation.source["commit-sha"];
|
|
931
|
-
const result = { src: spellSource(citation.source), status: "missing" };
|
|
932
|
-
if (commit !== void 0) result.commitSha = commit;
|
|
933
|
-
const source = await readSource(opts.root, opts.index, range, opts.key);
|
|
934
|
-
if (source.kind === "missing") {
|
|
935
|
-
result.missingReason = source.reason;
|
|
936
|
-
return result;
|
|
937
|
-
}
|
|
938
|
-
result.resolvedPath = source.resolvedPath;
|
|
939
|
-
const key = range.encrypted ? opts.key : void 0;
|
|
940
|
-
const pin = citation.source.integrity;
|
|
941
|
-
const lines = splitLines(source.text);
|
|
942
|
-
let here;
|
|
943
|
-
try {
|
|
944
|
-
here = hashLines(sliceLines(lines, range), key);
|
|
945
|
-
} catch {
|
|
946
|
-
here = void 0;
|
|
947
|
-
}
|
|
948
|
-
if (here === pin) {
|
|
949
|
-
result.status = "current";
|
|
950
|
-
return result;
|
|
951
|
-
}
|
|
952
|
-
let history = { kind: "none" };
|
|
953
|
-
if (commit !== void 0 && await opts.git.available()) {
|
|
954
|
-
history = await historyOf(opts.git, commit, source.resolvedPath, range, pin, key, opts.budget);
|
|
955
|
-
}
|
|
956
|
-
if (range.start !== void 0) {
|
|
957
|
-
const start = range.start;
|
|
958
|
-
const end = range.end ?? start;
|
|
959
|
-
const search = { around: start };
|
|
960
|
-
if (history.kind === "original") search.original = history.lines;
|
|
961
|
-
if (opts.budget !== void 0) search.budget = opts.budget;
|
|
962
|
-
const found = findWindows(lines, end - start + 1, pin, key, search);
|
|
963
|
-
if (found.truncated) result.truncatedSearch = true;
|
|
964
|
-
const spell = (at2) => formatSrc({ ...range, start: at2, end: at2 + (end - start) });
|
|
965
|
-
const [only] = found.starts;
|
|
966
|
-
if (found.starts.length === 1 && only !== void 0) {
|
|
967
|
-
result.status = "moved";
|
|
968
|
-
result.newSrc = spell(only);
|
|
969
|
-
result.newLines = String(lineSpec({ start: only, end: only + (end - start) }));
|
|
970
|
-
return result;
|
|
971
|
-
}
|
|
972
|
-
if (found.starts.length > 1) {
|
|
973
|
-
result.status = "moved-ambiguous";
|
|
974
|
-
result.candidates = found.starts.map(spell);
|
|
975
|
-
return result;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
if (history.kind === "never-true") {
|
|
979
|
-
result.status = "never-true";
|
|
980
|
-
return result;
|
|
981
|
-
}
|
|
982
|
-
result.status = "changed";
|
|
983
|
-
if (history.kind === "unavailable") result.historyAvailable = false;
|
|
984
|
-
if (history.kind === "unknown") result.truncatedSearch = true;
|
|
985
|
-
if (history.kind === "original" && commit !== void 0) {
|
|
986
|
-
result.historyAvailable = true;
|
|
987
|
-
result.commitsSince = await opts.git.subjectsSince(commit, source.resolvedPath);
|
|
988
|
-
result.diff = await opts.git.diffSince(commit, source.resolvedPath);
|
|
989
|
-
}
|
|
990
|
-
return result;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
838
|
// src/cite/core/claims.ts
|
|
994
839
|
function normalizeWhitespace(text) {
|
|
995
840
|
return text.replace(/\s+/g, " ").trim();
|
|
@@ -1002,19 +847,9 @@ function normalizeBlock(text) {
|
|
|
1002
847
|
function blockMatches(blockText, citedJoined) {
|
|
1003
848
|
return normalizeBlock(blockText) === normalizeBlock(citedJoined);
|
|
1004
849
|
}
|
|
1005
|
-
function toFileLines(lines, bodyLine) {
|
|
1006
|
-
return { start: bodyLine + lines.start - 1, end: bodyLine + lines.end - 1 };
|
|
1007
|
-
}
|
|
1008
|
-
function toBodyLines(lines, bodyLine) {
|
|
1009
|
-
return { start: lines.start - bodyLine + 1, end: lines.end - bodyLine + 1 };
|
|
1010
|
-
}
|
|
1011
850
|
function textAt(lines, range) {
|
|
1012
851
|
return lines.slice(range.start - 1, Math.min(range.end, lines.length));
|
|
1013
852
|
}
|
|
1014
|
-
function pinOfLines(lines, range) {
|
|
1015
|
-
if (range.start < 1 || range.end > lines.length) return void 0;
|
|
1016
|
-
return hashLines(lines.slice(range.start - 1, range.end).join("\n"));
|
|
1017
|
-
}
|
|
1018
853
|
function claimLine(claim) {
|
|
1019
854
|
const at2 = claim.fileLines === void 0 ? void 0 : parseLines(claim.fileLines);
|
|
1020
855
|
return at2?.start;
|
|
@@ -1188,6 +1023,99 @@ function noGit() {
|
|
|
1188
1023
|
};
|
|
1189
1024
|
}
|
|
1190
1025
|
|
|
1026
|
+
// src/cite/core/classify.ts
|
|
1027
|
+
async function historyOf(git, commit, path, range, pin, key, budget) {
|
|
1028
|
+
const shown = await git.showFile(commit, path);
|
|
1029
|
+
if ("missing" in shown) {
|
|
1030
|
+
return shown.missing === "commit" ? { kind: "unavailable" } : { kind: "never-true" };
|
|
1031
|
+
}
|
|
1032
|
+
const then = splitLines(shown.text);
|
|
1033
|
+
let joined;
|
|
1034
|
+
try {
|
|
1035
|
+
joined = sliceLines2(then, range);
|
|
1036
|
+
} catch {
|
|
1037
|
+
joined = void 0;
|
|
1038
|
+
}
|
|
1039
|
+
if (joined !== void 0 && hashLines(joined, key) === pin) {
|
|
1040
|
+
return { kind: "original", lines: joined.split("\n") };
|
|
1041
|
+
}
|
|
1042
|
+
if (range.start === void 0) return { kind: "never-true" };
|
|
1043
|
+
const length = (range.end ?? range.start) - range.start + 1;
|
|
1044
|
+
const search = { around: range.start };
|
|
1045
|
+
if (budget !== void 0) search.budget = budget;
|
|
1046
|
+
const found = findWindows(then, length, pin, key, search);
|
|
1047
|
+
const [first] = found.starts;
|
|
1048
|
+
if (first !== void 0) {
|
|
1049
|
+
return { kind: "original", lines: then.slice(first - 1, first - 1 + length) };
|
|
1050
|
+
}
|
|
1051
|
+
return found.truncated ? { kind: "unknown" } : { kind: "never-true" };
|
|
1052
|
+
}
|
|
1053
|
+
async function classifyCitation(entry, opts) {
|
|
1054
|
+
const { citation } = entry;
|
|
1055
|
+
const range = sourceRange(citation.source);
|
|
1056
|
+
const commit = citation.source["commit-sha"];
|
|
1057
|
+
const result = { src: spellSource(citation.source), status: "missing" };
|
|
1058
|
+
if (commit !== void 0) result.commitSha = commit;
|
|
1059
|
+
const source = await readSource(opts.root, opts.index, range, opts.key);
|
|
1060
|
+
if (source.kind === "missing") {
|
|
1061
|
+
result.missingReason = source.reason;
|
|
1062
|
+
return result;
|
|
1063
|
+
}
|
|
1064
|
+
result.resolvedPath = source.resolvedPath;
|
|
1065
|
+
const key = range.encrypted ? opts.key : void 0;
|
|
1066
|
+
const pin = citation.source.integrity;
|
|
1067
|
+
const lines = splitLines(source.text);
|
|
1068
|
+
let here;
|
|
1069
|
+
try {
|
|
1070
|
+
here = hashLines(sliceLines2(lines, range), key);
|
|
1071
|
+
} catch {
|
|
1072
|
+
here = void 0;
|
|
1073
|
+
}
|
|
1074
|
+
if (here === pin) {
|
|
1075
|
+
result.status = "current";
|
|
1076
|
+
return result;
|
|
1077
|
+
}
|
|
1078
|
+
let history = { kind: "none" };
|
|
1079
|
+
if (commit !== void 0 && await opts.git.available()) {
|
|
1080
|
+
history = await historyOf(opts.git, commit, source.resolvedPath, range, pin, key, opts.budget);
|
|
1081
|
+
}
|
|
1082
|
+
if (range.start !== void 0) {
|
|
1083
|
+
const start = range.start;
|
|
1084
|
+
const end = range.end ?? start;
|
|
1085
|
+
const search = { around: start };
|
|
1086
|
+
if (history.kind === "original") search.original = history.lines;
|
|
1087
|
+
if (opts.budget !== void 0) search.budget = opts.budget;
|
|
1088
|
+
const found = findWindows(lines, end - start + 1, pin, key, search);
|
|
1089
|
+
if (found.truncated) result.truncatedSearch = true;
|
|
1090
|
+
const spell = (at2) => formatSrc({ ...range, start: at2, end: at2 + (end - start) });
|
|
1091
|
+
const [only] = found.starts;
|
|
1092
|
+
if (found.starts.length === 1 && only !== void 0) {
|
|
1093
|
+
result.status = "moved";
|
|
1094
|
+
result.newSrc = spell(only);
|
|
1095
|
+
result.newLines = String(lineSpec({ start: only, end: only + (end - start) }));
|
|
1096
|
+
return result;
|
|
1097
|
+
}
|
|
1098
|
+
if (found.starts.length > 1) {
|
|
1099
|
+
result.status = "moved-ambiguous";
|
|
1100
|
+
result.candidates = found.starts.map(spell);
|
|
1101
|
+
return result;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (history.kind === "never-true") {
|
|
1105
|
+
result.status = "never-true";
|
|
1106
|
+
return result;
|
|
1107
|
+
}
|
|
1108
|
+
result.status = "changed";
|
|
1109
|
+
if (history.kind === "unavailable") result.historyAvailable = false;
|
|
1110
|
+
if (history.kind === "unknown") result.truncatedSearch = true;
|
|
1111
|
+
if (history.kind === "original" && commit !== void 0) {
|
|
1112
|
+
result.historyAvailable = true;
|
|
1113
|
+
result.commitsSince = await opts.git.subjectsSince(commit, source.resolvedPath);
|
|
1114
|
+
result.diff = await opts.git.diffSince(commit, source.resolvedPath);
|
|
1115
|
+
}
|
|
1116
|
+
return result;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1191
1119
|
// src/cite/core/page.ts
|
|
1192
1120
|
import { extname as extname2 } from "node:path";
|
|
1193
1121
|
import * as Ajv2020Ns from "ajv/dist/2020.js";
|
|
@@ -1308,326 +1236,6 @@ var citations_default = {
|
|
|
1308
1236
|
}
|
|
1309
1237
|
};
|
|
1310
1238
|
|
|
1311
|
-
// src/meta/core/external-metadata-write.ts
|
|
1312
|
-
import { posix } from "node:path";
|
|
1313
|
-
import {
|
|
1314
|
-
LineCounter,
|
|
1315
|
-
isMap,
|
|
1316
|
-
isNode,
|
|
1317
|
-
isPair,
|
|
1318
|
-
isScalar,
|
|
1319
|
-
isSeq,
|
|
1320
|
-
parseDocument,
|
|
1321
|
-
stringify
|
|
1322
|
-
} from "yaml";
|
|
1323
|
-
function spliceManifestValue(text, options) {
|
|
1324
|
-
const { entry, key, value, file } = options;
|
|
1325
|
-
const join4 = options.join ?? PATH_JOIN;
|
|
1326
|
-
const at2 = (line2) => {
|
|
1327
|
-
const name = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
1328
|
-
if (line2 === void 0) return name;
|
|
1329
|
-
return file === void 0 ? `${name} line ${String(line2)}` : `${name}:${String(line2)}`;
|
|
1330
|
-
};
|
|
1331
|
-
if (key === FILE_SCHEMA_KEY) {
|
|
1332
|
-
throw new DocmetaError(
|
|
1333
|
-
`${at2()}: refusing to write "${FILE_SCHEMA_KEY}" for "${entry}"; a manifest never chooses the schema a document is judged by. Use "overrides" in the config.`
|
|
1334
|
-
);
|
|
1335
|
-
}
|
|
1336
|
-
if (value === void 0) {
|
|
1337
|
-
throw new DocmetaError(`${at2()}: refusing to write "${key}" for "${entry}" with no value.`);
|
|
1338
|
-
}
|
|
1339
|
-
const eol = detectEol2(text);
|
|
1340
|
-
const lc = new LineCounter();
|
|
1341
|
-
const doc = parseDocument(text, { lineCounter: lc, uniqueKeys: false });
|
|
1342
|
-
const problem = doc.errors[0];
|
|
1343
|
-
if (problem) {
|
|
1344
|
-
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
1345
|
-
}
|
|
1346
|
-
const keyLine = (node) => {
|
|
1347
|
-
const r = rangeOf(node);
|
|
1348
|
-
return r ? lc.linePos(r[0]).line : void 0;
|
|
1349
|
-
};
|
|
1350
|
-
const same = join4 === PATH_JOIN ? (a, b) => posix.normalize(a) === posix.normalize(b) : (a, b) => a === b;
|
|
1351
|
-
const root = doc.contents;
|
|
1352
|
-
let spelled = entry;
|
|
1353
|
-
let edit;
|
|
1354
|
-
if (root === null || isScalar(root) && root.value === null && emptySource(text, root)) {
|
|
1355
|
-
edit = startManifest(text, entry, key, value, eol);
|
|
1356
|
-
} else if (!isMap(root)) {
|
|
1357
|
-
throw new DocmetaError(
|
|
1358
|
-
`${at2()}: the manifest must be a mapping from document ${join4 === PATH_JOIN ? "path" : `"${join4}"`} to owned keys.`
|
|
1359
|
-
);
|
|
1360
|
-
} else {
|
|
1361
|
-
const style = detectStyle(text, root, eol);
|
|
1362
|
-
const matches = root.items.filter((p) => same(keyString(p.key), entry));
|
|
1363
|
-
const [first, second] = matches;
|
|
1364
|
-
if (first && second) {
|
|
1365
|
-
throw new DocmetaError(
|
|
1366
|
-
`${at2(keyLine(second.key))}: "${keyString(second.key)}" is named twice (first at line ${String(keyLine(first.key) ?? "?")}). Merge the two entries into one.`
|
|
1367
|
-
);
|
|
1368
|
-
}
|
|
1369
|
-
if (first === void 0) {
|
|
1370
|
-
if (root.flow === true && root.items.length > 0) {
|
|
1371
|
-
throw new DocmetaError(
|
|
1372
|
-
`${at2()}: the manifest is a flow mapping ({ \u2026 }), which this writer does not add entries to. Rewrite it in block style.`
|
|
1373
|
-
);
|
|
1374
|
-
}
|
|
1375
|
-
edit = appendEntry(text, root, entry, key, value, style);
|
|
1376
|
-
} else {
|
|
1377
|
-
spelled = keyString(first.key);
|
|
1378
|
-
const where = at2(keyLine(first.key));
|
|
1379
|
-
const v = first.value;
|
|
1380
|
-
if (!isMap(v)) {
|
|
1381
|
-
throw new DocmetaError(`${where}: "${spelled}" must be a mapping of owned keys to values.`);
|
|
1382
|
-
}
|
|
1383
|
-
const hits = v.items.filter((kv) => keyString(kv.key) === key);
|
|
1384
|
-
const [hit, again] = hits;
|
|
1385
|
-
if (hit && again) {
|
|
1386
|
-
throw new DocmetaError(
|
|
1387
|
-
`${at2(keyLine(again.key))}: "${spelled}" sets "${key}" twice (first at line ${String(keyLine(hit.key) ?? "?")}). Remove one.`
|
|
1388
|
-
);
|
|
1389
|
-
}
|
|
1390
|
-
const flowRefusal = () => new DocmetaError(
|
|
1391
|
-
`${where}: "${spelled}" is a flow mapping ({ \u2026 }), which this writer does not add keys to. Rewrite the entry in block style.`
|
|
1392
|
-
);
|
|
1393
|
-
const formRefusal = () => new DocmetaError(
|
|
1394
|
-
`${where}: "${spelled}" writes a key in a form this writer does not edit. Write it as "${key}: \u2026".`
|
|
1395
|
-
);
|
|
1396
|
-
let made;
|
|
1397
|
-
if (v.flow === true) {
|
|
1398
|
-
if (hit) made = replaceFlowValue(text, hit, value);
|
|
1399
|
-
else if (v.items.length === 0) made = fillEmptyEntry(text, first, key, value, style);
|
|
1400
|
-
else throw flowRefusal();
|
|
1401
|
-
if (!made) throw hit ? flowRefusal() : formRefusal();
|
|
1402
|
-
} else {
|
|
1403
|
-
made = hit ? replaceBlockValue(text, hit, value, style) : insertKey(text, v, key, value, style);
|
|
1404
|
-
if (!made) throw formRefusal();
|
|
1405
|
-
}
|
|
1406
|
-
edit = made;
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
const out = text.slice(0, edit.start) + edit.insert + text.slice(edit.end);
|
|
1410
|
-
const line = readBack(
|
|
1411
|
-
doc,
|
|
1412
|
-
out,
|
|
1413
|
-
spelled,
|
|
1414
|
-
key,
|
|
1415
|
-
value,
|
|
1416
|
-
(why) => new DocmetaError(
|
|
1417
|
-
`${at2()}: writing "${key}" for "${entry}" did not read back as written, so nothing was written. ${why}`
|
|
1418
|
-
)
|
|
1419
|
-
);
|
|
1420
|
-
return { text: out, line };
|
|
1421
|
-
}
|
|
1422
|
-
function startManifest(text, entry, key, value, eol) {
|
|
1423
|
-
const style = { step: 2, indentSeq: true, eol };
|
|
1424
|
-
const block = blockLines({ [entry]: { [key]: value } }, 0, style);
|
|
1425
|
-
let insert;
|
|
1426
|
-
if (text === "" || text.endsWith("\n")) insert = block + eol;
|
|
1427
|
-
else insert = eol + block;
|
|
1428
|
-
return { start: text.length, end: text.length, insert };
|
|
1429
|
-
}
|
|
1430
|
-
function appendEntry(text, root, entry, key, value, style) {
|
|
1431
|
-
const body = { [entry]: { [key]: value } };
|
|
1432
|
-
if (root.flow === true) {
|
|
1433
|
-
const r = rangeOf(root);
|
|
1434
|
-
const start = r ? r[0] : text.length;
|
|
1435
|
-
const end = contentEnd(text, root) ?? start;
|
|
1436
|
-
return { start, end, insert: blockLines(body, colOf(text, start), style) };
|
|
1437
|
-
}
|
|
1438
|
-
const firstKey = rangeOf(root.items[0]?.key);
|
|
1439
|
-
const col = firstKey ? colOf(text, firstKey[0]) : 0;
|
|
1440
|
-
const pos = lineEnd2(text, contentEnd(text, root) ?? text.length);
|
|
1441
|
-
const last = root.items.at(-1);
|
|
1442
|
-
const spaced = root.items.length > 1 && isNode(last?.key) && last.key.spaceBefore === true;
|
|
1443
|
-
return {
|
|
1444
|
-
start: pos,
|
|
1445
|
-
end: pos,
|
|
1446
|
-
insert: style.eol + (spaced ? style.eol : "") + blockLines(body, col, style)
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
|
-
function insertKey(text, entryMap, key, value, style) {
|
|
1450
|
-
const firstKey = rangeOf(entryMap.items[0]?.key);
|
|
1451
|
-
const end = contentEnd(text, entryMap);
|
|
1452
|
-
if (!firstKey || end === void 0) return void 0;
|
|
1453
|
-
const pos = lineEnd2(text, end);
|
|
1454
|
-
return {
|
|
1455
|
-
start: pos,
|
|
1456
|
-
end: pos,
|
|
1457
|
-
insert: style.eol + blockLines({ [key]: value }, colOf(text, firstKey[0]), style)
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
function fillEmptyEntry(text, entryPair, key, value, style) {
|
|
1461
|
-
const start = colonEnd(text, entryPair);
|
|
1462
|
-
const keyRange = rangeOf(entryPair.key);
|
|
1463
|
-
const end = contentEnd(text, entryPair.value);
|
|
1464
|
-
if (start === void 0 || !keyRange || end === void 0) return void 0;
|
|
1465
|
-
const col = colOf(text, keyRange[0]) + style.step;
|
|
1466
|
-
return { start, end, insert: style.eol + blockLines({ [key]: value }, col, style) };
|
|
1467
|
-
}
|
|
1468
|
-
function replaceBlockValue(text, pair, value, style) {
|
|
1469
|
-
const colon = colonEnd(text, pair);
|
|
1470
|
-
const keyRange = rangeOf(pair.key);
|
|
1471
|
-
if (colon === void 0 || !keyRange) return void 0;
|
|
1472
|
-
const keyCol = colOf(text, keyRange[0]);
|
|
1473
|
-
let start = colon;
|
|
1474
|
-
let ownLine = false;
|
|
1475
|
-
let i = colon;
|
|
1476
|
-
while (text.charAt(i) === " " || text.charAt(i) === " ") i++;
|
|
1477
|
-
if (text.charAt(i) === "#") {
|
|
1478
|
-
start = lineEnd2(text, i);
|
|
1479
|
-
ownLine = true;
|
|
1480
|
-
}
|
|
1481
|
-
const old = pair.value;
|
|
1482
|
-
const oldEnd = isScalar(old) && old.value === null && emptySource(text, old) ? start : contentEnd(text, old) ?? start;
|
|
1483
|
-
const end = Math.max(start, oldEnd);
|
|
1484
|
-
let insert = afterColon(value, keyCol, style);
|
|
1485
|
-
if (ownLine && !insert.startsWith(style.eol)) {
|
|
1486
|
-
insert = style.eol + " ".repeat(keyCol + style.step) + insert.trimStart();
|
|
1487
|
-
}
|
|
1488
|
-
return { start, end, insert };
|
|
1489
|
-
}
|
|
1490
|
-
function replaceFlowValue(text, pair, value) {
|
|
1491
|
-
const r = rangeOf(pair.value);
|
|
1492
|
-
if (!r || emptySource(text, pair.value)) return void 0;
|
|
1493
|
-
const end = contentEnd(text, pair.value) ?? r[1];
|
|
1494
|
-
return { start: r[0], end, insert: flowText(value) };
|
|
1495
|
-
}
|
|
1496
|
-
function readBack(before, out, spelled, key, value, fail) {
|
|
1497
|
-
const lc = new LineCounter();
|
|
1498
|
-
const after = parseDocument(out, { lineCounter: lc, uniqueKeys: false });
|
|
1499
|
-
const problem = after.errors[0];
|
|
1500
|
-
if (problem) throw fail(`The result is not valid YAML: ${problem.message}`);
|
|
1501
|
-
const was = before.toJS({ maxAliasCount: 100 });
|
|
1502
|
-
const now = after.toJS({ maxAliasCount: 100 });
|
|
1503
|
-
const wasRoot = isRecord(was) ? was : {};
|
|
1504
|
-
const wasEntry = wasRoot[spelled];
|
|
1505
|
-
const expected = {
|
|
1506
|
-
...wasRoot,
|
|
1507
|
-
[spelled]: { ...isRecord(wasEntry) ? wasEntry : {}, [key]: value }
|
|
1508
|
-
};
|
|
1509
|
-
const nowEntry = isRecord(now) ? now[spelled] : void 0;
|
|
1510
|
-
if (!isRecord(nowEntry) || !deepEqual(nowEntry[key], value)) {
|
|
1511
|
-
throw fail(
|
|
1512
|
-
"The value reads back differently. A Date, an undefined member, or another value YAML cannot hold does not survive the trip."
|
|
1513
|
-
);
|
|
1514
|
-
}
|
|
1515
|
-
if (!deepEqual(now, expected)) {
|
|
1516
|
-
throw fail("Another value in the manifest would have changed.");
|
|
1517
|
-
}
|
|
1518
|
-
const root = after.contents;
|
|
1519
|
-
const pair = isMap(root) ? root.items.find((p) => keyString(p.key) === spelled) : void 0;
|
|
1520
|
-
const entryMap = pair?.value;
|
|
1521
|
-
const kv = isMap(entryMap) ? entryMap.items.find((p) => keyString(p.key) === key) : void 0;
|
|
1522
|
-
const r = rangeOf(kv?.value) ?? rangeOf(kv?.key);
|
|
1523
|
-
if (!r) throw fail("The written value could not be found again.");
|
|
1524
|
-
return lc.linePos(r[0]).line;
|
|
1525
|
-
}
|
|
1526
|
-
function blockLines(pair, col, style) {
|
|
1527
|
-
const s = stringify(pair, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
1528
|
-
return indentLines(s.replace(/\n$/, "").split("\n"), col, 0).join(style.eol);
|
|
1529
|
-
}
|
|
1530
|
-
function afterColon(value, col, style) {
|
|
1531
|
-
const s = stringify({ k: value }, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
1532
|
-
const lines = s.replace(/\n$/, "").slice("k:".length).split("\n");
|
|
1533
|
-
return indentLines(lines, col, 1).join(style.eol);
|
|
1534
|
-
}
|
|
1535
|
-
function indentLines(lines, col, from) {
|
|
1536
|
-
const pad = " ".repeat(col);
|
|
1537
|
-
return lines.map((l, i) => i < from || l === "" ? l : pad + l);
|
|
1538
|
-
}
|
|
1539
|
-
function flowText(value) {
|
|
1540
|
-
const s = stringify(value, { lineWidth: 0, collectionStyle: "flow" }).replace(/\n$/, "");
|
|
1541
|
-
return s.includes("\n") ? JSON.stringify(value) : s;
|
|
1542
|
-
}
|
|
1543
|
-
function detectEol2(text) {
|
|
1544
|
-
const i = text.indexOf("\n");
|
|
1545
|
-
return i > 0 && text.charAt(i - 1) === "\r" ? "\r\n" : "\n";
|
|
1546
|
-
}
|
|
1547
|
-
function detectStyle(text, root, eol) {
|
|
1548
|
-
let step = 2;
|
|
1549
|
-
for (const pair of root.items) {
|
|
1550
|
-
const v = pair.value;
|
|
1551
|
-
const entryKey = rangeOf(pair.key);
|
|
1552
|
-
const ownedKey = isMap(v) && v.flow !== true ? rangeOf(v.items[0]?.key) : void 0;
|
|
1553
|
-
if (entryKey && ownedKey) {
|
|
1554
|
-
const d = colOf(text, ownedKey[0]) - colOf(text, entryKey[0]);
|
|
1555
|
-
if (d > 0) {
|
|
1556
|
-
step = d;
|
|
1557
|
-
break;
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
return { step, indentSeq: seqIndented(text, root) ?? true, eol };
|
|
1562
|
-
}
|
|
1563
|
-
function seqIndented(text, node) {
|
|
1564
|
-
if (isMap(node)) {
|
|
1565
|
-
for (const pair of node.items) {
|
|
1566
|
-
const v = pair.value;
|
|
1567
|
-
if (isSeq(v) && v.flow !== true && v.items.length > 0) {
|
|
1568
|
-
const k = rangeOf(pair.key);
|
|
1569
|
-
const s = rangeOf(v);
|
|
1570
|
-
if (k && s) return colOf(text, s[0]) > colOf(text, k[0]);
|
|
1571
|
-
}
|
|
1572
|
-
const inner = seqIndented(text, v);
|
|
1573
|
-
if (inner !== void 0) return inner;
|
|
1574
|
-
}
|
|
1575
|
-
} else if (isSeq(node)) {
|
|
1576
|
-
for (const item of node.items) {
|
|
1577
|
-
const inner = seqIndented(text, item);
|
|
1578
|
-
if (inner !== void 0) return inner;
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
return void 0;
|
|
1582
|
-
}
|
|
1583
|
-
function contentEnd(text, node) {
|
|
1584
|
-
if (isMap(node) && node.flow !== true) {
|
|
1585
|
-
const last = node.items.at(-1);
|
|
1586
|
-
if (last) return contentEnd(text, last.value) ?? contentEnd(text, last.key);
|
|
1587
|
-
} else if (isSeq(node) && node.flow !== true) {
|
|
1588
|
-
const last = node.items.at(-1);
|
|
1589
|
-
if (last !== void 0) {
|
|
1590
|
-
return isPair(last) ? contentEnd(text, last.value) ?? contentEnd(text, last.key) : contentEnd(text, last);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
const r = rangeOf(node);
|
|
1594
|
-
if (!r) return void 0;
|
|
1595
|
-
let end = r[1];
|
|
1596
|
-
while (end > r[0] && /\s/.test(text.charAt(end - 1))) end--;
|
|
1597
|
-
return end;
|
|
1598
|
-
}
|
|
1599
|
-
function colonEnd(text, pair) {
|
|
1600
|
-
const r = rangeOf(pair.key);
|
|
1601
|
-
if (!r) return void 0;
|
|
1602
|
-
let i = r[1];
|
|
1603
|
-
while (text.charAt(i) === " " || text.charAt(i) === " ") i++;
|
|
1604
|
-
return text.charAt(i) === ":" ? i + 1 : void 0;
|
|
1605
|
-
}
|
|
1606
|
-
function lineEnd2(text, i) {
|
|
1607
|
-
const j = text.indexOf("\n", i);
|
|
1608
|
-
if (j < 0) return text.length;
|
|
1609
|
-
return j > 0 && text.charAt(j - 1) === "\r" ? j - 1 : j;
|
|
1610
|
-
}
|
|
1611
|
-
function colOf(text, offset) {
|
|
1612
|
-
if (offset === 0) return 0;
|
|
1613
|
-
let start = text.lastIndexOf("\n", offset - 1) + 1;
|
|
1614
|
-
if (start === 0 && text.startsWith("\uFEFF")) start = 1;
|
|
1615
|
-
return offset - start;
|
|
1616
|
-
}
|
|
1617
|
-
function rangeOf(node) {
|
|
1618
|
-
return isNode(node) ? node.range ?? void 0 : void 0;
|
|
1619
|
-
}
|
|
1620
|
-
function emptySource(text, node) {
|
|
1621
|
-
const r = rangeOf(node);
|
|
1622
|
-
return !r || text.slice(r[0], r[1]).trim() === "";
|
|
1623
|
-
}
|
|
1624
|
-
function keyString(key) {
|
|
1625
|
-
return isScalar(key) ? String(key.value) : String(key);
|
|
1626
|
-
}
|
|
1627
|
-
function isRecord(x) {
|
|
1628
|
-
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
1239
|
// src/cite/core/page.ts
|
|
1632
1240
|
var MAX_MARKERS_PER_PAGE = 500;
|
|
1633
1241
|
var ELEMENT_BACKED = /* @__PURE__ */ new Set(["html", "xml"]);
|
|
@@ -1653,11 +1261,11 @@ function validateEntry(entry) {
|
|
|
1653
1261
|
if (!first) return "invalid entry";
|
|
1654
1262
|
return `${first.instancePath} ${first.message ?? "is invalid"}`.trim();
|
|
1655
1263
|
}
|
|
1656
|
-
function
|
|
1264
|
+
function isRecord(value) {
|
|
1657
1265
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1658
1266
|
}
|
|
1659
1267
|
function toCitation(entry) {
|
|
1660
|
-
const source =
|
|
1268
|
+
const source = isRecord(entry.source) ? entry.source : {};
|
|
1661
1269
|
const citation = {
|
|
1662
1270
|
source: {
|
|
1663
1271
|
file: String(source.file),
|
|
@@ -1671,7 +1279,7 @@ function toCitation(entry) {
|
|
|
1671
1279
|
citation.source["commit-sha"] = source["commit-sha"];
|
|
1672
1280
|
}
|
|
1673
1281
|
if (typeof entry.id === "string") citation.id = entry.id;
|
|
1674
|
-
if (
|
|
1282
|
+
if (isRecord(entry.claim)) {
|
|
1675
1283
|
const claim = entry.claim;
|
|
1676
1284
|
citation.claim = { integrity: String(claim.integrity) };
|
|
1677
1285
|
if (typeof claim.lines === "number" || typeof claim.lines === "string") {
|
|
@@ -1703,9 +1311,9 @@ function named(id, text) {
|
|
|
1703
1311
|
}
|
|
1704
1312
|
function subjectOf(entry) {
|
|
1705
1313
|
const out = {};
|
|
1706
|
-
if (!
|
|
1314
|
+
if (!isRecord(entry)) return out;
|
|
1707
1315
|
if (typeof entry.id === "string") out.id = entry.id;
|
|
1708
|
-
if (
|
|
1316
|
+
if (isRecord(entry.source) && typeof entry.source.file === "string") out.src = entry.source.file;
|
|
1709
1317
|
return out;
|
|
1710
1318
|
}
|
|
1711
1319
|
function pickExtractor(file, format) {
|
|
@@ -1786,7 +1394,7 @@ function readPage(file, content, opts) {
|
|
|
1786
1394
|
if (origin.kind === "manifest") where.file = origin.file;
|
|
1787
1395
|
const entry = input.entry;
|
|
1788
1396
|
const error = validateEntry(entry);
|
|
1789
|
-
if (error !== void 0 || !
|
|
1397
|
+
if (error !== void 0 || !isRecord(entry)) {
|
|
1790
1398
|
findings.push(finding("entry-invalid", error ?? "must be object", { ...where, ...subjectOf(entry) }));
|
|
1791
1399
|
return;
|
|
1792
1400
|
}
|
|
@@ -2046,8 +1654,8 @@ function sidecarsFor(run3, over = {}) {
|
|
|
2046
1654
|
|
|
2047
1655
|
// src/cite/core/manifest.ts
|
|
2048
1656
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
2049
|
-
import { posix
|
|
2050
|
-
import { LineCounter
|
|
1657
|
+
import { posix } from "node:path";
|
|
1658
|
+
import { LineCounter, isMap, isNode, isScalar, isSeq, parseDocument } from "yaml";
|
|
2051
1659
|
|
|
2052
1660
|
// src/cite/core/write.ts
|
|
2053
1661
|
function extractorFor(format) {
|
|
@@ -2159,12 +1767,12 @@ function spliceEntryField(content, format, index, path, value) {
|
|
|
2159
1767
|
const out = content.slice(0, start) + parts.lead + spelled + parts.trail + content.slice(end);
|
|
2160
1768
|
const check = extractor.extract(out, "page").data.citations;
|
|
2161
1769
|
const entry = Array.isArray(check) ? check[index] : void 0;
|
|
2162
|
-
const block =
|
|
2163
|
-
const
|
|
2164
|
-
if (
|
|
1770
|
+
const block = isRecord2(entry) ? entry[which] : void 0;
|
|
1771
|
+
const readBack = isRecord2(block) ? block[field] : void 0;
|
|
1772
|
+
if (readBack !== value) throw refuse();
|
|
2165
1773
|
return out;
|
|
2166
1774
|
}
|
|
2167
|
-
function
|
|
1775
|
+
function isRecord2(value) {
|
|
2168
1776
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2169
1777
|
}
|
|
2170
1778
|
function insertStatementBefore(content, offset, statement) {
|
|
@@ -2290,25 +1898,25 @@ function splice(text, options) {
|
|
|
2290
1898
|
}
|
|
2291
1899
|
}
|
|
2292
1900
|
function itemLine(text, entry, index, join4) {
|
|
2293
|
-
const lc = new
|
|
2294
|
-
const doc =
|
|
1901
|
+
const lc = new LineCounter();
|
|
1902
|
+
const doc = parseDocument(text, { lineCounter: lc, uniqueKeys: false });
|
|
2295
1903
|
if (doc.errors.length > 0) return void 0;
|
|
2296
1904
|
const root = doc.contents;
|
|
2297
|
-
if (!
|
|
1905
|
+
if (!isMap(root)) return void 0;
|
|
2298
1906
|
const same = (key) => {
|
|
2299
|
-
const spelled =
|
|
2300
|
-
return join4 === "path" ?
|
|
1907
|
+
const spelled = isScalar(key) ? String(key.value) : String(key);
|
|
1908
|
+
return join4 === "path" ? posix.normalize(spelled) === posix.normalize(entry) : spelled === entry;
|
|
2301
1909
|
};
|
|
2302
1910
|
const pair = root.items.find((p) => same(p.key));
|
|
2303
1911
|
const value = pair?.value;
|
|
2304
|
-
if (!
|
|
1912
|
+
if (!isMap(value)) return void 0;
|
|
2305
1913
|
const kv = value.items.find(
|
|
2306
|
-
(p) => (
|
|
1914
|
+
(p) => (isScalar(p.key) ? String(p.key.value) : String(p.key)) === CITATIONS_KEY2
|
|
2307
1915
|
);
|
|
2308
1916
|
const list = kv?.value;
|
|
2309
|
-
if (!
|
|
1917
|
+
if (!isSeq(list)) return void 0;
|
|
2310
1918
|
const item = list.items[index];
|
|
2311
|
-
const range =
|
|
1919
|
+
const range = isNode(item) ? item.range : void 0;
|
|
2312
1920
|
return range ? lc.linePos(range[0]).line : void 0;
|
|
2313
1921
|
}
|
|
2314
1922
|
|
|
@@ -2509,7 +2117,7 @@ async function citedNow(input, source, entry) {
|
|
|
2509
2117
|
if (read.kind === "missing") return void 0;
|
|
2510
2118
|
const at2 = source.status === "moved" && source.newSrc !== void 0 ? parseSrc(source.newSrc) : range;
|
|
2511
2119
|
try {
|
|
2512
|
-
return
|
|
2120
|
+
return sliceLines2(splitLines(read.text), at2);
|
|
2513
2121
|
} catch {
|
|
2514
2122
|
return void 0;
|
|
2515
2123
|
}
|
|
@@ -2713,7 +2321,7 @@ async function mintCitation(opts) {
|
|
|
2713
2321
|
const index = opts.sourceIndex ?? await buildSourceIndex(opts.root, { gitClient: opts.gitClient });
|
|
2714
2322
|
const read = await readSource(opts.root, index, range, key);
|
|
2715
2323
|
if (read.kind === "missing") throw refusalFor(read.reason, range.path, range.encrypted);
|
|
2716
|
-
const joined =
|
|
2324
|
+
const joined = sliceLines2(splitLines(read.text), range, range.path);
|
|
2717
2325
|
const pinKey = encrypt ? key : void 0;
|
|
2718
2326
|
const file = pinKey !== void 0 && !range.encrypted ? encryptSourcePath(read.resolvedPath, pinKey) : range.path;
|
|
2719
2327
|
const lines = rangeLines(range);
|
|
@@ -3137,7 +2745,7 @@ async function citedText(root, index, src, key) {
|
|
|
3137
2745
|
if (source.kind === "missing") {
|
|
3138
2746
|
throw new CiteError(`Source not readable: ${range.path} could not be read.`);
|
|
3139
2747
|
}
|
|
3140
|
-
return
|
|
2748
|
+
return sliceLines2(splitLines(source.text), range, range.path);
|
|
3141
2749
|
}
|
|
3142
2750
|
async function runAdd(opts) {
|
|
3143
2751
|
const cwd = resolve4(opts.cwd ?? process.cwd());
|
|
@@ -3376,12 +2984,12 @@ function apply(content, format, plan) {
|
|
|
3376
2984
|
}
|
|
3377
2985
|
}
|
|
3378
2986
|
}
|
|
3379
|
-
function
|
|
2987
|
+
function isRecord3(value) {
|
|
3380
2988
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3381
2989
|
}
|
|
3382
2990
|
function applyToEntry(entry, plan) {
|
|
3383
|
-
if (!
|
|
3384
|
-
const end = (name) =>
|
|
2991
|
+
if (!isRecord3(entry)) return false;
|
|
2992
|
+
const end = (name) => isRecord3(entry[name]) ? entry[name] : void 0;
|
|
3385
2993
|
switch (plan.kind) {
|
|
3386
2994
|
case "claim-moved": {
|
|
3387
2995
|
const claim = end("claim");
|
|
@@ -3622,7 +3230,7 @@ async function pinnedLines(ctx, citation, range, path, key) {
|
|
|
3622
3230
|
const pin = citation.source.integrity;
|
|
3623
3231
|
let joined;
|
|
3624
3232
|
try {
|
|
3625
|
-
joined =
|
|
3233
|
+
joined = sliceLines2(splitLines(source.text), range);
|
|
3626
3234
|
} catch {
|
|
3627
3235
|
joined = void 0;
|
|
3628
3236
|
}
|
|
@@ -4472,6 +4080,7 @@ export {
|
|
|
4472
4080
|
meetsSeverity,
|
|
4473
4081
|
reencryptMetadata,
|
|
4474
4082
|
CiteError,
|
|
4083
|
+
asCiteError,
|
|
4475
4084
|
spellSource,
|
|
4476
4085
|
runAdd,
|
|
4477
4086
|
runCheck,
|
|
@@ -4489,4 +4098,4 @@ export {
|
|
|
4489
4098
|
runKeyRotate,
|
|
4490
4099
|
runKeySet
|
|
4491
4100
|
};
|
|
4492
|
-
//# sourceMappingURL=chunk-
|
|
4101
|
+
//# sourceMappingURL=chunk-UTXTVCBV.js.map
|