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 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
- line = makeIndent(indentLevel, cfg) + trimmed;
423
- if (RE_OPENING_BRACE.test(trimmed))
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) || RE_LINE_COMMENT.test(line) || RE_BLOCK_COMMENT.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
- const stmt = line.trim();
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
- imports.push(parsed);
733
- idx++;
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 rest = lines.slice(idx).join(`
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
- return rest.replace(/^\n+/, "");
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 sep = rest.length > 0 && !rest.startsWith(`
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}${rest.replace(/^\n+/, "")}`;
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 = /\{\s*$/;
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 = /(\S)\{/g;
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 = /(?<![=!<>])=(?![=><])/g;
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\])])<(\S)/g;
1193
- RE_GT_OP = /(\S)>([\w[(])/g;
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 isRegexStart = () => {
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 === "/" && isRegexStart()) {
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 === "/" && isRegexStart()) {
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 isRegexStart = () => {
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 === "/" && isRegexStart())
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 === "/" && isRegexStart())
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
- const isListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(line);
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 && line.trim().length > 0 && inList) {
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 (!isListItem && line.trim().length === 0) {
23820
+ } else if (isBlank) {
23554
23821
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
23555
- const nextIsListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(nextLine);
23556
- if (!nextIsListItem && inList) {
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
- const asteriskMatch = text.match(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/);
24124
- const underscoreMatch = text.match(/(?<!_)_(?!_)([^_]+)_(?!_)/);
24125
- if (asteriskMatch && (!underscoreMatch || asteriskMatch.index < underscoreMatch.index)) {
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
- } else if (underscoreMatch) {
24475
+ else if (firstUnderscore)
24128
24476
  targetStyle = "underscore";
24129
- }
24130
24477
  }
24131
- let fixed = text;
24132
- if (targetStyle === "asterisk") {
24133
- fixed = fixed.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*");
24134
- } else {
24135
- fixed = fixed.replace(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/g, "_$1_");
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 fixed;
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 patterns = [
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
- let fixed = line;
25836
- fixed = fixed.replace(/\*\*\s+([^*]+?)\*\*/g, "**$1**");
25837
- fixed = fixed.replace(/\*\*([^*]+?)\s+\*\*/g, "**$1**");
25838
- fixed = fixed.replace(/__\s+([^_]+?)__/g, "__$1__");
25839
- fixed = fixed.replace(/__([^_]+?)\s+__/g, "__$1__");
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 isRegexStart = (i) => {
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 === "/" && isRegexStart(i)) {
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 isRegexStart(lastSignificant, line, idx) {
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] !== "*" && isRegexStart(lastSig, ln, k)) {
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.34",
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",