token-goat 2.9.30 → 2.9.31
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 +24 -7
- package/SECURITY.md +10 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/native/win32-arm64/tg-hook.exe +0 -0
- package/dist/native/win32-x64/tg-hook.exe +0 -0
- package/dist/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
- package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
- package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
- package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
- package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
- package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
- package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
- package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
- package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
- package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
- package/dist/{token-goat-chunk-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
- package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
- package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
- package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
- package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
- package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
- package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
- package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
- package/dist/token-goat-chunk-646E6U44.mjs +398 -0
- package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
- package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
- package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
- package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
- package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
- package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
- package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
- package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
- package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
- package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
- package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
- package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
- package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
- package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
- package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
- package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
- package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
- package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
- package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
- package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
- package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
- package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
- package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
- package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
- package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
- package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
- package/dist/{token-goat-chunk-54K3EUV3.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
- package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
- package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
- package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
- package/dist/{token-goat-chunk-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
- package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
- package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
- package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
- package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
- package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
- package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
- package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
- package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
- package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
- package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
- package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
- package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
- package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
- package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
- package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
- package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
- package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
- package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
- package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
- package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
- package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
- package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
- package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
- package/dist/{token-goat-chunk-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
- package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
- package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
- package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
- package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
- package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
- package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
- package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
- package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
- package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
- package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
- package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
- package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
- package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
- package/dist/{token-goat-chunk-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
- package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
- package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
- package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
- package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
- package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
- package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
- package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
- package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
- package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
- package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
- package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
- package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
- package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
- package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
- package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
- package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
- package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
- package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
- package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
- package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
- package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
- package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
- package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
- package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
- package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
- package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
- package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
- package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
- package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
- package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
- package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
- package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
- package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
- package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
- package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
- package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
- package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
- package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
- package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
- package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
- package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
- package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
- package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
- package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
- package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
- package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
- package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
- package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
- package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
- package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
- package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
- package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
- package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
- package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
- package/dist/token-goat-hook-client.cjs +1 -1
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +67 -38
- package/dist/token-goat.core.mjs +4 -4
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +40 -21
- package/docs/install.md +19 -9
- package/docs/security.md +5 -3
- package/package.json +2 -1
- package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
- package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
- package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
- package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
- package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
- package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
- package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
- package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
- package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
- package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
- package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
- package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
- package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
|
@@ -0,0 +1,1178 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
escapeRegExp
|
|
5
|
+
} from "./token-goat-chunk-HU4TORC5.mjs";
|
|
6
|
+
import {
|
|
7
|
+
init_define_import_meta_env
|
|
8
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
9
|
+
|
|
10
|
+
// src/doc_comment.ts
|
|
11
|
+
init_define_import_meta_env();
|
|
12
|
+
function precedingDocComment(lines, lineStart, style) {
|
|
13
|
+
const aboveIdx = lineStart - 2;
|
|
14
|
+
if (aboveIdx < 0 || aboveIdx >= lines.length) return "";
|
|
15
|
+
const aboveLine = lines[aboveIdx];
|
|
16
|
+
if (aboveLine === void 0) return "";
|
|
17
|
+
const aboveTrimmed = aboveLine.trim();
|
|
18
|
+
if (style === "vb") {
|
|
19
|
+
if (!aboveTrimmed.startsWith("'''")) return "";
|
|
20
|
+
const collected = [];
|
|
21
|
+
for (let i = aboveIdx; i >= 0; i--) {
|
|
22
|
+
const trimmed = (lines[i] ?? "").trim();
|
|
23
|
+
if (!trimmed.startsWith("'''")) break;
|
|
24
|
+
collected.unshift(trimmed.replace(/^'''\s?/, ""));
|
|
25
|
+
}
|
|
26
|
+
return collected.join("\n").trim();
|
|
27
|
+
}
|
|
28
|
+
if (style === "hash") {
|
|
29
|
+
if (!aboveTrimmed.startsWith("#")) return "";
|
|
30
|
+
const collected = [];
|
|
31
|
+
let i = aboveIdx;
|
|
32
|
+
while (i >= 0) {
|
|
33
|
+
const line = lines[i];
|
|
34
|
+
if (line === void 0) break;
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (!trimmed.startsWith("#")) break;
|
|
37
|
+
collected.unshift(trimmed.replace(/^#+\s?/, ""));
|
|
38
|
+
i--;
|
|
39
|
+
}
|
|
40
|
+
return collected.join("\n").trim();
|
|
41
|
+
}
|
|
42
|
+
if (aboveTrimmed.endsWith("*/")) {
|
|
43
|
+
let blockStart = aboveIdx;
|
|
44
|
+
while (blockStart >= 0) {
|
|
45
|
+
const l = lines[blockStart];
|
|
46
|
+
if (l === void 0) break;
|
|
47
|
+
if (l.trim().startsWith("/*")) break;
|
|
48
|
+
blockStart--;
|
|
49
|
+
}
|
|
50
|
+
if (blockStart < 0) return "";
|
|
51
|
+
const opener = lines[blockStart];
|
|
52
|
+
if (opener === void 0 || !opener.trim().startsWith("/*")) return "";
|
|
53
|
+
const region = lines.slice(blockStart, aboveIdx + 1);
|
|
54
|
+
const joined = region.join("\n").trimEnd();
|
|
55
|
+
if (joined.indexOf("*/") !== joined.length - 2) return "";
|
|
56
|
+
return region.map(
|
|
57
|
+
(l) => l.trim().replace(/^\/\*+/, "").replace(/\*+\/$/, "").replace(/^\*\s?/, "").trim()
|
|
58
|
+
).filter((l) => l !== "").join("\n");
|
|
59
|
+
}
|
|
60
|
+
if (aboveTrimmed.startsWith("//")) {
|
|
61
|
+
const collected = [];
|
|
62
|
+
let i = aboveIdx;
|
|
63
|
+
while (i >= 0) {
|
|
64
|
+
const line = lines[i];
|
|
65
|
+
if (line === void 0) break;
|
|
66
|
+
const trimmed = line.trim();
|
|
67
|
+
if (!trimmed.startsWith("//")) break;
|
|
68
|
+
collected.unshift(trimmed.replace(/^\/\/[/!]?\s?/, ""));
|
|
69
|
+
i--;
|
|
70
|
+
}
|
|
71
|
+
return collected.join("\n").trim();
|
|
72
|
+
}
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/languages/common.ts
|
|
77
|
+
init_define_import_meta_env();
|
|
78
|
+
function buildLineIndex(text) {
|
|
79
|
+
const idx = [0];
|
|
80
|
+
for (let i = 0; i < text.length; i++) {
|
|
81
|
+
if (text[i] === "\n") idx.push(i + 1);
|
|
82
|
+
}
|
|
83
|
+
return idx;
|
|
84
|
+
}
|
|
85
|
+
function offsetToLine(lineIndex, offset) {
|
|
86
|
+
let lo = 0;
|
|
87
|
+
let hi = lineIndex.length - 1;
|
|
88
|
+
while (lo < hi) {
|
|
89
|
+
const mid = lo + hi + 1 >> 1;
|
|
90
|
+
const lineStart = lineIndex[mid];
|
|
91
|
+
if (lineStart === void 0 || lineStart > offset) {
|
|
92
|
+
hi = mid - 1;
|
|
93
|
+
} else {
|
|
94
|
+
lo = mid;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return lo + 1;
|
|
98
|
+
}
|
|
99
|
+
function lineTextAt(content, lineIndex, line) {
|
|
100
|
+
const start = lineIndex[line - 1];
|
|
101
|
+
if (start === void 0) return "";
|
|
102
|
+
const next = lineIndex[line];
|
|
103
|
+
return content.slice(start, next === void 0 ? content.length : next - 1).trim();
|
|
104
|
+
}
|
|
105
|
+
function stripCstyleComments(text, lineCommentRe) {
|
|
106
|
+
const lines = text.split("\n");
|
|
107
|
+
let inComment = false;
|
|
108
|
+
const outLines = [];
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
const { code, inComment: nextInComment } = stripBlockCommentSpan(line, inComment);
|
|
111
|
+
outLines.push(code);
|
|
112
|
+
inComment = nextInComment;
|
|
113
|
+
}
|
|
114
|
+
let out = outLines.join("\n");
|
|
115
|
+
if (lineCommentRe !== void 0) {
|
|
116
|
+
out = out.replace(lineCommentRe, (m) => " ".repeat(m.length));
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
function stripXmlComments(text) {
|
|
121
|
+
const lines = text.split("\n");
|
|
122
|
+
let inComment = false;
|
|
123
|
+
const outLines = [];
|
|
124
|
+
for (const line of lines) {
|
|
125
|
+
let result = "";
|
|
126
|
+
let j = 0;
|
|
127
|
+
while (j < line.length) {
|
|
128
|
+
if (!inComment) {
|
|
129
|
+
const open = line.indexOf("<!--", j);
|
|
130
|
+
if (open === -1) {
|
|
131
|
+
result += line.slice(j);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
result += line.slice(j, open);
|
|
135
|
+
const close = line.indexOf("-->", open + 4);
|
|
136
|
+
if (close === -1) {
|
|
137
|
+
result += " ".repeat(line.length - open);
|
|
138
|
+
inComment = true;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
result += " ".repeat(close + 3 - open);
|
|
142
|
+
j = close + 3;
|
|
143
|
+
inComment = false;
|
|
144
|
+
} else {
|
|
145
|
+
const close = line.indexOf("-->", j);
|
|
146
|
+
if (close === -1) {
|
|
147
|
+
result += " ".repeat(line.length - j);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
result += " ".repeat(close + 3 - j);
|
|
151
|
+
j = close + 3;
|
|
152
|
+
inComment = false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
outLines.push(result);
|
|
156
|
+
}
|
|
157
|
+
return outLines.join("\n");
|
|
158
|
+
}
|
|
159
|
+
function scanQuotedStringEnd(content, start) {
|
|
160
|
+
const quote = content[start];
|
|
161
|
+
const n = content.length;
|
|
162
|
+
let j = start + 1;
|
|
163
|
+
while (j < n) {
|
|
164
|
+
if (content[j] === "\\" && j + 1 < n) {
|
|
165
|
+
j += 2;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (content[j] === quote) {
|
|
169
|
+
j++;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
if (quote !== "`" && content[j] === "\n") {
|
|
173
|
+
j++;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
j++;
|
|
177
|
+
}
|
|
178
|
+
return j;
|
|
179
|
+
}
|
|
180
|
+
function stripJsComments(content) {
|
|
181
|
+
let out = "";
|
|
182
|
+
let i = 0;
|
|
183
|
+
const n = content.length;
|
|
184
|
+
while (i < n) {
|
|
185
|
+
const ch = content[i];
|
|
186
|
+
if (ch === "/" && content[i + 1] === "/") {
|
|
187
|
+
let j = i;
|
|
188
|
+
while (j < n && content[j] !== "\n") j++;
|
|
189
|
+
out += " ".repeat(j - i);
|
|
190
|
+
i = j;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (ch === "/" && content[i + 1] === "*") {
|
|
194
|
+
let j = i + 2;
|
|
195
|
+
while (j < n && !(content[j] === "*" && content[j + 1] === "/")) j++;
|
|
196
|
+
const end = j < n ? j + 2 : n;
|
|
197
|
+
out += content.slice(i, end).replace(/[^\n]/g, " ");
|
|
198
|
+
i = end;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
202
|
+
const j = scanQuotedStringEnd(content, i);
|
|
203
|
+
out += content.slice(i, j);
|
|
204
|
+
i = j;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
out += ch;
|
|
208
|
+
i++;
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
function stripHashComments(text) {
|
|
213
|
+
return text.split("\n").map((line) => {
|
|
214
|
+
for (let i = 0; i < line.length; i++) {
|
|
215
|
+
if (line[i] === "#" && !isInsideStringLiteral(line, i)) {
|
|
216
|
+
return line.slice(0, i) + " ".repeat(line.length - i);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return line;
|
|
220
|
+
}).join("\n");
|
|
221
|
+
}
|
|
222
|
+
var HTML_COMMENT_RE = /<!--[\s\S]*?-->/g;
|
|
223
|
+
var HTML_SCRIPT_BODY_RE = /(<script\b[^>]*>)([\s\S]*?)(<\/script\s*>)/gi;
|
|
224
|
+
var HTML_CDATA_RE = /<!\[CDATA\[[\s\S]*?\]\]>/g;
|
|
225
|
+
var LIQUID_COMMENT_RE = /{%-?\s*comment\s*-?%}[\s\S]*?{%-?\s*endcomment\s*-?%}/gi;
|
|
226
|
+
function maskHtmlNoise(text) {
|
|
227
|
+
let out = text.replace(
|
|
228
|
+
HTML_SCRIPT_BODY_RE,
|
|
229
|
+
(_m, open, body, close) => open + body.replace(/[^\n]/g, " ") + close
|
|
230
|
+
);
|
|
231
|
+
out = out.replace(HTML_COMMENT_RE, (m) => m.replace(/[^\n]/g, " "));
|
|
232
|
+
out = out.replace(LIQUID_COMMENT_RE, (m) => m.replace(/[^\n]/g, " "));
|
|
233
|
+
out = out.replace(HTML_CDATA_RE, (m) => m.replace(/[^\n]/g, " "));
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
var HTML_HEADING_RE = /<h([1-6])[^>]*>(.*?)<\/h\1>/gis;
|
|
237
|
+
var HTML_HEADING_TAG_STRIP_RE = /<[^>]+>/g;
|
|
238
|
+
function findHtmlHeadingMatches(content) {
|
|
239
|
+
const masked = maskHtmlNoise(content);
|
|
240
|
+
const matches = [];
|
|
241
|
+
for (const m of masked.matchAll(HTML_HEADING_RE)) {
|
|
242
|
+
const level = parseInt(m[1] ?? "1", 10);
|
|
243
|
+
const raw = m[2] ?? "";
|
|
244
|
+
const heading = raw.replace(HTML_HEADING_TAG_STRIP_RE, "").trim();
|
|
245
|
+
matches.push({ level, heading, offset: m.index ?? 0, tag: m[0] ?? "" });
|
|
246
|
+
}
|
|
247
|
+
return matches;
|
|
248
|
+
}
|
|
249
|
+
function isInsideStringLiteral(line, index, from = 0, opts = {}) {
|
|
250
|
+
let openQuote = null;
|
|
251
|
+
let i = from;
|
|
252
|
+
while (i < index) {
|
|
253
|
+
const ch = line[i];
|
|
254
|
+
if (opts.symbolLiterals === true && openQuote === null && ch === "'") {
|
|
255
|
+
const len = scalaCharLiteralLength(line, i);
|
|
256
|
+
i += len === 0 ? 1 : len;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (openQuote !== null && ch === "\\" && i + 1 < line.length) {
|
|
260
|
+
i += 2;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (ch === '"' || ch === "'") {
|
|
264
|
+
if (openQuote === null) {
|
|
265
|
+
openQuote = ch;
|
|
266
|
+
} else if (openQuote === ch) {
|
|
267
|
+
openQuote = null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
i++;
|
|
271
|
+
}
|
|
272
|
+
return openQuote !== null;
|
|
273
|
+
}
|
|
274
|
+
function nextBlockCommentOpen(line, from, opts = {}) {
|
|
275
|
+
const lineCommentIdx = lineCommentStartIndex(line, ["//"], from);
|
|
276
|
+
let open = line.indexOf("/*", from);
|
|
277
|
+
while (open !== -1 && (isInsideStringLiteral(line, open, from, opts) || lineCommentIdx !== -1 && open >= lineCommentIdx)) {
|
|
278
|
+
open = line.indexOf("/*", open + 1);
|
|
279
|
+
}
|
|
280
|
+
return open;
|
|
281
|
+
}
|
|
282
|
+
function stripBlockCommentSpan(line, inComment, opts = {}) {
|
|
283
|
+
let code = "";
|
|
284
|
+
let j = 0;
|
|
285
|
+
let comment = inComment;
|
|
286
|
+
while (j < line.length) {
|
|
287
|
+
if (!comment) {
|
|
288
|
+
const open = nextBlockCommentOpen(line, j, opts);
|
|
289
|
+
if (open === -1) {
|
|
290
|
+
code += line.slice(j);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
code += line.slice(j, open);
|
|
294
|
+
const close = line.indexOf("*/", open + 2);
|
|
295
|
+
if (close === -1) {
|
|
296
|
+
code += " ".repeat(line.length - open);
|
|
297
|
+
comment = true;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
code += " ".repeat(close + 2 - open);
|
|
301
|
+
j = close + 2;
|
|
302
|
+
comment = false;
|
|
303
|
+
} else {
|
|
304
|
+
const close = line.indexOf("*/", j);
|
|
305
|
+
if (close === -1) {
|
|
306
|
+
code += " ".repeat(line.length - j);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
code += " ".repeat(close + 2 - j);
|
|
310
|
+
j = close + 2;
|
|
311
|
+
comment = false;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return { code, inComment: comment };
|
|
315
|
+
}
|
|
316
|
+
function stripNestedBlockCommentSpan(line, depth, opts = {}) {
|
|
317
|
+
let code = "";
|
|
318
|
+
let j = 0;
|
|
319
|
+
let d = depth;
|
|
320
|
+
while (j < line.length) {
|
|
321
|
+
if (d === 0) {
|
|
322
|
+
const open = nextBlockCommentOpen(line, j, opts);
|
|
323
|
+
if (open === -1) {
|
|
324
|
+
code += line.slice(j);
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
code += line.slice(j, open);
|
|
328
|
+
code += " ";
|
|
329
|
+
j = open + 2;
|
|
330
|
+
d = 1;
|
|
331
|
+
} else {
|
|
332
|
+
const open = line.indexOf("/*", j);
|
|
333
|
+
const close = line.indexOf("*/", j);
|
|
334
|
+
if (close === -1 && open === -1) {
|
|
335
|
+
code += " ".repeat(line.length - j);
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
const next = close === -1 ? open : open === -1 ? close : Math.min(open, close);
|
|
339
|
+
code += " ".repeat(next + 2 - j);
|
|
340
|
+
d = Math.max(0, d + (next === open ? 1 : -1));
|
|
341
|
+
j = next + 2;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return { code, depth: d };
|
|
345
|
+
}
|
|
346
|
+
function stripLineComment(line, markers = ["//"], opts = {}) {
|
|
347
|
+
const cutIdx = lineCommentStartIndex(line, markers, 0, opts);
|
|
348
|
+
return cutIdx === -1 ? line : line.slice(0, cutIdx);
|
|
349
|
+
}
|
|
350
|
+
function lineCommentStartIndex(line, markers, from = 0, opts = {}) {
|
|
351
|
+
let cutIdx = -1;
|
|
352
|
+
for (const marker of markers) {
|
|
353
|
+
let idx = line.indexOf(marker, from);
|
|
354
|
+
while (idx !== -1 && isInsideStringLiteral(line, idx, from, opts)) {
|
|
355
|
+
idx = line.indexOf(marker, idx + 1);
|
|
356
|
+
}
|
|
357
|
+
if (idx !== -1 && (cutIdx === -1 || idx < cutIdx)) cutIdx = idx;
|
|
358
|
+
}
|
|
359
|
+
return cutIdx;
|
|
360
|
+
}
|
|
361
|
+
function scalaCharLiteralLength(line, index) {
|
|
362
|
+
if (line[index] !== "'") return 0;
|
|
363
|
+
if (line[index + 1] === "\\") {
|
|
364
|
+
if (line[index + 2] === "u") {
|
|
365
|
+
let i = index + 3;
|
|
366
|
+
while (line[i] === "u") i++;
|
|
367
|
+
return /^[0-9a-fA-F]{4}$/.test(line.slice(i, i + 4)) && line[i + 4] === "'" ? i + 5 - index : 0;
|
|
368
|
+
}
|
|
369
|
+
return line[index + 2] !== void 0 && line[index + 3] === "'" ? 4 : 0;
|
|
370
|
+
}
|
|
371
|
+
return line[index + 1] !== void 0 && line[index + 1] !== "'" && line[index + 2] === "'" ? 3 : 0;
|
|
372
|
+
}
|
|
373
|
+
function stripStringLiterals(line, opts = {}) {
|
|
374
|
+
const stringFrame = (idx, delim) => {
|
|
375
|
+
const quote = line[idx];
|
|
376
|
+
const prev = line[idx - 1] ?? "";
|
|
377
|
+
const bareBraceHole = quote === '"' && (idx > 0 && prev === "$" || idx > 1 && prev === "@" && line[idx - 2] === "$" || idx > 1 && prev === "$" && line[idx - 2] === "@");
|
|
378
|
+
const plain = opts.interpolatorPrefix === true && !/[A-Za-z0-9_]/.test(prev) || opts.singleQuoteHoles === true && prev === "r" && !/[A-Za-z0-9_$]/.test(line[idx - 2] ?? "");
|
|
379
|
+
return { kind: "string", quote: delim, bareBraceHole, plain };
|
|
380
|
+
};
|
|
381
|
+
const openDelim = (idx) => {
|
|
382
|
+
const q = line[idx];
|
|
383
|
+
if (opts.tripleQuotes && line[idx + 1] === q && line[idx + 2] === q) return q + q + q;
|
|
384
|
+
return q;
|
|
385
|
+
};
|
|
386
|
+
let out = "";
|
|
387
|
+
let i = 0;
|
|
388
|
+
const stack = [];
|
|
389
|
+
while (i < line.length) {
|
|
390
|
+
const ch = line[i];
|
|
391
|
+
if (ch === "\n") {
|
|
392
|
+
out += ch;
|
|
393
|
+
i++;
|
|
394
|
+
stack.length = 0;
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const top = stack[stack.length - 1];
|
|
398
|
+
if (top === void 0) {
|
|
399
|
+
if (opts.symbolLiterals === true && ch === "'" && scalaCharLiteralLength(line, i) === 0) {
|
|
400
|
+
out += ch;
|
|
401
|
+
i++;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (ch === '"' || ch === "'") {
|
|
405
|
+
const delim = openDelim(i);
|
|
406
|
+
stack.push(stringFrame(i, delim));
|
|
407
|
+
out += delim;
|
|
408
|
+
i += delim.length;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
out += ch;
|
|
412
|
+
i++;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (top.kind === "hole") {
|
|
416
|
+
if (top.paren === true && (ch === "(" || ch === ")")) {
|
|
417
|
+
if (ch === "(") {
|
|
418
|
+
top.depth++;
|
|
419
|
+
out += ch;
|
|
420
|
+
} else {
|
|
421
|
+
if (top.depth > 0) {
|
|
422
|
+
top.depth--;
|
|
423
|
+
out += ch;
|
|
424
|
+
} else {
|
|
425
|
+
stack.pop();
|
|
426
|
+
out += " ";
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
i++;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (top.paren === true && (ch === "{" || ch === "}")) {
|
|
433
|
+
out += ch;
|
|
434
|
+
i++;
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (opts.symbolLiterals === true && ch === "'" && scalaCharLiteralLength(line, i) === 0) {
|
|
438
|
+
out += ch;
|
|
439
|
+
i++;
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (ch === '"' || ch === "'") {
|
|
443
|
+
const delim = openDelim(i);
|
|
444
|
+
stack.push(stringFrame(i, delim));
|
|
445
|
+
out += delim;
|
|
446
|
+
i += delim.length;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (ch === "{") {
|
|
450
|
+
top.depth++;
|
|
451
|
+
out += ch;
|
|
452
|
+
i++;
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (ch === "}") {
|
|
456
|
+
if (top.depth > 0) {
|
|
457
|
+
top.depth--;
|
|
458
|
+
} else {
|
|
459
|
+
stack.pop();
|
|
460
|
+
}
|
|
461
|
+
out += ch;
|
|
462
|
+
i++;
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
out += ch;
|
|
466
|
+
i++;
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (opts.swiftInterpolation === true && top.quote === '"' && ch === "\\" && line[i + 1] === "(") {
|
|
470
|
+
stack.push({ kind: "hole", depth: 0, paren: true });
|
|
471
|
+
out += " ";
|
|
472
|
+
i += 2;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
if (ch === "\\" && i + 1 < line.length && line[i + 1] !== "\n") {
|
|
476
|
+
out += " ";
|
|
477
|
+
i += 2;
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
if (ch === top.quote[0] && (top.quote.length === 1 || line.startsWith(top.quote, i))) {
|
|
481
|
+
stack.pop();
|
|
482
|
+
out += top.quote;
|
|
483
|
+
i += top.quote.length;
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (!top.plain && (top.quote === '"' || opts.singleQuoteHoles === true && top.quote[0] === "'")) {
|
|
487
|
+
if (top.bareBraceHole && ch === "{") {
|
|
488
|
+
if (line[i + 1] === "{") {
|
|
489
|
+
out += " ";
|
|
490
|
+
i += 2;
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
stack.push({ kind: "hole", depth: 0 });
|
|
494
|
+
out += ch;
|
|
495
|
+
i++;
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
if (!top.bareBraceHole && ch === "$" && line[i + 1] === "{") {
|
|
499
|
+
stack.push({ kind: "hole", depth: 0 });
|
|
500
|
+
out += line.slice(i, i + 2);
|
|
501
|
+
i += 2;
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (!top.bareBraceHole && ch === "{" && line[i + 1] === "$") {
|
|
505
|
+
stack.push({ kind: "hole", depth: 0 });
|
|
506
|
+
out += ch;
|
|
507
|
+
i++;
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
out += " ";
|
|
512
|
+
i++;
|
|
513
|
+
}
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
516
|
+
function closingQuoteRunEnd(text, from, quote, len, runClose) {
|
|
517
|
+
for (let i = from; i < text.length; i++) {
|
|
518
|
+
if (text[i] !== quote) continue;
|
|
519
|
+
let run = 0;
|
|
520
|
+
while (text[i + run] === quote) run++;
|
|
521
|
+
if (run >= len) return runClose === "last" ? i + run : i + len;
|
|
522
|
+
i += run - 1;
|
|
523
|
+
}
|
|
524
|
+
return -1;
|
|
525
|
+
}
|
|
526
|
+
var MULTILINE_CLOSER_ANCHOR = {
|
|
527
|
+
// An Elixir heredoc is terminated only by a delimiter run that begins its own line, preceded by nothing but the whitespace that also sets the indentation stripped from the body (Elixir syntax reference, section "Strings", heredocs). A run appearing mid-line inside the body is content.
|
|
528
|
+
elixir: "lineStart",
|
|
529
|
+
// The closing delimiter of a Swift multi-line string literal has to appear on a line of its own, and its indentation sets what is stripped from each body line (The Swift Programming Language, "Strings and Characters", section "Multiline String Literals"). The same section's rules apply to the extended-delimiter multi-line form (`#"""`), whose only reachable state here is the cross-line one.
|
|
530
|
+
swift: "lineStart",
|
|
531
|
+
// A PHP heredoc or nowdoc closes on its identifier at the start of a line; PHP 7.3 allowed that identifier to be indented and to be followed by other characters (PHP language reference, "Strings", section "Heredoc text"). Read by the heredoc/nowdoc branch, which builds its anchor regex from this value.
|
|
532
|
+
php: "lineStart",
|
|
533
|
+
// A PowerShell here-string terminator (`"@` / `'@`) must be the first characters on its line, with no leading whitespace at all, which is the one language here that is stricter than `'lineStart'` (about_Quoting_Rules, "Here-Strings").
|
|
534
|
+
powershell: "column0",
|
|
535
|
+
// Kotlin's raw string is terminated by the next `"""` wherever it falls, so `val s = """a"""` on one line is a complete literal (Kotlin language specification, "Expressions", section "String literals").
|
|
536
|
+
kotlin: "anywhere",
|
|
537
|
+
// Scala's multi-line string literal is likewise terminated by the next run of three quotes on any line (Scala language specification, section 1.3.5 "Character Literals and String Literals").
|
|
538
|
+
scala: "anywhere",
|
|
539
|
+
// Dart's multi-line string production is a delimiter, content, then the delimiter, with no rule about where on a line the closing delimiter falls (Dart Programming Language Specification, section "Strings").
|
|
540
|
+
dart: "anywhere",
|
|
541
|
+
// A GraphQL block string closes at the next `"""` wherever it sits: the spec's BlockString production places no positional rule on the closing delimiter, and a one-line description such as `"""A user."""` is the ordinary form (GraphQL specification, section 2.9.4 "String Value").
|
|
542
|
+
graphql: "anywhere",
|
|
543
|
+
// C# has two cross-line forms and they disagree, so the language-level value is the permissive one. A verbatim string (`@"..."`) closes on the next non-doubled quote wherever it sits and has no positional rule (C# language reference, "String literals"). A multi-line raw string literal does require its closing run to begin its own line (C# language reference, "Raw string literals"), but that rule is unreachable as a mis-pairing here: the same section forbids the content from holding a quote run as long as the delimiter, so no run inside the body can be mistaken for the closer in the first place, and the run-length rule already in `closingQuoteRunEnd` is what enforces it.
|
|
544
|
+
csharp: "anywhere",
|
|
545
|
+
// R has no fixed-delimiter multi-line form and no positional rule: an ordinary character constant runs to its next unescaped quote (R Language Definition, section 10.3.1 "Literal constants") and a raw constant to its mirrored closing punctuation (R base help page `?Quotes`, "Raw character constants"), on whatever line either lands.
|
|
546
|
+
r: "anywhere"
|
|
547
|
+
};
|
|
548
|
+
function closerSearchStart(line, from, anchor) {
|
|
549
|
+
if (anchor === "anywhere") return from;
|
|
550
|
+
const indent = anchor === "column0" ? 0 : /^[ \t]*/.exec(line)?.[0].length ?? 0;
|
|
551
|
+
return from <= indent ? indent : -1;
|
|
552
|
+
}
|
|
553
|
+
var TRIPLE_QUOTE_RUN_CLOSE = {
|
|
554
|
+
kotlin: "last",
|
|
555
|
+
scala: "last",
|
|
556
|
+
// A GraphQL block string ends at the first `"""` run, because its grammar excludes that sequence from the body outright rather than letting the longest run win (GraphQL specification, section 2.9.4 "String Value", the BlockString production).
|
|
557
|
+
graphql: "first",
|
|
558
|
+
// Swift's closing delimiter has to stand alone on its own line (The Swift Programming Language, "Strings and Characters", section "Multiline String Literals"), so no run longer than three ever terminates a valid Swift literal; it is grouped with Kotlin and Scala so that the same-line and cross-line paths agree, not to assert a rule Swift itself defines.
|
|
559
|
+
swift: "last",
|
|
560
|
+
csharp: "last",
|
|
561
|
+
// An Elixir heredoc cannot open and close on one line, because its opening `"""` must be followed by a newline, so only the cross-line closer is reachable for valid Elixir and that path has always consumed the whole run.
|
|
562
|
+
elixir: "last",
|
|
563
|
+
dart: "first",
|
|
564
|
+
// No triple-quoted literal at all: PHP uses heredoc/nowdoc, PowerShell `@"`/`@'` here-strings, R ordinary and raw character constants. Present only because the Record is exhaustive; the value is never read for these three.
|
|
565
|
+
php: "last",
|
|
566
|
+
powershell: "last",
|
|
567
|
+
r: "last"
|
|
568
|
+
};
|
|
569
|
+
function quoteRunCloser(line, from, quote, len, state) {
|
|
570
|
+
const anchor = state.closerAnchor ?? "anywhere";
|
|
571
|
+
const start = closerSearchStart(line, from, anchor);
|
|
572
|
+
if (start === -1) return null;
|
|
573
|
+
if (anchor !== "anywhere") {
|
|
574
|
+
let run = 0;
|
|
575
|
+
while (line[start + run] === quote) run++;
|
|
576
|
+
if (run < len) return null;
|
|
577
|
+
}
|
|
578
|
+
const end = closingQuoteRunEnd(line, start, quote, len, state.runClose ?? "last");
|
|
579
|
+
return end === -1 ? null : { maskEnd: end };
|
|
580
|
+
}
|
|
581
|
+
function findMultilineCloser(line, from, state) {
|
|
582
|
+
switch (state.kind) {
|
|
583
|
+
case "heredoc":
|
|
584
|
+
case "nowdoc": {
|
|
585
|
+
const indent = (state.closerAnchor ?? "anywhere") === "column0" ? "" : "[ \\t]*";
|
|
586
|
+
const re = new RegExp(`^${indent}${escapeRegExp(state.identifier)}\\b`);
|
|
587
|
+
const m = re.exec(line);
|
|
588
|
+
return m ? { maskEnd: m[0].length } : null;
|
|
589
|
+
}
|
|
590
|
+
case "sigil": {
|
|
591
|
+
const end = elixirSigilEnd(line, from, state);
|
|
592
|
+
return end === -1 ? null : { maskEnd: end };
|
|
593
|
+
}
|
|
594
|
+
case "tripleSingleQuote": {
|
|
595
|
+
return quoteRunCloser(line, from, "'", 3, state);
|
|
596
|
+
}
|
|
597
|
+
case "tripleQuote": {
|
|
598
|
+
const n = state.identifier !== "" ? parseInt(state.identifier, 10) : 3;
|
|
599
|
+
return quoteRunCloser(line, from, '"', n, state);
|
|
600
|
+
}
|
|
601
|
+
case "rRaw":
|
|
602
|
+
case "swiftExtended": {
|
|
603
|
+
const anchor = state.closerAnchor ?? "anywhere";
|
|
604
|
+
if (anchor !== "anywhere") {
|
|
605
|
+
const start = closerSearchStart(line, from, anchor);
|
|
606
|
+
if (start === -1 || !line.startsWith(state.identifier, start)) return null;
|
|
607
|
+
return { maskEnd: start + state.identifier.length };
|
|
608
|
+
}
|
|
609
|
+
const idx = line.indexOf(state.identifier, from);
|
|
610
|
+
return idx === -1 ? null : { maskEnd: idx + state.identifier.length };
|
|
611
|
+
}
|
|
612
|
+
case "rString": {
|
|
613
|
+
const idx = findRQuoteEnd(line, from, state.identifier);
|
|
614
|
+
return idx === -1 ? null : { maskEnd: idx + 1 };
|
|
615
|
+
}
|
|
616
|
+
case "verbatim": {
|
|
617
|
+
if (!state.interpolated) {
|
|
618
|
+
let j2 = from;
|
|
619
|
+
while (j2 < line.length) {
|
|
620
|
+
if (line[j2] === '"') {
|
|
621
|
+
if (line[j2 + 1] === '"') {
|
|
622
|
+
j2 += 2;
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
return { maskEnd: j2 + 1 };
|
|
626
|
+
}
|
|
627
|
+
j2++;
|
|
628
|
+
}
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
let j = from;
|
|
632
|
+
let holeDepth = 0;
|
|
633
|
+
let nestedQuote = null;
|
|
634
|
+
while (j < line.length) {
|
|
635
|
+
const c = line[j];
|
|
636
|
+
if (nestedQuote !== null) {
|
|
637
|
+
if (c === "\\" && j + 1 < line.length) {
|
|
638
|
+
j += 2;
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
if (c === nestedQuote) {
|
|
642
|
+
nestedQuote = null;
|
|
643
|
+
}
|
|
644
|
+
j++;
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
if (holeDepth > 0) {
|
|
648
|
+
if (c === '"' || c === "'") {
|
|
649
|
+
nestedQuote = c;
|
|
650
|
+
j++;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
if (c === "{") holeDepth++;
|
|
654
|
+
else if (c === "}") holeDepth--;
|
|
655
|
+
j++;
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
if (c === "{") {
|
|
659
|
+
holeDepth = 1;
|
|
660
|
+
j++;
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
if (c === '"') {
|
|
664
|
+
if (line[j + 1] === '"') {
|
|
665
|
+
j += 2;
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
return { maskEnd: j + 1 };
|
|
669
|
+
}
|
|
670
|
+
j++;
|
|
671
|
+
}
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
case "psHereDouble":
|
|
675
|
+
case "psHereSingle": {
|
|
676
|
+
const start = closerSearchStart(line, from, state.closerAnchor ?? "anywhere");
|
|
677
|
+
const terminator = state.kind === "psHereDouble" ? '"@' : "'@";
|
|
678
|
+
if (start === -1 || !line.startsWith(terminator, start)) return null;
|
|
679
|
+
return { maskEnd: start + terminator.length };
|
|
680
|
+
}
|
|
681
|
+
default:
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
var MULTILINE_OPENER_COMMENT_MARKERS = {
|
|
686
|
+
php: ["//", "#"],
|
|
687
|
+
kotlin: ["//"],
|
|
688
|
+
graphql: ["#"],
|
|
689
|
+
csharp: ["//"],
|
|
690
|
+
powershell: ["#"],
|
|
691
|
+
swift: ["//"],
|
|
692
|
+
elixir: ["#"],
|
|
693
|
+
scala: ["//"],
|
|
694
|
+
dart: ["//"],
|
|
695
|
+
r: ["#"]
|
|
696
|
+
};
|
|
697
|
+
var MULTILINE_OPENER_BLOCK_COMMENT_LANGS = /* @__PURE__ */ new Set(["php", "kotlin", "csharp", "swift", "scala", "dart"]);
|
|
698
|
+
var R_RAW_OPENER_RE = /[rR](["'])(-*)([([{])/y;
|
|
699
|
+
var R_RAW_CLOSE_BRACKET = { "(": ")", "[": "]", "{": "}" };
|
|
700
|
+
var R_IDENT_CHAR_RE = /[A-Za-z0-9._]/;
|
|
701
|
+
function matchRRawOpener(text, index) {
|
|
702
|
+
const ch = text[index];
|
|
703
|
+
if (ch !== "r" && ch !== "R") return null;
|
|
704
|
+
if (R_IDENT_CHAR_RE.test(text[index - 1] ?? "")) return null;
|
|
705
|
+
R_RAW_OPENER_RE.lastIndex = index;
|
|
706
|
+
const m = R_RAW_OPENER_RE.exec(text);
|
|
707
|
+
if (m === null) return null;
|
|
708
|
+
const close = R_RAW_CLOSE_BRACKET[m[3] ?? ""];
|
|
709
|
+
if (close === void 0) return null;
|
|
710
|
+
return { openerEnd: index + m[0].length, closer: `${close}${m[2] ?? ""}${m[1] ?? ""}` };
|
|
711
|
+
}
|
|
712
|
+
var GROOVY_OPERAND_BEFORE = /* @__PURE__ */ new Set([..."([{,;=+-*/%<>!&|^~?:"]);
|
|
713
|
+
var MAX_GROOVY_SLASHY_BODY = 1024;
|
|
714
|
+
var GROOVY_OPERAND_KEYWORDS = /* @__PURE__ */ new Set(["return", "case", "in", "new", "assert", "instanceof"]);
|
|
715
|
+
function groovyOperandPosition(text, index) {
|
|
716
|
+
let i = index - 1;
|
|
717
|
+
while (i >= 0 && (text[i] === " " || text[i] === " ")) i--;
|
|
718
|
+
if (i < 0) return true;
|
|
719
|
+
const ch = text[i];
|
|
720
|
+
if (ch === "\n" || ch === "\r") return true;
|
|
721
|
+
if (GROOVY_OPERAND_BEFORE.has(ch)) return true;
|
|
722
|
+
if (!/[\w$]/.test(ch)) return false;
|
|
723
|
+
let j = i;
|
|
724
|
+
while (j >= 0 && /[\w$]/.test(text[j])) j--;
|
|
725
|
+
return GROOVY_OPERAND_KEYWORDS.has(text.slice(j + 1, i + 1));
|
|
726
|
+
}
|
|
727
|
+
function matchGroovySlashy(text, index) {
|
|
728
|
+
const dollar = text[index] === "$" && text[index + 1] === "/";
|
|
729
|
+
if (!dollar) {
|
|
730
|
+
if (text[index] !== "/") return null;
|
|
731
|
+
const next = text[index + 1];
|
|
732
|
+
if (next === "/" || next === "*") return null;
|
|
733
|
+
if (!groovyOperandPosition(text, index)) return null;
|
|
734
|
+
}
|
|
735
|
+
const bodyStart = index + (dollar ? 2 : 1);
|
|
736
|
+
const limit = Math.min(text.length, bodyStart + MAX_GROOVY_SLASHY_BODY);
|
|
737
|
+
for (let i = bodyStart; i < limit; i++) {
|
|
738
|
+
const ch = text[i];
|
|
739
|
+
if (dollar) {
|
|
740
|
+
if (ch === "$" && (text[i + 1] === "$" || text[i + 1] === "/")) {
|
|
741
|
+
i++;
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
if (ch === "/" && text[i + 1] === "$") return { bodyStart, bodyEnd: i, end: i + 2 };
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (ch === "\\" && text[i + 1] === "/") {
|
|
748
|
+
i++;
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
if (ch === "\n") return null;
|
|
752
|
+
if (ch === "/") return { bodyStart, bodyEnd: i, end: i + 1 };
|
|
753
|
+
}
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
756
|
+
var ELIXIR_SIGIL_CLOSER = { "(": ")", "[": "]", "{": "}", "<": ">", "/": "/", "|": "|", '"': '"', "'": "'" };
|
|
757
|
+
var ELIXIR_SIGIL_OPENER = { ")": "(", "]": "[", "}": "{", ">": "<" };
|
|
758
|
+
function matchElixirSigilOpener(line, index) {
|
|
759
|
+
if (line[index] !== "~") return null;
|
|
760
|
+
let i = index + 1;
|
|
761
|
+
const first = line[i] ?? "";
|
|
762
|
+
let escapes;
|
|
763
|
+
if (first >= "a" && first <= "z") {
|
|
764
|
+
escapes = true;
|
|
765
|
+
i++;
|
|
766
|
+
} else if (first >= "A" && first <= "Z") {
|
|
767
|
+
escapes = false;
|
|
768
|
+
while (i < line.length && (line[i] ?? "") >= "A" && (line[i] ?? "") <= "Z") i++;
|
|
769
|
+
} else {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
const delim = line[i] ?? "";
|
|
773
|
+
const closer = ELIXIR_SIGIL_CLOSER[delim];
|
|
774
|
+
if (closer === void 0) return null;
|
|
775
|
+
if ((delim === '"' || delim === "'") && line[i + 1] === delim && line[i + 2] === delim) return null;
|
|
776
|
+
return { openerEnd: i + 1, closer, escapes };
|
|
777
|
+
}
|
|
778
|
+
function elixirSigilEnd(line, from, state) {
|
|
779
|
+
const closer = state.identifier;
|
|
780
|
+
const opener = ELIXIR_SIGIL_OPENER[closer];
|
|
781
|
+
for (let i = from; i < line.length; i++) {
|
|
782
|
+
const ch = line[i];
|
|
783
|
+
if (state.escapes === true && ch === "\\") {
|
|
784
|
+
i++;
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
if (opener !== void 0 && ch === opener) {
|
|
788
|
+
state.depth = (state.depth ?? 0) + 1;
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
if (ch === closer) {
|
|
792
|
+
if ((state.depth ?? 0) > 0) {
|
|
793
|
+
state.depth = (state.depth ?? 0) - 1;
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
return i + 1;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return -1;
|
|
800
|
+
}
|
|
801
|
+
var SWIFT_EXTENDED_OPENER_RE = /(#+)("""|")/y;
|
|
802
|
+
function matchSwiftExtendedOpener(text, index) {
|
|
803
|
+
if (text[index] !== "#") return null;
|
|
804
|
+
SWIFT_EXTENDED_OPENER_RE.lastIndex = index;
|
|
805
|
+
const m = SWIFT_EXTENDED_OPENER_RE.exec(text);
|
|
806
|
+
if (m === null) return null;
|
|
807
|
+
const hashes = m[1] ?? "";
|
|
808
|
+
const multiline = m[2] === '"""';
|
|
809
|
+
return { openerEnd: index + m[0].length, multiline, closer: `${multiline ? '"""' : '"'}${hashes}` };
|
|
810
|
+
}
|
|
811
|
+
var BASH_WORD_TERMINATORS = /* @__PURE__ */ new Set([" ", " ", "\n", "|", "&", ";", "(", ")", "<", ">"]);
|
|
812
|
+
function matchBashHeredocOpener(text, index) {
|
|
813
|
+
if (text[index] !== "<" || text[index + 1] !== "<") return null;
|
|
814
|
+
if (text[index - 1] === "<" || text[index + 2] === "<") return null;
|
|
815
|
+
let i = index + 2;
|
|
816
|
+
if (text[i] === "-") i++;
|
|
817
|
+
while (text[i] === " " || text[i] === " ") i++;
|
|
818
|
+
let terminator = "";
|
|
819
|
+
while (i < text.length) {
|
|
820
|
+
const ch = text[i];
|
|
821
|
+
if (ch === "'") {
|
|
822
|
+
const close = text.indexOf("'", i + 1);
|
|
823
|
+
if (close === -1) return null;
|
|
824
|
+
terminator += text.slice(i + 1, close);
|
|
825
|
+
i = close + 1;
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
if (ch === '"') {
|
|
829
|
+
let j = i + 1;
|
|
830
|
+
for (; j < text.length; j++) {
|
|
831
|
+
if (text[j] === "\\") {
|
|
832
|
+
terminator += text[j + 1] ?? "";
|
|
833
|
+
j++;
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (text[j] === '"') break;
|
|
837
|
+
terminator += text[j];
|
|
838
|
+
}
|
|
839
|
+
if (j >= text.length) return null;
|
|
840
|
+
i = j + 1;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if (ch === "\\") {
|
|
844
|
+
if (i + 1 >= text.length) break;
|
|
845
|
+
terminator += text[i + 1];
|
|
846
|
+
i += 2;
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
if (ch === void 0 || BASH_WORD_TERMINATORS.has(ch)) break;
|
|
850
|
+
terminator += ch;
|
|
851
|
+
i++;
|
|
852
|
+
}
|
|
853
|
+
if (terminator === "") return null;
|
|
854
|
+
return { openerEnd: i, terminator };
|
|
855
|
+
}
|
|
856
|
+
function findRQuoteEnd(line, start, quote) {
|
|
857
|
+
for (let j = start; j < line.length; j++) {
|
|
858
|
+
const c = line[j];
|
|
859
|
+
if (c === "\\") {
|
|
860
|
+
j++;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
if (c === quote) return j;
|
|
864
|
+
}
|
|
865
|
+
return -1;
|
|
866
|
+
}
|
|
867
|
+
function isInsideSameLineBlockComment(line, idx, from = 0) {
|
|
868
|
+
let comment = false;
|
|
869
|
+
let j = from;
|
|
870
|
+
while (j < idx) {
|
|
871
|
+
if (!comment) {
|
|
872
|
+
const open = line.indexOf("/*", j);
|
|
873
|
+
if (open === -1 || open >= idx) return false;
|
|
874
|
+
if (isInsideStringLiteral(line, open, from)) {
|
|
875
|
+
j = open + 2;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
comment = true;
|
|
879
|
+
j = open + 2;
|
|
880
|
+
} else {
|
|
881
|
+
const close = line.indexOf("*/", j);
|
|
882
|
+
if (close === -1 || close >= idx) return true;
|
|
883
|
+
comment = false;
|
|
884
|
+
j = close + 2;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return comment;
|
|
888
|
+
}
|
|
889
|
+
function findMultilineOpener(line, from, lang) {
|
|
890
|
+
const commentIdx = lineCommentStartIndex(line, MULTILINE_OPENER_COMMENT_MARKERS[lang], from);
|
|
891
|
+
const isCommented = (idx) => commentIdx !== -1 && idx >= commentIdx || MULTILINE_OPENER_BLOCK_COMMENT_LANGS.has(lang) && isInsideSameLineBlockComment(line, idx, from);
|
|
892
|
+
if (lang === "php") {
|
|
893
|
+
const re = /<<<\s*(['"]?)([A-Za-z_]\w*)\1/g;
|
|
894
|
+
re.lastIndex = from;
|
|
895
|
+
const m = re.exec(line);
|
|
896
|
+
if (!m || isInsideStringLiteral(line, m.index, from) || isCommented(m.index)) return null;
|
|
897
|
+
const identifier = m[2] ?? "";
|
|
898
|
+
const kind = m[1] === "'" ? "nowdoc" : "heredoc";
|
|
899
|
+
return { openStart: m.index, closesSameLine: null, state: { kind, identifier, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] } };
|
|
900
|
+
}
|
|
901
|
+
if (lang === "kotlin" || lang === "swift" || lang === "scala" || lang === "graphql") {
|
|
902
|
+
let swiftExt = null;
|
|
903
|
+
if (lang === "swift") {
|
|
904
|
+
for (let h = line.indexOf("#", from); h !== -1; h = line.indexOf("#", h + 1)) {
|
|
905
|
+
const ext = matchSwiftExtendedOpener(line, h);
|
|
906
|
+
if (ext === null || isInsideStringLiteral(line, h, from) || isCommented(h)) continue;
|
|
907
|
+
const extClose = line.indexOf(ext.closer, ext.openerEnd);
|
|
908
|
+
const extState = { kind: "swiftExtended", identifier: ext.closer, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] };
|
|
909
|
+
if (extClose !== -1) {
|
|
910
|
+
swiftExt = { openStart: h, closesSameLine: extClose + ext.closer.length, state: extState };
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
913
|
+
if (ext.multiline) {
|
|
914
|
+
swiftExt = { openStart: h, closesSameLine: null, state: extState };
|
|
915
|
+
break;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
const idx = line.indexOf('"""', from);
|
|
920
|
+
if (swiftExt !== null && (idx === -1 || swiftExt.openStart < idx)) return swiftExt;
|
|
921
|
+
if (idx === -1 || isInsideStringLiteral(line, idx, from) || isCommented(idx)) return null;
|
|
922
|
+
const runClose = TRIPLE_QUOTE_RUN_CLOSE[lang];
|
|
923
|
+
const tripleState = { kind: "tripleQuote", identifier: "3", runClose, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] };
|
|
924
|
+
const closeEnd = closingQuoteRunEnd(line, idx + 3, '"', 3, runClose);
|
|
925
|
+
if (closeEnd !== -1) {
|
|
926
|
+
return { openStart: idx, closesSameLine: closeEnd, state: tripleState };
|
|
927
|
+
}
|
|
928
|
+
return { openStart: idx, closesSameLine: null, state: tripleState };
|
|
929
|
+
}
|
|
930
|
+
if (lang === "elixir" || lang === "dart") {
|
|
931
|
+
const candidates = [];
|
|
932
|
+
const dq = line.indexOf('"""', from);
|
|
933
|
+
if (dq !== -1) candidates.push([dq, "tripleQuote", '"""']);
|
|
934
|
+
const sq = line.indexOf("'''", from);
|
|
935
|
+
if (sq !== -1) candidates.push([sq, "tripleSingleQuote", "'''"]);
|
|
936
|
+
candidates.sort((a, b) => a[0] - b[0]);
|
|
937
|
+
const first = candidates[0];
|
|
938
|
+
if (lang === "elixir") {
|
|
939
|
+
for (let t = line.indexOf("~", from); t !== -1; t = line.indexOf("~", t + 1)) {
|
|
940
|
+
if (first !== void 0 && first[0] < t) break;
|
|
941
|
+
const open = matchElixirSigilOpener(line, t);
|
|
942
|
+
if (open === null || isInsideStringLiteral(line, t, from) || isCommented(t)) continue;
|
|
943
|
+
const state2 = { kind: "sigil", identifier: open.closer, depth: 0, escapes: open.escapes };
|
|
944
|
+
const end = elixirSigilEnd(line, open.openerEnd, state2);
|
|
945
|
+
return { openStart: t, closesSameLine: end === -1 ? null : end, state: state2 };
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
if (first === void 0) return null;
|
|
949
|
+
const [idx, kind, delim] = first;
|
|
950
|
+
if (isInsideStringLiteral(line, idx, from) || isCommented(idx)) return null;
|
|
951
|
+
const runClose = TRIPLE_QUOTE_RUN_CLOSE[lang];
|
|
952
|
+
const state = { kind, identifier: "3", runClose, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] };
|
|
953
|
+
const closeEnd = closingQuoteRunEnd(line, idx + 3, delim[0] ?? '"', 3, runClose);
|
|
954
|
+
if (closeEnd !== -1) return { openStart: idx, closesSameLine: closeEnd, state };
|
|
955
|
+
return { openStart: idx, closesSameLine: null, state };
|
|
956
|
+
}
|
|
957
|
+
if (lang === "r") {
|
|
958
|
+
const limit = commentIdx === -1 ? line.length : commentIdx;
|
|
959
|
+
let i = from;
|
|
960
|
+
while (i < limit) {
|
|
961
|
+
const ch = line[i] ?? "";
|
|
962
|
+
if (ch === "`") {
|
|
963
|
+
const end = line.indexOf("`", i + 1);
|
|
964
|
+
if (end === -1 || end >= limit) return null;
|
|
965
|
+
i = end + 1;
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
const raw = matchRRawOpener(line, i);
|
|
969
|
+
if (raw !== null) {
|
|
970
|
+
const closeIdx = line.indexOf(raw.closer, raw.openerEnd);
|
|
971
|
+
if (closeIdx === -1) return { openStart: i, closesSameLine: null, state: { kind: "rRaw", identifier: raw.closer, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] } };
|
|
972
|
+
i = closeIdx + raw.closer.length;
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
if (ch === '"' || ch === "'") {
|
|
976
|
+
const closeIdx = findRQuoteEnd(line, i + 1, ch);
|
|
977
|
+
if (closeIdx === -1) return { openStart: i, closesSameLine: null, state: { kind: "rString", identifier: ch, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] } };
|
|
978
|
+
i = closeIdx + 1;
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
i++;
|
|
982
|
+
}
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
if (lang === "csharp") {
|
|
986
|
+
const tripleRe = /"{3,}/g;
|
|
987
|
+
tripleRe.lastIndex = from;
|
|
988
|
+
const tripleM = tripleRe.exec(line);
|
|
989
|
+
let tripleIdx = tripleM ? tripleM.index : -1;
|
|
990
|
+
const tripleLen = tripleM ? tripleM[0].length : 0;
|
|
991
|
+
if (tripleIdx !== -1 && (isInsideStringLiteral(line, tripleIdx, from) || isCommented(tripleIdx))) tripleIdx = -1;
|
|
992
|
+
const verbRe = /\$?@\$?"/g;
|
|
993
|
+
verbRe.lastIndex = from;
|
|
994
|
+
const verbM = verbRe.exec(line);
|
|
995
|
+
let verbIdx = verbM ? verbM.index : -1;
|
|
996
|
+
if (verbIdx !== -1 && isCommented(verbIdx)) verbIdx = -1;
|
|
997
|
+
if (verbIdx !== -1 && isInsideStringLiteral(line, verbIdx, from)) verbIdx = -1;
|
|
998
|
+
if (tripleIdx === -1 && verbIdx === -1) return null;
|
|
999
|
+
const useTriple = tripleIdx !== -1 && (verbIdx === -1 || tripleIdx < verbIdx);
|
|
1000
|
+
if (useTriple) {
|
|
1001
|
+
const rawState = { kind: "tripleQuote", identifier: String(tripleLen), runClose: TRIPLE_QUOTE_RUN_CLOSE.csharp, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] };
|
|
1002
|
+
const closeEnd = closingQuoteRunEnd(line, tripleIdx + tripleLen, '"', tripleLen, rawState.runClose ?? "last");
|
|
1003
|
+
if (closeEnd !== -1) {
|
|
1004
|
+
return { openStart: tripleIdx, closesSameLine: closeEnd, state: rawState };
|
|
1005
|
+
}
|
|
1006
|
+
return { openStart: tripleIdx, closesSameLine: null, state: rawState };
|
|
1007
|
+
}
|
|
1008
|
+
const quoteIdx = verbIdx + (verbM?.[0].length ?? 1) - 1;
|
|
1009
|
+
const interpolated = (verbM?.[0] ?? "").includes("$");
|
|
1010
|
+
const closer = findMultilineCloser(line, quoteIdx + 1, { kind: "verbatim", identifier: "", interpolated });
|
|
1011
|
+
if (closer !== null) {
|
|
1012
|
+
return { openStart: verbIdx, closesSameLine: closer.maskEnd, state: { kind: "verbatim", identifier: "", interpolated } };
|
|
1013
|
+
}
|
|
1014
|
+
return { openStart: verbIdx, closesSameLine: null, state: { kind: "verbatim", identifier: "", interpolated } };
|
|
1015
|
+
}
|
|
1016
|
+
if (lang === "powershell") {
|
|
1017
|
+
const re = /@("|')\s*$/;
|
|
1018
|
+
const tail = line.slice(from);
|
|
1019
|
+
const m = re.exec(tail);
|
|
1020
|
+
if (!m) return null;
|
|
1021
|
+
const openStart = from + m.index;
|
|
1022
|
+
if (isCommented(openStart)) return null;
|
|
1023
|
+
if (isInsideStringLiteral(line, openStart, from)) return null;
|
|
1024
|
+
const kind = m[1] === '"' ? "psHereDouble" : "psHereSingle";
|
|
1025
|
+
return { openStart, closesSameLine: null, state: { kind, identifier: "", closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] } };
|
|
1026
|
+
}
|
|
1027
|
+
return null;
|
|
1028
|
+
}
|
|
1029
|
+
function stripMultilineStringSpan(line, state, lang) {
|
|
1030
|
+
let code = "";
|
|
1031
|
+
let i = 0;
|
|
1032
|
+
let cur = state;
|
|
1033
|
+
while (i < line.length) {
|
|
1034
|
+
if (cur !== null) {
|
|
1035
|
+
const closed = findMultilineCloser(line, i, cur);
|
|
1036
|
+
if (closed === null) {
|
|
1037
|
+
code += " ".repeat(line.length - i);
|
|
1038
|
+
i = line.length;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
code += " ".repeat(closed.maskEnd - i);
|
|
1042
|
+
i = closed.maskEnd;
|
|
1043
|
+
cur = null;
|
|
1044
|
+
continue;
|
|
1045
|
+
}
|
|
1046
|
+
const opened = findMultilineOpener(line, i, lang);
|
|
1047
|
+
if (opened === null) {
|
|
1048
|
+
code += line.slice(i);
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
1051
|
+
code += line.slice(i, opened.openStart);
|
|
1052
|
+
if (opened.closesSameLine !== null) {
|
|
1053
|
+
code += " ".repeat(opened.closesSameLine - opened.openStart);
|
|
1054
|
+
i = opened.closesSameLine;
|
|
1055
|
+
cur = null;
|
|
1056
|
+
} else {
|
|
1057
|
+
code += " ".repeat(line.length - opened.openStart);
|
|
1058
|
+
i = line.length;
|
|
1059
|
+
cur = opened.state;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return { code, state: cur };
|
|
1063
|
+
}
|
|
1064
|
+
function makeSpanSymbol(filePath, name, kind, span, parent = "", lines, style) {
|
|
1065
|
+
return {
|
|
1066
|
+
filePath,
|
|
1067
|
+
name,
|
|
1068
|
+
kind,
|
|
1069
|
+
lineStart: span.startLine,
|
|
1070
|
+
lineEnd: span.endLine,
|
|
1071
|
+
body: span.body,
|
|
1072
|
+
docstring: lines !== void 0 && style !== void 0 ? precedingDocComment(lines, span.startLine, style) : "",
|
|
1073
|
+
parent
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
function makeLineSymbol(filePath, name, kind, line, sig, parent, lines, style) {
|
|
1077
|
+
return {
|
|
1078
|
+
filePath,
|
|
1079
|
+
name,
|
|
1080
|
+
kind,
|
|
1081
|
+
lineStart: line,
|
|
1082
|
+
lineEnd: line,
|
|
1083
|
+
body: sig ?? "",
|
|
1084
|
+
docstring: lines !== void 0 && style !== void 0 ? precedingDocComment(lines, line, style) : "",
|
|
1085
|
+
parent: parent ?? ""
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
function makeSymbolEmitter(symbols, sections, seen, filePath, maxSymbols = 1e4, maxHeadingLen = 120) {
|
|
1089
|
+
return function emit(name, kind, line) {
|
|
1090
|
+
if (!name || name.length > maxHeadingLen) return;
|
|
1091
|
+
if (symbols.length >= maxSymbols) return;
|
|
1092
|
+
const key = `${name}\0${kind}\0${line}`;
|
|
1093
|
+
if (seen.has(key)) return;
|
|
1094
|
+
seen.add(key);
|
|
1095
|
+
symbols.push({
|
|
1096
|
+
filePath,
|
|
1097
|
+
name,
|
|
1098
|
+
kind,
|
|
1099
|
+
lineStart: line,
|
|
1100
|
+
lineEnd: line,
|
|
1101
|
+
body: "",
|
|
1102
|
+
docstring: "",
|
|
1103
|
+
parent: ""
|
|
1104
|
+
});
|
|
1105
|
+
sections.push({ heading: name, level: 1, line, endLine: line });
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
function assignFlatEndLines(sections, totalLines) {
|
|
1109
|
+
for (let i = 0; i < sections.length; i++) {
|
|
1110
|
+
const s = sections[i];
|
|
1111
|
+
if (s === void 0) continue;
|
|
1112
|
+
let j = i + 1;
|
|
1113
|
+
while (j < sections.length && (sections[j]?.line ?? 0) <= s.line) j++;
|
|
1114
|
+
const next = sections[j];
|
|
1115
|
+
const end = next !== void 0 ? next.line - 1 : totalLines;
|
|
1116
|
+
s.endLine = end < s.line ? s.line : end;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
function propagateEndLinesToSymbols(symbols, sections) {
|
|
1120
|
+
const sectionMap = /* @__PURE__ */ new Map();
|
|
1121
|
+
for (const sec of sections) {
|
|
1122
|
+
const key = `${sec.heading}\0${sec.line}`;
|
|
1123
|
+
const queue = sectionMap.get(key);
|
|
1124
|
+
if (queue !== void 0) queue.push(sec.endLine);
|
|
1125
|
+
else sectionMap.set(key, [sec.endLine]);
|
|
1126
|
+
}
|
|
1127
|
+
return symbols.map((sym) => {
|
|
1128
|
+
const key = `${sym.name}\0${sym.lineStart}`;
|
|
1129
|
+
const endLine = sectionMap.get(key)?.shift();
|
|
1130
|
+
if (endLine !== void 0 && endLine !== sym.lineEnd) {
|
|
1131
|
+
return { ...sym, lineEnd: endLine };
|
|
1132
|
+
}
|
|
1133
|
+
return sym;
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
function lastContentLine(rawLines) {
|
|
1137
|
+
let n = rawLines.length;
|
|
1138
|
+
while (n > 0 && rawLines[n - 1].trim() === "") n--;
|
|
1139
|
+
return Math.max(1, n);
|
|
1140
|
+
}
|
|
1141
|
+
function nestedAngleClause(depth) {
|
|
1142
|
+
let inner = "[^<>]*";
|
|
1143
|
+
for (let i = 0; i < depth; i++) inner = "[^<>]*(?:<" + inner + ">[^<>]*)*";
|
|
1144
|
+
return "<" + inner + ">";
|
|
1145
|
+
}
|
|
1146
|
+
var GENERIC_CLAUSE = nestedAngleClause(4);
|
|
1147
|
+
|
|
1148
|
+
export {
|
|
1149
|
+
precedingDocComment,
|
|
1150
|
+
buildLineIndex,
|
|
1151
|
+
offsetToLine,
|
|
1152
|
+
lineTextAt,
|
|
1153
|
+
stripCstyleComments,
|
|
1154
|
+
stripXmlComments,
|
|
1155
|
+
scanQuotedStringEnd,
|
|
1156
|
+
stripJsComments,
|
|
1157
|
+
stripHashComments,
|
|
1158
|
+
maskHtmlNoise,
|
|
1159
|
+
findHtmlHeadingMatches,
|
|
1160
|
+
isInsideStringLiteral,
|
|
1161
|
+
stripBlockCommentSpan,
|
|
1162
|
+
stripNestedBlockCommentSpan,
|
|
1163
|
+
stripLineComment,
|
|
1164
|
+
scalaCharLiteralLength,
|
|
1165
|
+
stripStringLiterals,
|
|
1166
|
+
closingQuoteRunEnd,
|
|
1167
|
+
matchRRawOpener,
|
|
1168
|
+
matchGroovySlashy,
|
|
1169
|
+
matchBashHeredocOpener,
|
|
1170
|
+
stripMultilineStringSpan,
|
|
1171
|
+
makeSpanSymbol,
|
|
1172
|
+
makeLineSymbol,
|
|
1173
|
+
makeSymbolEmitter,
|
|
1174
|
+
assignFlatEndLines,
|
|
1175
|
+
propagateEndLinesToSymbols,
|
|
1176
|
+
lastContentLine,
|
|
1177
|
+
GENERIC_CLAUSE
|
|
1178
|
+
};
|