markdownlint 0.23.1 → 0.24.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 +35 -10
- package/demo/markdownlint-browser.js +253 -166
- package/doc/Prettier.md +23 -0
- package/doc/Rules.md +16 -1
- package/helpers/helpers.js +47 -5
- package/helpers/package.json +1 -1
- package/lib/cache.js +18 -9
- package/lib/markdownlint.d.ts +24 -8
- package/lib/markdownlint.js +106 -38
- package/lib/md010.js +5 -1
- package/lib/md011.js +31 -27
- package/lib/md037.js +14 -2
- package/lib/md043.js +8 -3
- package/lib/md044.js +54 -71
- package/package.json +24 -16
- package/schema/.markdownlint.jsonc +4 -2
- package/schema/.markdownlint.yaml +3 -1
- package/schema/markdownlint-config-schema.json +13 -3
package/doc/Prettier.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Using markdownlint with Prettier
|
|
2
|
+
|
|
3
|
+
[`Prettier`](https://prettier.io) is a popular code formatter. For the most part,
|
|
4
|
+
it works seamlessly with `markdownlint`. Special situations are documented
|
|
5
|
+
below.
|
|
6
|
+
|
|
7
|
+
## List item indentation
|
|
8
|
+
|
|
9
|
+
The default settings of `markdownlint` and `Prettier` are compatible and don't
|
|
10
|
+
result in any linting violations. If `Prettier` is used with `--tab-width` set
|
|
11
|
+
to `4`, the following `markdownlint` configuration can be used:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"MD007": {
|
|
16
|
+
"indent": 4
|
|
17
|
+
},
|
|
18
|
+
"MD030": {
|
|
19
|
+
"ul_single": 3,
|
|
20
|
+
"ul_multi": 3
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
package/doc/Rules.md
CHANGED
|
@@ -329,6 +329,8 @@ issue for multi-markdown parsers, which require 4-space indents. More informatio
|
|
|
329
329
|
<https://cirosantilli.com/markdown-style-guide#indentation-of-content-inside-lists>
|
|
330
330
|
and <http://support.markedapp.com/discussions/problems/21-sub-lists-not-indenting>.
|
|
331
331
|
|
|
332
|
+
Note: See [Prettier.md](Prettier.md) for compatibility information.
|
|
333
|
+
|
|
332
334
|
<a name="md009"></a>
|
|
333
335
|
|
|
334
336
|
## MD009 - Trailing spaces
|
|
@@ -388,7 +390,7 @@ Tags: whitespace, hard_tab
|
|
|
388
390
|
|
|
389
391
|
Aliases: no-hard-tabs
|
|
390
392
|
|
|
391
|
-
Parameters: code_blocks (boolean; default true)
|
|
393
|
+
Parameters: code_blocks, spaces_per_tab (boolean; default true, number; default 1)
|
|
392
394
|
|
|
393
395
|
Fixable: Most violations can be fixed by tooling
|
|
394
396
|
|
|
@@ -420,6 +422,9 @@ You have the option to exclude this rule for code blocks. To do so, set the
|
|
|
420
422
|
`code_blocks` parameter to `false`. Code blocks are included by default since
|
|
421
423
|
handling of tabs by tools is often inconsistent (ex: using 4 vs. 8 spaces).
|
|
422
424
|
|
|
425
|
+
If you would like the fixer to change tabs to x spaces, then configure the `spaces_per_tab`
|
|
426
|
+
parameter to the number x. The default value would be 1.
|
|
427
|
+
|
|
423
428
|
Rationale: Hard tabs are often rendered inconsistently by different editors and
|
|
424
429
|
can be harder to work with than spaces.
|
|
425
430
|
|
|
@@ -1180,6 +1185,8 @@ for your selected document style.
|
|
|
1180
1185
|
|
|
1181
1186
|
Rationale: Violations of this rule can lead to improperly rendered content.
|
|
1182
1187
|
|
|
1188
|
+
Note: See [Prettier.md](Prettier.md) for compatibility information.
|
|
1189
|
+
|
|
1183
1190
|
<a name="md031"></a>
|
|
1184
1191
|
|
|
1185
1192
|
## MD031 - Fenced code blocks should be surrounded by blank lines
|
|
@@ -1569,6 +1576,14 @@ echo Hello world
|
|
|
1569
1576
|
```
|
|
1570
1577
|
````
|
|
1571
1578
|
|
|
1579
|
+
To display a code block without syntax highlighting, use:
|
|
1580
|
+
|
|
1581
|
+
````markdown
|
|
1582
|
+
```text
|
|
1583
|
+
Plain text in a code block
|
|
1584
|
+
```
|
|
1585
|
+
````
|
|
1586
|
+
|
|
1572
1587
|
Rationale: Specifying a language improves content rendering by using the
|
|
1573
1588
|
correct syntax highlighting for code. More information:
|
|
1574
1589
|
<https://cirosantilli.com/markdown-style-guide#option-code-fenced>.
|
package/helpers/helpers.js
CHANGED
|
@@ -29,10 +29,11 @@ module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
|
|
|
29
29
|
const emphasisMarkersRe = /[_*]/g;
|
|
30
30
|
|
|
31
31
|
// Regular expression for inline links and shortcut reference links
|
|
32
|
-
const linkRe =
|
|
32
|
+
const linkRe = /(\[(?:[^[\]]|\[[^\]]*\])*\])(\(\S*\)|\[\S*\])?/g;
|
|
33
|
+
module.exports.linkRe = linkRe;
|
|
33
34
|
|
|
34
|
-
//
|
|
35
|
-
module.exports.
|
|
35
|
+
// Regular expression for link reference definition lines
|
|
36
|
+
module.exports.linkReferenceRe = /^ {0,3}\[[^\]]+]:\s.*$/;
|
|
36
37
|
|
|
37
38
|
// All punctuation characters (normal and full-width)
|
|
38
39
|
const allPunctuation = ".,;:!?。,;:!?";
|
|
@@ -302,14 +303,14 @@ module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
|
|
|
302
303
|
};
|
|
303
304
|
|
|
304
305
|
// Returns (nested) lists as a flat array (in order)
|
|
305
|
-
module.exports.flattenLists = function flattenLists(
|
|
306
|
+
module.exports.flattenLists = function flattenLists(tokens) {
|
|
306
307
|
const flattenedLists = [];
|
|
307
308
|
const stack = [];
|
|
308
309
|
let current = null;
|
|
309
310
|
let nesting = 0;
|
|
310
311
|
const nestingStack = [];
|
|
311
312
|
let lastWithMap = { "map": [ 0, 1 ] };
|
|
312
|
-
|
|
313
|
+
tokens.forEach((token) => {
|
|
313
314
|
if (isMathBlock(token) && token.map[1]) {
|
|
314
315
|
// markdown-it-texmath plugin does not account for math_block_end
|
|
315
316
|
token.map[1]++;
|
|
@@ -519,6 +520,47 @@ module.exports.addErrorContext = function addErrorContext(
|
|
|
519
520
|
addError(onError, lineNumber, null, context, range, fixInfo);
|
|
520
521
|
};
|
|
521
522
|
|
|
523
|
+
/**
|
|
524
|
+
* Returns an array of code span ranges.
|
|
525
|
+
*
|
|
526
|
+
* @param {string[]} lines Lines to scan for code span ranges.
|
|
527
|
+
* @returns {number[][]} Array of ranges (line, index, length).
|
|
528
|
+
*/
|
|
529
|
+
module.exports.inlineCodeSpanRanges = (lines) => {
|
|
530
|
+
const exclusions = [];
|
|
531
|
+
forEachInlineCodeSpan(
|
|
532
|
+
lines.join("\n"),
|
|
533
|
+
(code, lineIndex, columnIndex) => {
|
|
534
|
+
const codeLines = code.split(newLineRe);
|
|
535
|
+
// eslint-disable-next-line unicorn/no-for-loop
|
|
536
|
+
for (let i = 0; i < codeLines.length; i++) {
|
|
537
|
+
exclusions.push(
|
|
538
|
+
[ lineIndex + i, columnIndex, codeLines[i].length ]
|
|
539
|
+
);
|
|
540
|
+
columnIndex = 0;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
return exclusions;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Determines whether the specified range overlaps another range.
|
|
549
|
+
*
|
|
550
|
+
* @param {number[][]} ranges Array of ranges (line, index, length).
|
|
551
|
+
* @param {number} lineIndex Line index to check.
|
|
552
|
+
* @param {number} index Index to check.
|
|
553
|
+
* @param {number} length Length to check.
|
|
554
|
+
* @returns {boolean} True iff the specified range overlaps.
|
|
555
|
+
*/
|
|
556
|
+
module.exports.overlapsAnyRange = (ranges, lineIndex, index, length) => (
|
|
557
|
+
!ranges.every((span) => (
|
|
558
|
+
(lineIndex !== span[0]) ||
|
|
559
|
+
(index + length < span[1]) ||
|
|
560
|
+
(index > span[1] + span[2])
|
|
561
|
+
))
|
|
562
|
+
);
|
|
563
|
+
|
|
522
564
|
// Returns a range object for a line by applying a RegExp
|
|
523
565
|
module.exports.rangeFromRegExp = function rangeFromRegExp(line, regexp) {
|
|
524
566
|
let range = null;
|
package/helpers/package.json
CHANGED
package/lib/cache.js
CHANGED
|
@@ -2,14 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
let lineMetadata = null;
|
|
6
|
-
module.exports.lineMetadata = (value) => {
|
|
7
|
-
if (value) {
|
|
8
|
-
lineMetadata = value;
|
|
9
|
-
}
|
|
10
|
-
return lineMetadata;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
5
|
let flattenedLists = null;
|
|
14
6
|
module.exports.flattenedLists = (value) => {
|
|
15
7
|
if (value) {
|
|
@@ -18,7 +10,24 @@ module.exports.flattenedLists = (value) => {
|
|
|
18
10
|
return flattenedLists;
|
|
19
11
|
};
|
|
20
12
|
|
|
13
|
+
let inlineCodeSpanRanges = null;
|
|
14
|
+
module.exports.inlineCodeSpanRanges = (value) => {
|
|
15
|
+
if (value) {
|
|
16
|
+
inlineCodeSpanRanges = value;
|
|
17
|
+
}
|
|
18
|
+
return inlineCodeSpanRanges;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
let lineMetadata = null;
|
|
22
|
+
module.exports.lineMetadata = (value) => {
|
|
23
|
+
if (value) {
|
|
24
|
+
lineMetadata = value;
|
|
25
|
+
}
|
|
26
|
+
return lineMetadata;
|
|
27
|
+
};
|
|
28
|
+
|
|
21
29
|
module.exports.clear = () => {
|
|
22
|
-
lineMetadata = null;
|
|
23
30
|
flattenedLists = null;
|
|
31
|
+
inlineCodeSpanRanges = null;
|
|
32
|
+
lineMetadata = null;
|
|
24
33
|
};
|
package/lib/markdownlint.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export = markdownlint;
|
|
|
8
8
|
*/
|
|
9
9
|
declare function markdownlint(options: Options, callback: LintCallback): void;
|
|
10
10
|
declare namespace markdownlint {
|
|
11
|
-
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback };
|
|
11
|
+
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Configuration options.
|
|
@@ -52,9 +52,13 @@ type Options = {
|
|
|
52
52
|
* Additional plugins.
|
|
53
53
|
*/
|
|
54
54
|
markdownItPlugins?: Plugin[];
|
|
55
|
+
/**
|
|
56
|
+
* File system implementation.
|
|
57
|
+
*/
|
|
58
|
+
fs?: any;
|
|
55
59
|
};
|
|
56
60
|
/**
|
|
57
|
-
* Called with the result of the lint
|
|
61
|
+
* Called with the result of the lint function.
|
|
58
62
|
*/
|
|
59
63
|
type LintCallback = (err: Error | null, results?: LintResults) => void;
|
|
60
64
|
/**
|
|
@@ -70,18 +74,21 @@ declare function markdownlintSync(options: Options): LintResults;
|
|
|
70
74
|
* @param {string} file Configuration file name.
|
|
71
75
|
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
|
72
76
|
* function(s).
|
|
77
|
+
* @param {Object} [fs] File system implementation.
|
|
73
78
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
|
74
79
|
* @returns {void}
|
|
75
80
|
*/
|
|
76
|
-
declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, callback?: ReadConfigCallback): void;
|
|
81
|
+
declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, fs?: any, callback?: ReadConfigCallback): void;
|
|
77
82
|
/**
|
|
78
83
|
* Read specified configuration file synchronously.
|
|
79
84
|
*
|
|
80
85
|
* @param {string} file Configuration file name.
|
|
81
86
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
87
|
+
* @param {Object} [fs] File system implementation.
|
|
82
88
|
* @returns {Configuration} Configuration object.
|
|
89
|
+
* @throws An Error if processing fails.
|
|
83
90
|
*/
|
|
84
|
-
declare function readConfigSync(file: string, parsers?: ConfigurationParser[]): Configuration;
|
|
91
|
+
declare function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: any): Configuration;
|
|
85
92
|
/**
|
|
86
93
|
* Gets the (semantic) version of the library.
|
|
87
94
|
*
|
|
@@ -316,6 +323,10 @@ type LintError = {
|
|
|
316
323
|
* Fix information.
|
|
317
324
|
*/
|
|
318
325
|
type FixInfo = {
|
|
326
|
+
/**
|
|
327
|
+
* Line number (1-based).
|
|
328
|
+
*/
|
|
329
|
+
lineNumber?: number;
|
|
319
330
|
/**
|
|
320
331
|
* Column of the fix (1-based).
|
|
321
332
|
*/
|
|
@@ -334,20 +345,24 @@ type FixInfo = {
|
|
|
334
345
|
* {@link ../schema/markdownlint-config-schema.json}.
|
|
335
346
|
*/
|
|
336
347
|
type Configuration = {
|
|
337
|
-
[x: string]:
|
|
348
|
+
[x: string]: RuleConfiguration;
|
|
338
349
|
};
|
|
339
350
|
/**
|
|
340
351
|
* Rule configuration.
|
|
341
352
|
*/
|
|
342
|
-
type RuleConfiguration = any;
|
|
353
|
+
type RuleConfiguration = boolean | any;
|
|
343
354
|
/**
|
|
344
355
|
* Parses a configuration string and returns a configuration object.
|
|
345
356
|
*/
|
|
346
357
|
type ConfigurationParser = (text: string) => Configuration;
|
|
347
358
|
/**
|
|
348
|
-
* Called with the result of the readConfig
|
|
359
|
+
* Called with the result of the readConfig function.
|
|
349
360
|
*/
|
|
350
361
|
type ReadConfigCallback = (err: Error | null, config?: Configuration) => void;
|
|
362
|
+
/**
|
|
363
|
+
* Called with the result of the resolveConfigExtends function.
|
|
364
|
+
*/
|
|
365
|
+
type ResolveConfigExtendsCallback = (err: Error | null, path?: string) => void;
|
|
351
366
|
/**
|
|
352
367
|
* Lint specified Markdown files.
|
|
353
368
|
*
|
|
@@ -360,6 +375,7 @@ declare function markdownlintPromise(options: Options): Promise<LintResults>;
|
|
|
360
375
|
*
|
|
361
376
|
* @param {string} file Configuration file name.
|
|
362
377
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
378
|
+
* @param {Object} [fs] File system implementation.
|
|
363
379
|
* @returns {Promise<Configuration>} Configuration object.
|
|
364
380
|
*/
|
|
365
|
-
declare function readConfigPromise(file: string, parsers?: ConfigurationParser[]): Promise<Configuration>;
|
|
381
|
+
declare function readConfigPromise(file: string, parsers?: ConfigurationParser[], fs?: any): Promise<Configuration>;
|
package/lib/markdownlint.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const fs = require("fs");
|
|
6
5
|
const path = require("path");
|
|
7
6
|
const { promisify } = require("util");
|
|
8
7
|
const markdownIt = require("markdown-it");
|
|
@@ -190,7 +189,7 @@ function annotateTokens(tokens, lines) {
|
|
|
190
189
|
(token.type === "thead_open") ||
|
|
191
190
|
(token.type === "tbody_open")
|
|
192
191
|
) {
|
|
193
|
-
tableMap = token.map
|
|
192
|
+
tableMap = [ ...token.map ];
|
|
194
193
|
} else if (
|
|
195
194
|
(token.type === "tr_close") &&
|
|
196
195
|
tableMap
|
|
@@ -203,7 +202,7 @@ function annotateTokens(tokens, lines) {
|
|
|
203
202
|
tableMap = null;
|
|
204
203
|
}
|
|
205
204
|
if (tableMap && !token.map) {
|
|
206
|
-
token.map = tableMap
|
|
205
|
+
token.map = [ ...tableMap ];
|
|
207
206
|
}
|
|
208
207
|
// Update token metadata
|
|
209
208
|
if (token.map) {
|
|
@@ -516,7 +515,8 @@ function lintContent(
|
|
|
516
515
|
frontMatterLines
|
|
517
516
|
};
|
|
518
517
|
cache.lineMetadata(helpers.getLineMetadata(params));
|
|
519
|
-
cache.flattenedLists(helpers.flattenLists(params));
|
|
518
|
+
cache.flattenedLists(helpers.flattenLists(params.tokens));
|
|
519
|
+
cache.inlineCodeSpanRanges(helpers.inlineCodeSpanRanges(params.lines));
|
|
520
520
|
// Function to run for each rule
|
|
521
521
|
const result = (resultVersion === 0) ? {} : [];
|
|
522
522
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
@@ -684,6 +684,7 @@ function lintContent(
|
|
|
684
684
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
685
685
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
686
686
|
* @param {number} resultVersion Version of the LintResults object to return.
|
|
687
|
+
* @param {Object} fs File system implementation.
|
|
687
688
|
* @param {boolean} synchronous Whether to execute synchronously.
|
|
688
689
|
* @param {Function} callback Callback (err, result) function.
|
|
689
690
|
* @returns {void}
|
|
@@ -697,6 +698,7 @@ function lintFile(
|
|
|
697
698
|
handleRuleFailures,
|
|
698
699
|
noInlineConfig,
|
|
699
700
|
resultVersion,
|
|
701
|
+
fs,
|
|
700
702
|
synchronous,
|
|
701
703
|
callback) {
|
|
702
704
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
@@ -709,10 +711,9 @@ function lintFile(
|
|
|
709
711
|
}
|
|
710
712
|
// Make a/synchronous call to read file
|
|
711
713
|
if (synchronous) {
|
|
712
|
-
|
|
713
|
-
lintContentWrapper(null, fs.readFileSync(file, helpers.utf8Encoding));
|
|
714
|
+
lintContentWrapper(null, fs.readFileSync(file, "utf8"));
|
|
714
715
|
} else {
|
|
715
|
-
fs.readFile(file,
|
|
716
|
+
fs.readFile(file, "utf8", lintContentWrapper);
|
|
716
717
|
}
|
|
717
718
|
}
|
|
718
719
|
|
|
@@ -736,7 +737,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
736
737
|
}
|
|
737
738
|
let files = [];
|
|
738
739
|
if (Array.isArray(options.files)) {
|
|
739
|
-
files = options.files
|
|
740
|
+
files = [ ...options.files ];
|
|
740
741
|
} else if (options.files) {
|
|
741
742
|
files = [ String(options.files) ];
|
|
742
743
|
}
|
|
@@ -755,6 +756,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
755
756
|
// @ts-ignore
|
|
756
757
|
md.use(...plugin);
|
|
757
758
|
});
|
|
759
|
+
const fs = options.fs || require("fs");
|
|
758
760
|
const results = newResults(ruleList);
|
|
759
761
|
let done = false;
|
|
760
762
|
// Linting of strings is always synchronous
|
|
@@ -794,6 +796,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
794
796
|
handleRuleFailures,
|
|
795
797
|
noInlineConfig,
|
|
796
798
|
resultVersion,
|
|
799
|
+
fs,
|
|
797
800
|
synchronous,
|
|
798
801
|
syncCallback
|
|
799
802
|
);
|
|
@@ -818,6 +821,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
818
821
|
handleRuleFailures,
|
|
819
822
|
noInlineConfig,
|
|
820
823
|
resultVersion,
|
|
824
|
+
fs,
|
|
821
825
|
synchronous,
|
|
822
826
|
(err, result) => {
|
|
823
827
|
concurrency--;
|
|
@@ -928,17 +932,47 @@ function parseConfiguration(name, content, parsers) {
|
|
|
928
932
|
*
|
|
929
933
|
* @param {string} configFile Configuration file name.
|
|
930
934
|
* @param {string} referenceId Referenced identifier to resolve.
|
|
935
|
+
* @param {Object} fs File system implementation.
|
|
936
|
+
* @param {ResolveConfigExtendsCallback} [callback] Callback (err, result)
|
|
937
|
+
* function.
|
|
938
|
+
* @returns {void}
|
|
939
|
+
*/
|
|
940
|
+
function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
|
941
|
+
const configFileDirname = path.dirname(configFile);
|
|
942
|
+
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
|
943
|
+
fs.access(resolvedExtendsFile, (err) => {
|
|
944
|
+
if (err) {
|
|
945
|
+
// Not a file, try require.resolve
|
|
946
|
+
try {
|
|
947
|
+
return callback(null, dynamicRequire.resolve(
|
|
948
|
+
referenceId,
|
|
949
|
+
{ "paths": [ configFileDirname ] }
|
|
950
|
+
));
|
|
951
|
+
} catch {
|
|
952
|
+
// Unable to resolve, use resolvedExtendsFile
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return callback(null, resolvedExtendsFile);
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Resolve referenced "extends" path in a configuration file
|
|
961
|
+
* using path.resolve() with require.resolve() as a fallback.
|
|
962
|
+
*
|
|
963
|
+
* @param {string} configFile Configuration file name.
|
|
964
|
+
* @param {string} referenceId Referenced identifier to resolve.
|
|
965
|
+
* @param {Object} fs File system implementation.
|
|
931
966
|
* @returns {string} Resolved path to file.
|
|
932
967
|
*/
|
|
933
|
-
function
|
|
968
|
+
function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
|
934
969
|
const configFileDirname = path.dirname(configFile);
|
|
935
970
|
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
|
936
971
|
try {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
972
|
+
fs.accessSync(resolvedExtendsFile);
|
|
973
|
+
return resolvedExtendsFile;
|
|
940
974
|
} catch {
|
|
941
|
-
//
|
|
975
|
+
// Not a file, try require.resolve
|
|
942
976
|
}
|
|
943
977
|
try {
|
|
944
978
|
return dynamicRequire.resolve(
|
|
@@ -946,7 +980,7 @@ function resolveConfigExtends(configFile, referenceId) {
|
|
|
946
980
|
{ "paths": [ configFileDirname ] }
|
|
947
981
|
);
|
|
948
982
|
} catch {
|
|
949
|
-
//
|
|
983
|
+
// Unable to resolve, return resolvedExtendsFile
|
|
950
984
|
}
|
|
951
985
|
return resolvedExtendsFile;
|
|
952
986
|
}
|
|
@@ -957,17 +991,26 @@ function resolveConfigExtends(configFile, referenceId) {
|
|
|
957
991
|
* @param {string} file Configuration file name.
|
|
958
992
|
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
|
959
993
|
* function(s).
|
|
994
|
+
* @param {Object} [fs] File system implementation.
|
|
960
995
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
|
961
996
|
* @returns {void}
|
|
962
997
|
*/
|
|
963
|
-
function readConfig(file, parsers, callback) {
|
|
998
|
+
function readConfig(file, parsers, fs, callback) {
|
|
964
999
|
if (!callback) {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1000
|
+
if (fs) {
|
|
1001
|
+
callback = fs;
|
|
1002
|
+
fs = null;
|
|
1003
|
+
} else {
|
|
1004
|
+
// @ts-ignore
|
|
1005
|
+
callback = parsers;
|
|
1006
|
+
parsers = null;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
if (!fs) {
|
|
1010
|
+
fs = require("fs");
|
|
968
1011
|
}
|
|
969
1012
|
// Read file
|
|
970
|
-
fs.readFile(file,
|
|
1013
|
+
fs.readFile(file, "utf8", (err, content) => {
|
|
971
1014
|
if (err) {
|
|
972
1015
|
return callback(err);
|
|
973
1016
|
}
|
|
@@ -981,16 +1024,25 @@ function readConfig(file, parsers, callback) {
|
|
|
981
1024
|
const configExtends = config.extends;
|
|
982
1025
|
if (configExtends) {
|
|
983
1026
|
delete config.extends;
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1027
|
+
return resolveConfigExtends(
|
|
1028
|
+
file,
|
|
1029
|
+
configExtends,
|
|
1030
|
+
fs,
|
|
1031
|
+
(_, resolvedExtends) => readConfig(
|
|
1032
|
+
resolvedExtends,
|
|
1033
|
+
parsers,
|
|
1034
|
+
fs,
|
|
1035
|
+
(errr, extendsConfig) => {
|
|
1036
|
+
if (errr) {
|
|
1037
|
+
return callback(errr);
|
|
1038
|
+
}
|
|
1039
|
+
return callback(null, {
|
|
1040
|
+
...extendsConfig,
|
|
1041
|
+
...config
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
)
|
|
1045
|
+
);
|
|
994
1046
|
}
|
|
995
1047
|
return callback(null, config);
|
|
996
1048
|
});
|
|
@@ -1003,11 +1055,12 @@ const readConfigPromisify = promisify && promisify(readConfig);
|
|
|
1003
1055
|
*
|
|
1004
1056
|
* @param {string} file Configuration file name.
|
|
1005
1057
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
1058
|
+
* @param {Object} [fs] File system implementation.
|
|
1006
1059
|
* @returns {Promise<Configuration>} Configuration object.
|
|
1007
1060
|
*/
|
|
1008
|
-
function readConfigPromise(file, parsers) {
|
|
1061
|
+
function readConfigPromise(file, parsers, fs) {
|
|
1009
1062
|
// @ts-ignore
|
|
1010
|
-
return readConfigPromisify(file, parsers);
|
|
1063
|
+
return readConfigPromisify(file, parsers, fs);
|
|
1011
1064
|
}
|
|
1012
1065
|
|
|
1013
1066
|
/**
|
|
@@ -1015,12 +1068,16 @@ function readConfigPromise(file, parsers) {
|
|
|
1015
1068
|
*
|
|
1016
1069
|
* @param {string} file Configuration file name.
|
|
1017
1070
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
1071
|
+
* @param {Object} [fs] File system implementation.
|
|
1018
1072
|
* @returns {Configuration} Configuration object.
|
|
1073
|
+
* @throws An Error if processing fails.
|
|
1019
1074
|
*/
|
|
1020
|
-
function readConfigSync(file, parsers) {
|
|
1075
|
+
function readConfigSync(file, parsers, fs) {
|
|
1076
|
+
if (!fs) {
|
|
1077
|
+
fs = require("fs");
|
|
1078
|
+
}
|
|
1021
1079
|
// Read file
|
|
1022
|
-
|
|
1023
|
-
const content = fs.readFileSync(file, helpers.utf8Encoding);
|
|
1080
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1024
1081
|
// Try to parse file
|
|
1025
1082
|
const { config, message } = parseConfiguration(file, content, parsers);
|
|
1026
1083
|
if (!config) {
|
|
@@ -1030,9 +1087,9 @@ function readConfigSync(file, parsers) {
|
|
|
1030
1087
|
const configExtends = config.extends;
|
|
1031
1088
|
if (configExtends) {
|
|
1032
1089
|
delete config.extends;
|
|
1033
|
-
const resolvedExtends =
|
|
1090
|
+
const resolvedExtends = resolveConfigExtendsSync(file, configExtends, fs);
|
|
1034
1091
|
return {
|
|
1035
|
-
...readConfigSync(resolvedExtends, parsers),
|
|
1092
|
+
...readConfigSync(resolvedExtends, parsers, fs),
|
|
1036
1093
|
...config
|
|
1037
1094
|
};
|
|
1038
1095
|
}
|
|
@@ -1155,6 +1212,7 @@ module.exports = markdownlint;
|
|
|
1155
1212
|
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
|
1156
1213
|
* @property {number} [resultVersion] Results object version.
|
|
1157
1214
|
* @property {Plugin[]} [markdownItPlugins] Additional plugins.
|
|
1215
|
+
* @property {Object} [fs] File system implementation.
|
|
1158
1216
|
*/
|
|
1159
1217
|
|
|
1160
1218
|
/**
|
|
@@ -1196,13 +1254,14 @@ module.exports = markdownlint;
|
|
|
1196
1254
|
* Fix information.
|
|
1197
1255
|
*
|
|
1198
1256
|
* @typedef {Object} FixInfo
|
|
1257
|
+
* @property {number} [lineNumber] Line number (1-based).
|
|
1199
1258
|
* @property {number} [editColumn] Column of the fix (1-based).
|
|
1200
1259
|
* @property {number} [deleteCount] Count of characters to delete.
|
|
1201
1260
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
1202
1261
|
*/
|
|
1203
1262
|
|
|
1204
1263
|
/**
|
|
1205
|
-
* Called with the result of the lint
|
|
1264
|
+
* Called with the result of the lint function.
|
|
1206
1265
|
*
|
|
1207
1266
|
* @callback LintCallback
|
|
1208
1267
|
* @param {Error | null} err Error object or null.
|
|
@@ -1232,10 +1291,19 @@ module.exports = markdownlint;
|
|
|
1232
1291
|
*/
|
|
1233
1292
|
|
|
1234
1293
|
/**
|
|
1235
|
-
* Called with the result of the readConfig
|
|
1294
|
+
* Called with the result of the readConfig function.
|
|
1236
1295
|
*
|
|
1237
1296
|
* @callback ReadConfigCallback
|
|
1238
1297
|
* @param {Error | null} err Error object or null.
|
|
1239
1298
|
* @param {Configuration} [config] Configuration object.
|
|
1240
1299
|
* @returns {void}
|
|
1241
1300
|
*/
|
|
1301
|
+
|
|
1302
|
+
/**
|
|
1303
|
+
* Called with the result of the resolveConfigExtends function.
|
|
1304
|
+
*
|
|
1305
|
+
* @callback ResolveConfigExtendsCallback
|
|
1306
|
+
* @param {Error | null} err Error object or null.
|
|
1307
|
+
* @param {string} [path] Resolved path to file.
|
|
1308
|
+
* @returns {void}
|
|
1309
|
+
*/
|
package/lib/md010.js
CHANGED
|
@@ -14,6 +14,10 @@ module.exports = {
|
|
|
14
14
|
"function": function MD010(params, onError) {
|
|
15
15
|
const codeBlocks = params.config.code_blocks;
|
|
16
16
|
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
17
|
+
const spacesPerTab = params.config.spaces_per_tab;
|
|
18
|
+
const spaceMultiplier = (spacesPerTab === undefined) ?
|
|
19
|
+
1 :
|
|
20
|
+
Math.max(0, Number(spacesPerTab));
|
|
17
21
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
18
22
|
if (!inCode || includeCodeBlocks) {
|
|
19
23
|
let match = null;
|
|
@@ -29,7 +33,7 @@ module.exports = {
|
|
|
29
33
|
{
|
|
30
34
|
"editColumn": column,
|
|
31
35
|
"deleteCount": length,
|
|
32
|
-
"insertText": "".padEnd(length)
|
|
36
|
+
"insertText": "".padEnd(length * spaceMultiplier)
|
|
33
37
|
});
|
|
34
38
|
}
|
|
35
39
|
}
|