pickier 0.1.14 → 0.1.16

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
@@ -353,13 +353,18 @@ function detectQuoteIssues(line, preferred) {
353
353
  }
354
354
  return indices;
355
355
  }
356
- function hasIndentIssue(leading, indentSize, indentStyle = "spaces") {
356
+ function hasIndentIssue(leading, indentSize, indentStyle = "spaces", lineContent) {
357
357
  if (indentStyle === "tabs") {
358
358
  return /[^\t]/.test(leading);
359
359
  }
360
360
  if (/\t/.test(leading))
361
361
  return true;
362
362
  const spaces = leading.length;
363
+ if (lineContent && spaces % indentSize === 1) {
364
+ const trimmed = lineContent.trimStart();
365
+ if (trimmed.startsWith("* ") || trimmed.startsWith("*/") || trimmed === "*")
366
+ return false;
367
+ }
363
368
  return spaces % indentSize !== 0;
364
369
  }
365
370
  function maskStrings(input) {
@@ -5996,10 +6001,13 @@ var init_config = __esm(async () => {
5996
6001
  "**/.claude/**",
5997
6002
  "**/.github/**",
5998
6003
  "**/*.test.ts",
5999
- "**/*.spec.ts"
6004
+ "**/*.spec.ts",
6005
+ "**/*.lock",
6006
+ "**/package-lock.json",
6007
+ "**/pnpm-lock.yaml"
6000
6008
  ],
6001
6009
  lint: {
6002
- extensions: ["ts", "js", "html", "css", "json", "jsonc", "md", "yaml", "yml", "stx", "lock"],
6010
+ extensions: ["ts", "js", "html", "css", "json", "jsonc", "md", "yaml", "yml", "stx"],
6003
6011
  reporter: "stylish",
6004
6012
  cache: false,
6005
6013
  maxWarnings: -1
@@ -17154,38 +17162,41 @@ var init_blanks_around_fences = __esm(() => {
17154
17162
  check: (text, ctx) => {
17155
17163
  const issues = [];
17156
17164
  const lines = text.split(/\r?\n/);
17165
+ let inFence = false;
17157
17166
  for (let i = 0;i < lines.length; i++) {
17158
17167
  const line = lines[i];
17159
- const prevLine = i > 0 ? lines[i - 1] : "";
17160
- const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
17161
- const isFence = /^(`{3,}|~{3,})/.test(line);
17168
+ const isFence = /^(`{3,}|~{3,})/.test(line.trim());
17162
17169
  if (isFence) {
17163
- let isOpening = true;
17164
- for (let j = i - 1;j >= 0; j--) {
17165
- if (/^(`{3,}|~{3,})/.test(lines[j])) {
17166
- isOpening = false;
17167
- break;
17170
+ if (!inFence) {
17171
+ const prevLine = i > 0 ? lines[i - 1] : "";
17172
+ if (i > 0 && prevLine.trim().length > 0) {
17173
+ if (!/^:::/.test(prevLine.trim())) {
17174
+ issues.push({
17175
+ filePath: ctx.filePath,
17176
+ line: i + 1,
17177
+ column: 1,
17178
+ ruleId: "markdown/blanks-around-fences",
17179
+ message: "Fenced code blocks should be surrounded by blank lines",
17180
+ severity: "error"
17181
+ });
17182
+ }
17168
17183
  }
17169
- }
17170
- if (isOpening && i > 0 && prevLine.trim().length > 0) {
17171
- issues.push({
17172
- filePath: ctx.filePath,
17173
- line: i + 1,
17174
- column: 1,
17175
- ruleId: "markdown/blanks-around-fences",
17176
- message: "Fenced code blocks should be surrounded by blank lines",
17177
- severity: "error"
17178
- });
17179
- }
17180
- if (!isOpening && i + 1 < lines.length && nextLine.trim().length > 0) {
17181
- issues.push({
17182
- filePath: ctx.filePath,
17183
- line: i + 1,
17184
- column: 1,
17185
- ruleId: "markdown/blanks-around-fences",
17186
- message: "Fenced code blocks should be surrounded by blank lines",
17187
- severity: "error"
17188
- });
17184
+ inFence = true;
17185
+ } else {
17186
+ const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
17187
+ if (i + 1 < lines.length && nextLine.trim().length > 0) {
17188
+ if (!/^:::/.test(nextLine.trim())) {
17189
+ issues.push({
17190
+ filePath: ctx.filePath,
17191
+ line: i + 1,
17192
+ column: 1,
17193
+ ruleId: "markdown/blanks-around-fences",
17194
+ message: "Fenced code blocks should be surrounded by blank lines",
17195
+ severity: "error"
17196
+ });
17197
+ }
17198
+ }
17199
+ inFence = false;
17189
17200
  }
17190
17201
  }
17191
17202
  }
@@ -17198,10 +17209,10 @@ var init_blanks_around_fences = __esm(() => {
17198
17209
  for (let i = 0;i < lines.length; i++) {
17199
17210
  const line = lines[i];
17200
17211
  const prevLine = i > 0 ? lines[i - 1] : "";
17201
- const isFence = /^(`{3,}|~{3,})/.test(line);
17212
+ const isFence = /^(`{3,}|~{3,})/.test(line.trim());
17202
17213
  if (isFence) {
17203
17214
  if (!inFence) {
17204
- if (i > 0 && prevLine.trim().length > 0 && result.length > 0) {
17215
+ if (i > 0 && prevLine.trim().length > 0 && !/^:::/.test(prevLine.trim()) && result.length > 0) {
17205
17216
  result.push("");
17206
17217
  }
17207
17218
  inFence = true;
@@ -17212,7 +17223,7 @@ var init_blanks_around_fences = __esm(() => {
17212
17223
  result.push(line);
17213
17224
  if (isFence && !inFence && i + 1 < lines.length) {
17214
17225
  const nextLine = lines[i + 1];
17215
- if (nextLine.trim().length > 0) {
17226
+ if (nextLine.trim().length > 0 && !/^:::/.test(nextLine.trim())) {
17216
17227
  result.push("");
17217
17228
  }
17218
17229
  }
@@ -17233,10 +17244,17 @@ var init_blanks_around_headings = __esm(() => {
17233
17244
  check: (text, ctx) => {
17234
17245
  const issues = [];
17235
17246
  const lines = text.split(/\r?\n/);
17247
+ let inFencedCodeBlock = false;
17236
17248
  for (let i = 0;i < lines.length; i++) {
17237
17249
  const line = lines[i];
17238
17250
  const prevLine = i > 0 ? lines[i - 1] : "";
17239
17251
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
17252
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17253
+ inFencedCodeBlock = !inFencedCodeBlock;
17254
+ continue;
17255
+ }
17256
+ if (inFencedCodeBlock)
17257
+ continue;
17240
17258
  const isAtxHeading = /^#{1,6}\s/.test(line);
17241
17259
  const isSetextHeading = i + 1 < lines.length && /^(=+|-+)\s*$/.test(nextLine) && line.trim().length > 0;
17242
17260
  if (isAtxHeading) {
@@ -17290,10 +17308,20 @@ var init_blanks_around_headings = __esm(() => {
17290
17308
  fix: (text) => {
17291
17309
  const lines = text.split(/\r?\n/);
17292
17310
  const result = [];
17311
+ let inFencedCodeBlock = false;
17293
17312
  for (let i = 0;i < lines.length; i++) {
17294
17313
  const line = lines[i];
17295
17314
  const prevLine = i > 0 ? lines[i - 1] : "";
17296
17315
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
17316
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17317
+ inFencedCodeBlock = !inFencedCodeBlock;
17318
+ result.push(line);
17319
+ continue;
17320
+ }
17321
+ if (inFencedCodeBlock) {
17322
+ result.push(line);
17323
+ continue;
17324
+ }
17297
17325
  const isAtxHeading = /^#{1,6}\s/.test(line);
17298
17326
  const isSetextHeading = i + 1 < lines.length && /^(=+|-+)\s*$/.test(nextLine) && line.trim().length > 0;
17299
17327
  if (isAtxHeading || isSetextHeading) {
@@ -17331,14 +17359,22 @@ var init_blanks_around_lists = __esm(() => {
17331
17359
  const issues = [];
17332
17360
  const lines = text.split(/\r?\n/);
17333
17361
  let inList = false;
17334
- let listStartLine = -1;
17362
+ let inFence = false;
17335
17363
  for (let i = 0;i < lines.length; i++) {
17336
17364
  const line = lines[i];
17337
17365
  const prevLine = i > 0 ? lines[i - 1] : "";
17366
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17367
+ inFence = !inFence;
17368
+ if (inList)
17369
+ inList = false;
17370
+ continue;
17371
+ }
17372
+ if (inFence)
17373
+ continue;
17338
17374
  const isListItem = /^(\s*)([*\-+]|\d+\.)\s+/.test(line);
17375
+ const isListContinuation = inList && !isListItem && line.trim().length > 0 && /^\s+/.test(line);
17339
17376
  if (isListItem && !inList) {
17340
17377
  inList = true;
17341
- listStartLine = i;
17342
17378
  if (i > 0 && prevLine.trim().length > 0) {
17343
17379
  issues.push({
17344
17380
  filePath: ctx.filePath,
@@ -17349,7 +17385,7 @@ var init_blanks_around_lists = __esm(() => {
17349
17385
  severity: "error"
17350
17386
  });
17351
17387
  }
17352
- } else if (!isListItem && inList && line.trim().length > 0) {
17388
+ } else if (!isListItem && !isListContinuation && inList && line.trim().length > 0) {
17353
17389
  inList = false;
17354
17390
  const prevLineIsListItem = /^(\s*)([*\-+]|\d+\.)\s+/.test(prevLine);
17355
17391
  if (prevLineIsListItem) {
@@ -17410,15 +17446,21 @@ var init_blanks_around_tables = __esm(() => {
17410
17446
  const issues = [];
17411
17447
  const lines = text.split(/\r?\n/);
17412
17448
  let inTable = false;
17413
- let tableStartLine = -1;
17449
+ let inFence = false;
17414
17450
  for (let i = 0;i < lines.length; i++) {
17415
17451
  const line = lines[i];
17416
17452
  const prevLine = i > 0 ? lines[i - 1] : "";
17417
- const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
17453
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17454
+ inFence = !inFence;
17455
+ if (inTable)
17456
+ inTable = false;
17457
+ continue;
17458
+ }
17459
+ if (inFence)
17460
+ continue;
17418
17461
  const isTableLine = /\|/.test(line) && line.trim().length > 0;
17419
17462
  if (isTableLine && !inTable) {
17420
17463
  inTable = true;
17421
- tableStartLine = i;
17422
17464
  if (i > 0 && prevLine.trim().length > 0) {
17423
17465
  issues.push({
17424
17466
  filePath: ctx.filePath,
@@ -17900,8 +17942,15 @@ var init_heading_increment = __esm(() => {
17900
17942
  const issues = [];
17901
17943
  const lines = text.split(/\r?\n/);
17902
17944
  let previousLevel = 0;
17945
+ let inFence = false;
17903
17946
  for (let i = 0;i < lines.length; i++) {
17904
17947
  const line = lines[i];
17948
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17949
+ inFence = !inFence;
17950
+ continue;
17951
+ }
17952
+ if (inFence)
17953
+ continue;
17905
17954
  const atxMatch = line.match(/^(#{1,6})\s/);
17906
17955
  if (atxMatch) {
17907
17956
  const level = atxMatch[1].length;
@@ -17933,8 +17982,15 @@ var init_heading_start_left = __esm(() => {
17933
17982
  check: (text, ctx) => {
17934
17983
  const issues = [];
17935
17984
  const lines = text.split(/\r?\n/);
17985
+ let inFence = false;
17936
17986
  for (let i = 0;i < lines.length; i++) {
17937
17987
  const line = lines[i];
17988
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
17989
+ inFence = !inFence;
17990
+ continue;
17991
+ }
17992
+ if (inFence)
17993
+ continue;
17938
17994
  const match = line.match(/^(\s+)(#{1,6}\s)/);
17939
17995
  if (match) {
17940
17996
  issues.push({
@@ -18229,8 +18285,24 @@ var init_link_image_style = __esm(() => {
18229
18285
  const options = ctx.options || {};
18230
18286
  const style = options.style || "consistent";
18231
18287
  let detectedStyle = null;
18288
+ let inFence = false;
18289
+ let inHtmlComment = false;
18232
18290
  for (let i = 0;i < lines.length; i++) {
18233
18291
  const line = lines[i];
18292
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18293
+ inFence = !inFence;
18294
+ continue;
18295
+ }
18296
+ if (inFence)
18297
+ continue;
18298
+ if (line.includes("<!--"))
18299
+ inHtmlComment = true;
18300
+ if (line.includes("-->")) {
18301
+ inHtmlComment = false;
18302
+ continue;
18303
+ }
18304
+ if (inHtmlComment)
18305
+ continue;
18234
18306
  if (line.match(/^\[([^\]]+)\]:\s*\S+/)) {
18235
18307
  continue;
18236
18308
  }
@@ -18447,19 +18519,34 @@ var init_no_bare_urls = __esm(() => {
18447
18519
  check: (text, ctx) => {
18448
18520
  const issues = [];
18449
18521
  const lines = text.split(/\r?\n/);
18522
+ let inFence = false;
18523
+ let inHtmlComment = false;
18450
18524
  for (let i = 0;i < lines.length; i++) {
18451
18525
  const line = lines[i];
18452
- if (line.trim().startsWith("```") || line.trim().startsWith("~~~")) {
18526
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18527
+ inFence = !inFence;
18453
18528
  continue;
18454
18529
  }
18455
- const urlPattern = /(?<![<`(])https?:\/\/[^\s<>`)\]]+(?![>\])`])/g;
18456
- const matches = line.matchAll(urlPattern);
18530
+ if (inFence)
18531
+ continue;
18532
+ if (line.includes("<!--"))
18533
+ inHtmlComment = true;
18534
+ if (line.includes("-->")) {
18535
+ inHtmlComment = false;
18536
+ continue;
18537
+ }
18538
+ if (inHtmlComment)
18539
+ continue;
18540
+ if (/^\[([^\]]+)\]:\s*\S+/.test(line))
18541
+ continue;
18542
+ const stripped = line.replace(/`[^`]+`/g, (m) => " ".repeat(m.length));
18543
+ const urlPattern = /(?<![<(="'])https?:\/\/[^\s<>`)\]"']+(?![>\])"'])/g;
18544
+ const matches = stripped.matchAll(urlPattern);
18457
18545
  for (const match of matches) {
18458
- const column = match.index + 1;
18459
18546
  issues.push({
18460
18547
  filePath: ctx.filePath,
18461
18548
  line: i + 1,
18462
- column,
18549
+ column: match.index + 1,
18463
18550
  ruleId: "markdown/no-bare-urls",
18464
18551
  message: "Bare URL used. Wrap in angle brackets: <url>",
18465
18552
  severity: "error"
@@ -18470,11 +18557,26 @@ var init_no_bare_urls = __esm(() => {
18470
18557
  },
18471
18558
  fix: (text) => {
18472
18559
  const lines = text.split(/\r?\n/);
18560
+ let inFence = false;
18561
+ let inHtmlComment = false;
18473
18562
  const fixedLines = lines.map((line) => {
18474
- if (line.trim().startsWith("```") || line.trim().startsWith("~~~")) {
18563
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18564
+ inFence = !inFence;
18565
+ return line;
18566
+ }
18567
+ if (inFence)
18568
+ return line;
18569
+ if (line.includes("<!--"))
18570
+ inHtmlComment = true;
18571
+ if (line.includes("-->")) {
18572
+ inHtmlComment = false;
18475
18573
  return line;
18476
18574
  }
18477
- return line.replace(/(?<![<`(])https?:\/\/[^\s<>`)\]]+(?![>\])`])/g, "<$&>");
18575
+ if (inHtmlComment)
18576
+ return line;
18577
+ if (/^\[([^\]]+)\]:\s*\S+/.test(line))
18578
+ return line;
18579
+ return line.replace(/(?<![<(="'])https?:\/\/[^\s<>`)\]"']+(?![>\])"'])/g, "<$&>");
18478
18580
  });
18479
18581
  return fixedLines.join(`
18480
18582
  `);
@@ -18530,8 +18632,15 @@ var init_no_duplicate_heading = __esm(() => {
18530
18632
  const issues = [];
18531
18633
  const lines = text.split(/\r?\n/);
18532
18634
  const headings = new Map;
18635
+ let inFence = false;
18533
18636
  for (let i = 0;i < lines.length; i++) {
18534
18637
  const line = lines[i];
18638
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18639
+ inFence = !inFence;
18640
+ continue;
18641
+ }
18642
+ if (inFence)
18643
+ continue;
18535
18644
  const atxMatch = line.match(/^#{1,6}\s+(.+?)(?:\s*#+\s*)?$/);
18536
18645
  if (atxMatch) {
18537
18646
  const content = atxMatch[1].trim();
@@ -18580,10 +18689,17 @@ var init_no_emphasis_as_heading = __esm(() => {
18580
18689
  check: (text, ctx) => {
18581
18690
  const issues = [];
18582
18691
  const lines = text.split(/\r?\n/);
18692
+ let inFence = false;
18583
18693
  for (let i = 0;i < lines.length; i++) {
18584
18694
  const line = lines[i];
18585
18695
  const prevLine = i > 0 ? lines[i - 1] : "";
18586
18696
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
18697
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18698
+ inFence = !inFence;
18699
+ continue;
18700
+ }
18701
+ if (inFence)
18702
+ continue;
18587
18703
  const isBoldLine = /^\*\*[^*]+\*\*\s*$/.test(line) || /^__[^_]+__\s*$/.test(line);
18588
18704
  const isItalicLine = /^\*[^*]+\*\s*$/.test(line) || /^_[^_]+_\s*$/.test(line);
18589
18705
  const isStandalone = prevLine.trim().length === 0 && nextLine.trim().length === 0;
@@ -18689,9 +18805,17 @@ var init_no_inline_html = __esm(() => {
18689
18805
  const lines = text.split(/\r?\n/);
18690
18806
  const options = ctx.options || {};
18691
18807
  const allowedElements = options.allowed_elements || [];
18808
+ let inFence = false;
18692
18809
  for (let i = 0;i < lines.length; i++) {
18693
18810
  const line = lines[i];
18694
- const matches = line.matchAll(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi);
18811
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
18812
+ inFence = !inFence;
18813
+ continue;
18814
+ }
18815
+ if (inFence)
18816
+ continue;
18817
+ const stripped = line.replace(/`[^`]+`/g, (m) => " ".repeat(m.length));
18818
+ const matches = stripped.matchAll(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi);
18695
18819
  for (const match of matches) {
18696
18820
  const tagName = match[1].toLowerCase();
18697
18821
  if (!allowedElements.includes(tagName)) {
@@ -19007,27 +19131,54 @@ var init_no_space_in_code = __esm(() => {
19007
19131
  check: (text, ctx) => {
19008
19132
  const issues = [];
19009
19133
  const lines = text.split(/\r?\n/);
19134
+ let inFence = false;
19010
19135
  for (let i = 0;i < lines.length; i++) {
19011
19136
  const line = lines[i];
19012
- const matches = line.matchAll(/(`+)\s+([^`]+?)\s+\1/g);
19013
- for (const match of matches) {
19014
- const column = match.index + 1;
19015
- issues.push({
19016
- filePath: ctx.filePath,
19017
- line: i + 1,
19018
- column,
19019
- ruleId: "markdown/no-space-in-code",
19020
- message: "Spaces inside code span elements",
19021
- severity: "error"
19022
- });
19137
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19138
+ inFence = !inFence;
19139
+ continue;
19140
+ }
19141
+ if (inFence)
19142
+ continue;
19143
+ const codeSpanPattern = /(`+)([\s\S]*?)\1/g;
19144
+ for (const match of line.matchAll(codeSpanPattern)) {
19145
+ const content = match[2];
19146
+ if (content.startsWith(" ") && content.endsWith(" ") && content.trim().length > 0) {
19147
+ issues.push({
19148
+ filePath: ctx.filePath,
19149
+ line: i + 1,
19150
+ column: match.index + 1,
19151
+ ruleId: "markdown/no-space-in-code",
19152
+ message: "Spaces inside code span elements",
19153
+ severity: "error"
19154
+ });
19155
+ }
19023
19156
  }
19024
19157
  }
19025
19158
  return issues;
19026
19159
  },
19027
19160
  fix: (text) => {
19028
- return text.replace(/(`+)\s+([^`]+?)\s+\1/g, (match, backticks, content) => {
19029
- return `${backticks}${content.trim()}${backticks}`;
19030
- });
19161
+ const lines = text.split(/\r?\n/);
19162
+ let inFence = false;
19163
+ const result = [];
19164
+ for (const line of lines) {
19165
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19166
+ inFence = !inFence;
19167
+ result.push(line);
19168
+ continue;
19169
+ }
19170
+ if (inFence) {
19171
+ result.push(line);
19172
+ continue;
19173
+ }
19174
+ result.push(line.replace(/(`+)([\s\S]*?)\1/g, (match, backticks, content) => {
19175
+ if (content.startsWith(" ") && content.endsWith(" ") && content.trim().length > 0)
19176
+ return `${backticks}${content.trim()}${backticks}`;
19177
+ return match;
19178
+ }));
19179
+ }
19180
+ return result.join(`
19181
+ `);
19031
19182
  }
19032
19183
  };
19033
19184
  });
@@ -19042,20 +19193,28 @@ var init_no_space_in_emphasis = __esm(() => {
19042
19193
  check: (text, ctx) => {
19043
19194
  const issues = [];
19044
19195
  const lines = text.split(/\r?\n/);
19196
+ let inFence = false;
19045
19197
  for (let i = 0;i < lines.length; i++) {
19046
19198
  const line = lines[i];
19199
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19200
+ inFence = !inFence;
19201
+ continue;
19202
+ }
19203
+ if (inFence)
19204
+ continue;
19205
+ const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
19047
19206
  const patterns = [
19048
- /(\*\*|\*|__?)\s+/g,
19049
- /\s+(\*\*|\*|__?)/g
19207
+ /\*\*\s+[^*]+?\*\*/g,
19208
+ /\*\*[^*]+?\s+\*\*/g,
19209
+ /__\s+[^_]+?__/g,
19210
+ /__[^_]+?\s+__/g
19050
19211
  ];
19051
19212
  for (const pattern of patterns) {
19052
- const matches = line.matchAll(pattern);
19053
- for (const match of matches) {
19054
- const column = match.index + 1;
19213
+ for (const match of stripped.matchAll(pattern)) {
19055
19214
  issues.push({
19056
19215
  filePath: ctx.filePath,
19057
19216
  line: i + 1,
19058
- column,
19217
+ column: match.index + 1,
19059
19218
  ruleId: "markdown/no-space-in-emphasis",
19060
19219
  message: "Spaces inside emphasis markers",
19061
19220
  severity: "error"
@@ -19066,9 +19225,28 @@ var init_no_space_in_emphasis = __esm(() => {
19066
19225
  return issues;
19067
19226
  },
19068
19227
  fix: (text) => {
19069
- let fixed = text.replace(/(\*\*|\*|__?)\s+/g, "$1");
19070
- fixed = fixed.replace(/\s+(\*\*|\*|__?)/g, "$1");
19071
- return fixed;
19228
+ const lines = text.split(/\r?\n/);
19229
+ let inFence = false;
19230
+ const result = [];
19231
+ for (const line of lines) {
19232
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19233
+ inFence = !inFence;
19234
+ result.push(line);
19235
+ continue;
19236
+ }
19237
+ if (inFence) {
19238
+ result.push(line);
19239
+ continue;
19240
+ }
19241
+ let fixed = line;
19242
+ fixed = fixed.replace(/\*\*\s+([^*]+?)\*\*/g, "**$1**");
19243
+ fixed = fixed.replace(/\*\*([^*]+?)\s+\*\*/g, "**$1**");
19244
+ fixed = fixed.replace(/__\s+([^_]+?)__/g, "__$1__");
19245
+ fixed = fixed.replace(/__([^_]+?)\s+__/g, "__$1__");
19246
+ result.push(fixed);
19247
+ }
19248
+ return result.join(`
19249
+ `);
19072
19250
  }
19073
19251
  };
19074
19252
  });
@@ -19372,20 +19550,37 @@ var init_reference_links_images = __esm(() => {
19372
19550
  definitions.add(defMatch[1].toLowerCase());
19373
19551
  }
19374
19552
  }
19553
+ let inFence = false;
19554
+ let inHtmlComment = false;
19375
19555
  for (let i = 0;i < lines.length; i++) {
19376
19556
  const line = lines[i];
19377
- const linkMatches = line.matchAll(/\[([^\]]+)\](?:\[([^\]]+)\])?(?!\()/g);
19557
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19558
+ inFence = !inFence;
19559
+ continue;
19560
+ }
19561
+ if (inFence)
19562
+ continue;
19563
+ if (line.includes("<!--"))
19564
+ inHtmlComment = true;
19565
+ if (line.includes("-->")) {
19566
+ inHtmlComment = false;
19567
+ continue;
19568
+ }
19569
+ if (inHtmlComment)
19570
+ continue;
19571
+ if (/^\[([^\]]+)\]:\s*\S+/.test(line))
19572
+ continue;
19573
+ const stripped = line.replace(/`[^`]+`/g, (m) => " ".repeat(m.length));
19574
+ const linkMatches = stripped.matchAll(/\[([^\]]+)\](?:\[([^\]]+)\])?(?!\()/g);
19378
19575
  for (const match of linkMatches) {
19379
19576
  const label = (match[2] || match[1]).toLowerCase();
19380
- if (line.match(/^\[([^\]]+)\]:\s*\S+/)) {
19577
+ if (/^[xX ]$/.test(label))
19381
19578
  continue;
19382
- }
19383
19579
  if (!definitions.has(label)) {
19384
- const column = match.index + 1;
19385
19580
  issues.push({
19386
19581
  filePath: ctx.filePath,
19387
19582
  line: i + 1,
19388
- column,
19583
+ column: match.index + 1,
19389
19584
  ruleId: "markdown/reference-links-images",
19390
19585
  message: `Reference link '[${label}]' is not defined`,
19391
19586
  severity: "error"
@@ -19452,9 +19647,16 @@ var init_single_title = __esm(() => {
19452
19647
  const issues = [];
19453
19648
  const lines = text.split(/\r?\n/);
19454
19649
  let firstH1Line = -1;
19650
+ let inFencedCodeBlock = false;
19455
19651
  for (let i = 0;i < lines.length; i++) {
19456
19652
  const line = lines[i];
19457
19653
  const nextLine = i + 1 < lines.length ? lines[i + 1] : "";
19654
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19655
+ inFencedCodeBlock = !inFencedCodeBlock;
19656
+ continue;
19657
+ }
19658
+ if (inFencedCodeBlock)
19659
+ continue;
19458
19660
  let isH1 = false;
19459
19661
  if (/^#\s/.test(line)) {
19460
19662
  isH1 = true;
@@ -19721,8 +19923,15 @@ var init_table_pipe_style = __esm(() => {
19721
19923
  const lines = text.split(/\r?\n/);
19722
19924
  const options = ctx.options || {};
19723
19925
  const style = options.style || "leading_and_trailing";
19926
+ let inFence = false;
19724
19927
  for (let i = 0;i < lines.length; i++) {
19725
19928
  const line = lines[i];
19929
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
19930
+ inFence = !inFence;
19931
+ continue;
19932
+ }
19933
+ if (inFence)
19934
+ continue;
19726
19935
  if (/\|/.test(line) && line.trim().length > 0) {
19727
19936
  const hasLeading = line.trim().startsWith("|");
19728
19937
  const hasTrailing = line.trim().endsWith("|");
@@ -19790,8 +19999,15 @@ var init_ul_indent = __esm(() => {
19790
19999
  const lines = text.split(/\r?\n/);
19791
20000
  const options = ctx.options || {};
19792
20001
  const expectedIndent = options.indent || 2;
20002
+ let inFence = false;
19793
20003
  for (let i = 0;i < lines.length; i++) {
19794
20004
  const line = lines[i];
20005
+ if (/^(`{3,}|~{3,})/.test(line.trim())) {
20006
+ inFence = !inFence;
20007
+ continue;
20008
+ }
20009
+ if (inFence)
20010
+ continue;
19795
20011
  const match = line.match(/^(\s*)([*\-+])\s+/);
19796
20012
  if (match) {
19797
20013
  const indent = match[1].length;
@@ -19905,18 +20121,49 @@ var init_ul_style = __esm(() => {
19905
20121
  });
19906
20122
 
19907
20123
  // src/plugins/markdown.ts
20124
+ function stripFrontmatter(content) {
20125
+ const lines = content.split(/\r?\n/);
20126
+ if (lines[0]?.trim() !== "---")
20127
+ return { text: content, frontmatter: null, frontmatterEndLine: 0 };
20128
+ for (let i = 1;i < lines.length; i++) {
20129
+ if (lines[i].trim() === "---") {
20130
+ const frontmatter = lines.slice(0, i + 1);
20131
+ const blanked = frontmatter.map(() => "");
20132
+ return {
20133
+ text: [...blanked, ...lines.slice(i + 1)].join(`
20134
+ `),
20135
+ frontmatter,
20136
+ frontmatterEndLine: i + 1
20137
+ };
20138
+ }
20139
+ }
20140
+ return { text: content, frontmatter: null, frontmatterEndLine: 0 };
20141
+ }
20142
+ function restoreFrontmatter(content, frontmatter) {
20143
+ if (!frontmatter)
20144
+ return content;
20145
+ const lines = content.split(/\r?\n/);
20146
+ return [...frontmatter, ...lines.slice(frontmatter.length)].join(`
20147
+ `);
20148
+ }
19908
20149
  function markdownOnly(rule) {
19909
20150
  return {
19910
20151
  meta: rule.meta,
19911
20152
  check: (content, context) => {
19912
20153
  if (!context.filePath.endsWith(".md"))
19913
20154
  return [];
19914
- return rule.check(content, context);
20155
+ const { text, frontmatterEndLine } = stripFrontmatter(content);
20156
+ const issues = rule.check(text, context);
20157
+ if (frontmatterEndLine > 0)
20158
+ return issues.filter((issue) => issue.line > frontmatterEndLine + 1);
20159
+ return issues;
19915
20160
  },
19916
20161
  fix: rule.fix ? (content, context) => {
19917
20162
  if (!context.filePath.endsWith(".md"))
19918
20163
  return content;
19919
- return rule.fix(content, context);
20164
+ const { text, frontmatter } = stripFrontmatter(content);
20165
+ const fixed = rule.fix(text, context);
20166
+ return restoreFrontmatter(fixed, frontmatter);
19920
20167
  } : undefined
19921
20168
  };
19922
20169
  }
@@ -25605,13 +25852,13 @@ var init_style = __esm(() => {
25605
25852
  stylePlugin = {
25606
25853
  name: "style",
25607
25854
  rules: {
25608
- "brace-style": braceStyle,
25609
- curly: curlyRule,
25610
- "max-statements-per-line": maxStatementsPerLineRule,
25611
- "if-newline": ifNewlineRule,
25612
- "consistent-chaining": consistentChainingRule,
25613
- "consistent-list-newline": consistentListNewlineRule,
25614
- "indent-unindent": indentUnindentRule,
25855
+ "brace-style": codeOnly(braceStyle),
25856
+ curly: codeOnly(curlyRule),
25857
+ "max-statements-per-line": codeOnly(maxStatementsPerLineRule),
25858
+ "if-newline": codeOnly(ifNewlineRule),
25859
+ "consistent-chaining": codeOnly(consistentChainingRule),
25860
+ "consistent-list-newline": codeOnly(consistentListNewlineRule),
25861
+ "indent-unindent": codeOnly(indentUnindentRule),
25615
25862
  "no-multi-spaces": noMultiSpaces,
25616
25863
  "no-multiple-empty-lines": noMultipleEmptyLines,
25617
25864
  "no-trailing-spaces": noTrailingSpaces,
@@ -28025,6 +28272,18 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
28025
28272
  const wantNoCondAssign = sevMap(cfg.rules.noCondAssign);
28026
28273
  const consoleCall = /\bconsole\.log\s*\(/;
28027
28274
  const debuggerStmt = /^\s*debugger\b/;
28275
+ const linesInFencedCodeBlock = new Set;
28276
+ if (fileExt === "md") {
28277
+ let inFence = false;
28278
+ for (let li = 0;li < lines.length; li++) {
28279
+ if (/^(`{3,}|~{3,})/.test(lines[li].trim())) {
28280
+ inFence = !inFence;
28281
+ continue;
28282
+ }
28283
+ if (inFence)
28284
+ linesInFencedCodeBlock.add(li + 1);
28285
+ }
28286
+ }
28028
28287
  const linesInTemplate = new Set;
28029
28288
  let inTemplate = false;
28030
28289
  let escaped = false;
@@ -28073,7 +28332,7 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
28073
28332
  }
28074
28333
  const leadingMatch = line.match(/^[ \t]*/);
28075
28334
  const leading = leadingMatch ? leadingMatch[0] : "";
28076
- if (leading.length > 0 && hasIndentIssue(leading, cfg.format.indent, cfg.format.indentStyle)) {
28335
+ if (leading.length > 0 && !linesInFencedCodeBlock.has(lineNo) && hasIndentIssue(leading, cfg.format.indent, cfg.format.indentStyle, line)) {
28077
28336
  if (!isSuppressed("indent", lineNo, suppress))
28078
28337
  issues.push({ filePath, line: lineNo, column: 1, ruleId: "indent", message: "Incorrect indentation detected", severity: "warning", help: `Use ${cfg.format.indentStyle === "spaces" ? `${cfg.format.indent} spaces` : "tabs"} for indentation. Configure with format.indent and format.indentStyle in your config` });
28079
28338
  }
@@ -32419,7 +32678,7 @@ var require_package = __commonJS((exports, module) => {
32419
32678
  module.exports = {
32420
32679
  name: "pickier",
32421
32680
  type: "module",
32422
- version: "0.1.14",
32681
+ version: "0.1.16",
32423
32682
  description: "Format, lint and more in a fraction of seconds.",
32424
32683
  author: "Chris Breuer <chris@stacksjs.org>",
32425
32684
  license: "MIT",