eslint-plugin-markdown-preferences 0.32.0 → 0.33.0

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/lib/index.d.ts CHANGED
@@ -538,7 +538,7 @@ declare namespace meta_d_exports {
538
538
  export { name, version };
539
539
  }
540
540
  declare const name: "eslint-plugin-markdown-preferences";
541
- declare const version: "0.32.0";
541
+ declare const version: "0.33.0";
542
542
  //#endregion
543
543
  //#region src/language/ast-types.d.ts
544
544
  type Node = mdast.Node;
package/lib/index.js CHANGED
@@ -11278,11 +11278,14 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11278
11278
  const options = parseOptions(context.options[0]);
11279
11279
  class TableContext {
11280
11280
  rows;
11281
+ delimiterRow;
11281
11282
  columnCount;
11282
- _cacheHasSpaceBetweenContentAndTrailingPipe = /* @__PURE__ */ new Map();
11283
+ _cacheNeedSpaceBetweenLeadingPipeAndContent = /* @__PURE__ */ new Map();
11284
+ _cacheNeedSpaceBetweenContentAndTrailingPipe = /* @__PURE__ */ new Map();
11283
11285
  _cacheExpectedPipePosition = /* @__PURE__ */ new Map();
11284
11286
  constructor(parsed) {
11285
- const rows = [parsedTableRowToRowData(parsed.headerRow), parsedTableDelimiterRowToRowData(parsed.delimiterRow)];
11287
+ this.delimiterRow = parsedTableDelimiterRowToRowData(parsed.delimiterRow);
11288
+ const rows = [parsedTableRowToRowData(parsed.headerRow), this.delimiterRow];
11286
11289
  for (const bodyRow of parsed.bodyRows) rows.push(parsedTableRowToRowData(bodyRow));
11287
11290
  this.rows = rows;
11288
11291
  let columnCount = 0;
@@ -11300,17 +11303,29 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11300
11303
  return v;
11301
11304
  }
11302
11305
  /**
11306
+ * Check if there is at least one space between leading pipe and content
11307
+ */
11308
+ isNeedSpaceBetweenLeadingPipeAndContent(pipeIndex) {
11309
+ let v = this._cacheNeedSpaceBetweenLeadingPipeAndContent.get(pipeIndex);
11310
+ if (v != null) return v;
11311
+ if (getCurrentTablePipeSpacingOption(sourceCode)?.leadingSpace === "always") v = true;
11312
+ else v = this._hasSpaceBetweenLeadingPipeAndContentWithoutCache(pipeIndex);
11313
+ this._cacheNeedSpaceBetweenLeadingPipeAndContent.set(pipeIndex, v);
11314
+ return v;
11315
+ }
11316
+ /**
11303
11317
  * Check if there is at least one space between content and trailing pipe
11304
11318
  * for the index
11305
11319
  *
11306
11320
  * This is used to determine if the pipe should be aligned with a space before it.
11307
11321
  */
11308
- hasSpaceBetweenContentAndTrailingPipe(pipeIndex) {
11322
+ isNeedSpaceBetweenContentAndTrailingPipe(pipeIndex) {
11309
11323
  if (pipeIndex === 0) return false;
11310
- let v = this._cacheHasSpaceBetweenContentAndTrailingPipe.get(pipeIndex);
11324
+ let v = this._cacheNeedSpaceBetweenContentAndTrailingPipe.get(pipeIndex);
11311
11325
  if (v != null) return v;
11312
- v = this._hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex);
11313
- this._cacheHasSpaceBetweenContentAndTrailingPipe.set(pipeIndex, v);
11326
+ if (getCurrentTablePipeSpacingOption(sourceCode)?.trailingSpace === "always") v = true;
11327
+ else v = this._hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex);
11328
+ this._cacheNeedSpaceBetweenContentAndTrailingPipe.set(pipeIndex, v);
11314
11329
  return v;
11315
11330
  }
