eslint-plugin-markdown-preferences 0.4.0 → 0.5.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/README.md +1 -1
- package/lib/index.d.ts +66 -3
- package/lib/index.js +123 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ The rules with the following star ⭐ are included in the configs.
|
|
|
92
92
|
|:--------|:------------|:-------:|:-----------:|
|
|
93
93
|
| [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style. | 🔧 | ⭐ |
|
|
94
94
|
| [markdown-preferences/no-text-backslash-linebreak](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html) | disallow text backslash at the end of a line. | | ⭐ |
|
|
95
|
-
| [markdown-preferences/no-trailing-spaces](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html) | trailing whitespace at the end of lines in Markdown files. | 🔧 | |
|
|
95
|
+
| [markdown-preferences/no-trailing-spaces](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html) | disallow trailing whitespace at the end of lines in Markdown files. | 🔧 | |
|
|
96
96
|
| [markdown-preferences/prefer-inline-code-words](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-inline-code-words.html) | enforce the use of inline code for specific words. | 🔧 | |
|
|
97
97
|
| [markdown-preferences/prefer-linked-words](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-linked-words.html) | enforce the specified word to be a link. | 🔧 | |
|
|
98
98
|
|
package/lib/index.d.ts
CHANGED
|
@@ -3,7 +3,70 @@ import * as _eslint_core0 from "@eslint/core";
|
|
|
3
3
|
import { RuleDefinition } from "@eslint/core";
|
|
4
4
|
import { ESLint, Linter } from "eslint";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/rule-types.d.ts
|
|
7
|
+
declare module 'eslint' {
|
|
8
|
+
namespace Linter {
|
|
9
|
+
interface RulesRecord extends RuleOptions {}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
interface RuleOptions {
|
|
13
|
+
/**
|
|
14
|
+
* enforce consistent hard linebreak style.
|
|
15
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html
|
|
16
|
+
*/
|
|
17
|
+
'markdown-preferences/hard-linebreak-style'?: Linter.RuleEntry<MarkdownPreferencesHardLinebreakStyle>;
|
|
18
|
+
/**
|
|
19
|
+
* disallow text backslash at the end of a line.
|
|
20
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html
|
|
21
|
+
*/
|
|
22
|
+
'markdown-preferences/no-text-backslash-linebreak'?: Linter.RuleEntry<[]>;
|
|
23
|
+
/**
|
|
24
|
+
* disallow trailing whitespace at the end of lines in Markdown files.
|
|
25
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html
|
|
26
|
+
*/
|
|
27
|
+
'markdown-preferences/no-trailing-spaces'?: Linter.RuleEntry<MarkdownPreferencesNoTrailingSpaces>;
|
|
28
|
+
/**
|
|
29
|
+
* enforce the use of inline code for specific words.
|
|
30
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-inline-code-words.html
|
|
31
|
+
*/
|
|
32
|
+
'markdown-preferences/prefer-inline-code-words'?: Linter.RuleEntry<MarkdownPreferencesPreferInlineCodeWords>;
|
|
33
|
+
/**
|
|
34
|
+
* enforce the specified word to be a link.
|
|
35
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/prefer-linked-words.html
|
|
36
|
+
*/
|
|
37
|
+
'markdown-preferences/prefer-linked-words'?: Linter.RuleEntry<MarkdownPreferencesPreferLinkedWords>;
|
|
38
|
+
}
|
|
39
|
+
type MarkdownPreferencesHardLinebreakStyle = [] | [{
|
|
40
|
+
style?: ("backslash" | "spaces");
|
|
41
|
+
}];
|
|
42
|
+
type MarkdownPreferencesNoTrailingSpaces = [] | [{
|
|
43
|
+
skipBlankLines?: boolean;
|
|
44
|
+
ignoreComments?: boolean;
|
|
45
|
+
}];
|
|
46
|
+
type MarkdownPreferencesPreferInlineCodeWords = [] | [{
|
|
47
|
+
words: string[];
|
|
48
|
+
ignores?: {
|
|
49
|
+
words?: (string | string[]);
|
|
50
|
+
node?: {
|
|
51
|
+
[k: string]: unknown | undefined;
|
|
52
|
+
};
|
|
53
|
+
[k: string]: unknown | undefined;
|
|
54
|
+
}[];
|
|
55
|
+
[k: string]: unknown | undefined;
|
|
56
|
+
}];
|
|
57
|
+
type MarkdownPreferencesPreferLinkedWords = [] | [{
|
|
58
|
+
words: ({
|
|
59
|
+
[k: string]: (string | null);
|
|
60
|
+
} | string[]);
|
|
61
|
+
ignores?: {
|
|
62
|
+
words?: (string | string[]);
|
|
63
|
+
node?: {
|
|
64
|
+
[k: string]: unknown | undefined;
|
|
65
|
+
};
|
|
66
|
+
[k: string]: unknown | undefined;
|
|
67
|
+
}[];
|
|
68
|
+
[k: string]: unknown | undefined;
|
|
69
|
+
}];
|
|
7
70
|
declare namespace recommended_d_exports {
|
|
8
71
|
export { files, language, name$1 as name, plugins, rules$1 as rules };
|
|
9
72
|
}
|
|
@@ -19,7 +82,7 @@ declare namespace meta_d_exports {
|
|
|
19
82
|
export { name, version };
|
|
20
83
|
}
|
|
21
84
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
22
|
-
declare const version: "0.
|
|
85
|
+
declare const version: "0.5.0";
|
|
23
86
|
//#endregion
|
|
24
87
|
//#region src/index.d.ts
|
|
25
88
|
declare const configs: {
|
|
@@ -34,4 +97,4 @@ declare const _default: {
|
|
|
34
97
|
rules: Record<string, RuleDefinition<_eslint_core0.RuleDefinitionTypeOptions>>;
|
|
35
98
|
};
|
|
36
99
|
//#endregion
|
|
37
|
-
export { configs, _default as default, meta_d_exports as meta, rules };
|
|
100
|
+
export { RuleOptions, configs, _default as default, meta_d_exports as meta, rules };
|
package/lib/index.js
CHANGED
|
@@ -131,7 +131,7 @@ var no_trailing_spaces_default = createRule("no-trailing-spaces", {
|
|
|
131
131
|
meta: {
|
|
132
132
|
type: "layout",
|
|
133
133
|
docs: {
|
|
134
|
-
description: "trailing whitespace at the end of lines in Markdown files.",
|
|
134
|
+
description: "disallow trailing whitespace at the end of lines in Markdown files.",
|
|
135
135
|
categories: []
|
|
136
136
|
},
|
|
137
137
|
fixable: "whitespace",
|
|
@@ -249,9 +249,10 @@ const RE_BOUNDARY = /^[\s\p{Letter_Number}\p{Modifier_Letter}\p{Modifier_Symbol}
|
|
|
249
249
|
/**
|
|
250
250
|
* Iterate through words in a text node that match the specified words.
|
|
251
251
|
*/
|
|
252
|
-
function* iterateSearchWords(sourceCode, node, words) {
|
|
252
|
+
function* iterateSearchWords({ sourceCode, node, words, ignores }) {
|
|
253
253
|
const text = sourceCode.getText(node);
|
|
254
254
|
for (const word of words) {
|
|
255
|
+
if (ignores.ignore(word)) continue;
|
|
255
256
|
let startPosition = 0;
|
|
256
257
|
while (true) {
|
|
257
258
|
const index = text.indexOf(word, startPosition);
|
|
@@ -280,6 +281,57 @@ function* iterateSearchWords(sourceCode, node, words) {
|
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
}
|
|
284
|
+
const IGNORES_SCHEMA = {
|
|
285
|
+
type: "array",
|
|
286
|
+
items: {
|
|
287
|
+
type: "object",
|
|
288
|
+
properties: {
|
|
289
|
+
words: { anyOf: [{ type: "string" }, {
|
|
290
|
+
type: "array",
|
|
291
|
+
items: { type: "string" }
|
|
292
|
+
}] },
|
|
293
|
+
node: { type: "object" }
|
|
294
|
+
},
|
|
295
|
+
additionalProperties: true
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* Create a context for ignoring specific words or nodes.
|
|
300
|
+
*/
|
|
301
|
+
function createSearchWordsIgnoreContext(ignores) {
|
|
302
|
+
if (!ignores || ignores.length === 0) return {
|
|
303
|
+
enter: () => void 0,
|
|
304
|
+
exit: () => void 0,
|
|
305
|
+
ignore: () => false
|
|
306
|
+
};
|
|
307
|
+
const conditions = ignores.map((ignore) => {
|
|
308
|
+
const isIgnoreWord = ignore.words == null ? () => true : Array.isArray(ignore.words) ? (word) => ignore.words.includes(word) : (word) => ignore.words === word;
|
|
309
|
+
const node = ignore.node || {};
|
|
310
|
+
const keys = Object.keys(node);
|
|
311
|
+
return {
|
|
312
|
+
isIgnoreWord,
|
|
313
|
+
isIgnoreNode: (nodeToCheck) => {
|
|
314
|
+
return keys.every((key) => nodeToCheck[key] === node[key]);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
});
|
|
318
|
+
const currentIgnores = /* @__PURE__ */ new Set();
|
|
319
|
+
return {
|
|
320
|
+
enter(node) {
|
|
321
|
+
for (const ignore of conditions) if (ignore.isIgnoreNode(node)) currentIgnores.add({
|
|
322
|
+
node,
|
|
323
|
+
condition: ignore
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
exit(node) {
|
|
327
|
+
for (const element of [...currentIgnores]) if (element.node === node) currentIgnores.delete(element);
|
|
328
|
+
},
|
|
329
|
+
ignore(word) {
|
|
330
|
+
for (const { condition } of currentIgnores) if (condition.isIgnoreWord(word)) return true;
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
283
335
|
|
|
284
336
|
//#endregion
|
|
285
337
|
//#region src/rules/prefer-inline-code-words.ts
|
|
@@ -294,19 +346,30 @@ var prefer_inline_code_words_default = createRule("prefer-inline-code-words", {
|
|
|
294
346
|
hasSuggestions: false,
|
|
295
347
|
schema: [{
|
|
296
348
|
type: "object",
|
|
297
|
-
properties: {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
349
|
+
properties: {
|
|
350
|
+
words: {
|
|
351
|
+
type: "array",
|
|
352
|
+
items: { type: "string" }
|
|
353
|
+
},
|
|
354
|
+
ignores: IGNORES_SCHEMA
|
|
355
|
+
},
|
|
356
|
+
required: ["words"],
|
|
357
|
+
additionalProperties: true
|
|
302
358
|
}],
|
|
303
359
|
messages: { requireInlineCode: "The word \"{{name}}\" should be in inline code." }
|
|
304
360
|
},
|
|
305
361
|
create(context) {
|
|
306
362
|
const sourceCode = context.sourceCode;
|
|
307
363
|
const words = context.options[0]?.words || [];
|
|
364
|
+
const ignores = createSearchWordsIgnoreContext(context.options[0]?.ignores);
|
|
308
365
|
let shortcutLinkReference = null;
|
|
309
366
|
return {
|
|
367
|
+
"*"(node) {
|
|
368
|
+
ignores.enter(node);
|
|
369
|
+
},
|
|
370
|
+
"*:exit"(node) {
|
|
371
|
+
ignores.exit(node);
|
|
372
|
+
},
|
|
310
373
|
linkReference(node) {
|
|
311
374
|
if (node.referenceType !== "shortcut") return;
|
|
312
375
|
if (shortcutLinkReference) return;
|
|
@@ -316,7 +379,12 @@ var prefer_inline_code_words_default = createRule("prefer-inline-code-words", {
|
|
|
316
379
|
if (shortcutLinkReference === node) shortcutLinkReference = null;
|
|
317
380
|
},
|
|
318
381
|
text(node) {
|
|
319
|
-
for (const { word, loc, range } of iterateSearchWords(
|
|
382
|
+
for (const { word, loc, range } of iterateSearchWords({
|
|
383
|
+
sourceCode,
|
|
384
|
+
node,
|
|
385
|
+
words,
|
|
386
|
+
ignores
|
|
387
|
+
})) {
|
|
320
388
|
const shortcutLinkReferenceToReport = shortcutLinkReference;
|
|
321
389
|
context.report({
|
|
322
390
|
node,
|
|
@@ -348,20 +416,25 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
348
416
|
hasSuggestions: false,
|
|
349
417
|
schema: [{
|
|
350
418
|
type: "object",
|
|
351
|
-
properties: {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
419
|
+
properties: {
|
|
420
|
+
words: { anyOf: [{
|
|
421
|
+
type: "object",
|
|
422
|
+
patternProperties: { "^[\\s\\S]+$": { type: ["string", "null"] } }
|
|
423
|
+
}, {
|
|
424
|
+
type: "array",
|
|
425
|
+
items: { type: "string" }
|
|
426
|
+
}] },
|
|
427
|
+
ignores: IGNORES_SCHEMA
|
|
428
|
+
},
|
|
429
|
+
required: ["words"],
|
|
430
|
+
additionalProperties: true
|
|
359
431
|
}],
|
|
360
432
|
messages: { requireLink: "The word \"{{name}}\" should be a link." }
|
|
361
433
|
},
|
|
362
434
|
create(context) {
|
|
363
435
|
const sourceCode = context.sourceCode;
|
|
364
436
|
const wordsOption = context.options[0]?.words || {};
|
|
437
|
+
const ignores = createSearchWordsIgnoreContext(context.options[0]?.ignores);
|
|
365
438
|
const links = Object.create(null);
|
|
366
439
|
const words = [];
|
|
367
440
|
if (Array.isArray(wordsOption)) words.push(...wordsOption);
|
|
@@ -373,18 +446,29 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
373
446
|
}
|
|
374
447
|
words.push(word);
|
|
375
448
|
}
|
|
376
|
-
let
|
|
449
|
+
let linkedNode = null;
|
|
377
450
|
return {
|
|
378
|
-
"
|
|
379
|
-
|
|
380
|
-
|
|
451
|
+
"*"(node) {
|
|
452
|
+
ignores.enter(node);
|
|
453
|
+
},
|
|
454
|
+
"*:exit"(node) {
|
|
455
|
+
ignores.exit(node);
|
|
381
456
|
},
|
|
382
|
-
"link, linkReference
|
|
383
|
-
if (
|
|
457
|
+
"link, linkReference"(node) {
|
|
458
|
+
if (linkedNode) return;
|
|
459
|
+
linkedNode = node;
|
|
460
|
+
},
|
|
461
|
+
"link, linkReference:exit"(node) {
|
|
462
|
+
if (linkedNode === node) linkedNode = null;
|
|
384
463
|
},
|
|
385
464
|
text(node) {
|
|
386
|
-
if (
|
|
387
|
-
for (const { word, loc, range } of iterateSearchWords(
|
|
465
|
+
if (linkedNode) return;
|
|
466
|
+
for (const { word, loc, range } of iterateSearchWords({
|
|
467
|
+
sourceCode,
|
|
468
|
+
node,
|
|
469
|
+
words,
|
|
470
|
+
ignores
|
|
471
|
+
})) {
|
|
388
472
|
const link = links[word];
|
|
389
473
|
context.report({
|
|
390
474
|
node,
|
|
@@ -398,17 +482,20 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
398
482
|
}
|
|
399
483
|
},
|
|
400
484
|
inlineCode(node) {
|
|
401
|
-
if (
|
|
402
|
-
for (const word of words)
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
485
|
+
if (linkedNode) return;
|
|
486
|
+
for (const word of words) {
|
|
487
|
+
if (ignores.ignore(word)) continue;
|
|
488
|
+
if (node.value === word) {
|
|
489
|
+
const link = links[word];
|
|
490
|
+
context.report({
|
|
491
|
+
node,
|
|
492
|
+
messageId: "requireLink",
|
|
493
|
+
data: { name: word },
|
|
494
|
+
fix: link ? (fixer) => {
|
|
495
|
+
return fixer.replaceText(node, `[\`${word}\`](${link})`);
|
|
496
|
+
} : null
|
|
497
|
+
});
|
|
498
|
+
}
|
|
412
499
|
}
|
|
413
500
|
}
|
|
414
501
|
};
|
|
@@ -466,7 +553,7 @@ __export(meta_exports, {
|
|
|
466
553
|
version: () => version
|
|
467
554
|
});
|
|
468
555
|
const name = "eslint-plugin-markdown-preferences";
|
|
469
|
-
const version = "0.
|
|
556
|
+
const version = "0.5.0";
|
|
470
557
|
|
|
471
558
|
//#endregion
|
|
472
559
|
//#region src/index.ts
|