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/src/index.js CHANGED
@@ -8882,6 +8882,37 @@ var init_config = __esm(() => {
8882
8882
  });
8883
8883
 
8884
8884
  // src/format.ts
8885
+ function isHangingControlLine(code) {
8886
+ const m = RE_CONTROL_OPEN.exec(code);
8887
+ if (!m)
8888
+ return /^(?:else|do)\s*$/.test(code);
8889
+ let depth = 0;
8890
+ let inStr = null;
8891
+ for (let i = m[0].length - 1;i < code.length; i++) {
8892
+ const ch = code[i];
8893
+ if (inStr) {
8894
+ if (ch === "\\") {
8895
+ i++;
8896
+ continue;
8897
+ }
8898
+ if (ch === inStr)
8899
+ inStr = null;
8900
+ continue;
8901
+ }
8902
+ if (ch === "'" || ch === '"' || ch === "`") {
8903
+ inStr = ch;
8904
+ continue;
8905
+ }
8906
+ if (ch === "(") {
8907
+ depth++;
8908
+ } else if (ch === ")") {
8909
+ depth--;
8910
+ if (depth === 0)
8911
+ return code.slice(i + 1).trim().length === 0;
8912
+ }
8913
+ }
8914
+ return false;
8915
+ }
8885
8916
  function getFileExt(filePath) {
8886
8917
  const idx = filePath.lastIndexOf(".");
8887
8918
  return idx >= 0 ? filePath.slice(idx) : "";
@@ -9032,6 +9063,25 @@ function fixQuotesLine(line, preferred) {
9032
9063
  while (i < line.length) {
9033
9064
  const ch = line[i];
9034
9065
  if (inString === 0) {
9066
+ if (ch === "/") {
9067
+ const nxt = line[i + 1];
9068
+ if (nxt === "/")
9069
+ break;
9070
+ if (nxt === "*") {
9071
+ const end = line.indexOf("*/", i + 2);
9072
+ i = end === -1 ? line.length : end + 2;
9073
+ continue;
9074
+ }
9075
+ if (isRegexStart(line, i)) {
9076
+ const end = scanRegexEnd(line, i);
9077
+ if (end !== -1) {
9078
+ i = end;
9079
+ continue;
9080
+ }
9081
+ }
9082
+ i++;
9083
+ continue;
9084
+ }
9035
9085
  if (ch === '"') {
9036
9086
  inString = 2;
9037
9087
  stringStart = i;
@@ -9099,6 +9149,8 @@ function normalizeSpacingLine(line) {
9099
9149
  const c = line[firstNonSpace];
9100
9150
  if (c === "/" && (line[firstNonSpace + 1] === "/" || line[firstNonSpace + 1] === "*"))
9101
9151
  return line;
9152
+ if (c === "*")
9153
+ return line;
9102
9154
  }
9103
9155
  let hasSpacingChar = false;
9104
9156
  for (let j = firstNonSpace;j < line.length; j++) {
@@ -9211,6 +9263,49 @@ function advanceTemplateState(line, stack) {
9211
9263
  }
9212
9264
  return -1;
9213
9265
  }
9266
+ function blockCommentStateAfter(line, startsIn) {
9267
+ let inBlock = startsIn;
9268
+ let inStr = null;
9269
+ let i = 0;
9270
+ while (i < line.length) {
9271
+ const ch = line[i];
9272
+ if (inBlock) {
9273
+ if (ch === "*" && line[i + 1] === "/") {
9274
+ inBlock = false;
9275
+ i += 2;
9276
+ continue;
9277
+ }
9278
+ i++;
9279
+ continue;
9280
+ }
9281
+ if (inStr) {
9282
+ if (ch === "\\") {
9283
+ i += 2;
9284
+ continue;
9285
+ }
9286
+ if (ch === inStr)
9287
+ inStr = null;
9288
+ i++;
9289
+ continue;
9290
+ }
9291
+ if (ch === "'" || ch === '"' || ch === "`") {
9292
+ inStr = ch;
9293
+ i++;
9294
+ continue;
9295
+ }
9296
+ if (ch === "/") {
9297
+ if (line[i + 1] === "/")
9298
+ break;
9299
+ if (line[i + 1] === "*") {
9300
+ inBlock = true;
9301
+ i += 2;
9302
+ continue;
9303
+ }
9304
+ }
9305
+ i++;
9306
+ }
9307
+ return inBlock;
9308
+ }
9214
9309
  function processCodeLinesFused(content, cfg) {
9215
9310
  const lines = content.split(`
9216
9311
  `);
@@ -9219,9 +9314,16 @@ function processCodeLinesFused(content, cfg) {
9219
9314
  const preferred = cfg.format.quotes;
9220
9315
  const doSemiRemoval = cfg.format.semi === true;
9221
9316
  let indentLevel = 0;
9317
+ let hangDepth = 0;
9318
+ let inBlockComment = false;
9222
9319
  const tmplStack = [];
9223
9320
  for (let idx = 0;idx < len; idx++) {
9224
9321
  let line = lines[idx];
9322
+ if (inBlockComment) {
9323
+ inBlockComment = blockCommentStateAfter(line, true);
9324
+ result[idx] = line;
9325
+ continue;
9326
+ }
9225
9327
  const protectedLine = inTemplateText(tmplStack);
9226
9328
  let splitIdx = -1;
9227
9329
  if (tmplStack.length > 0 || line.indexOf("`") !== -1)
@@ -9230,6 +9332,8 @@ function processCodeLinesFused(content, cfg) {
9230
9332
  result[idx] = line;
9231
9333
  continue;
9232
9334
  }
9335
+ if (splitIdx < 0 && tmplStack.length === 0)
9336
+ inBlockComment = blockCommentStateAfter(line, false);
9233
9337
  let tmplTail = "";
9234
9338
  let prefixEndedWithSpace = false;
9235
9339
  if (splitIdx >= 0) {
@@ -9253,9 +9357,15 @@ function processCodeLinesFused(content, cfg) {
9253
9357
  const trimmed = line.slice(wsEnd).trimEnd();
9254
9358
  if (RE_CLOSING_BRACE.test(trimmed))
9255
9359
  indentLevel = Math.max(0, indentLevel - 1);
9256
- line = makeIndent(indentLevel, cfg) + trimmed;
9257
- if (RE_OPENING_BRACE.test(trimmed))
9360
+ const continuationBump = RE_CONTINUATION_LINE.test(trimmed) ? 1 : 0;
9361
+ line = makeIndent(indentLevel + hangDepth + continuationBump, cfg) + trimmed;
9362
+ if (RE_OPENING_BRACE.test(trimmed)) {
9258
9363
  indentLevel += 1;
9364
+ hangDepth = 0;
9365
+ } else if (!trimmed.startsWith("//") && !trimmed.startsWith("*") && !trimmed.startsWith("/*")) {
9366
+ const code = trimmed.replace(RE_TRAILING_LINE_COMMENT, "");
9367
+ hangDepth = isHangingControlLine(code) ? hangDepth + 1 : 0;
9368
+ }
9259
9369
  line = normalizeSpacingLine(line);
9260
9370
  if (doSemiRemoval) {
9261
9371
  if (!RE_FOR_LOOP.test(line)) {
@@ -9487,8 +9597,48 @@ function skipTemplate(input, start) {
9487
9597
  }
9488
9598
  return i;
9489
9599
  }
9600
+ function isRegexStart(input, slashIdx) {
9601
+ let j = slashIdx - 1;
9602
+ while (j >= 0 && (input[j] === " " || input[j] === "\t"))
9603
+ j--;
9604
+ if (j < 0)
9605
+ return true;
9606
+ const prev = input[j];
9607
+ if ("(,=:[!&|?;{}<>+-*%^~".includes(prev))
9608
+ return true;
9609
+ if (/[\w$]/.test(prev)) {
9610
+ let k = j;
9611
+ while (k >= 0 && /[\w$]/.test(input[k]))
9612
+ k--;
9613
+ return REGEX_PRECEDING_KEYWORDS.has(input.slice(k + 1, j + 1));
9614
+ }
9615
+ return false;
9616
+ }
9617
+ function scanRegexEnd(input, start) {
9618
+ let i = start + 1;
9619
+ let inClass = false;
9620
+ while (i < input.length) {
9621
+ const c = input[i];
9622
+ if (c === "\\") {
9623
+ i += 2;
9624
+ continue;
9625
+ }
9626
+ if (c === "[") {
9627
+ inClass = true;
9628
+ } else if (c === "]") {
9629
+ inClass = false;
9630
+ } else if (c === "/" && !inClass) {
9631
+ i++;
9632
+ while (i < input.length && /[a-z]/i.test(input[i]))
9633
+ i++;
9634
+ return i;
9635
+ }
9636
+ i++;
9637
+ }
9638
+ return -1;
9639
+ }
9490
9640
  function maskStrings(input) {
9491
- if (!input.includes("'") && !input.includes('"') && !input.includes("`"))
9641
+ if (!input.includes("'") && !input.includes('"') && !input.includes("`") && !input.includes("/"))
9492
9642
  return { text: input, strings: [] };
9493
9643
  const strings = [];
9494
9644
  const parts = [];
@@ -9496,6 +9646,42 @@ function maskStrings(input) {
9496
9646
  let segStart = 0;
9497
9647
  while (i < input.length) {
9498
9648
  const ch = input[i];
9649
+ if (ch === "/") {
9650
+ const next = input[i + 1];
9651
+ if (next === "/") {
9652
+ if (i > segStart)
9653
+ parts.push(input.slice(segStart, i));
9654
+ strings.push(input.slice(i));
9655
+ parts.push(`@@S${strings.length - 1}@@`);
9656
+ segStart = input.length;
9657
+ break;
9658
+ }
9659
+ if (next === "*") {
9660
+ const end = input.indexOf("*/", i + 2);
9661
+ const stop = end === -1 ? input.length : end + 2;
9662
+ if (i > segStart)
9663
+ parts.push(input.slice(segStart, i));
9664
+ strings.push(input.slice(i, stop));
9665
+ parts.push(`@@S${strings.length - 1}@@`);
9666
+ i = stop;
9667
+ segStart = i;
9668
+ continue;
9669
+ }
9670
+ if (isRegexStart(input, i)) {
9671
+ const end = scanRegexEnd(input, i);
9672
+ if (end !== -1) {
9673
+ if (i > segStart)
9674
+ parts.push(input.slice(segStart, i));
9675
+ strings.push(input.slice(i, end));
9676
+ parts.push(`@@S${strings.length - 1}@@`);
9677
+ i = end;
9678
+ segStart = i;
9679
+ continue;
9680
+ }
9681
+ }
9682
+ i++;
9683
+ continue;
9684
+ }
9499
9685
  if (ch === "'" || ch === '"' || ch === "`") {
9500
9686
  if (i > segStart)
9501
9687
  parts.push(input.slice(segStart, i));
@@ -9551,24 +9737,65 @@ function formatImports(source) {
9551
9737
  const lines = source.split(`
9552
9738
  `);
9553
9739
  const imports = [];
9740
+ const preamble = [];
9741
+ const interleaved = [];
9554
9742
  let idx = 0;
9743
+ let lastEnd = 0;
9744
+ let pendingStart = -1;
9745
+ let sawImport = false;
9555
9746
  while (idx < lines.length) {
9556
9747
  const line = lines[idx];
9557
- if (RE_BLANK_LINE.test(line) || RE_LINE_COMMENT.test(line) || RE_BLOCK_COMMENT.test(line)) {
9748
+ if (RE_BLANK_LINE.test(line)) {
9558
9749
  idx++;
9559
9750
  continue;
9560
9751
  }
9752
+ if (RE_LINE_COMMENT.test(line) || RE_BLOCK_COMMENT.test(line)) {
9753
+ const start = idx;
9754
+ if (RE_BLOCK_COMMENT.test(line)) {
9755
+ while (idx < lines.length && !lines[idx].includes("*/"))
9756
+ idx++;
9757
+ idx++;
9758
+ } else {
9759
+ idx++;
9760
+ }
9761
+ if (!sawImport) {
9762
+ for (let k = start;k < idx && k < lines.length; k++)
9763
+ preamble.push(lines[k]);
9764
+ lastEnd = idx;
9765
+ } else if (pendingStart < 0) {
9766
+ pendingStart = start;
9767
+ }
9768
+ continue;
9769
+ }
9561
9770
  if (!RE_IMPORT_STMT.test(line))
9562
9771
  break;
9563
- const stmt = line.trim();
9772
+ let stmt = line.trim();
9773
+ let stmtEnd = idx + 1;
9774
+ while (!RE_IMPORT_COMPLETE.test(stmt) && stmtEnd < lines.length && stmtEnd - idx < 50) {
9775
+ stmt += ` ${lines[stmtEnd].trim()}`;
9776
+ stmtEnd++;
9777
+ }
9778
+ if (!RE_IMPORT_COMPLETE.test(stmt))
9779
+ return source;
9564
9780
  const parsed = parseImportStatement(stmt);
9565
- if (parsed)
9566
- imports.push(parsed);
9567
- idx++;
9781
+ if (!parsed)
9782
+ return source;
9783
+ if (pendingStart >= 0) {
9784
+ for (let k = pendingStart;k < idx; k++) {
9785
+ if (!RE_BLANK_LINE.test(lines[k]))
9786
+ interleaved.push(lines[k]);
9787
+ }
9788
+ pendingStart = -1;
9789
+ }
9790
+ imports.push(parsed);
9791
+ idx = stmtEnd;
9792
+ lastEnd = idx;
9793
+ sawImport = true;
9568
9794
  }
9569
9795
  if (imports.length === 0)
9570
9796
  return source;
9571
- const rest = lines.slice(idx).join(`
9797
+ const restStart = pendingStart >= 0 ? pendingStart : lastEnd;
9798
+ const rest = lines.slice(restStart).join(`
9572
9799
  `);
9573
9800
  const usedIdentifiers = collectIdentifierSet(rest);
9574
9801
  const used = (name) => usedIdentifiers.has(name);
@@ -9689,17 +9916,29 @@ function formatImports(source) {
9689
9916
  }
9690
9917
  return a.source.localeCompare(b.source);
9691
9918
  });
9919
+ const head = preamble.length > 0 ? `${preamble.join(`
9920
+ `)}
9921
+ ` : "";
9692
9922
  if (entries.length === 0) {
9693
- return rest.replace(/^\n+/, "");
9923
+ const restClean2 = rest.replace(/^\n+/, "");
9924
+ const kept = [...interleaved];
9925
+ if (head || kept.length > 0)
9926
+ return `${head}${kept.length > 0 ? `${kept.join(`
9927
+ `)}
9928
+ ` : ""}${restClean2}`;
9929
+ return restClean2;
9694
9930
  }
9695
9931
  const rendered = entries.map(renderImport).join(`
9696
9932
  `);
9697
- const sep = rest.length > 0 && !rest.startsWith(`
9698
- `) ? `
9933
+ const mid = interleaved.length > 0 ? `
9934
+ ${interleaved.join(`
9935
+ `)}` : "";
9936
+ const restClean = rest.replace(/^\n+/, "");
9937
+ const sep = restClean.length > 0 ? `
9699
9938
 
9700
9939
  ` : `
9701
9940
  `;
9702
- return `${rendered}${sep}${rest.replace(/^\n+/, "")}`;
9941
+ return `${head}${rendered}${mid}${sep}${restClean}`;
9703
9942
  }
9704
9943
  function renderImport(imp) {
9705
9944
  if (imp.kind === "side-effect")
@@ -10002,39 +10241,44 @@ function sortTsconfigContent(text) {
10002
10241
  }
10003
10242
  return JSON.stringify(outTop, null, 2);
10004
10243
  }
10005
- 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;
10244
+ 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;
10006
10245
  var init_format = __esm(() => {
10007
10246
  CODE_EXTS = new Set([".ts", ".js"]);
10008
10247
  JSON_EXTS = new Set([".json", ".jsonc"]);
10009
10248
  YAML_EXTS = new Set([".yaml", ".yml"]);
10010
10249
  SHELL_EXTS = new Set([".sh", ".bash", ".zsh", ".ksh", ".dash"]);
10011
10250
  SHELL_SHEBANG_RE = /^#!\s*(?:\/usr\/bin\/env\s+)?(?:ba|z|k|da)?sh\b/;
10012
- RE_CLOSING_BRACE = /^\}/;
10013
- RE_OPENING_BRACE = /\{\s*$/;
10251
+ RE_CLOSING_BRACE = /^[}\])]/;
10252
+ RE_OPENING_BRACE = /[{[(]\s*$/;
10253
+ RE_TRAILING_LINE_COMMENT = /\s*\/\/.*$/;
10254
+ RE_CONTROL_OPEN = /^(?:if|else\s+if|for|while)\s*\(/;
10255
+ RE_CONTINUATION_LINE = /^(?:\.[\w$[]|\?[\s.:]|:\s|&&|\|\|)/;
10014
10256
  RE_FOR_LOOP = /^\s*for\s*\(/;
10015
10257
  RE_EMPTY_SEMI = new RegExp("^\\s*" + ";" + "\\s*$");
10016
10258
  RE_DUP_SEMI = new RegExp(";" + "{2,}\\s*$");
10017
- RE_SPACE_BEFORE_BRACE = /(\S)\{/g;
10259
+ RE_SPACE_BEFORE_BRACE = /([\w)])\{/g;
10018
10260
  RE_SPACE_AFTER_BRACE_KW = /\{(return|if|for|while|switch|const|let|var|function)\b/g;
10019
10261
  RE_COMMA_SPACE = /,(\S)/g;
10020
- RE_EQUALS_SPACE = /(?<![=!<>])=(?![=><])/g;
10262
+ RE_EQUALS_SPACE = /(?<![=!<>+\-*/%&|^?])=(?![=><])/g;
10021
10263
  RE_PLUS_OP = /(\w)\+(\w)/g;
10022
10264
  RE_MINUS_OP = /(\w)-(\w)/g;
10023
10265
  RE_STAR_OP = /(\w)\*(\w)/g;
10024
10266
  RE_SLASH_OP = /(\w)\/(\w)/g;
10025
- RE_SEMI_SPACE = new RegExp(";" + "([^\\s" + ";" + "])", "g");
10026
- RE_LT_OP = /([\w\])])<(\S)/g;
10027
- RE_GT_OP = /(\S)>([\w[(])/g;
10267
+ RE_SEMI_SPACE = new RegExp("(?<=\\S);" + "([^\\s" + ";" + "])", "g");
10268
+ RE_LT_OP = /([\w)\]])<(\d)/g;
10269
+ RE_GT_OP = /([\w)\]])>(\d)/g;
10028
10270
  RE_MULTI_SPACE = /\s{2,}/g;
10029
10271
  RE_BLANK_LINE = /^\s*$/;
10030
10272
  RE_LINE_COMMENT = /^\s*\/\//;
10031
10273
  RE_BLOCK_COMMENT = /^\s*\/\*/;
10032
10274
  RE_IMPORT_STMT = /^\s*import\b/;
10275
+ RE_IMPORT_COMPLETE = /\bfrom\s*['"][^'"]+['"]|^\s*import\s+['"][^'"]+['"]/;
10033
10276
  RE_PACKAGE_JSON = /package\.json$/i;
10034
10277
  RE_TSCONFIG_JSON = /[jt]sconfig(?:\..+)?\.json$/i;
10035
10278
  RE_TRAILING_WS = /[ \t]+$/;
10036
10279
  RE_LEADING_BLANKS = /^\n+/;
10037
10280
  SPACING_CHARS = new Set(["{", ",", "=", "+", "-", "*", "/", ";", "<", ">"]);
10281
+ REGEX_PRECEDING_KEYWORDS = new Set(["return", "typeof", "instanceof", "in", "of", "new", "delete", "void", "do", "else", "case", "yield", "await"]);
10038
10282
  });
10039
10283
 
10040
10284
  // ../../node_modules/@stacksjs/clarity/dist/src/index.js
@@ -20365,7 +20609,7 @@ var init_no_unused_vars = __esm(() => {
20365
20609
  let tInBlockComment = false;
20366
20610
  let tEscaped = false;
20367
20611
  let prevSig = "";
20368
- const isRegexStart = () => {
20612
+ const isRegexStart2 = () => {
20369
20613
  if (prevSig === "")
20370
20614
  return true;
20371
20615
  if ("=([{,;!&|?:+-*/%^~<>".includes(prevSig))
@@ -20467,7 +20711,7 @@ var init_no_unused_vars = __esm(() => {
20467
20711
  else
20468
20712
  tmplStack.pop();
20469
20713
  prevSig = "}";
20470
- } else if (ch === "/" && isRegexStart()) {
20714
+ } else if (ch === "/" && isRegexStart2()) {
20471
20715
  tInRegex = true;
20472
20716
  } else if (!/\s/.test(ch)) {
20473
20717
  prevSig = ch;
@@ -20483,7 +20727,7 @@ var init_no_unused_vars = __esm(() => {
20483
20727
  } else if (ch === '"') {
20484
20728
  tInDouble = true;
20485
20729
  prevSig = '"';
20486
- } else if (ch === "/" && isRegexStart()) {
20730
+ } else if (ch === "/" && isRegexStart2()) {
20487
20731
  tInRegex = true;
20488
20732
  } else if (!/\s/.test(ch)) {
20489
20733
  prevSig = ch;
@@ -20520,6 +20764,15 @@ var init_no_unused_vars = __esm(() => {
20520
20764
  continue;
20521
20765
  }
20522
20766
  if (!inString) {
20767
+ if (ch === "/" && after[k + 1] === "/")
20768
+ break;
20769
+ if (ch === "/" && after[k + 1] === "*") {
20770
+ k += 2;
20771
+ while (k < after.length && !(after[k] === "*" && after[k + 1] === "/"))
20772
+ k++;
20773
+ k++;
20774
+ continue;
20775
+ }
20523
20776
  if (ch === "'") {
20524
20777
  inString = "single";
20525
20778
  } else if (ch === '"') {
@@ -21682,7 +21935,7 @@ function computeLineStartsInTemplate(text) {
21682
21935
  let inBlockComment = false;
21683
21936
  let escaped = false;
21684
21937
  let prevSig = "";
21685
- const isRegexStart = () => {
21938
+ const isRegexStart2 = () => {
21686
21939
  if (prevSig === "")
21687
21940
  return true;
21688
21941
  return "=([{,;!&|?:+-*/%^~<>".includes(prevSig);
@@ -21782,7 +22035,7 @@ function computeLineStartsInTemplate(text) {
21782
22035
  else
21783
22036
  tmplStack.pop();
21784
22037
  prevSig = "}";
21785
- } else if (ch === "/" && isRegexStart())
22038
+ } else if (ch === "/" && isRegexStart2())
21786
22039
  inRegex = true;
21787
22040
  else if (!/\s/.test(ch))
21788
22041
  prevSig = ch;
@@ -21797,7 +22050,7 @@ function computeLineStartsInTemplate(text) {
21797
22050
  } else if (ch === '"') {
21798
22051
  inDouble = true;
21799
22052
  prevSig = '"';
21800
- } else if (ch === "/" && isRegexStart())
22053
+ } else if (ch === "/" && isRegexStart2())
21801
22054
  inRegex = true;
21802
22055
  else if (!/\s/.test(ch))
21803
22056
  prevSig = ch;
@@ -23134,24 +23387,39 @@ var init_blanks_around_lists = __esm(() => {
23134
23387
  const lines = text.split(/\r?\n/);
23135
23388
  const result = [];
23136
23389
  let inList = false;
23390
+ let inFence = false;
23391
+ const isListItemLine = (l) => /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(l);
23137
23392
  for (let i = 0;i < lines.length; i++) {
23138
23393
  const line = lines[i];
23139
23394
  const prevLine = i > 0 ? lines[i - 1] : "";
23140
- const isListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(line);
23395
+ if (/^(?:`{3,}|~{3,})/.test(line.trim())) {
23396
+ inFence = !inFence;
23397
+ inList = false;
23398
+ result.push(line);
23399
+ continue;
23400
+ }
23401
+ if (inFence) {
23402
+ result.push(line);
23403
+ continue;
23404
+ }
23405
+ const isListItem = isListItemLine(line);
23406
+ const isBlank = line.trim().length === 0;
23407
+ const isContinuation = inList && !isListItem && !isBlank && /^\s/.test(line);
23141
23408
  if (isListItem && !inList) {
23142
23409
  if (i > 0 && prevLine.trim().length > 0 && result.length > 0) {
23143
23410
  result.push("");
23144
23411
  }
23145
23412
  inList = true;
23146
- } else if (!isListItem && line.trim().length > 0 && inList) {
23413
+ } else if (!isListItem && !isContinuation && !isBlank && inList) {
23147
23414
  inList = false;
23148
23415
  if (result.length > 0) {
23149
23416
  result.push("");
23150
23417
  }
23151
- } else if (!isListItem && line.trim().length === 0) {
23418
+ } else if (isBlank) {
23152
23419
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
23153
- const nextIsListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(nextLine);
23154
- if (!nextIsListItem && inList) {
23420
+ const nextIsListItem = isListItemLine(nextLine);
23421
+ const nextIsContinuation = /^\s+\S/.test(nextLine);
23422
+ if (!nextIsListItem && !nextIsContinuation && inList) {
23155
23423
  inList = false;
23156
23424
  }
23157
23425
  }
@@ -23222,6 +23490,64 @@ function getCodeBlockLines(lines) {
23222
23490
  }
23223
23491
  return out;
23224
23492
  }
23493
+ function eachInlineSegment(line, onText, onCode) {
23494
+ let i = 0;
23495
+ let textStart = 0;
23496
+ while (i < line.length) {
23497
+ if (line[i] !== "`") {
23498
+ i++;
23499
+ continue;
23500
+ }
23501
+ let n = 0;
23502
+ while (line[i + n] === "`")
23503
+ n++;
23504
+ let j = i + n;
23505
+ let close = -1;
23506
+ while (j < line.length) {
23507
+ if (line[j] === "`") {
23508
+ let k = 0;
23509
+ while (line[j + k] === "`")
23510
+ k++;
23511
+ if (k === n) {
23512
+ close = j;
23513
+ break;
23514
+ }
23515
+ j += k;
23516
+ } else {
23517
+ j++;
23518
+ }
23519
+ }
23520
+ if (close === -1) {
23521
+ i += n;
23522
+ continue;
23523
+ }
23524
+ if (textStart < i)
23525
+ onText(line.slice(textStart, i));
23526
+ onCode(line.slice(i, close + n));
23527
+ i = close + n;
23528
+ textStart = i;
23529
+ }
23530
+ if (textStart < line.length)
23531
+ onText(line.slice(textStart));
23532
+ }
23533
+ function replaceOutsideInlineCode(line, transform) {
23534
+ let out = "";
23535
+ eachInlineSegment(line, (seg) => {
23536
+ out += transform(seg);
23537
+ }, (seg) => {
23538
+ out += seg;
23539
+ });
23540
+ return out;
23541
+ }
23542
+ function maskInlineCode(line) {
23543
+ let out = "";
23544
+ eachInlineSegment(line, (seg) => {
23545
+ out += seg;
23546
+ }, (seg) => {
23547
+ out += " ".repeat(seg.length);
23548
+ });
23549
+ return out;
23550
+ }
23225
23551
 
23226
23552
  // src/rules/markdown/_shared.ts
23227
23553
  function findTableRows(lines) {
@@ -23632,8 +23958,10 @@ var init_descriptive_link_text = __esm(() => {
23632
23958
  });
23633
23959
 
23634
23960
  // src/rules/markdown/emphasis-style.ts
23635
- var emphasisStyleRule;
23961
+ var ASTERISK_EMPHASIS, UNDERSCORE_EMPHASIS, emphasisStyleRule;
23636
23962
  var init_emphasis_style = __esm(() => {
23963
+ ASTERISK_EMPHASIS = /(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/;
23964
+ UNDERSCORE_EMPHASIS = /(?<!_)_(?!_)([^_]+)_(?!_)/;
23637
23965
  emphasisStyleRule = {
23638
23966
  meta: {
23639
23967
  docs: "Emphasis style should be consistent (asterisk or underscore)"
@@ -23712,27 +24040,51 @@ var init_emphasis_style = __esm(() => {
23712
24040
  fix: (text, ctx) => {
23713
24041
  const options = ctx.options || {};
23714
24042
  const style = options.style || "consistent";
24043
+ const lines = text.split(/\r?\n/);
24044
+ const inCode = getCodeBlockLines(lines);
23715
24045
  let targetStyle = "asterisk";
23716
24046
  if (style === "asterisk") {
23717
24047
  targetStyle = "asterisk";
23718
24048
  } else if (style === "underscore") {
23719
24049
  targetStyle = "underscore";
23720
24050
  } else if (style === "consistent") {
23721
- const asteriskMatch = text.match(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/);
23722
- const underscoreMatch = text.match(/(?<!_)_(?!_)([^_]+)_(?!_)/);
23723
- if (asteriskMatch && (!underscoreMatch || asteriskMatch.index < underscoreMatch.index)) {
24051
+ let firstAsterisk = null;
24052
+ let firstUnderscore = null;
24053
+ for (let i = 0;i < lines.length; i++) {
24054
+ if (inCode.has(i))
24055
+ continue;
24056
+ const stripped = maskInlineCode(lines[i]);
24057
+ if (firstAsterisk === null) {
24058
+ const m = stripped.match(ASTERISK_EMPHASIS);
24059
+ if (m)
24060
+ firstAsterisk = { line: i, col: m.index };
24061
+ }
24062
+ if (firstUnderscore === null) {
24063
+ const m = stripped.match(UNDERSCORE_EMPHASIS);
24064
+ if (m)
24065
+ firstUnderscore = { line: i, col: m.index };
24066
+ }
24067
+ if (firstAsterisk && firstUnderscore)
24068
+ break;
24069
+ }
24070
+ const cmp = (a, b) => a.line !== b.line ? a.line - b.line : a.col - b.col;
24071
+ if (firstAsterisk && (!firstUnderscore || cmp(firstAsterisk, firstUnderscore) < 0))
23724
24072
  targetStyle = "asterisk";
23725
- } else if (underscoreMatch) {
24073
+ else if (firstUnderscore)
23726
24074
  targetStyle = "underscore";
23727
- }
23728
24075
  }
23729
- let fixed = text;
23730
- if (targetStyle === "asterisk") {
23731
- fixed = fixed.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*");
23732
- } else {
23733
- fixed = fixed.replace(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/g, "_$1_");
24076
+ let changed = false;
24077
+ for (let i = 0;i < lines.length; i++) {
24078
+ if (inCode.has(i))
24079
+ continue;
24080
+ const after = replaceOutsideInlineCode(lines[i], (seg) => targetStyle === "asterisk" ? seg.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*") : seg.replace(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/g, "_$1_"));
24081
+ if (after !== lines[i]) {
24082
+ lines[i] = after;
24083
+ changed = true;
24084
+ }
23734
24085
  }
23735
- return fixed;
24086
+ return changed ? lines.join(`
24087
+ `) : text;
23736
24088
  }
23737
24089
  };
23738
24090
  });
@@ -25376,8 +25728,14 @@ var init_no_space_in_code = __esm(() => {
25376
25728
  });
25377
25729
 
25378
25730
  // src/rules/markdown/no-space-in-emphasis.ts
25379
- var noSpaceInEmphasisRule;
25731
+ var EMPHASIS_SPACE_PATTERNS, noSpaceInEmphasisRule;
25380
25732
  var init_no_space_in_emphasis = __esm(() => {
25733
+ EMPHASIS_SPACE_PATTERNS = [
25734
+ /(?<![A-Za-z0-9])\*\*\s+[^*]+?\*\*(?![A-Za-z0-9])/g,
25735
+ /(?<![A-Za-z0-9])\*\*[^*]+?\s+\*\*(?![A-Za-z0-9])/g,
25736
+ /(?<![A-Za-z0-9])__\s+[^_]+?__(?![A-Za-z0-9])/g,
25737
+ /(?<![A-Za-z0-9])__[^_]+?\s+__(?![A-Za-z0-9])/g
25738
+ ];
25381
25739
  noSpaceInEmphasisRule = {
25382
25740
  meta: {
25383
25741
  docs: "Emphasis markers should not have spaces inside them"
@@ -25395,13 +25753,7 @@ var init_no_space_in_emphasis = __esm(() => {
25395
25753
  if (inFence)
25396
25754
  continue;
25397
25755
  const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
25398
- const patterns = [
25399
- /\*\*\s+[^*]+?\*\*/g,
25400
- /\*\*[^*]+?\s+\*\*/g,
25401
- /__\s+[^_]+?__/g,
25402
- /__[^_]+?\s+__/g
25403
- ];
25404
- for (const pattern of patterns) {
25756
+ for (const pattern of EMPHASIS_SPACE_PATTERNS) {
25405
25757
  for (const match of stripped.matchAll(pattern)) {
25406
25758
  issues.push({
25407
25759
  filePath: ctx.filePath,
@@ -25430,11 +25782,14 @@ var init_no_space_in_emphasis = __esm(() => {
25430
25782
  result.push(line);
25431
25783
  continue;
25432
25784
  }
25433
- let fixed = line;
25434
- fixed = fixed.replace(/\*\*\s+([^*]+?)\*\*/g, "**$1**");
25435
- fixed = fixed.replace(/\*\*([^*]+?)\s+\*\*/g, "**$1**");
25436
- fixed = fixed.replace(/__\s+([^_]+?)__/g, "__$1__");
25437
- fixed = fixed.replace(/__([^_]+?)\s+__/g, "__$1__");
25785
+ const fixed = replaceOutsideInlineCode(line, (seg) => {
25786
+ let s = seg;
25787
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)\s+([^*]+?)\*\*(?![A-Za-z0-9])/g, "$1$2**");
25788
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)([^*]+?)\s+\*\*(?![A-Za-z0-9])/g, "$1$2**");
25789
+ s = s.replace(/(?<![A-Za-z0-9])(__)\s+([^_]+?)__(?![A-Za-z0-9])/g, "$1$2__");
25790
+ s = s.replace(/(?<![A-Za-z0-9])(__)([^_]+?)\s+__(?![A-Za-z0-9])/g, "$1$2__");
25791
+ return s;
25792
+ });
25438
25793
  result.push(fixed);
25439
25794
  }
25440
25795
  return result.join(`
@@ -32443,7 +32798,7 @@ function findMatching(text, start, open, close) {
32443
32798
  }
32444
32799
  return i;
32445
32800
  };
32446
- const isRegexStart = (i) => {
32801
+ const isRegexStart2 = (i) => {
32447
32802
  let j = i - 1;
32448
32803
  while (j >= 0 && isWhitespace(text[j])) {
32449
32804
  j--;
@@ -32499,7 +32854,7 @@ function findMatching(text, start, open, close) {
32499
32854
  i = skipBlockComment(i) - 1;
32500
32855
  continue;
32501
32856
  }
32502
- if (ch === "/" && isRegexStart(i)) {
32857
+ if (ch === "/" && isRegexStart2(i)) {
32503
32858
  i = skipRegex(i) - 1;
32504
32859
  continue;
32505
32860
  }
@@ -38677,7 +39032,7 @@ function stripRegexLiterals(line) {
38677
39032
  }
38678
39033
  return result;
38679
39034
  }
38680
- function isRegexStart(lastSignificant, line, idx) {
39035
+ function isRegexStart2(lastSignificant, line, idx) {
38681
39036
  if (lastSignificant === "")
38682
39037
  return true;
38683
39038
  const regexAfter = "([{,:;!?&|=<>~^+*%-";
@@ -38763,6 +39118,7 @@ function getCommentLines(content) {
38763
39118
  let lineHasCode = false;
38764
39119
  let lineSawComment = false;
38765
39120
  let lineStartedInBlockComment = false;
39121
+ const interpStack = [];
38766
39122
  for (let i = 0;i < content.length; i++) {
38767
39123
  const ch = content[i];
38768
39124
  const next = content[i + 1];
@@ -38886,6 +39242,20 @@ function getCommentLines(content) {
38886
39242
  } else if (ch === "`") {
38887
39243
  state = "string-template";
38888
39244
  lineHasCode = true;
39245
+ } else if (ch === "{") {
39246
+ if (interpStack.length)
39247
+ interpStack[interpStack.length - 1]++;
39248
+ lineHasCode = true;
39249
+ } else if (ch === "}") {
39250
+ if (interpStack.length) {
39251
+ if (interpStack[interpStack.length - 1] === 0) {
39252
+ interpStack.pop();
39253
+ state = "string-template";
39254
+ } else {
39255
+ interpStack[interpStack.length - 1]--;
39256
+ }
39257
+ }
39258
+ lineHasCode = true;
38889
39259
  } else if (!/\s/.test(ch)) {
38890
39260
  lineHasCode = true;
38891
39261
  }
@@ -38911,6 +39281,12 @@ function getCommentLines(content) {
38911
39281
  i++;
38912
39282
  break;
38913
39283
  }
39284
+ if (ch === "$" && next === "{") {
39285
+ interpStack.push(0);
39286
+ state = "code";
39287
+ i++;
39288
+ break;
39289
+ }
38914
39290
  if (ch === "`")
38915
39291
  state = "code";
38916
39292
  break;
@@ -39100,7 +39476,7 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
39100
39476
  prev = ch;
39101
39477
  continue;
39102
39478
  }
39103
- if (ch === "/" && ln[k + 1] !== "/" && ln[k + 1] !== "*" && isRegexStart(lastSig, ln, k)) {
39479
+ if (ch === "/" && ln[k + 1] !== "/" && ln[k + 1] !== "*" && isRegexStart2(lastSig, ln, k)) {
39104
39480
  inRegex = true;
39105
39481
  inRegexClass = false;
39106
39482
  prev = ch;