pickier 0.1.34 → 0.1.36
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/dist/bin/cli.js +438 -62
- package/dist/rules/markdown/_fence-tracking.d.ts +14 -0
- package/dist/src/index.js +437 -61
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -48,6 +48,37 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
48
48
|
var __require = import.meta.require;
|
|
49
49
|
|
|
50
50
|
// src/format.ts
|
|
51
|
+
function isHangingControlLine(code) {
|
|
52
|
+
const m = RE_CONTROL_OPEN.exec(code);
|
|
53
|
+
if (!m)
|
|
54
|
+
return /^(?:else|do)\s*$/.test(code);
|
|
55
|
+
let depth = 0;
|
|
56
|
+
let inStr = null;
|
|
57
|
+
for (let i = m[0].length - 1;i < code.length; i++) {
|
|
58
|
+
const ch = code[i];
|
|
59
|
+
if (inStr) {
|
|
60
|
+
if (ch === "\\") {
|
|
61
|
+
i++;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (ch === inStr)
|
|
65
|
+
inStr = null;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (ch === "'" || ch === '"' || ch === "`") {
|
|
69
|
+
inStr = ch;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (ch === "(") {
|
|
73
|
+
depth++;
|
|
74
|
+
} else if (ch === ")") {
|
|
75
|
+
depth--;
|
|
76
|
+
if (depth === 0)
|
|
77
|
+
return code.slice(i + 1).trim().length === 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
51
82
|
function getFileExt(filePath) {
|
|
52
83
|
const idx = filePath.lastIndexOf(".");
|
|
53
84
|
return idx >= 0 ? filePath.slice(idx) : "";
|
|
@@ -198,6 +229,25 @@ function fixQuotesLine(line, preferred) {
|
|
|
198
229
|
while (i < line.length) {
|
|
199
230
|
const ch = line[i];
|
|
200
231
|
if (inString === 0) {
|
|
232
|
+
if (ch === "/") {
|
|
233
|
+
const nxt = line[i + 1];
|
|
234
|
+
if (nxt === "/")
|
|
235
|
+
break;
|
|
236
|
+
if (nxt === "*") {
|
|
237
|
+
const end = line.indexOf("*/", i + 2);
|
|
238
|
+
i = end === -1 ? line.length : end + 2;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (isRegexStart(line, i)) {
|
|
242
|
+
const end = scanRegexEnd(line, i);
|
|
243
|
+
if (end !== -1) {
|
|
244
|
+
i = end;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
i++;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
201
251
|
if (ch === '"') {
|
|
202
252
|
inString = 2;
|
|
203
253
|
stringStart = i;
|
|
@@ -265,6 +315,8 @@ function normalizeSpacingLine(line) {
|
|
|
265
315
|
const c = line[firstNonSpace];
|
|
266
316
|
if (c === "/" && (line[firstNonSpace + 1] === "/" || line[firstNonSpace + 1] === "*"))
|
|
267
317
|
return line;
|
|
318
|
+
if (c === "*")
|
|
319
|
+
return line;
|
|
268
320
|
}
|
|
269
321
|
let hasSpacingChar = false;
|
|
270
322
|
for (let j = firstNonSpace;j < line.length; j++) {
|
|
@@ -377,6 +429,49 @@ function advanceTemplateState(line, stack) {
|
|
|
377
429
|
}
|
|
378
430
|
return -1;
|
|
379
431
|
}
|
|
432
|
+
function blockCommentStateAfter(line, startsIn) {
|
|
433
|
+
let inBlock = startsIn;
|
|
434
|
+
let inStr = null;
|
|
435
|
+
let i = 0;
|
|
436
|
+
while (i < line.length) {
|
|
437
|
+
const ch = line[i];
|
|
438
|
+
if (inBlock) {
|
|
439
|
+
if (ch === "*" && line[i + 1] === "/") {
|
|
440
|
+
inBlock = false;
|
|
441
|
+
i += 2;
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
i++;
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (inStr) {
|
|
448
|
+
if (ch === "\\") {
|
|
449
|
+
i += 2;
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (ch === inStr)
|
|
453
|
+
inStr = null;
|
|
454
|
+
i++;
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (ch === "'" || ch === '"' || ch === "`") {
|
|
458
|
+
inStr = ch;
|
|
459
|
+
i++;
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
if (ch === "/") {
|
|
463
|
+
if (line[i + 1] === "/")
|
|
464
|
+
break;
|
|
465
|
+
if (line[i + 1] === "*") {
|
|
466
|
+
inBlock = true;
|
|
467
|
+
i += 2;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
i++;
|
|
472
|
+
}
|
|
473
|
+
return inBlock;
|
|
474
|
+
}
|
|
380
475
|
function processCodeLinesFused(content, cfg) {
|
|
381
476
|
const lines = content.split(`
|
|
382
477
|
`);
|
|
@@ -385,9 +480,16 @@ function processCodeLinesFused(content, cfg) {
|
|
|
385
480
|
const preferred = cfg.format.quotes;
|
|
386
481
|
const doSemiRemoval = cfg.format.semi === true;
|
|
387
482
|
let indentLevel = 0;
|
|
483
|
+
let hangDepth = 0;
|
|
484
|
+
let inBlockComment = false;
|
|
388
485
|
const tmplStack = [];
|
|
389
486
|
for (let idx = 0;idx < len; idx++) {
|
|
390
487
|
let line = lines[idx];
|
|
488
|
+
if (inBlockComment) {
|
|
489
|
+
inBlockComment = blockCommentStateAfter(line, true);
|
|
490
|
+
result[idx] = line;
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
391
493
|
const protectedLine = inTemplateText(tmplStack);
|
|
392
494
|
let splitIdx = -1;
|
|
393
495
|
if (tmplStack.length > 0 || line.indexOf("`") !== -1)
|
|
@@ -396,6 +498,8 @@ function processCodeLinesFused(content, cfg) {
|
|
|
396
498
|
result[idx] = line;
|
|
397
499
|
continue;
|
|
398
500
|
}
|
|
501
|
+
if (splitIdx < 0 && tmplStack.length === 0)
|
|
502
|
+
inBlockComment = blockCommentStateAfter(line, false);
|
|
399
503
|
let tmplTail = "";
|
|
400
504
|
let prefixEndedWithSpace = false;
|
|
401
505
|
if (splitIdx >= 0) {
|
|
@@ -419,9 +523,15 @@ function processCodeLinesFused(content, cfg) {
|
|
|
419
523
|
const trimmed = line.slice(wsEnd).trimEnd();
|
|
420
524
|
if (RE_CLOSING_BRACE.test(trimmed))
|
|
421
525
|
indentLevel = Math.max(0, indentLevel - 1);
|
|
422
|
-
|
|
423
|
-
|
|
526
|
+
const continuationBump = RE_CONTINUATION_LINE.test(trimmed) ? 1 : 0;
|
|
527
|
+
line = makeIndent(indentLevel + hangDepth + continuationBump, cfg) + trimmed;
|
|
528
|
+
if (RE_OPENING_BRACE.test(trimmed)) {
|
|
424
529
|
indentLevel += 1;
|
|
530
|
+
hangDepth = 0;
|
|
531
|
+
} else if (!trimmed.startsWith("//") && !trimmed.startsWith("*") && !trimmed.startsWith("/*")) {
|
|
532
|
+
const code = trimmed.replace(RE_TRAILING_LINE_COMMENT, "");
|
|
533
|
+
hangDepth = isHangingControlLine(code) ? hangDepth + 1 : 0;
|
|
534
|
+
}
|
|
425
535
|
line = normalizeSpacingLine(line);
|
|
426
536
|
if (doSemiRemoval) {
|
|
427
537
|
if (!RE_FOR_LOOP.test(line)) {
|
|
@@ -653,8 +763,48 @@ function skipTemplate(input, start) {
|
|
|
653
763
|
}
|
|
654
764
|
return i;
|
|
655
765
|
}
|
|
766
|
+
function isRegexStart(input, slashIdx) {
|
|
767
|
+
let j = slashIdx - 1;
|
|
768
|
+
while (j >= 0 && (input[j] === " " || input[j] === "\t"))
|
|
769
|
+
j--;
|
|
770
|
+
if (j < 0)
|
|
771
|
+
return true;
|
|
772
|
+
const prev = input[j];
|
|
773
|
+
if ("(,=:[!&|?;{}<>+-*%^~".includes(prev))
|
|
774
|
+
return true;
|
|
775
|
+
if (/[\w$]/.test(prev)) {
|
|
776
|
+
let k = j;
|
|
777
|
+
while (k >= 0 && /[\w$]/.test(input[k]))
|
|
778
|
+
k--;
|
|
779
|
+
return REGEX_PRECEDING_KEYWORDS.has(input.slice(k + 1, j + 1));
|
|
780
|
+
}
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
function scanRegexEnd(input, start) {
|
|
784
|
+
let i = start + 1;
|
|
785
|
+
let inClass = false;
|
|
786
|
+
while (i < input.length) {
|
|
787
|
+
const c = input[i];
|
|
788
|
+
if (c === "\\") {
|
|
789
|
+
i += 2;
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
if (c === "[") {
|
|
793
|
+
inClass = true;
|
|
794
|
+
} else if (c === "]") {
|
|
795
|
+
inClass = false;
|
|
796
|
+
} else if (c === "/" && !inClass) {
|
|
797
|
+
i++;
|
|
798
|
+
while (i < input.length && /[a-z]/i.test(input[i]))
|
|
799
|
+
i++;
|
|
800
|
+
return i;
|
|
801
|
+
}
|
|
802
|
+
i++;
|
|
803
|
+
}
|
|
804
|
+
return -1;
|
|
805
|
+
}
|
|
656
806
|
function maskStrings(input) {
|
|
657
|
-
if (!input.includes("'") && !input.includes('"') && !input.includes("`"))
|
|
807
|
+
if (!input.includes("'") && !input.includes('"') && !input.includes("`") && !input.includes("/"))
|
|
658
808
|
return { text: input, strings: [] };
|
|
659
809
|
const strings = [];
|
|
660
810
|
const parts = [];
|
|
@@ -662,6 +812,42 @@ function maskStrings(input) {
|
|
|
662
812
|
let segStart = 0;
|
|
663
813
|
while (i < input.length) {
|
|
664
814
|
const ch = input[i];
|
|
815
|
+
if (ch === "/") {
|
|
816
|
+
const next = input[i + 1];
|
|
817
|
+
if (next === "/") {
|
|
818
|
+
if (i > segStart)
|
|
819
|
+
parts.push(input.slice(segStart, i));
|
|
820
|
+
strings.push(input.slice(i));
|
|
821
|
+
parts.push(`@@S${strings.length - 1}@@`);
|
|
822
|
+
segStart = input.length;
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
if (next === "*") {
|
|
826
|
+
const end = input.indexOf("*/", i + 2);
|
|
827
|
+
const stop = end === -1 ? input.length : end + 2;
|
|
828
|
+
if (i > segStart)
|
|
829
|
+
parts.push(input.slice(segStart, i));
|
|
830
|
+
strings.push(input.slice(i, stop));
|
|
831
|
+
parts.push(`@@S${strings.length - 1}@@`);
|
|
832
|
+
i = stop;
|
|
833
|
+
segStart = i;
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (isRegexStart(input, i)) {
|
|
837
|
+
const end = scanRegexEnd(input, i);
|
|
838
|
+
if (end !== -1) {
|
|
839
|
+
if (i > segStart)
|
|
840
|
+
parts.push(input.slice(segStart, i));
|
|
841
|
+
strings.push(input.slice(i, end));
|
|
842
|
+
parts.push(`@@S${strings.length - 1}@@`);
|
|
843
|
+
i = end;
|
|
844
|
+
segStart = i;
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
i++;
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
665
851
|
if (ch === "'" || ch === '"' || ch === "`") {
|
|
666
852
|
if (i > segStart)
|
|
667
853
|
parts.push(input.slice(segStart, i));
|
|
@@ -717,24 +903,65 @@ function formatImports(source) {
|
|
|
717
903
|
const lines = source.split(`
|
|
718
904
|
`);
|
|
719
905
|
const imports = [];
|
|
906
|
+
const preamble = [];
|
|
907
|
+
const interleaved = [];
|
|
720
908
|
let idx = 0;
|
|
909
|
+
let lastEnd = 0;
|
|
910
|
+
let pendingStart = -1;
|
|
911
|
+
let sawImport = false;
|
|
721
912
|
while (idx < lines.length) {
|
|
722
913
|
const line = lines[idx];
|
|
723
|
-
if (RE_BLANK_LINE.test(line)
|
|
914
|
+
if (RE_BLANK_LINE.test(line)) {
|
|
724
915
|
idx++;
|
|
725
916
|
continue;
|
|
726
917
|
}
|
|
918
|
+
if (RE_LINE_COMMENT.test(line) || RE_BLOCK_COMMENT.test(line)) {
|
|
919
|
+
const start = idx;
|
|
920
|
+
if (RE_BLOCK_COMMENT.test(line)) {
|
|
921
|
+
while (idx < lines.length && !lines[idx].includes("*/"))
|
|
922
|
+
idx++;
|
|
923
|
+
idx++;
|
|
924
|
+
} else {
|
|
925
|
+
idx++;
|
|
926
|
+
}
|
|
927
|
+
if (!sawImport) {
|
|
928
|
+
for (let k = start;k < idx && k < lines.length; k++)
|
|
929
|
+
preamble.push(lines[k]);
|
|
930
|
+
lastEnd = idx;
|
|
931
|
+
} else if (pendingStart < 0) {
|
|
932
|
+
pendingStart = start;
|
|
933
|
+
}
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
727
936
|
if (!RE_IMPORT_STMT.test(line))
|
|
728
937
|
break;
|
|
729
|
-
|
|
938
|
+
let stmt = line.trim();
|
|
939
|
+
let stmtEnd = idx + 1;
|
|
940
|
+
while (!RE_IMPORT_COMPLETE.test(stmt) && stmtEnd < lines.length && stmtEnd - idx < 50) {
|
|
941
|
+
stmt += ` ${lines[stmtEnd].trim()}`;
|
|
942
|
+
stmtEnd++;
|
|
943
|
+
}
|
|
944
|
+
if (!RE_IMPORT_COMPLETE.test(stmt))
|
|
945
|
+
return source;
|
|
730
946
|
const parsed = parseImportStatement(stmt);
|
|
731
|
-
if (parsed)
|
|
732
|
-
|
|
733
|
-
|
|
947
|
+
if (!parsed)
|
|
948
|
+
return source;
|
|
949
|
+
if (pendingStart >= 0) {
|
|
950
|
+
for (let k = pendingStart;k < idx; k++) {
|
|
951
|
+
if (!RE_BLANK_LINE.test(lines[k]))
|
|
952
|
+
interleaved.push(lines[k]);
|
|
953
|
+
}
|
|
954
|
+
pendingStart = -1;
|
|
955
|
+
}
|
|
956
|
+
imports.push(parsed);
|
|
957
|
+
idx = stmtEnd;
|
|
958
|
+
lastEnd = idx;
|
|
959
|
+
sawImport = true;
|
|
734
960
|
}
|
|
735
961
|
if (imports.length === 0)
|
|
736
962
|
return source;
|
|
737
|
-
const
|
|
963
|
+
const restStart = pendingStart >= 0 ? pendingStart : lastEnd;
|
|
964
|
+
const rest = lines.slice(restStart).join(`
|
|
738
965
|
`);
|
|
739
966
|
const usedIdentifiers = collectIdentifierSet(rest);
|
|
740
967
|
const used = (name) => usedIdentifiers.has(name);
|
|
@@ -855,17 +1082,29 @@ function formatImports(source) {
|
|
|
855
1082
|
}
|
|
856
1083
|
return a.source.localeCompare(b.source);
|
|
857
1084
|
});
|
|
1085
|
+
const head = preamble.length > 0 ? `${preamble.join(`
|
|
1086
|
+
`)}
|
|
1087
|
+
` : "";
|
|
858
1088
|
if (entries.length === 0) {
|
|
859
|
-
|
|
1089
|
+
const restClean2 = rest.replace(/^\n+/, "");
|
|
1090
|
+
const kept = [...interleaved];
|
|
1091
|
+
if (head || kept.length > 0)
|
|
1092
|
+
return `${head}${kept.length > 0 ? `${kept.join(`
|
|
1093
|
+
`)}
|
|
1094
|
+
` : ""}${restClean2}`;
|
|
1095
|
+
return restClean2;
|
|
860
1096
|
}
|
|
861
1097
|
const rendered = entries.map(renderImport).join(`
|
|
862
1098
|
`);
|
|
863
|
-
const
|
|
864
|
-
`
|
|
1099
|
+
const mid = interleaved.length > 0 ? `
|
|
1100
|
+
${interleaved.join(`
|
|
1101
|
+
`)}` : "";
|
|
1102
|
+
const restClean = rest.replace(/^\n+/, "");
|
|
1103
|
+
const sep = restClean.length > 0 ? `
|
|
865
1104
|
|
|
866
1105
|
` : `
|
|
867
1106
|
`;
|
|
868
|
-
return `${rendered}${sep}${
|
|
1107
|
+
return `${head}${rendered}${mid}${sep}${restClean}`;
|
|
869
1108
|
}
|
|
870
1109
|
function renderImport(imp) {
|
|
871
1110
|
if (imp.kind === "side-effect")
|
|
@@ -1168,39 +1407,44 @@ function sortTsconfigContent(text) {
|
|
|
1168
1407
|
}
|
|
1169
1408
|
return JSON.stringify(outTop, null, 2);
|
|
1170
1409
|
}
|
|
1171
|
-
var CODE_EXTS, JSON_EXTS, YAML_EXTS, SHELL_EXTS, SHELL_SHEBANG_RE, RE_CLOSING_BRACE, RE_OPENING_BRACE, RE_FOR_LOOP, RE_EMPTY_SEMI, RE_DUP_SEMI, RE_SPACE_BEFORE_BRACE, RE_SPACE_AFTER_BRACE_KW, RE_COMMA_SPACE, RE_EQUALS_SPACE, RE_PLUS_OP, RE_MINUS_OP, RE_STAR_OP, RE_SLASH_OP, RE_SEMI_SPACE, RE_LT_OP, RE_GT_OP, RE_MULTI_SPACE, RE_BLANK_LINE, RE_LINE_COMMENT, RE_BLOCK_COMMENT, RE_IMPORT_STMT, RE_PACKAGE_JSON, RE_TSCONFIG_JSON, RE_TRAILING_WS, RE_LEADING_BLANKS, SPACING_CHARS;
|
|
1410
|
+
var CODE_EXTS, JSON_EXTS, YAML_EXTS, SHELL_EXTS, SHELL_SHEBANG_RE, RE_CLOSING_BRACE, RE_OPENING_BRACE, RE_TRAILING_LINE_COMMENT, RE_CONTROL_OPEN, RE_CONTINUATION_LINE, RE_FOR_LOOP, RE_EMPTY_SEMI, RE_DUP_SEMI, RE_SPACE_BEFORE_BRACE, RE_SPACE_AFTER_BRACE_KW, RE_COMMA_SPACE, RE_EQUALS_SPACE, RE_PLUS_OP, RE_MINUS_OP, RE_STAR_OP, RE_SLASH_OP, RE_SEMI_SPACE, RE_LT_OP, RE_GT_OP, RE_MULTI_SPACE, RE_BLANK_LINE, RE_LINE_COMMENT, RE_BLOCK_COMMENT, RE_IMPORT_STMT, RE_IMPORT_COMPLETE, RE_PACKAGE_JSON, RE_TSCONFIG_JSON, RE_TRAILING_WS, RE_LEADING_BLANKS, SPACING_CHARS, REGEX_PRECEDING_KEYWORDS;
|
|
1172
1411
|
var init_format = __esm(() => {
|
|
1173
1412
|
CODE_EXTS = new Set([".ts", ".js"]);
|
|
1174
1413
|
JSON_EXTS = new Set([".json", ".jsonc"]);
|
|
1175
1414
|
YAML_EXTS = new Set([".yaml", ".yml"]);
|
|
1176
1415
|
SHELL_EXTS = new Set([".sh", ".bash", ".zsh", ".ksh", ".dash"]);
|
|
1177
1416
|
SHELL_SHEBANG_RE = /^#!\s*(?:\/usr\/bin\/env\s+)?(?:ba|z|k|da)?sh\b/;
|
|
1178
|
-
RE_CLOSING_BRACE =
|
|
1179
|
-
RE_OPENING_BRACE =
|
|
1417
|
+
RE_CLOSING_BRACE = /^[}\])]/;
|
|
1418
|
+
RE_OPENING_BRACE = /[{[(]\s*$/;
|
|
1419
|
+
RE_TRAILING_LINE_COMMENT = /\s*\/\/.*$/;
|
|
1420
|
+
RE_CONTROL_OPEN = /^(?:if|else\s+if|for|while)\s*\(/;
|
|
1421
|
+
RE_CONTINUATION_LINE = /^(?:\.[\w$[]|\?[\s.:]|:\s|&&|\|\|)/;
|
|
1180
1422
|
RE_FOR_LOOP = /^\s*for\s*\(/;
|
|
1181
1423
|
RE_EMPTY_SEMI = new RegExp("^\\s*" + ";" + "\\s*$");
|
|
1182
1424
|
RE_DUP_SEMI = new RegExp(";" + "{2,}\\s*$");
|
|
1183
|
-
RE_SPACE_BEFORE_BRACE = /(\
|
|
1425
|
+
RE_SPACE_BEFORE_BRACE = /([\w)])\{/g;
|
|
1184
1426
|
RE_SPACE_AFTER_BRACE_KW = /\{(return|if|for|while|switch|const|let|var|function)\b/g;
|
|
1185
1427
|
RE_COMMA_SPACE = /,(\S)/g;
|
|
1186
|
-
RE_EQUALS_SPACE = /(?<![
|
|
1428
|
+
RE_EQUALS_SPACE = /(?<![=!<>+\-*/%&|^?])=(?![=><])/g;
|
|
1187
1429
|
RE_PLUS_OP = /(\w)\+(\w)/g;
|
|
1188
1430
|
RE_MINUS_OP = /(\w)-(\w)/g;
|
|
1189
1431
|
RE_STAR_OP = /(\w)\*(\w)/g;
|
|
1190
1432
|
RE_SLASH_OP = /(\w)\/(\w)/g;
|
|
1191
|
-
RE_SEMI_SPACE = new RegExp(";" + "([^\\s" + ";" + "])", "g");
|
|
1192
|
-
RE_LT_OP = /([\w\]
|
|
1193
|
-
RE_GT_OP = /(\
|
|
1433
|
+
RE_SEMI_SPACE = new RegExp("(?<=\\S);" + "([^\\s" + ";" + "])", "g");
|
|
1434
|
+
RE_LT_OP = /([\w)\]])<(\d)/g;
|
|
1435
|
+
RE_GT_OP = /([\w)\]])>(\d)/g;
|
|
1194
1436
|
RE_MULTI_SPACE = /\s{2,}/g;
|
|
1195
1437
|
RE_BLANK_LINE = /^\s*$/;
|
|
1196
1438
|
RE_LINE_COMMENT = /^\s*\/\//;
|
|
1197
1439
|
RE_BLOCK_COMMENT = /^\s*\/\*/;
|
|
1198
1440
|
RE_IMPORT_STMT = /^\s*import\b/;
|
|
1441
|
+
RE_IMPORT_COMPLETE = /\bfrom\s*['"][^'"]+['"]|^\s*import\s+['"][^'"]+['"]/;
|
|
1199
1442
|
RE_PACKAGE_JSON = /package\.json$/i;
|
|
1200
1443
|
RE_TSCONFIG_JSON = /[jt]sconfig(?:\..+)?\.json$/i;
|
|
1201
1444
|
RE_TRAILING_WS = /[ \t]+$/;
|
|
1202
1445
|
RE_LEADING_BLANKS = /^\n+/;
|
|
1203
1446
|
SPACING_CHARS = new Set(["{", ",", "=", "+", "-", "*", "/", ";", "<", ">"]);
|
|
1447
|
+
REGEX_PRECEDING_KEYWORDS = new Set(["return", "typeof", "instanceof", "in", "of", "new", "delete", "void", "do", "else", "case", "yield", "await"]);
|
|
1204
1448
|
});
|
|
1205
1449
|
|
|
1206
1450
|
// ../../node_modules/bunfig/dist/index.js
|
|
@@ -20767,7 +21011,7 @@ var init_no_unused_vars = __esm(() => {
|
|
|
20767
21011
|
let tInBlockComment = false;
|
|
20768
21012
|
let tEscaped = false;
|
|
20769
21013
|
let prevSig = "";
|
|
20770
|
-
const
|
|
21014
|
+
const isRegexStart2 = () => {
|
|
20771
21015
|
if (prevSig === "")
|
|
20772
21016
|
return true;
|
|
20773
21017
|
if ("=([{,;!&|?:+-*/%^~<>".includes(prevSig))
|
|
@@ -20869,7 +21113,7 @@ var init_no_unused_vars = __esm(() => {
|
|
|
20869
21113
|
else
|
|
20870
21114
|
tmplStack.pop();
|
|
20871
21115
|
prevSig = "}";
|
|
20872
|
-
} else if (ch === "/" &&
|
|
21116
|
+
} else if (ch === "/" && isRegexStart2()) {
|
|
20873
21117
|
tInRegex = true;
|
|
20874
21118
|
} else if (!/\s/.test(ch)) {
|
|
20875
21119
|
prevSig = ch;
|
|
@@ -20885,7 +21129,7 @@ var init_no_unused_vars = __esm(() => {
|
|
|
20885
21129
|
} else if (ch === '"') {
|
|
20886
21130
|
tInDouble = true;
|
|
20887
21131
|
prevSig = '"';
|
|
20888
|
-
} else if (ch === "/" &&
|
|
21132
|
+
} else if (ch === "/" && isRegexStart2()) {
|
|
20889
21133
|
tInRegex = true;
|
|
20890
21134
|
} else if (!/\s/.test(ch)) {
|
|
20891
21135
|
prevSig = ch;
|
|
@@ -20922,6 +21166,15 @@ var init_no_unused_vars = __esm(() => {
|
|
|
20922
21166
|
continue;
|
|
20923
21167
|
}
|
|
20924
21168
|
if (!inString) {
|
|
21169
|
+
if (ch === "/" && after[k + 1] === "/")
|
|
21170
|
+
break;
|
|
21171
|
+
if (ch === "/" && after[k + 1] === "*") {
|
|
21172
|
+
k += 2;
|
|
21173
|
+
while (k < after.length && !(after[k] === "*" && after[k + 1] === "/"))
|
|
21174
|
+
k++;
|
|
21175
|
+
k++;
|
|
21176
|
+
continue;
|
|
21177
|
+
}
|
|
20925
21178
|
if (ch === "'") {
|
|
20926
21179
|
inString = "single";
|
|
20927
21180
|
} else if (ch === '"') {
|
|
@@ -22084,7 +22337,7 @@ function computeLineStartsInTemplate(text) {
|
|
|
22084
22337
|
let inBlockComment = false;
|
|
22085
22338
|
let escaped = false;
|
|
22086
22339
|
let prevSig = "";
|
|
22087
|
-
const
|
|
22340
|
+
const isRegexStart2 = () => {
|
|
22088
22341
|
if (prevSig === "")
|
|
22089
22342
|
return true;
|
|
22090
22343
|
return "=([{,;!&|?:+-*/%^~<>".includes(prevSig);
|
|
@@ -22184,7 +22437,7 @@ function computeLineStartsInTemplate(text) {
|
|
|
22184
22437
|
else
|
|
22185
22438
|
tmplStack.pop();
|
|
22186
22439
|
prevSig = "}";
|
|
22187
|
-
} else if (ch === "/" &&
|
|
22440
|
+
} else if (ch === "/" && isRegexStart2())
|
|
22188
22441
|
inRegex = true;
|
|
22189
22442
|
else if (!/\s/.test(ch))
|
|
22190
22443
|
prevSig = ch;
|
|
@@ -22199,7 +22452,7 @@ function computeLineStartsInTemplate(text) {
|
|
|
22199
22452
|
} else if (ch === '"') {
|
|
22200
22453
|
inDouble = true;
|
|
22201
22454
|
prevSig = '"';
|
|
22202
|
-
} else if (ch === "/" &&
|
|
22455
|
+
} else if (ch === "/" && isRegexStart2())
|
|
22203
22456
|
inRegex = true;
|
|
22204
22457
|
else if (!/\s/.test(ch))
|
|
22205
22458
|
prevSig = ch;
|
|
@@ -23536,24 +23789,39 @@ var init_blanks_around_lists = __esm(() => {
|
|
|
23536
23789
|
const lines = text.split(/\r?\n/);
|
|
23537
23790
|
const result = [];
|
|
23538
23791
|
let inList = false;
|
|
23792
|
+
let inFence = false;
|
|
23793
|
+
const isListItemLine = (l) => /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(l);
|
|
23539
23794
|
for (let i = 0;i < lines.length; i++) {
|
|
23540
23795
|
const line = lines[i];
|
|
23541
23796
|
const prevLine = i > 0 ? lines[i - 1] : "";
|
|
23542
|
-
|
|
23797
|
+
if (/^(?:`{3,}|~{3,})/.test(line.trim())) {
|
|
23798
|
+
inFence = !inFence;
|
|
23799
|
+
inList = false;
|
|
23800
|
+
result.push(line);
|
|
23801
|
+
continue;
|
|
23802
|
+
}
|
|
23803
|
+
if (inFence) {
|
|
23804
|
+
result.push(line);
|
|
23805
|
+
continue;
|
|
23806
|
+
}
|
|
23807
|
+
const isListItem = isListItemLine(line);
|
|
23808
|
+
const isBlank = line.trim().length === 0;
|
|
23809
|
+
const isContinuation = inList && !isListItem && !isBlank && /^\s/.test(line);
|
|
23543
23810
|
if (isListItem && !inList) {
|
|
23544
23811
|
if (i > 0 && prevLine.trim().length > 0 && result.length > 0) {
|
|
23545
23812
|
result.push("");
|
|
23546
23813
|
}
|
|
23547
23814
|
inList = true;
|
|
23548
|
-
} else if (!isListItem &&
|
|
23815
|
+
} else if (!isListItem && !isContinuation && !isBlank && inList) {
|
|
23549
23816
|
inList = false;
|
|
23550
23817
|
if (result.length > 0) {
|
|
23551
23818
|
result.push("");
|
|
23552
23819
|
}
|
|
23553
|
-
} else if (
|
|
23820
|
+
} else if (isBlank) {
|
|
23554
23821
|
const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
|
|
23555
|
-
const nextIsListItem =
|
|
23556
|
-
|
|
23822
|
+
const nextIsListItem = isListItemLine(nextLine);
|
|
23823
|
+
const nextIsContinuation = /^\s+\S/.test(nextLine);
|
|
23824
|
+
if (!nextIsListItem && !nextIsContinuation && inList) {
|
|
23557
23825
|
inList = false;
|
|
23558
23826
|
}
|
|
23559
23827
|
}
|
|
@@ -23624,6 +23892,64 @@ function getCodeBlockLines(lines) {
|
|
|
23624
23892
|
}
|
|
23625
23893
|
return out;
|
|
23626
23894
|
}
|
|
23895
|
+
function eachInlineSegment(line, onText, onCode) {
|
|
23896
|
+
let i = 0;
|
|
23897
|
+
let textStart = 0;
|
|
23898
|
+
while (i < line.length) {
|
|
23899
|
+
if (line[i] !== "`") {
|
|
23900
|
+
i++;
|
|
23901
|
+
continue;
|
|
23902
|
+
}
|
|
23903
|
+
let n = 0;
|
|
23904
|
+
while (line[i + n] === "`")
|
|
23905
|
+
n++;
|
|
23906
|
+
let j = i + n;
|
|
23907
|
+
let close = -1;
|
|
23908
|
+
while (j < line.length) {
|
|
23909
|
+
if (line[j] === "`") {
|
|
23910
|
+
let k = 0;
|
|
23911
|
+
while (line[j + k] === "`")
|
|
23912
|
+
k++;
|
|
23913
|
+
if (k === n) {
|
|
23914
|
+
close = j;
|
|
23915
|
+
break;
|
|
23916
|
+
}
|
|
23917
|
+
j += k;
|
|
23918
|
+
} else {
|
|
23919
|
+
j++;
|
|
23920
|
+
}
|
|
23921
|
+
}
|
|
23922
|
+
if (close === -1) {
|
|
23923
|
+
i += n;
|
|
23924
|
+
continue;
|
|
23925
|
+
}
|
|
23926
|
+
if (textStart < i)
|
|
23927
|
+
onText(line.slice(textStart, i));
|
|
23928
|
+
onCode(line.slice(i, close + n));
|
|
23929
|
+
i = close + n;
|
|
23930
|
+
textStart = i;
|
|
23931
|
+
}
|
|
23932
|
+
if (textStart < line.length)
|
|
23933
|
+
onText(line.slice(textStart));
|
|
23934
|
+
}
|
|
23935
|
+
function replaceOutsideInlineCode(line, transform) {
|
|
23936
|
+
let out = "";
|
|
23937
|
+
eachInlineSegment(line, (seg) => {
|
|
23938
|
+
out += transform(seg);
|
|
23939
|
+
}, (seg) => {
|
|
23940
|
+
out += seg;
|
|
23941
|
+
});
|
|
23942
|
+
return out;
|
|
23943
|
+
}
|
|
23944
|
+
function maskInlineCode(line) {
|
|
23945
|
+
let out = "";
|
|
23946
|
+
eachInlineSegment(line, (seg) => {
|
|
23947
|
+
out += seg;
|
|
23948
|
+
}, (seg) => {
|
|
23949
|
+
out += " ".repeat(seg.length);
|
|
23950
|
+
});
|
|
23951
|
+
return out;
|
|
23952
|
+
}
|
|
23627
23953
|
|
|
23628
23954
|
// src/rules/markdown/_shared.ts
|
|
23629
23955
|
function findTableRows(lines) {
|
|
@@ -24034,8 +24360,10 @@ var init_descriptive_link_text = __esm(() => {
|
|
|
24034
24360
|
});
|
|
24035
24361
|
|
|
24036
24362
|
// src/rules/markdown/emphasis-style.ts
|
|
24037
|
-
var emphasisStyleRule;
|
|
24363
|
+
var ASTERISK_EMPHASIS, UNDERSCORE_EMPHASIS, emphasisStyleRule;
|
|
24038
24364
|
var init_emphasis_style = __esm(() => {
|
|
24365
|
+
ASTERISK_EMPHASIS = /(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/;
|
|
24366
|
+
UNDERSCORE_EMPHASIS = /(?<!_)_(?!_)([^_]+)_(?!_)/;
|
|
24039
24367
|
emphasisStyleRule = {
|
|
24040
24368
|
meta: {
|
|
24041
24369
|
docs: "Emphasis style should be consistent (asterisk or underscore)"
|
|
@@ -24114,27 +24442,51 @@ var init_emphasis_style = __esm(() => {
|
|
|
24114
24442
|
fix: (text, ctx) => {
|
|
24115
24443
|
const options = ctx.options || {};
|
|
24116
24444
|
const style = options.style || "consistent";
|
|
24445
|
+
const lines = text.split(/\r?\n/);
|
|
24446
|
+
const inCode = getCodeBlockLines(lines);
|
|
24117
24447
|
let targetStyle = "asterisk";
|
|
24118
24448
|
if (style === "asterisk") {
|
|
24119
24449
|
targetStyle = "asterisk";
|
|
24120
24450
|
} else if (style === "underscore") {
|
|
24121
24451
|
targetStyle = "underscore";
|
|
24122
24452
|
} else if (style === "consistent") {
|
|
24123
|
-
|
|
24124
|
-
|
|
24125
|
-
|
|
24453
|
+
let firstAsterisk = null;
|
|
24454
|
+
let firstUnderscore = null;
|
|
24455
|
+
for (let i = 0;i < lines.length; i++) {
|
|
24456
|
+
if (inCode.has(i))
|
|
24457
|
+
continue;
|
|
24458
|
+
const stripped = maskInlineCode(lines[i]);
|
|
24459
|
+
if (firstAsterisk === null) {
|
|
24460
|
+
const m = stripped.match(ASTERISK_EMPHASIS);
|
|
24461
|
+
if (m)
|
|
24462
|
+
firstAsterisk = { line: i, col: m.index };
|
|
24463
|
+
}
|
|
24464
|
+
if (firstUnderscore === null) {
|
|
24465
|
+
const m = stripped.match(UNDERSCORE_EMPHASIS);
|
|
24466
|
+
if (m)
|
|
24467
|
+
firstUnderscore = { line: i, col: m.index };
|
|
24468
|
+
}
|
|
24469
|
+
if (firstAsterisk && firstUnderscore)
|
|
24470
|
+
break;
|
|
24471
|
+
}
|
|
24472
|
+
const cmp = (a, b) => a.line !== b.line ? a.line - b.line : a.col - b.col;
|
|
24473
|
+
if (firstAsterisk && (!firstUnderscore || cmp(firstAsterisk, firstUnderscore) < 0))
|
|
24126
24474
|
targetStyle = "asterisk";
|
|
24127
|
-
|
|
24475
|
+
else if (firstUnderscore)
|
|
24128
24476
|
targetStyle = "underscore";
|
|
24129
|
-
}
|
|
24130
24477
|
}
|
|
24131
|
-
let
|
|
24132
|
-
|
|
24133
|
-
|
|
24134
|
-
|
|
24135
|
-
|
|
24478
|
+
let changed = false;
|
|
24479
|
+
for (let i = 0;i < lines.length; i++) {
|
|
24480
|
+
if (inCode.has(i))
|
|
24481
|
+
continue;
|
|
24482
|
+
const after = replaceOutsideInlineCode(lines[i], (seg) => targetStyle === "asterisk" ? seg.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*") : seg.replace(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/g, "_$1_"));
|
|
24483
|
+
if (after !== lines[i]) {
|
|
24484
|
+
lines[i] = after;
|
|
24485
|
+
changed = true;
|
|
24486
|
+
}
|
|
24136
24487
|
}
|
|
24137
|
-
return
|
|
24488
|
+
return changed ? lines.join(`
|
|
24489
|
+
`) : text;
|
|
24138
24490
|
}
|
|
24139
24491
|
};
|
|
24140
24492
|
});
|
|
@@ -25778,8 +26130,14 @@ var init_no_space_in_code = __esm(() => {
|
|
|
25778
26130
|
});
|
|
25779
26131
|
|
|
25780
26132
|
// src/rules/markdown/no-space-in-emphasis.ts
|
|
25781
|
-
var noSpaceInEmphasisRule;
|
|
26133
|
+
var EMPHASIS_SPACE_PATTERNS, noSpaceInEmphasisRule;
|
|
25782
26134
|
var init_no_space_in_emphasis = __esm(() => {
|
|
26135
|
+
EMPHASIS_SPACE_PATTERNS = [
|
|
26136
|
+
/(?<![A-Za-z0-9])\*\*\s+[^*]+?\*\*(?![A-Za-z0-9])/g,
|
|
26137
|
+
/(?<![A-Za-z0-9])\*\*[^*]+?\s+\*\*(?![A-Za-z0-9])/g,
|
|
26138
|
+
/(?<![A-Za-z0-9])__\s+[^_]+?__(?![A-Za-z0-9])/g,
|
|
26139
|
+
/(?<![A-Za-z0-9])__[^_]+?\s+__(?![A-Za-z0-9])/g
|
|
26140
|
+
];
|
|
25783
26141
|
noSpaceInEmphasisRule = {
|
|
25784
26142
|
meta: {
|
|
25785
26143
|
docs: "Emphasis markers should not have spaces inside them"
|
|
@@ -25797,13 +26155,7 @@ var init_no_space_in_emphasis = __esm(() => {
|
|
|
25797
26155
|
if (inFence)
|
|
25798
26156
|
continue;
|
|
25799
26157
|
const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
|
|
25800
|
-
const
|
|
25801
|
-
/\*\*\s+[^*]+?\*\*/g,
|
|
25802
|
-
/\*\*[^*]+?\s+\*\*/g,
|
|
25803
|
-
/__\s+[^_]+?__/g,
|
|
25804
|
-
/__[^_]+?\s+__/g
|
|
25805
|
-
];
|
|
25806
|
-
for (const pattern of patterns) {
|
|
26158
|
+
for (const pattern of EMPHASIS_SPACE_PATTERNS) {
|
|
25807
26159
|
for (const match of stripped.matchAll(pattern)) {
|
|
25808
26160
|
issues.push({
|
|
25809
26161
|
filePath: ctx.filePath,
|
|
@@ -25832,11 +26184,14 @@ var init_no_space_in_emphasis = __esm(() => {
|
|
|
25832
26184
|
result.push(line);
|
|
25833
26185
|
continue;
|
|
25834
26186
|
}
|
|
25835
|
-
|
|
25836
|
-
|
|
25837
|
-
|
|
25838
|
-
|
|
25839
|
-
|
|
26187
|
+
const fixed = replaceOutsideInlineCode(line, (seg) => {
|
|
26188
|
+
let s = seg;
|
|
26189
|
+
s = s.replace(/(?<![A-Za-z0-9])(\*\*)\s+([^*]+?)\*\*(?![A-Za-z0-9])/g, "$1$2**");
|
|
26190
|
+
s = s.replace(/(?<![A-Za-z0-9])(\*\*)([^*]+?)\s+\*\*(?![A-Za-z0-9])/g, "$1$2**");
|
|
26191
|
+
s = s.replace(/(?<![A-Za-z0-9])(__)\s+([^_]+?)__(?![A-Za-z0-9])/g, "$1$2__");
|
|
26192
|
+
s = s.replace(/(?<![A-Za-z0-9])(__)([^_]+?)\s+__(?![A-Za-z0-9])/g, "$1$2__");
|
|
26193
|
+
return s;
|
|
26194
|
+
});
|
|
25840
26195
|
result.push(fixed);
|
|
25841
26196
|
}
|
|
25842
26197
|
return result.join(`
|
|
@@ -32845,7 +33200,7 @@ function findMatching(text, start, open, close) {
|
|
|
32845
33200
|
}
|
|
32846
33201
|
return i;
|
|
32847
33202
|
};
|
|
32848
|
-
const
|
|
33203
|
+
const isRegexStart2 = (i) => {
|
|
32849
33204
|
let j = i - 1;
|
|
32850
33205
|
while (j >= 0 && isWhitespace(text[j])) {
|
|
32851
33206
|
j--;
|
|
@@ -32901,7 +33256,7 @@ function findMatching(text, start, open, close) {
|
|
|
32901
33256
|
i = skipBlockComment(i) - 1;
|
|
32902
33257
|
continue;
|
|
32903
33258
|
}
|
|
32904
|
-
if (ch === "/" &&
|
|
33259
|
+
if (ch === "/" && isRegexStart2(i)) {
|
|
32905
33260
|
i = skipRegex(i) - 1;
|
|
32906
33261
|
continue;
|
|
32907
33262
|
}
|
|
@@ -38678,7 +39033,7 @@ function stripRegexLiterals(line) {
|
|
|
38678
39033
|
}
|
|
38679
39034
|
return result;
|
|
38680
39035
|
}
|
|
38681
|
-
function
|
|
39036
|
+
function isRegexStart2(lastSignificant, line, idx) {
|
|
38682
39037
|
if (lastSignificant === "")
|
|
38683
39038
|
return true;
|
|
38684
39039
|
const regexAfter = "([{,:;!?&|=<>~^+*%-";
|
|
@@ -38764,6 +39119,7 @@ function getCommentLines(content) {
|
|
|
38764
39119
|
let lineHasCode = false;
|
|
38765
39120
|
let lineSawComment = false;
|
|
38766
39121
|
let lineStartedInBlockComment = false;
|
|
39122
|
+
const interpStack = [];
|
|
38767
39123
|
for (let i = 0;i < content.length; i++) {
|
|
38768
39124
|
const ch = content[i];
|
|
38769
39125
|
const next = content[i + 1];
|
|
@@ -38887,6 +39243,20 @@ function getCommentLines(content) {
|
|
|
38887
39243
|
} else if (ch === "`") {
|
|
38888
39244
|
state = "string-template";
|
|
38889
39245
|
lineHasCode = true;
|
|
39246
|
+
} else if (ch === "{") {
|
|
39247
|
+
if (interpStack.length)
|
|
39248
|
+
interpStack[interpStack.length - 1]++;
|
|
39249
|
+
lineHasCode = true;
|
|
39250
|
+
} else if (ch === "}") {
|
|
39251
|
+
if (interpStack.length) {
|
|
39252
|
+
if (interpStack[interpStack.length - 1] === 0) {
|
|
39253
|
+
interpStack.pop();
|
|
39254
|
+
state = "string-template";
|
|
39255
|
+
} else {
|
|
39256
|
+
interpStack[interpStack.length - 1]--;
|
|
39257
|
+
}
|
|
39258
|
+
}
|
|
39259
|
+
lineHasCode = true;
|
|
38890
39260
|
} else if (!/\s/.test(ch)) {
|
|
38891
39261
|
lineHasCode = true;
|
|
38892
39262
|
}
|
|
@@ -38912,6 +39282,12 @@ function getCommentLines(content) {
|
|
|
38912
39282
|
i++;
|
|
38913
39283
|
break;
|
|
38914
39284
|
}
|
|
39285
|
+
if (ch === "$" && next === "{") {
|
|
39286
|
+
interpStack.push(0);
|
|
39287
|
+
state = "code";
|
|
39288
|
+
i++;
|
|
39289
|
+
break;
|
|
39290
|
+
}
|
|
38915
39291
|
if (ch === "`")
|
|
38916
39292
|
state = "code";
|
|
38917
39293
|
break;
|
|
@@ -39101,7 +39477,7 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
|
|
|
39101
39477
|
prev = ch;
|
|
39102
39478
|
continue;
|
|
39103
39479
|
}
|
|
39104
|
-
if (ch === "/" && ln[k + 1] !== "/" && ln[k + 1] !== "*" &&
|
|
39480
|
+
if (ch === "/" && ln[k + 1] !== "/" && ln[k + 1] !== "*" && isRegexStart2(lastSig, ln, k)) {
|
|
39105
39481
|
inRegex = true;
|
|
39106
39482
|
inRegexClass = false;
|
|
39107
39483
|
prev = ch;
|
|
@@ -43690,7 +44066,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
43690
44066
|
module.exports = {
|
|
43691
44067
|
name: "pickier",
|
|
43692
44068
|
type: "module",
|
|
43693
|
-
version: "0.1.
|
|
44069
|
+
version: "0.1.36",
|
|
43694
44070
|
description: "Format, lint and more in a fraction of seconds.",
|
|
43695
44071
|
author: "Chris Breuer <chris@stacksjs.org>",
|
|
43696
44072
|
license: "MIT",
|