11316
11331
  /**
@@ -11321,7 +11336,7 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11321
11336
  const firstCell = this.rows[0].cells[0];
11322
11337
  const firstToken = firstCell.leadingPipe ?? firstCell.content;
11323
11338
  if (!firstToken) return null;
11324
- return getTextWidth(sourceCode.lines[firstToken.loc.start.line - 1].slice(0, firstToken.loc.start.column - 1));
11339
+ return getTextWidth(sourceCode.lines[firstToken.loc.start.line - 1], 0, firstToken.loc.start.column - 1);
11325
11340
  }
11326
11341
  if (options.columnOption === "minimum") return this.getMinimumPipePosition(pipeIndex);
11327
11342
  else if (options.columnOption === "consistent") {
@@ -11330,7 +11345,7 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11330
11345
  if (row.cells.length <= columnIndex) continue;
11331
11346
  const cell = row.cells[columnIndex];
11332
11347
  if (cell.type === "delimiter" || !cell.trailingPipe) continue;
11333
- const width = getTextWidth(sourceCode.lines[cell.trailingPipe.loc.start.line - 1].slice(0, cell.trailingPipe.loc.start.column - 1));
11348
+ const width = getTextWidth(sourceCode.lines[cell.trailingPipe.loc.start.line - 1], 0, cell.trailingPipe.loc.start.column - 1);
11334
11349
  return Math.max(width, this.getMinimumPipePosition(pipeIndex) || 0);
11335
11350
  }
11336
11351
  }
@@ -11340,20 +11355,29 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11340
11355
  * Get the minimum pipe position for the index
11341
11356
  */
