eslint-plugin-markdown-preferences 0.34.2 → 0.35.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 +1 -1
- package/lib/index.js +189 -23
- package/package.json +3 -2
package/lib/index.d.ts
CHANGED
|
@@ -545,7 +545,7 @@ declare namespace meta_d_exports {
|
|
|
545
545
|
export { name, version };
|
|
546
546
|
}
|
|
547
547
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
548
|
-
declare const version: "0.
|
|
548
|
+
declare const version: "0.35.0";
|
|
549
549
|
//#endregion
|
|
550
550
|
//#region src/language/ast-types.d.ts
|
|
551
551
|
type Node = mdast.Node;
|
package/lib/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { __export } from "./chunk-CTAAG5j7.js";
|
|
|
2
2
|
import stringWidth from "string-width";
|
|
3
3
|
import emojiRegex from "emoji-regex-xs";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import diffSequence from "diff-sequences";
|
|
5
6
|
import markdown from "@eslint/markdown";
|
|
6
7
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
7
8
|
import { frontmatterFromMarkdown } from "mdast-util-frontmatter";
|
|
@@ -10280,6 +10281,55 @@ var setext_heading_underline_length_default = createRule("setext-heading-underli
|
|
|
10280
10281
|
}
|
|
10281
10282
|
});
|
|
10282
10283
|
|
|
10284
|
+
//#endregion
|
|
10285
|
+
//#region src/utils/calc-shortest-edit-script.ts
|
|
10286
|
+
/**
|
|
10287
|
+
* Given the contents of two sequences, returns diff information.
|
|
10288
|
+
* @param a The first sequence.
|
|
10289
|
+
* @param b The second sequence.
|
|
10290
|
+
* @param [options] The options object.
|
|
10291
|
+
* @param [options.isEqual] A function that returns true if two elements are equal.
|
|
10292
|
+
* @returns An array of diff objects.
|
|
10293
|
+
*/
|
|
10294
|
+
function calcShortestEditScript(a, b) {
|
|
10295
|
+
let aStartIndex = 0;
|
|
10296
|
+
let bStartIndex = 0;
|
|
10297
|
+
const result = [];
|
|
10298
|
+
(diffSequence.default || diffSequence)(a.length, b.length, (aIndex, bIndex) => a[aIndex] === b[bIndex], (nCommon, aCommon, bCommon) => {
|
|
10299
|
+
pushDelIns(aStartIndex, aCommon, bStartIndex, bCommon);
|
|
10300
|
+
aStartIndex = aCommon + nCommon;
|
|
10301
|
+
bStartIndex = bCommon + nCommon;
|
|
10302
|
+
if (nCommon > 0) for (let index = 0; index < nCommon; index++) {
|
|
10303
|
+
const elementA = a[aCommon + index];
|
|
10304
|
+
const elementB = b[bCommon + index];
|
|
10305
|
+
result.push({
|
|
10306
|
+
type: "common",
|
|
10307
|
+
a: elementA,
|
|
10308
|
+
b: elementB
|
|
10309
|
+
});
|
|
10310
|
+
}
|
|
10311
|
+
});
|
|
10312
|
+
pushDelIns(aStartIndex, a.length, bStartIndex, b.length);
|
|
10313
|
+
return result;
|
|
10314
|
+
/**
|
|
10315
|
+
* Pushes delete and insert sequences to the result.
|
|
10316
|
+
* @param aStart The start index of the delete sequence in `a`.
|
|
10317
|
+
* @param aEnd The end index of the delete sequence in `a`.
|
|
10318
|
+
* @param bStart The start index of the insert sequence in `b`.
|
|
10319
|
+
* @param bEnd The end index of the insert sequence in `b`.
|
|
10320
|
+
*/
|
|
10321
|
+
function pushDelIns(aStart, aEnd, bStart, bEnd) {
|
|
10322
|
+
for (const element of a.slice(aStart, aEnd)) result.push({
|
|
10323
|
+
type: "delete",
|
|
10324
|
+
a: element
|
|
10325
|
+
});
|
|
10326
|
+
for (const element of b.slice(bStart, bEnd)) result.push({
|
|
10327
|
+
type: "insert",
|
|
10328
|
+
b: element
|
|
10329
|
+
});
|
|
10330
|
+
}
|
|
10331
|
+
}
|
|
10332
|
+
|
|
10283
10333
|
//#endregion
|
|
10284
10334
|
//#region src/rules/sort-definitions.ts
|
|
10285
10335
|
var sort_definitions_default = createRule("sort-definitions", {
|
|
@@ -10327,7 +10377,10 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
10327
10377
|
},
|
|
10328
10378
|
additionalProperties: false
|
|
10329
10379
|
}],
|
|
10330
|
-
messages: {
|
|
10380
|
+
messages: {
|
|
10381
|
+
shouldBeBefore: "The definition '{{currentKey}}' should be before '{{prevKey}}'.",
|
|
10382
|
+
shouldBeAfter: "The definition '{{currentKey}}' should be after '{{nextKey}}'."
|
|
10383
|
+
}
|
|
10331
10384
|
},
|
|
10332
10385
|
create(context) {
|
|
10333
10386
|
const sourceCode = context.sourceCode;
|
|
@@ -10348,12 +10401,12 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
10348
10401
|
return `[^${node.identifier}]: ${childrenText}`;
|
|
10349
10402
|
}
|
|
10350
10403
|
/** Report */
|
|
10351
|
-
function
|
|
10404
|
+
function reportFixToMoveUp(node, previousNode, definitions) {
|
|
10352
10405
|
const currentKey = getDefinitionText(node);
|
|
10353
10406
|
const prevKey = getDefinitionText(previousNode);
|
|
10354
10407
|
context.report({
|
|
10355
10408
|
node,
|
|
10356
|
-
messageId: "
|
|
10409
|
+
messageId: "shouldBeBefore",
|
|
10357
10410
|
data: {
|
|
10358
10411
|
currentKey,
|
|
10359
10412
|
prevKey
|
|
@@ -10370,33 +10423,146 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
10370
10423
|
...previousNodes,
|
|
10371
10424
|
...after
|
|
10372
10425
|
];
|
|
10373
|
-
return
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10426
|
+
return fixReplaceDefinitions(fixer, definitions, movedNodes);
|
|
10427
|
+
}
|
|
10428
|
+
});
|
|
10429
|
+
}
|
|
10430
|
+
/** Report */
|
|
10431
|
+
function reportFixToMoveDown(node, nextNode, definitions) {
|
|
10432
|
+
const currentKey = getDefinitionText(node);
|
|
10433
|
+
const nextKey = getDefinitionText(nextNode);
|
|
10434
|
+
context.report({
|
|
10435
|
+
node,
|
|
10436
|
+
messageId: "shouldBeAfter",
|
|
10437
|
+
data: {
|
|
10438
|
+
currentKey,
|
|
10439
|
+
nextKey
|
|
10440
|
+
},
|
|
10441
|
+
fix(fixer) {
|
|
10442
|
+
const nextNodeIndex = definitions.indexOf(nextNode);
|
|
10443
|
+
const targetNodeIndex = definitions.indexOf(node);
|
|
10444
|
+
const nextNodes = definitions.slice(targetNodeIndex + 1, nextNodeIndex + 1);
|
|
10445
|
+
const before = definitions.slice(0, targetNodeIndex);
|
|
10446
|
+
const after = definitions.slice(nextNodeIndex + 1);
|
|
10447
|
+
const movedNodes = [
|
|
10448
|
+
...before,
|
|
10449
|
+
...nextNodes,
|
|
10450
|
+
node,
|
|
10451
|
+
...after
|
|
10452
|
+
];
|
|
10453
|
+
return fixReplaceDefinitions(fixer, definitions, movedNodes);
|
|
10383
10454
|
}
|
|
10384
10455
|
});
|
|
10385
10456
|
}
|
|
10386
10457
|
/**
|
|
10458
|
+
* Fix by replacing the definition array.
|
|
10459
|
+
*/
|
|
10460
|
+
function fixReplaceDefinitions(fixer, definitions, newDefinitions) {
|
|
10461
|
+
const fixes = [];
|
|
10462
|
+
let removeLine = null;
|
|
10463
|
+
for (let index = 0; index < newDefinitions.length; index++) {
|
|
10464
|
+
const newNode = newDefinitions[index];
|
|
10465
|
+
const oldNode = definitions[index];
|
|
10466
|
+
let newText = sourceCode.getText(newNode);
|
|
10467
|
+
if (needLineBreakBetweenKind(index)) {
|
|
10468
|
+
const oldLoc = sourceCode.getLoc(oldNode);
|
|
10469
|
+
newText = `\n${sourceCode.lines[oldLoc.start.line - 1].slice(0, oldLoc.start.column - 1).replaceAll(/[^\s>]/g, " ")}${newText}`;
|
|
10470
|
+
} else if (newNode === oldNode) continue;
|
|
10471
|
+
fixes.push(fixer.replaceText(oldNode, newText));
|
|
10472
|
+
if (removeLine) {
|
|
10473
|
+
fixes.push(fixer.removeRange(removeLine));
|
|
10474
|
+
removeLine = null;
|
|
10475
|
+
}
|
|
10476
|
+
}
|
|
10477
|
+
return fixes;
|
|
10478
|
+
/**
|
|
10479
|
+
* Determine if a line break is needed between different kinds of definitions.
|
|
10480
|
+
*/
|
|
10481
|
+
function needLineBreakBetweenKind(index) {
|
|
10482
|
+
if (index === 0) return false;
|
|
10483
|
+
if (newDefinitions[index].type !== "definition") return false;
|
|
10484
|
+
if (newDefinitions[index - 1].type !== "footnoteDefinition") return false;
|
|
10485
|
+
const oldPrevNode = definitions[index - 1];
|
|
10486
|
+
const oldNode = definitions[index];
|
|
10487
|
+
const footnoteLoc = sourceCode.getLoc(oldPrevNode);
|
|
10488
|
+
const linkLoc = sourceCode.getLoc(oldNode);
|
|
10489
|
+
if (linkLoc.start.line - footnoteLoc.end.line > 1) return false;
|
|
10490
|
+
if (index + 1 < newDefinitions.length) {
|
|
10491
|
+
if (newDefinitions[index + 1].type === "definition") {
|
|
10492
|
+
const oldNextNode = definitions[index + 1];
|
|
10493
|
+
const oldNextLoc = sourceCode.getLoc(oldNextNode);
|
|
10494
|
+
if (oldNextLoc.start.line - linkLoc.end.line > 1) {
|
|
10495
|
+
const parsedLine = getParsedLines(sourceCode).get(oldNextLoc.start.line - 1);
|
|
10496
|
+
if (!parsedLine.text.replaceAll(">", "").trim()) removeLine = parsedLine.range;
|
|
10497
|
+
}
|
|
10498
|
+
}
|
|
10499
|
+
}
|
|
10500
|
+
return true;
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
/**
|
|
10387
10504
|
* Verify definitions and footnote definitions.
|
|
10388
10505
|
*/
|
|
10389
10506
|
function verify(definitions) {
|
|
10390
10507
|
if (definitions.length === 0) return;
|
|
10391
|
-
const
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
const
|
|
10395
|
-
if (
|
|
10396
|
-
|
|
10397
|
-
|
|
10508
|
+
const sorted = [...definitions].sort(option.compare);
|
|
10509
|
+
const editScript = calcShortestEditScript(definitions, sorted);
|
|
10510
|
+
for (let index = 0; index < editScript.length; index++) {
|
|
10511
|
+
const edit = editScript[index];
|
|
10512
|
+
if (edit.type !== "delete") continue;
|
|
10513
|
+
const insertEditIndex = editScript.findIndex((e) => e.type === "insert" && e.b === edit.a);
|
|
10514
|
+
if (insertEditIndex === -1) continue;
|
|
10515
|
+
if (index < insertEditIndex) {
|
|
10516
|
+
const target = findInsertAfterTarget(edit.a, insertEditIndex);
|
|
10517
|
+
if (!target) continue;
|
|
10518
|
+
reportFixToMoveDown(edit.a, target, definitions);
|
|
10519
|
+
} else {
|
|
10520
|
+
const target = findInsertBeforeTarget(edit.a, insertEditIndex);
|
|
10521
|
+
if (!target) continue;
|
|
10522
|
+
reportFixToMoveUp(edit.a, target, definitions);
|
|
10523
|
+
}
|
|
10524
|
+
}
|
|
10525
|
+
/**
|
|
10526
|
+
* Find insert after target
|
|
10527
|
+
*/
|
|
10528
|
+
function findInsertAfterTarget(def, insertEditIndex) {
|
|
10529
|
+
for (let index = insertEditIndex - 1; index >= 0; index--) {
|
|
10530
|
+
const edit = editScript[index];
|
|
10531
|
+
if (edit.type === "delete" && edit.a === def) break;
|
|
10532
|
+
if (edit.type !== "common") continue;
|
|
10533
|
+
return edit.a;
|
|
10534
|
+
}
|
|
10535
|
+
let lastTarget = null;
|
|
10536
|
+
for (let index = definitions.indexOf(def) + 1; index < definitions.length; index++) {
|
|
10537
|
+
const element = definitions[index];
|
|
10538
|
+
if (option.compare(element, def) <= 0) {
|
|
10539
|
+
lastTarget = element;
|
|
10540
|
+
continue;
|
|
10541
|
+
}
|
|
10542
|
+
return lastTarget;
|
|
10543
|
+
}
|
|
10544
|
+
return lastTarget;
|
|
10545
|
+
}
|
|
10546
|
+
/**
|
|
10547
|
+
* Find insert before target
|
|
10548
|
+
*/
|
|
10549
|
+
function findInsertBeforeTarget(def, insertEditIndex) {
|
|
10550
|
+
for (let index = insertEditIndex + 1; index < editScript.length; index++) {
|
|
10551
|
+
const edit = editScript[index];
|
|
10552
|
+
if (edit.type === "delete" && edit.a === def) break;
|
|
10553
|
+
if (edit.type !== "common") continue;
|
|
10554
|
+
return edit.a;
|
|
10555
|
+
}
|
|
10556
|
+
let lastTarget = null;
|
|
10557
|
+
for (let index = definitions.indexOf(def) - 1; index >= 0; index--) {
|
|
10558
|
+
const element = definitions[index];
|
|
10559
|
+
if (option.compare(def, element) <= 0) {
|
|
10560
|
+
lastTarget = element;
|
|
10561
|
+
continue;
|
|
10562
|
+
}
|
|
10563
|
+
return lastTarget;
|
|
10398
10564
|
}
|
|
10399
|
-
|
|
10565
|
+
return lastTarget;
|
|
10400
10566
|
}
|
|
10401
10567
|
}
|
|
10402
10568
|
return {
|
|
@@ -10412,7 +10578,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
10412
10578
|
if (node.type === "definition" || node.type === "footnoteDefinition") group.push(node);
|
|
10413
10579
|
},
|
|
10414
10580
|
"root:exit"() {
|
|
10415
|
-
verify(group);
|
|
10581
|
+
verify(group.filter((definition) => !option.ignore(definition)));
|
|
10416
10582
|
}
|
|
10417
10583
|
};
|
|
10418
10584
|
/** Parse options */
|
|
@@ -11990,7 +12156,7 @@ var meta_exports = /* @__PURE__ */ __export({
|
|
|
11990
12156
|
version: () => version
|
|
11991
12157
|
});
|
|
11992
12158
|
const name = "eslint-plugin-markdown-preferences";
|
|
11993
|
-
const version = "0.
|
|
12159
|
+
const version = "0.35.0";
|
|
11994
12160
|
|
|
11995
12161
|
//#endregion
|
|
11996
12162
|
//#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.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "ESLint plugin that enforces our markdown preferences",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"eslint": ">=9.0.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
+
"diff-sequences": "^29.6.3",
|
|
65
66
|
"emoji-regex-xs": "^2.0.1",
|
|
66
67
|
"mdast-util-from-markdown": "^2.0.2",
|
|
67
68
|
"mdast-util-frontmatter": "^2.0.1",
|
|
@@ -104,7 +105,7 @@
|
|
|
104
105
|
"eslint-plugin-json-schema-validator": "^5.3.1",
|
|
105
106
|
"eslint-plugin-jsonc": "^2.19.1",
|
|
106
107
|
"eslint-plugin-markdown": "^5.1.0",
|
|
107
|
-
"eslint-plugin-markdown-links": "^0.
|
|
108
|
+
"eslint-plugin-markdown-links": "^0.6.0",
|
|
108
109
|
"eslint-plugin-n": "^17.16.2",
|
|
109
110
|
"eslint-plugin-node-dependencies": "^1.0.0",
|
|
110
111
|
"eslint-plugin-prettier": "^5.2.3",
|