pickier 0.1.35 → 0.1.37

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
@@ -21166,6 +21166,15 @@ var init_no_unused_vars = __esm(() => {
21166
21166
  continue;
21167
21167
  }
21168
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
+ }
21169
21178
  if (ch === "'") {
21170
21179
  inString = "single";
21171
21180
  } else if (ch === '"') {
@@ -23780,24 +23789,39 @@ var init_blanks_around_lists = __esm(() => {
23780
23789
  const lines = text.split(/\r?\n/);
23781
23790
  const result = [];
23782
23791
  let inList = false;
23792
+ let inFence = false;
23793
+ const isListItemLine = (l) => /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(l);
23783
23794
  for (let i = 0;i < lines.length; i++) {
23784
23795
  const line = lines[i];
23785
23796
  const prevLine = i > 0 ? lines[i - 1] : "";
23786
- 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);
23787
23810
  if (isListItem && !inList) {
23788
23811
  if (i > 0 && prevLine.trim().length > 0 && result.length > 0) {
23789
23812
  result.push("");
23790
23813
  }
23791
23814
  inList = true;
23792
- } else if (!isListItem && line.trim().length > 0 && inList) {
23815
+ } else if (!isListItem && !isContinuation && !isBlank && inList) {
23793
23816
  inList = false;
23794
23817
  if (result.length > 0) {
23795
23818
  result.push("");
23796
23819
  }
23797
- } else if (!isListItem && line.trim().length === 0) {
23820
+ } else if (isBlank) {
23798
23821
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
23799
- const nextIsListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(nextLine);
23800
- if (!nextIsListItem && inList) {
23822
+ const nextIsListItem = isListItemLine(nextLine);
23823
+ const nextIsContinuation = /^\s+\S/.test(nextLine);
23824
+ if (!nextIsListItem && !nextIsContinuation && inList) {
23801
23825
  inList = false;
23802
23826
  }
23803
23827
  }
@@ -23868,6 +23892,64 @@ function getCodeBlockLines(lines) {
23868
23892
  }
23869
23893
  return out;
23870
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
+ }
23871
23953
 
23872
23954
  // src/rules/markdown/_shared.ts
23873
23955
  function findTableRows(lines) {
@@ -24278,8 +24360,10 @@ var init_descriptive_link_text = __esm(() => {
24278
24360
  });
24279
24361
 
24280
24362
  // src/rules/markdown/emphasis-style.ts
24281
- var emphasisStyleRule;
24363
+ var ASTERISK_EMPHASIS, UNDERSCORE_EMPHASIS, emphasisStyleRule;
24282
24364
  var init_emphasis_style = __esm(() => {
24365
+ ASTERISK_EMPHASIS = /(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/;
24366
+ UNDERSCORE_EMPHASIS = /(?<!_)_(?!_)([^_]+)_(?!_)/;
24283
24367
  emphasisStyleRule = {
24284
24368
  meta: {
24285
24369
  docs: "Emphasis style should be consistent (asterisk or underscore)"
@@ -24358,27 +24442,51 @@ var init_emphasis_style = __esm(() => {
24358
24442
  fix: (text, ctx) => {
24359
24443
  const options = ctx.options || {};
24360
24444
  const style = options.style || "consistent";
24445
+ const lines = text.split(/\r?\n/);
24446
+ const inCode = getCodeBlockLines(lines);
24361
24447
  let targetStyle = "asterisk";
24362
24448
  if (style === "asterisk") {
24363
24449
  targetStyle = "asterisk";
24364
24450
  } else if (style === "underscore") {
24365
24451
  targetStyle = "underscore";
24366
24452
  } else if (style === "consistent") {
24367
- const asteriskMatch = text.match(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/);
24368
- const underscoreMatch = text.match(/(?<!_)_(?!_)([^_]+)_(?!_)/);
24369
- 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))
24370
24474
  targetStyle = "asterisk";
24371
- } else if (underscoreMatch) {
24475
+ else if (firstUnderscore)
24372
24476
  targetStyle = "underscore";
24373
- }
24374
24477
  }
24375
- let fixed = text;
24376
- if (targetStyle === "asterisk") {
24377
- fixed = fixed.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*");
24378
- } else {
24379
- 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
+ }
24380
24487
  }
24381
- return fixed;
24488
+ return changed ? lines.join(`
24489
+ `) : text;
24382
24490
  }
24383
24491
  };
24384
24492
  });
@@ -25681,7 +25789,10 @@ var init_no_missing_space_atx = __esm(() => {
25681
25789
  check: (text, ctx) => {
25682
25790
  const issues = [];
25683
25791
  const lines = text.split(/\r?\n/);
25792
+ const codeLines = getCodeBlockLines(lines);
25684
25793
  for (let i = 0;i < lines.length; i++) {
25794
+ if (codeLines.has(i))
25795
+ continue;
25685
25796
  const line = lines[i];
25686
25797
  const match = line.match(/^(#{1,6})([^\s#])/);
25687
25798
  if (match) {
@@ -25699,7 +25810,10 @@ var init_no_missing_space_atx = __esm(() => {
25699
25810
  },
25700
25811
  fix: (text) => {
25701
25812
  const lines = text.split(/\r?\n/);
25702
- const fixedLines = lines.map((line) => {
25813
+ const codeLines = getCodeBlockLines(lines);
25814
+ const fixedLines = lines.map((line, i) => {
25815
+ if (codeLines.has(i))
25816
+ return line;
25703
25817
  return line.replace(/^(#{1,6})([^\s#])/, "$1 $2");
25704
25818
  });
25705
25819
  return fixedLines.join(`
@@ -25718,7 +25832,10 @@ var init_no_missing_space_closed_atx = __esm(() => {
25718
25832
  check: (text, ctx) => {
25719
25833
  const issues = [];
25720
25834
  const lines = text.split(/\r?\n/);
25835
+ const codeLines = getCodeBlockLines(lines);
25721
25836
  for (let i = 0;i < lines.length; i++) {
25837
+ if (codeLines.has(i))
25838
+ continue;
25722
25839
  const line = lines[i];
25723
25840
  const match = line.match(/^(#{1,6})\s+(.+?)(#{1,6})\s*$/);
25724
25841
  if (match) {
@@ -25820,7 +25937,10 @@ var init_no_multiple_space_atx = __esm(() => {
25820
25937
  check: (text, ctx) => {
25821
25938
  const issues = [];
25822
25939
  const lines = text.split(/\r?\n/);
25940
+ const codeLines = getCodeBlockLines(lines);
25823
25941
  for (let i = 0;i < lines.length; i++) {
25942
+ if (codeLines.has(i))
25943
+ continue;
25824
25944
  const line = lines[i];
25825
25945
  const match = line.match(/^(#{1,6})\s{2,}/);
25826
25946
  if (match) {
@@ -25838,7 +25958,10 @@ var init_no_multiple_space_atx = __esm(() => {
25838
25958
  },
25839
25959
  fix: (text) => {
25840
25960
  const lines = text.split(/\r?\n/);
25841
- const fixedLines = lines.map((line) => {
25961
+ const codeLines = getCodeBlockLines(lines);
25962
+ const fixedLines = lines.map((line, i) => {
25963
+ if (codeLines.has(i))
25964
+ return line;
25842
25965
  return line.replace(/^(#{1,6})\s{2,}/, "$1 ");
25843
25966
  });
25844
25967
  return fixedLines.join(`
@@ -25857,7 +25980,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
25857
25980
  check: (text, ctx) => {
25858
25981
  const issues = [];
25859
25982
  const lines = text.split(/\r?\n/);
25983
+ const codeLines = getCodeBlockLines(lines);
25860
25984
  for (let i = 0;i < lines.length; i++) {
25985
+ if (codeLines.has(i))
25986
+ continue;
25861
25987
  const line = lines[i];
25862
25988
  const match = line.match(/^(\s*)(>+)\s{2,}/);
25863
25989
  if (match) {
@@ -25876,7 +26002,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
25876
26002
  },
25877
26003
  fix: (text) => {
25878
26004
  const lines = text.split(/\r?\n/);
25879
- const fixedLines = lines.map((line) => {
26005
+ const codeLines = getCodeBlockLines(lines);
26006
+ const fixedLines = lines.map((line, i) => {
26007
+ if (codeLines.has(i))
26008
+ return line;
25880
26009
  return line.replace(/^(\s*>+)\s{2,}/, "$1 ");
25881
26010
  });
25882
26011
  return fixedLines.join(`
@@ -25895,7 +26024,10 @@ var init_no_multiple_space_closed_atx = __esm(() => {
25895
26024
  check: (text, ctx) => {
25896
26025
  const issues = [];
25897
26026
  const lines = text.split(/\r?\n/);
26027
+ const codeLines = getCodeBlockLines(lines);
25898
26028
  for (let i = 0;i < lines.length; i++) {
26029
+ if (codeLines.has(i))
26030
+ continue;
25899
26031
  const line = lines[i];
25900
26032
  const openMatch = line.match(/^(#{1,6})\s{2,}(?:\S.*?|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])#{1,6}\s*$/);
25901
26033
  if (openMatch) {
@@ -26022,8 +26154,14 @@ var init_no_space_in_code = __esm(() => {
26022
26154
  });
26023
26155
 
26024
26156
  // src/rules/markdown/no-space-in-emphasis.ts
26025
- var noSpaceInEmphasisRule;
26157
+ var EMPHASIS_SPACE_PATTERNS, noSpaceInEmphasisRule;
26026
26158
  var init_no_space_in_emphasis = __esm(() => {
26159
+ EMPHASIS_SPACE_PATTERNS = [
26160
+ /(?<![A-Za-z0-9])\*\*\s+[^*]+?\*\*(?![A-Za-z0-9])/g,
26161
+ /(?<![A-Za-z0-9])\*\*[^*]+?\s+\*\*(?![A-Za-z0-9])/g,
26162
+ /(?<![A-Za-z0-9])__\s+[^_]+?__(?![A-Za-z0-9])/g,
26163
+ /(?<![A-Za-z0-9])__[^_]+?\s+__(?![A-Za-z0-9])/g
26164
+ ];
26027
26165
  noSpaceInEmphasisRule = {
26028
26166
  meta: {
26029
26167
  docs: "Emphasis markers should not have spaces inside them"
@@ -26041,13 +26179,7 @@ var init_no_space_in_emphasis = __esm(() => {
26041
26179
  if (inFence)
26042
26180
  continue;
26043
26181
  const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
26044
- const patterns = [
26045
- /\*\*\s+[^*]+?\*\*/g,
26046
- /\*\*[^*]+?\s+\*\*/g,
26047
- /__\s+[^_]+?__/g,
26048
- /__[^_]+?\s+__/g
26049
- ];
26050
- for (const pattern of patterns) {
26182
+ for (const pattern of EMPHASIS_SPACE_PATTERNS) {
26051
26183
  for (const match of stripped.matchAll(pattern)) {
26052
26184
  issues.push({
26053
26185
  filePath: ctx.filePath,
@@ -26076,11 +26208,14 @@ var init_no_space_in_emphasis = __esm(() => {
26076
26208
  result.push(line);
26077
26209
  continue;
26078
26210
  }
26079
- let fixed = line;
26080
- fixed = fixed.replace(/\*\*\s+([^*]+?)\*\*/g, "**$1**");
26081
- fixed = fixed.replace(/\*\*([^*]+?)\s+\*\*/g, "**$1**");
26082
- fixed = fixed.replace(/__\s+([^_]+?)__/g, "__$1__");
26083
- fixed = fixed.replace(/__([^_]+?)\s+__/g, "__$1__");
26211
+ const fixed = replaceOutsideInlineCode(line, (seg) => {
26212
+ let s = seg;
26213
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)\s+([^*]+?)\*\*(?![A-Za-z0-9])/g, "$1$2**");
26214
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)([^*]+?)\s+\*\*(?![A-Za-z0-9])/g, "$1$2**");
26215
+ s = s.replace(/(?<![A-Za-z0-9])(__)\s+([^_]+?)__(?![A-Za-z0-9])/g, "$1$2__");
26216
+ s = s.replace(/(?<![A-Za-z0-9])(__)([^_]+?)\s+__(?![A-Za-z0-9])/g, "$1$2__");
26217
+ return s;
26218
+ });
26084
26219
  result.push(fixed);
26085
26220
  }
26086
26221
  return result.join(`
@@ -39008,6 +39143,7 @@ function getCommentLines(content) {
39008
39143
  let lineHasCode = false;
39009
39144
  let lineSawComment = false;
39010
39145
  let lineStartedInBlockComment = false;
39146
+ const interpStack = [];
39011
39147
  for (let i = 0;i < content.length; i++) {
39012
39148
  const ch = content[i];
39013
39149
  const next = content[i + 1];
@@ -39131,6 +39267,20 @@ function getCommentLines(content) {
39131
39267
  } else if (ch === "`") {
39132
39268
  state = "string-template";
39133
39269
  lineHasCode = true;
39270
+ } else if (ch === "{") {
39271
+ if (interpStack.length)
39272
+ interpStack[interpStack.length - 1]++;
39273
+ lineHasCode = true;
39274
+ } else if (ch === "}") {
39275
+ if (interpStack.length) {
39276
+ if (interpStack[interpStack.length - 1] === 0) {
39277
+ interpStack.pop();
39278
+ state = "string-template";
39279
+ } else {
39280
+ interpStack[interpStack.length - 1]--;
39281
+ }
39282
+ }
39283
+ lineHasCode = true;
39134
39284
  } else if (!/\s/.test(ch)) {
39135
39285
  lineHasCode = true;
39136
39286
  }
@@ -39156,6 +39306,12 @@ function getCommentLines(content) {
39156
39306
  i++;
39157
39307
  break;
39158
39308
  }
39309
+ if (ch === "$" && next === "{") {
39310
+ interpStack.push(0);
39311
+ state = "code";
39312
+ i++;
39313
+ break;
39314
+ }
39159
39315
  if (ch === "`")
39160
39316
  state = "code";
39161
39317
  break;
@@ -43934,7 +44090,7 @@ var require_package = __commonJS((exports, module) => {
43934
44090
  module.exports = {
43935
44091
  name: "pickier",
43936
44092
  type: "module",
43937
- version: "0.1.35",
44093
+ version: "0.1.37",
43938
44094
  description: "Format, lint and more in a fraction of seconds.",
43939
44095
  author: "Chris Breuer <chris@stacksjs.org>",
43940
44096
  license: "MIT",
@@ -30,3 +30,17 @@ export declare function getCodeBlockLines(lines: string[]): Set<number>;
30
30
  * don't already have the set computed.
31
31
  */
32
32
  export declare function isInsideCodeBlock(lines: string[], targetIdx: number): boolean;
33
+ /**
34
+ * Apply `transform` to the parts of `line` that are OUTSIDE inline code
35
+ * spans, leaving code-span text (and its backticks) verbatim. Lets
36
+ * emphasis/style fixers rewrite prose without corrupting literal markers
37
+ * such as `reverse_proxy` inside `` `caddy reverse_proxy` ``.
38
+ */
39
+ export declare function replaceOutsideInlineCode(line: string, transform: (segment: string) => string): string;
40
+ /**
41
+ * Blank out inline code spans (replacing every character — backticks and
42
+ * content — with spaces) while preserving length and column positions. Used
43
+ * by detectors that want to scan prose for markers without matching anything
44
+ * inside a code span.
45
+ */
46
+ export declare function maskInlineCode(line: string): string;
package/dist/src/index.js CHANGED
@@ -20764,6 +20764,15 @@ var init_no_unused_vars = __esm(() => {
20764
20764
  continue;
20765
20765
  }
20766
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
+ }
20767
20776
  if (ch === "'") {
20768
20777
  inString = "single";
20769
20778
  } else if (ch === '"') {
@@ -23378,24 +23387,39 @@ var init_blanks_around_lists = __esm(() => {
23378
23387
  const lines = text.split(/\r?\n/);
23379
23388
  const result = [];
23380
23389
  let inList = false;
23390
+ let inFence = false;
23391
+ const isListItemLine = (l) => /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(l);
23381
23392
  for (let i = 0;i < lines.length; i++) {
23382
23393
  const line = lines[i];
23383
23394
  const prevLine = i > 0 ? lines[i - 1] : "";
23384
- 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);
23385
23408
  if (isListItem && !inList) {
23386
23409
  if (i > 0 && prevLine.trim().length > 0 && result.length > 0) {
23387
23410
  result.push("");
23388
23411
  }
23389
23412
  inList = true;
23390
- } else if (!isListItem && line.trim().length > 0 && inList) {
23413
+ } else if (!isListItem && !isContinuation && !isBlank && inList) {
23391
23414
  inList = false;
23392
23415
  if (result.length > 0) {
23393
23416
  result.push("");
23394
23417
  }
23395
- } else if (!isListItem && line.trim().length === 0) {
23418
+ } else if (isBlank) {
23396
23419
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
23397
- const nextIsListItem = /^(?:\s*)(?:[*\-+]|\d+\.)\s+/.test(nextLine);
23398
- if (!nextIsListItem && inList) {
23420
+ const nextIsListItem = isListItemLine(nextLine);
23421
+ const nextIsContinuation = /^\s+\S/.test(nextLine);
23422
+ if (!nextIsListItem && !nextIsContinuation && inList) {
23399
23423
  inList = false;
23400
23424
  }
23401
23425
  }
@@ -23466,6 +23490,64 @@ function getCodeBlockLines(lines) {
23466
23490
  }
23467
23491
  return out;
23468
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
+ }
23469
23551
 
23470
23552
  // src/rules/markdown/_shared.ts
23471
23553
  function findTableRows(lines) {
@@ -23876,8 +23958,10 @@ var init_descriptive_link_text = __esm(() => {
23876
23958
  });
23877
23959
 
23878
23960
  // src/rules/markdown/emphasis-style.ts
23879
- var emphasisStyleRule;
23961
+ var ASTERISK_EMPHASIS, UNDERSCORE_EMPHASIS, emphasisStyleRule;
23880
23962
  var init_emphasis_style = __esm(() => {
23963
+ ASTERISK_EMPHASIS = /(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/;
23964
+ UNDERSCORE_EMPHASIS = /(?<!_)_(?!_)([^_]+)_(?!_)/;
23881
23965
  emphasisStyleRule = {
23882
23966
  meta: {
23883
23967
  docs: "Emphasis style should be consistent (asterisk or underscore)"
@@ -23956,27 +24040,51 @@ var init_emphasis_style = __esm(() => {
23956
24040
  fix: (text, ctx) => {
23957
24041
  const options = ctx.options || {};
23958
24042
  const style = options.style || "consistent";
24043
+ const lines = text.split(/\r?\n/);
24044
+ const inCode = getCodeBlockLines(lines);
23959
24045
  let targetStyle = "asterisk";
23960
24046
  if (style === "asterisk") {
23961
24047
  targetStyle = "asterisk";
23962
24048
  } else if (style === "underscore") {
23963
24049
  targetStyle = "underscore";
23964
24050
  } else if (style === "consistent") {
23965
- const asteriskMatch = text.match(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/);
23966
- const underscoreMatch = text.match(/(?<!_)_(?!_)([^_]+)_(?!_)/);
23967
- 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))
23968
24072
  targetStyle = "asterisk";
23969
- } else if (underscoreMatch) {
24073
+ else if (firstUnderscore)
23970
24074
  targetStyle = "underscore";
23971
- }
23972
24075
  }
23973
- let fixed = text;
23974
- if (targetStyle === "asterisk") {
23975
- fixed = fixed.replace(/(?<!_)_(?!_)([^_]+)_(?!_)/g, "*$1*");
23976
- } else {
23977
- 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
+ }
23978
24085
  }
23979
- return fixed;
24086
+ return changed ? lines.join(`
24087
+ `) : text;
23980
24088
  }
23981
24089
  };
23982
24090
  });
@@ -25279,7 +25387,10 @@ var init_no_missing_space_atx = __esm(() => {
25279
25387
  check: (text, ctx) => {
25280
25388
  const issues = [];
25281
25389
  const lines = text.split(/\r?\n/);
25390
+ const codeLines = getCodeBlockLines(lines);
25282
25391
  for (let i = 0;i < lines.length; i++) {
25392
+ if (codeLines.has(i))
25393
+ continue;
25283
25394
  const line = lines[i];
25284
25395
  const match = line.match(/^(#{1,6})([^\s#])/);
25285
25396
  if (match) {
@@ -25297,7 +25408,10 @@ var init_no_missing_space_atx = __esm(() => {
25297
25408
  },
25298
25409
  fix: (text) => {
25299
25410
  const lines = text.split(/\r?\n/);
25300
- const fixedLines = lines.map((line) => {
25411
+ const codeLines = getCodeBlockLines(lines);
25412
+ const fixedLines = lines.map((line, i) => {
25413
+ if (codeLines.has(i))
25414
+ return line;
25301
25415
  return line.replace(/^(#{1,6})([^\s#])/, "$1 $2");
25302
25416
  });
25303
25417
  return fixedLines.join(`
@@ -25316,7 +25430,10 @@ var init_no_missing_space_closed_atx = __esm(() => {
25316
25430
  check: (text, ctx) => {
25317
25431
  const issues = [];
25318
25432
  const lines = text.split(/\r?\n/);
25433
+ const codeLines = getCodeBlockLines(lines);
25319
25434
  for (let i = 0;i < lines.length; i++) {
25435
+ if (codeLines.has(i))
25436
+ continue;
25320
25437
  const line = lines[i];
25321
25438
  const match = line.match(/^(#{1,6})\s+(.+?)(#{1,6})\s*$/);
25322
25439
  if (match) {
@@ -25418,7 +25535,10 @@ var init_no_multiple_space_atx = __esm(() => {
25418
25535
  check: (text, ctx) => {
25419
25536
  const issues = [];
25420
25537
  const lines = text.split(/\r?\n/);
25538
+ const codeLines = getCodeBlockLines(lines);
25421
25539
  for (let i = 0;i < lines.length; i++) {
25540
+ if (codeLines.has(i))
25541
+ continue;
25422
25542
  const line = lines[i];
25423
25543
  const match = line.match(/^(#{1,6})\s{2,}/);
25424
25544
  if (match) {
@@ -25436,7 +25556,10 @@ var init_no_multiple_space_atx = __esm(() => {
25436
25556
  },
25437
25557
  fix: (text) => {
25438
25558
  const lines = text.split(/\r?\n/);
25439
- const fixedLines = lines.map((line) => {
25559
+ const codeLines = getCodeBlockLines(lines);
25560
+ const fixedLines = lines.map((line, i) => {
25561
+ if (codeLines.has(i))
25562
+ return line;
25440
25563
  return line.replace(/^(#{1,6})\s{2,}/, "$1 ");
25441
25564
  });
25442
25565
  return fixedLines.join(`
@@ -25455,7 +25578,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
25455
25578
  check: (text, ctx) => {
25456
25579
  const issues = [];
25457
25580
  const lines = text.split(/\r?\n/);
25581
+ const codeLines = getCodeBlockLines(lines);
25458
25582
  for (let i = 0;i < lines.length; i++) {
25583
+ if (codeLines.has(i))
25584
+ continue;
25459
25585
  const line = lines[i];
25460
25586
  const match = line.match(/^(\s*)(>+)\s{2,}/);
25461
25587
  if (match) {
@@ -25474,7 +25600,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
25474
25600
  },
25475
25601
  fix: (text) => {
25476
25602
  const lines = text.split(/\r?\n/);
25477
- const fixedLines = lines.map((line) => {
25603
+ const codeLines = getCodeBlockLines(lines);
25604
+ const fixedLines = lines.map((line, i) => {
25605
+ if (codeLines.has(i))
25606
+ return line;
25478
25607
  return line.replace(/^(\s*>+)\s{2,}/, "$1 ");
25479
25608
  });
25480
25609
  return fixedLines.join(`
@@ -25493,7 +25622,10 @@ var init_no_multiple_space_closed_atx = __esm(() => {
25493
25622
  check: (text, ctx) => {
25494
25623
  const issues = [];
25495
25624
  const lines = text.split(/\r?\n/);
25625
+ const codeLines = getCodeBlockLines(lines);
25496
25626
  for (let i = 0;i < lines.length; i++) {
25627
+ if (codeLines.has(i))
25628
+ continue;
25497
25629
  const line = lines[i];
25498
25630
  const openMatch = line.match(/^(#{1,6})\s{2,}(?:\S.*?|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])#{1,6}\s*$/);
25499
25631
  if (openMatch) {
@@ -25620,8 +25752,14 @@ var init_no_space_in_code = __esm(() => {
25620
25752
  });
25621
25753
 
25622
25754
  // src/rules/markdown/no-space-in-emphasis.ts
25623
- var noSpaceInEmphasisRule;
25755
+ var EMPHASIS_SPACE_PATTERNS, noSpaceInEmphasisRule;
25624
25756
  var init_no_space_in_emphasis = __esm(() => {
25757
+ EMPHASIS_SPACE_PATTERNS = [
25758
+ /(?<![A-Za-z0-9])\*\*\s+[^*]+?\*\*(?![A-Za-z0-9])/g,
25759
+ /(?<![A-Za-z0-9])\*\*[^*]+?\s+\*\*(?![A-Za-z0-9])/g,
25760
+ /(?<![A-Za-z0-9])__\s+[^_]+?__(?![A-Za-z0-9])/g,
25761
+ /(?<![A-Za-z0-9])__[^_]+?\s+__(?![A-Za-z0-9])/g
25762
+ ];
25625
25763
  noSpaceInEmphasisRule = {
25626
25764
  meta: {
25627
25765
  docs: "Emphasis markers should not have spaces inside them"
@@ -25639,13 +25777,7 @@ var init_no_space_in_emphasis = __esm(() => {
25639
25777
  if (inFence)
25640
25778
  continue;
25641
25779
  const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
25642
- const patterns = [
25643
- /\*\*\s+[^*]+?\*\*/g,
25644
- /\*\*[^*]+?\s+\*\*/g,
25645
- /__\s+[^_]+?__/g,
25646
- /__[^_]+?\s+__/g
25647
- ];
25648
- for (const pattern of patterns) {
25780
+ for (const pattern of EMPHASIS_SPACE_PATTERNS) {
25649
25781
  for (const match of stripped.matchAll(pattern)) {
25650
25782
  issues.push({
25651
25783
  filePath: ctx.filePath,
@@ -25674,11 +25806,14 @@ var init_no_space_in_emphasis = __esm(() => {
25674
25806
  result.push(line);
25675
25807
  continue;
25676
25808
  }
25677
- let fixed = line;
25678
- fixed = fixed.replace(/\*\*\s+([^*]+?)\*\*/g, "**$1**");
25679
- fixed = fixed.replace(/\*\*([^*]+?)\s+\*\*/g, "**$1**");
25680
- fixed = fixed.replace(/__\s+([^_]+?)__/g, "__$1__");
25681
- fixed = fixed.replace(/__([^_]+?)\s+__/g, "__$1__");
25809
+ const fixed = replaceOutsideInlineCode(line, (seg) => {
25810
+ let s = seg;
25811
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)\s+([^*]+?)\*\*(?![A-Za-z0-9])/g, "$1$2**");
25812
+ s = s.replace(/(?<![A-Za-z0-9])(\*\*)([^*]+?)\s+\*\*(?![A-Za-z0-9])/g, "$1$2**");
25813
+ s = s.replace(/(?<![A-Za-z0-9])(__)\s+([^_]+?)__(?![A-Za-z0-9])/g, "$1$2__");
25814
+ s = s.replace(/(?<![A-Za-z0-9])(__)([^_]+?)\s+__(?![A-Za-z0-9])/g, "$1$2__");
25815
+ return s;
25816
+ });
25682
25817
  result.push(fixed);
25683
25818
  }
25684
25819
  return result.join(`
@@ -39007,6 +39142,7 @@ function getCommentLines(content) {
39007
39142
  let lineHasCode = false;
39008
39143
  let lineSawComment = false;
39009
39144
  let lineStartedInBlockComment = false;
39145
+ const interpStack = [];
39010
39146
  for (let i = 0;i < content.length; i++) {
39011
39147
  const ch = content[i];
39012
39148
  const next = content[i + 1];
@@ -39130,6 +39266,20 @@ function getCommentLines(content) {
39130
39266
  } else if (ch === "`") {
39131
39267
  state = "string-template";
39132
39268
  lineHasCode = true;
39269
+ } else if (ch === "{") {
39270
+ if (interpStack.length)
39271
+ interpStack[interpStack.length - 1]++;
39272
+ lineHasCode = true;
39273
+ } else if (ch === "}") {
39274
+ if (interpStack.length) {
39275
+ if (interpStack[interpStack.length - 1] === 0) {
39276
+ interpStack.pop();
39277
+ state = "string-template";
39278
+ } else {
39279
+ interpStack[interpStack.length - 1]--;
39280
+ }
39281
+ }
39282
+ lineHasCode = true;
39133
39283
  } else if (!/\s/.test(ch)) {
39134
39284
  lineHasCode = true;
39135
39285
  }
@@ -39155,6 +39305,12 @@ function getCommentLines(content) {
39155
39305
  i++;
39156
39306
  break;
39157
39307
  }
39308
+ if (ch === "$" && next === "{") {
39309
+ interpStack.push(0);
39310
+ state = "code";
39311
+ i++;
39312
+ break;
39313
+ }
39158
39314
  if (ch === "`")
39159
39315
  state = "code";
39160
39316
  break;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pickier",
3
3
  "type": "module",
4
- "version": "0.1.35",
4
+ "version": "0.1.37",
5
5
  "description": "Format, lint and more in a fraction of seconds.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",