11342
11357
  getMinimumPipePosition(pipeIndex) {
11343
- const spacingRuleOptions = getCurrentTablePipeSpacingOption(sourceCode);
11344
- const needSpaceBeforePipe = spacingRuleOptions ? spacingRuleOptions.trailingSpace === "always" : this.hasSpaceBetweenContentAndTrailingPipe(pipeIndex);
11358
+ const needSpaceAfterPipe = this.isNeedSpaceBetweenLeadingPipeAndContent(pipeIndex - 1);
11359
+ const needSpaceBeforePipe = this.isNeedSpaceBetweenContentAndTrailingPipe(pipeIndex);
11345
11360
  let maxWidth = 0;
11346
11361
  const columnIndex = pipeIndex - 1;
11347
11362
  for (const row of this.rows) {
11348
11363
  if (row.cells.length <= columnIndex) continue;
11349
11364
  const cell = row.cells[columnIndex];
11350
11365
  let width;
11351
- if (cell.type === "delimiter") {
11366
+ if (cell.leadingPipe) {
11367
+ const leadingPipeEndOffset = getTextWidth(sourceCode.lines[cell.leadingPipe.loc.end.line - 1], 0, cell.leadingPipe.loc.end.column - 1);
11368
+ let contentLength;
11369
+ if (cell.type === "delimiter") contentLength = getMinimumDelimiterLength(cell.align);
11370
+ else {
11371
+ if (!cell.content) continue;
11372
+ contentLength = getTextWidth(sourceCode.lines[cell.content.loc.start.line - 1], cell.content.loc.start.column - 1, cell.content.loc.end.column - 1);
11373
+ }
11374
+ width = leadingPipeEndOffset + (needSpaceAfterPipe ? 1 : 0) + contentLength;
11375
+ } else if (cell.type === "delimiter") {
11352
11376
  const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
11353
- width = getTextWidth(sourceCode.lines[cell.delimiter.loc.start.line - 1].slice(0, cell.delimiter.loc.start.column - 1)) + minimumDelimiterLength;
11377
+ width = getTextWidth(sourceCode.lines[cell.delimiter.loc.start.line - 1], 0, cell.delimiter.loc.start.column - 1) + minimumDelimiterLength;
11354
11378
  } else {
11355
11379
  if (!cell.content) continue;
11356
- width = getTextWidth(sourceCode.lines[cell.content.loc.end.line - 1].slice(0, cell.content.loc.end.column - 1));
11380
+ width = getTextWidth(sourceCode.lines[cell.content.loc.end.line - 1], 0, cell.content.loc.end.column - 1);
11357
11381
  }
11358
11382
  if (needSpaceBeforePipe) width += 1;
11359
11383
  maxWidth = Math.max(maxWidth, width);
@@ -11361,6 +11385,26 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11361
11385
  return maxWidth;
11362
11386
  }
11363
11387
  /**
11388
+ * Check if there is at least one space between leading pipe and content
11389
+ */
11390
+ _hasSpaceBetweenLeadingPipeAndContentWithoutCache(pipeIndex) {
11391
+ const columnIndex = pipeIndex;
11392
+ for (const row of this.rows) {
11393
+ if (row.cells.length <= columnIndex) continue;
11394
+ const cell = row.cells[columnIndex];
11395
+ if (!cell.leadingPipe) continue;
11396
+ let content;
11397
+ if (cell.type === "delimiter") content = cell.delimiter;
11398
+ else {
11399
+ if (!cell.content) continue;
11400
+ content = cell.content;
11401
+ }
11402
+ if (cell.leadingPipe.range[1] < content.range[0]) continue;
11403
+ return false;
11404
+ }
11405
+ return true;
11406
+ }
11407
+ /**
11364
11408
  * Check if there is at least one space between content and trailing pipe
11365
11409
  */
11366
11410
  _hasSpaceBetweenContentAndTrailingPipeWithoutCache(pipeIndex) {
@@ -11413,7 +11457,7 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11413
11457
  function verifyPipe(pipe, pipeIndex, table, cell) {
11414
11458
  const expected = table.getExpectedPipePosition(pipeIndex);
11415
11459
  if (expected == null) return true;
11416
- const actual = getTextWidth(sourceCode.lines[pipe.loc.start.line - 1].slice(0, pipe.loc.start.column - 1));
11460
+ const actual = getTextWidth(sourceCode.lines[pipe.loc.start.line - 1], 0, pipe.loc.start.column - 1);
11417
11461
  const diff = expected - actual;
11418
11462
  if (diff === 0) return true;
11419
11463
  context.report({
@@ -11436,12 +11480,19 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11436
11480
  const widthBeforeDelimiter = getTextWidth(beforeDelimiter);
11437
11481
  const newLength = expected - widthBeforeDelimiter;
11438
11482
  const minimumDelimiterLength = getMinimumDelimiterLength(cell.align);
11439
- const spaceAfter = table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? " " : "";
11440
- if (newLength < minimumDelimiterLength + spaceAfter.length) return null;
11483
+ const spaceAfter = table.isNeedSpaceBetweenContentAndTrailingPipe(pipeIndex) ? " " : "";
11484
+ if (newLength < minimumDelimiterLength + spaceAfter.length) {
11485
+ const edit = fixRemoveSpacesFromLeadingSpaces(Math.abs(newLength - minimumDelimiterLength) + spaceAfter.length);
11486
+ if (!edit) return null;
11487
+ const delimiterPrefix$1 = cell.align === "left" || cell.align === "center" ? ":" : "";
11488
+ const delimiterSuffix$1 = cell.align === "right" || cell.align === "center" ? ":" : "";
11489
+ const newDelimiter$1 = "-".repeat(minimumDelimiterLength - delimiterPrefix$1.length - delimiterSuffix$1.length);
11490
+ return [edit, fixer.replaceTextRange([cell.delimiter.range[0], pipe.range[0]], delimiterPrefix$1 + newDelimiter$1 + delimiterSuffix$1 + spaceAfter)];
11491
+ }
11441
11492
  const delimiterPrefix = cell.align === "left" || cell.align === "center" ? ":" : "";
11442
- const delimiterSuffix = (cell.align === "right" || cell.align === "center" ? ":" : "") + spaceAfter;
11443
- const newDelimiter = "-".repeat(newLength - delimiterPrefix.length - delimiterSuffix.length);
11444
- return fixer.replaceTextRange([cell.delimiter.range[0], pipe.range[0]], delimiterPrefix + newDelimiter + delimiterSuffix);
11493
+ const delimiterSuffix = cell.align === "right" || cell.align === "center" ? ":" : "";
11494
+ const newDelimiter = "-".repeat(newLength - delimiterPrefix.length - delimiterSuffix.length - spaceAfter.length);
11495
+ return fixer.replaceTextRange([cell.delimiter.range[0], pipe.range[0]], delimiterPrefix + newDelimiter + delimiterSuffix + spaceAfter);
11445
11496
  /**
11446
11497
  * Fixer to remove spaces before the pipe
11447
11498
  */
@@ -11451,9 +11502,25 @@ var table_pipe_alignment_default = createRule("table-pipe-alignment", {
11451
11502
  const spacesBeforePipeLength = beforePipe.length - trimmedBeforePipe.length;
11452
11503
  const widthBeforePipe = getTextWidth(trimmedBeforePipe);
11453
11504
  const newSpacesLength = expected - widthBeforePipe;
11454
- if (newSpacesLength < (table.hasSpaceBetweenContentAndTrailingPipe(pipeIndex) ? 1 : 0)) return null;
11505
+ const minTrailingSpaceWidth = table.isNeedSpaceBetweenContentAndTrailingPipe(pipeIndex) ? 1 : 0;
11506
+ if (newSpacesLength < minTrailingSpaceWidth) {
11507
+ const edit = fixRemoveSpacesFromLeadingSpaces(Math.abs(newSpacesLength) + minTrailingSpaceWidth);
11508
+ if (!edit) return null;
11509
+ return [edit, fixer.replaceTextRange([pipe.range[0] - spacesBeforePipeLength, pipe.range[0]], " ".repeat(minTrailingSpaceWidth))];
11510
+ }
11455
11511
  return fixer.replaceTextRange([pipe.range[0] - spacesBeforePipeLength, pipe.range[0]], " ".repeat(newSpacesLength));
11456
11512
  }
11513
+ /**
11514
+ * Fixer to remove spaces from the leading spaces
11515
+ */
11516
+ function fixRemoveSpacesFromLeadingSpaces(removeSpaceLength) {
11517
+ if (!cell.leadingPipe || pipeIndex === 0) return null;
11518
+ const content = cell.type === "delimiter" ? cell.delimiter : cell.content;
11519
+ if (!content) return null;
11520
+ const newSpacesLength = getTextWidth(sourceCode.lines[cell.leadingPipe.loc.end.line - 1], cell.leadingPipe.loc.end.column - 1, content.loc.start.column - 1) - removeSpaceLength;
11521
+ if (newSpacesLength < (table.isNeedSpaceBetweenLeadingPipeAndContent(pipeIndex - 1) ? 1 : 0)) return null;
11522
+ return fixer.replaceTextRange([cell.leadingPipe.range[1], content.range[0]], " ".repeat(newSpacesLength));
11523
+ }
11457
11524
  }
11458
11525
  });
11459
11526
  return false;
@@ -11870,7 +11937,7 @@ var meta_exports = /* @__PURE__ */ __export({
11870
11937
  version: () => version
11871
11938
  });
11872
11939
  const name = "eslint-plugin-markdown-preferences";
11873
- const version = "0.32.0";
11940
+ const version = "0.33.0";
11874
11941
 
11875
11942
  //#endregion
11876
11943
  //#region src/language/extensions/micromark-custom-container.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-markdown-preferences",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "ESLint plugin that enforces our markdown preferences",
5
5
  "type": "module",
6
6
  "exports": {