markdownlint 0.34.0 → 0.36.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/CHANGELOG.md +21 -0
- package/README.md +97 -45
- package/demo/markdownlint-browser.js +2186 -2164
- package/doc/CustomRules.md +66 -255
- package/doc/Rules.md +102 -29
- package/doc/md003.md +2 -2
- package/doc/md004.md +4 -3
- package/doc/md034.md +5 -0
- package/doc/md035.md +3 -8
- package/doc/md044.md +10 -0
- package/doc/md046.md +2 -2
- package/doc/md048.md +3 -2
- package/doc/md049.md +4 -3
- package/doc/md050.md +4 -4
- package/doc/md051.md +11 -3
- package/doc/md055.md +3 -2
- package/doc/md058.md +48 -0
- package/helpers/README.md +2 -45
- package/helpers/helpers.js +115 -607
- package/helpers/micromark-helpers.cjs +296 -0
- package/helpers/micromark-parse.cjs +313 -0
- package/helpers/package.json +5 -2
- package/helpers/shared.js +6 -0
- package/helpers/test.cjs +28 -0
- package/lib/cache.js +62 -13
- package/lib/configuration-strict.d.ts +1199 -0
- package/lib/configuration.d.ts +3 -1173
- package/lib/constants.js +3 -2
- package/lib/markdownit.cjs +172 -0
- package/lib/markdownlint.d.ts +103 -56
- package/lib/markdownlint.js +180 -120
- package/lib/md001.js +15 -9
- package/lib/md003.js +14 -9
- package/lib/md004.js +55 -48
- package/lib/md005.js +4 -13
- package/lib/md007.js +7 -11
- package/lib/md009.js +50 -44
- package/lib/md010.js +52 -33
- package/lib/md011.js +32 -23
- package/lib/md012.js +17 -9
- package/lib/md013.js +44 -38
- package/lib/md014.js +31 -38
- package/lib/md018.js +17 -9
- package/lib/md019-md021.js +80 -0
- package/lib/md020.js +14 -8
- package/lib/md022.js +13 -29
- package/lib/md023.js +22 -23
- package/lib/md024.js +12 -9
- package/lib/md025.js +15 -10
- package/lib/md026.js +2 -7
- package/lib/md027.js +7 -12
- package/lib/md028.js +3 -8
- package/lib/md029.js +40 -34
- package/lib/md030.js +4 -10
- package/lib/md031.js +45 -23
- package/lib/md032.js +33 -31
- package/lib/md033.js +3 -8
- package/lib/md034.js +21 -34
- package/lib/md035.js +2 -7
- package/lib/md036.js +19 -24
- package/lib/md037.js +3 -8
- package/lib/md038.js +11 -22
- package/lib/md039.js +64 -54
- package/lib/md040.js +13 -20
- package/lib/md041.js +5 -5
- package/lib/md042.js +44 -38
- package/lib/md043.js +20 -14
- package/lib/md044.js +34 -36
- package/lib/md045.js +5 -10
- package/lib/md046.js +2 -8
- package/lib/md048.js +30 -23
- package/lib/md049-md050.js +22 -12
- package/lib/md051.js +20 -28
- package/lib/md052.js +2 -2
- package/lib/md053.js +7 -6
- package/lib/md054.js +16 -23
- package/lib/md055.js +41 -49
- package/lib/md056.js +32 -33
- package/lib/md058.js +58 -0
- package/lib/rules.js +11 -4
- package/package.json +23 -20
- package/schema/.markdownlint.jsonc +58 -52
- package/schema/.markdownlint.yaml +56 -51
- package/schema/ValidatingConfiguration.md +6 -8
- package/schema/markdownlint-config-schema-strict.json +1841 -0
- package/schema/markdownlint-config-schema.json +141 -109
- package/style/prettier.json +1 -0
- package/helpers/micromark.cjs +0 -445
- package/lib/md019.js +0 -42
- package/lib/md021.js +0 -65
package/helpers/helpers.js
CHANGED
|
@@ -2,34 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const micromark = require("./micromark.cjs");
|
|
5
|
+
const micromark = require("./micromark-helpers.cjs");
|
|
6
6
|
|
|
7
7
|
const { newLineRe, nextLinesRe } = require("./shared.js");
|
|
8
8
|
|
|
9
9
|
module.exports.newLineRe = newLineRe;
|
|
10
10
|
module.exports.nextLinesRe = nextLinesRe;
|
|
11
11
|
|
|
12
|
+
/** @typedef {import("../lib/markdownlint.js").RuleOnError} RuleOnError */
|
|
13
|
+
/** @typedef {import("../lib/markdownlint.js").RuleOnErrorFixInfo} RuleOnErrorFixInfo */
|
|
14
|
+
|
|
12
15
|
// Regular expression for matching common front matter (YAML and TOML)
|
|
13
16
|
module.exports.frontMatterRe =
|
|
14
|
-
/((
|
|
17
|
+
/((^---[^\S\r\n\u2028\u2029]*$[\s\S]+?^---\s*)|(^\+\+\+[^\S\r\n\u2028\u2029]*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{[^\S\r\n\u2028\u2029]*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m;
|
|
15
18
|
|
|
16
19
|
// Regular expression for matching the start of inline disable/enable comments
|
|
17
20
|
const inlineCommentStartRe =
|
|
18
21
|
/(<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file|disable-line|disable-next-line|configure-file))(?:\s|-->)/gi;
|
|
19
22
|
module.exports.inlineCommentStartRe = inlineCommentStartRe;
|
|
20
23
|
|
|
21
|
-
// Regular expressions for range matching
|
|
22
|
-
module.exports.listItemMarkerRe = /^([\s>]*)(?:[*+-]|\d+[.)])\s+/;
|
|
23
|
-
module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
|
|
24
|
-
|
|
25
|
-
// Regular expression for blockquote prefixes
|
|
26
|
-
const blockquotePrefixRe = /^[>\s]*/;
|
|
27
|
-
module.exports.blockquotePrefixRe = blockquotePrefixRe;
|
|
28
|
-
|
|
29
|
-
// Regular expression for link reference definitions
|
|
30
|
-
const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
|
|
31
|
-
module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe;
|
|
32
|
-
|
|
33
24
|
// Regular expression for identifying an HTML entity at the end of a line
|
|
34
25
|
module.exports.endOfLineHtmlEntityRe =
|
|
35
26
|
/&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/;
|
|
@@ -143,7 +134,6 @@ function isBlankLine(line) {
|
|
|
143
134
|
const startComment = "<!--";
|
|
144
135
|
const endComment = "-->";
|
|
145
136
|
const removeComments = (s) => {
|
|
146
|
-
// eslint-disable-next-line no-constant-condition
|
|
147
137
|
while (true) {
|
|
148
138
|
const start = s.indexOf(startComment);
|
|
149
139
|
const end = s.indexOf(endComment);
|
|
@@ -170,35 +160,6 @@ function isBlankLine(line) {
|
|
|
170
160
|
}
|
|
171
161
|
module.exports.isBlankLine = isBlankLine;
|
|
172
162
|
|
|
173
|
-
/**
|
|
174
|
-
* Compare function for Array.prototype.sort for ascending order of numbers.
|
|
175
|
-
*
|
|
176
|
-
* @param {number} a First number.
|
|
177
|
-
* @param {number} b Second number.
|
|
178
|
-
* @returns {number} Positive value if a>b, negative value if b<a, 0 otherwise.
|
|
179
|
-
*/
|
|
180
|
-
module.exports.numericSortAscending = function numericSortAscending(a, b) {
|
|
181
|
-
return a - b;
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
// Returns true iff the sorted array contains the specified element
|
|
185
|
-
module.exports.includesSorted = function includesSorted(array, element) {
|
|
186
|
-
let left = 0;
|
|
187
|
-
let right = array.length - 1;
|
|
188
|
-
while (left <= right) {
|
|
189
|
-
// eslint-disable-next-line no-bitwise
|
|
190
|
-
const mid = (left + right) >> 1;
|
|
191
|
-
if (array[mid] < element) {
|
|
192
|
-
left = mid + 1;
|
|
193
|
-
} else if (array[mid] > element) {
|
|
194
|
-
right = mid - 1;
|
|
195
|
-
} else {
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return false;
|
|
200
|
-
};
|
|
201
|
-
|
|
202
163
|
// Replaces the content of properly-formatted CommonMark comments with "."
|
|
203
164
|
// This preserves the line/column information for the rest of the document
|
|
204
165
|
// https://spec.commonmark.org/0.29/#html-blocks
|
|
@@ -257,301 +218,6 @@ module.exports.escapeForRegExp = function escapeForRegExp(str) {
|
|
|
257
218
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
258
219
|
};
|
|
259
220
|
|
|
260
|
-
/**
|
|
261
|
-
* Return the string representation of a fence markup character.
|
|
262
|
-
*
|
|
263
|
-
* @param {string} markup Fence string.
|
|
264
|
-
* @returns {string} String representation.
|
|
265
|
-
*/
|
|
266
|
-
module.exports.fencedCodeBlockStyleFor =
|
|
267
|
-
function fencedCodeBlockStyleFor(markup) {
|
|
268
|
-
switch (markup[0]) {
|
|
269
|
-
case "~":
|
|
270
|
-
return "tilde";
|
|
271
|
-
default:
|
|
272
|
-
return "backtick";
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Return the string representation of a emphasis or strong markup character.
|
|
278
|
-
*
|
|
279
|
-
* @param {string} markup Emphasis or strong string.
|
|
280
|
-
* @returns {"asterisk" | "underscore"} String representation.
|
|
281
|
-
*/
|
|
282
|
-
module.exports.emphasisOrStrongStyleFor =
|
|
283
|
-
function emphasisOrStrongStyleFor(markup) {
|
|
284
|
-
switch (markup[0]) {
|
|
285
|
-
case "*":
|
|
286
|
-
return "asterisk";
|
|
287
|
-
default:
|
|
288
|
-
return "underscore";
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Return the number of characters of indent for a token.
|
|
294
|
-
*
|
|
295
|
-
* @param {Object} token MarkdownItToken instance.
|
|
296
|
-
* @returns {number} Characters of indent.
|
|
297
|
-
*/
|
|
298
|
-
function indentFor(token) {
|
|
299
|
-
const line = token.line.replace(/^[\s>]*(> |>)/, "");
|
|
300
|
-
return line.length - line.trimStart().length;
|
|
301
|
-
}
|
|
302
|
-
module.exports.indentFor = indentFor;
|
|
303
|
-
|
|
304
|
-
// Returns the heading style for a heading token
|
|
305
|
-
module.exports.headingStyleFor = function headingStyleFor(token) {
|
|
306
|
-
if ((token.map[1] - token.map[0]) === 1) {
|
|
307
|
-
if (/[^\\]#\s*$/.test(token.line)) {
|
|
308
|
-
return "atx_closed";
|
|
309
|
-
}
|
|
310
|
-
return "atx";
|
|
311
|
-
}
|
|
312
|
-
return "setext";
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Return the string representation of an unordered list marker.
|
|
317
|
-
*
|
|
318
|
-
* @param {Object} token MarkdownItToken instance.
|
|
319
|
-
* @returns {"asterisk" | "dash" | "plus"} String representation.
|
|
320
|
-
*/
|
|
321
|
-
module.exports.unorderedListStyleFor = function unorderedListStyleFor(token) {
|
|
322
|
-
switch (token.markup) {
|
|
323
|
-
case "-":
|
|
324
|
-
return "dash";
|
|
325
|
-
case "+":
|
|
326
|
-
return "plus";
|
|
327
|
-
// case "*":
|
|
328
|
-
default:
|
|
329
|
-
return "asterisk";
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* @callback TokenCallback
|
|
335
|
-
* @param {MarkdownItToken} token Current token.
|
|
336
|
-
* @returns {void}
|
|
337
|
-
*/
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Calls the provided function for each matching token.
|
|
341
|
-
*
|
|
342
|
-
* @param {Object} params RuleParams instance.
|
|
343
|
-
* @param {string} type Token type identifier.
|
|
344
|
-
* @param {TokenCallback} handler Callback function.
|
|
345
|
-
* @returns {void}
|
|
346
|
-
*/
|
|
347
|
-
function filterTokens(params, type, handler) {
|
|
348
|
-
for (const token of params.parsers.markdownit.tokens) {
|
|
349
|
-
if (token.type === type) {
|
|
350
|
-
handler(token);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
module.exports.filterTokens = filterTokens;
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* @typedef {Array} LineMetadata
|
|
358
|
-
*/
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Gets a line metadata array.
|
|
362
|
-
*
|
|
363
|
-
* @param {Object} params RuleParams instance.
|
|
364
|
-
* @returns {LineMetadata} Line metadata.
|
|
365
|
-
*/
|
|
366
|
-
function getLineMetadata(params) {
|
|
367
|
-
const lineMetadata = params.lines.map(
|
|
368
|
-
(line, index) => [ line, index, false, 0, false, false, false ]
|
|
369
|
-
);
|
|
370
|
-
filterTokens(params, "fence", (token) => {
|
|
371
|
-
lineMetadata[token.map[0]][3] = 1;
|
|
372
|
-
lineMetadata[token.map[1] - 1][3] = -1;
|
|
373
|
-
for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) {
|
|
374
|
-
lineMetadata[i][2] = true;
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
filterTokens(params, "code_block", (token) => {
|
|
378
|
-
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
379
|
-
lineMetadata[i][2] = true;
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
filterTokens(params, "table_open", (token) => {
|
|
383
|
-
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
384
|
-
lineMetadata[i][4] = true;
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
filterTokens(params, "list_item_open", (token) => {
|
|
388
|
-
let count = 1;
|
|
389
|
-
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
390
|
-
lineMetadata[i][5] = count;
|
|
391
|
-
count++;
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
filterTokens(params, "hr", (token) => {
|
|
395
|
-
lineMetadata[token.map[0]][6] = true;
|
|
396
|
-
});
|
|
397
|
-
return lineMetadata;
|
|
398
|
-
}
|
|
399
|
-
module.exports.getLineMetadata = getLineMetadata;
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* @callback EachLineCallback
|
|
403
|
-
* @param {string} line Line content.
|
|
404
|
-
* @param {number} lineIndex Line index (0-based).
|
|
405
|
-
* @param {boolean} inCode Iff in a code block.
|
|
406
|
-
* @param {number} onFence + if open, - if closed, 0 otherwise.
|
|
407
|
-
* @param {boolean} inTable Iff in a table.
|
|
408
|
-
* @param {boolean} inItem Iff in a list item.
|
|
409
|
-
* @param {boolean} inBreak Iff in semantic break.
|
|
410
|
-
* @returns {void}
|
|
411
|
-
*/
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Calls the provided function for each line.
|
|
415
|
-
*
|
|
416
|
-
* @param {LineMetadata} lineMetadata Line metadata object.
|
|
417
|
-
* @param {EachLineCallback} handler Function taking (line, lineIndex, inCode,
|
|
418
|
-
* onFence, inTable, inItem, inBreak).
|
|
419
|
-
* @returns {void}
|
|
420
|
-
*/
|
|
421
|
-
function forEachLine(lineMetadata, handler) {
|
|
422
|
-
for (const metadata of lineMetadata) {
|
|
423
|
-
// @ts-ignore
|
|
424
|
-
handler(...metadata);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
module.exports.forEachLine = forEachLine;
|
|
428
|
-
|
|
429
|
-
// Returns (nested) lists as a flat array (in order)
|
|
430
|
-
module.exports.flattenLists = function flattenLists(tokens) {
|
|
431
|
-
const flattenedLists = [];
|
|
432
|
-
const stack = [];
|
|
433
|
-
let current = null;
|
|
434
|
-
let nesting = 0;
|
|
435
|
-
const nestingStack = [];
|
|
436
|
-
let lastWithMap = { "map": [ 0, 1 ] };
|
|
437
|
-
for (const token of tokens) {
|
|
438
|
-
if ((token.type === "bullet_list_open") ||
|
|
439
|
-
(token.type === "ordered_list_open")) {
|
|
440
|
-
// Save current context and start a new one
|
|
441
|
-
stack.push(current);
|
|
442
|
-
current = {
|
|
443
|
-
"unordered": (token.type === "bullet_list_open"),
|
|
444
|
-
"parentsUnordered": !current ||
|
|
445
|
-
(current.unordered && current.parentsUnordered),
|
|
446
|
-
"open": token,
|
|
447
|
-
"indent": indentFor(token),
|
|
448
|
-
"parentIndent": (current && current.indent) || 0,
|
|
449
|
-
"items": [],
|
|
450
|
-
"nesting": nesting,
|
|
451
|
-
"lastLineIndex": -1,
|
|
452
|
-
"insert": flattenedLists.length
|
|
453
|
-
};
|
|
454
|
-
nesting++;
|
|
455
|
-
} else if ((token.type === "bullet_list_close") ||
|
|
456
|
-
(token.type === "ordered_list_close")) {
|
|
457
|
-
// Finalize current context and restore previous
|
|
458
|
-
current.lastLineIndex = lastWithMap.map[1];
|
|
459
|
-
flattenedLists.splice(current.insert, 0, current);
|
|
460
|
-
delete current.insert;
|
|
461
|
-
current = stack.pop();
|
|
462
|
-
nesting--;
|
|
463
|
-
} else if (token.type === "list_item_open") {
|
|
464
|
-
// Add list item
|
|
465
|
-
current.items.push(token);
|
|
466
|
-
} else if (token.type === "blockquote_open") {
|
|
467
|
-
nestingStack.push(nesting);
|
|
468
|
-
nesting = 0;
|
|
469
|
-
} else if (token.type === "blockquote_close") {
|
|
470
|
-
nesting = nestingStack.pop() || 0;
|
|
471
|
-
}
|
|
472
|
-
if (token.map) {
|
|
473
|
-
// Track last token with map
|
|
474
|
-
lastWithMap = token;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
return flattenedLists;
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
// Calls the provided function for each heading's content
|
|
481
|
-
module.exports.forEachHeading = function forEachHeading(params, handler) {
|
|
482
|
-
let heading = null;
|
|
483
|
-
for (const token of params.parsers.markdownit.tokens) {
|
|
484
|
-
if (token.type === "heading_open") {
|
|
485
|
-
heading = token;
|
|
486
|
-
} else if (token.type === "heading_close") {
|
|
487
|
-
heading = null;
|
|
488
|
-
} else if ((token.type === "inline") && heading) {
|
|
489
|
-
handler(heading, token.content, token);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* @callback InlineCodeSpanCallback
|
|
496
|
-
* @param {string} code Code content.
|
|
497
|
-
* @param {number} lineIndex Line index (0-based).
|
|
498
|
-
* @param {number} columnIndex Column index (0-based).
|
|
499
|
-
* @param {number} ticks Count of backticks.
|
|
500
|
-
* @returns {void}
|
|
501
|
-
*/
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Calls the provided function for each inline code span's content.
|
|
505
|
-
*
|
|
506
|
-
* @param {string} input Markdown content.
|
|
507
|
-
* @param {InlineCodeSpanCallback} handler Callback function taking (code,
|
|
508
|
-
* lineIndex, columnIndex, ticks).
|
|
509
|
-
* @returns {void}
|
|
510
|
-
*/
|
|
511
|
-
function forEachInlineCodeSpan(input, handler) {
|
|
512
|
-
const backtickRe = /`+/g;
|
|
513
|
-
let match = null;
|
|
514
|
-
const backticksLengthAndIndex = [];
|
|
515
|
-
while ((match = backtickRe.exec(input)) !== null) {
|
|
516
|
-
backticksLengthAndIndex.push([ match[0].length, match.index ]);
|
|
517
|
-
}
|
|
518
|
-
const newLinesIndex = [];
|
|
519
|
-
while ((match = newLineRe.exec(input)) !== null) {
|
|
520
|
-
newLinesIndex.push(match.index);
|
|
521
|
-
}
|
|
522
|
-
let lineIndex = 0;
|
|
523
|
-
let lineStartIndex = 0;
|
|
524
|
-
let k = 0;
|
|
525
|
-
for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) {
|
|
526
|
-
const [ startLength, startIndex ] = backticksLengthAndIndex[i];
|
|
527
|
-
if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) {
|
|
528
|
-
for (let j = i + 1; j < backticksLengthAndIndex.length; j++) {
|
|
529
|
-
const [ endLength, endIndex ] = backticksLengthAndIndex[j];
|
|
530
|
-
if (startLength === endLength) {
|
|
531
|
-
for (; k < newLinesIndex.length; k++) {
|
|
532
|
-
const newLineIndex = newLinesIndex[k];
|
|
533
|
-
if (startIndex < newLineIndex) {
|
|
534
|
-
break;
|
|
535
|
-
}
|
|
536
|
-
lineIndex++;
|
|
537
|
-
lineStartIndex = newLineIndex + 1;
|
|
538
|
-
}
|
|
539
|
-
const columnIndex = startIndex - lineStartIndex + startLength;
|
|
540
|
-
handler(
|
|
541
|
-
input.slice(startIndex + startLength, endIndex),
|
|
542
|
-
lineIndex,
|
|
543
|
-
columnIndex,
|
|
544
|
-
startLength
|
|
545
|
-
);
|
|
546
|
-
i = j;
|
|
547
|
-
break;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
module.exports.forEachInlineCodeSpan = forEachInlineCodeSpan;
|
|
554
|
-
|
|
555
221
|
/**
|
|
556
222
|
* Adds ellipsis to the left/right/middle of the specified text.
|
|
557
223
|
*
|
|
@@ -577,12 +243,12 @@ module.exports.ellipsify = ellipsify;
|
|
|
577
243
|
/**
|
|
578
244
|
* Adds a generic error object via the onError callback.
|
|
579
245
|
*
|
|
580
|
-
* @param {
|
|
246
|
+
* @param {RuleOnError} onError RuleOnError instance.
|
|
581
247
|
* @param {number} lineNumber Line number.
|
|
582
248
|
* @param {string} [detail] Error details.
|
|
583
249
|
* @param {string} [context] Error context.
|
|
584
250
|
* @param {number[]} [range] Column and length of error.
|
|
585
|
-
* @param {
|
|
251
|
+
* @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
|
|
586
252
|
* @returns {void}
|
|
587
253
|
*/
|
|
588
254
|
function addError(onError, lineNumber, detail, context, range, fixInfo) {
|
|
@@ -596,8 +262,20 @@ function addError(onError, lineNumber, detail, context, range, fixInfo) {
|
|
|
596
262
|
}
|
|
597
263
|
module.exports.addError = addError;
|
|
598
264
|
|
|
599
|
-
|
|
600
|
-
|
|
265
|
+
/**
|
|
266
|
+
* Adds an error object with details conditionally via the onError callback.
|
|
267
|
+
*
|
|
268
|
+
* @param {RuleOnError} onError RuleOnError instance.
|
|
269
|
+
* @param {number} lineNumber Line number.
|
|
270
|
+
* @param {Object} expected Expected value.
|
|
271
|
+
* @param {Object} actual Actual value.
|
|
272
|
+
* @param {string} [detail] Error details.
|
|
273
|
+
* @param {string} [context] Error context.
|
|
274
|
+
* @param {number[]} [range] Column and length of error.
|
|
275
|
+
* @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
|
|
276
|
+
* @returns {void}
|
|
277
|
+
*/
|
|
278
|
+
function addErrorDetailIf(
|
|
601
279
|
onError, lineNumber, expected, actual, detail, context, range, fixInfo) {
|
|
602
280
|
if (expected !== actual) {
|
|
603
281
|
addError(
|
|
@@ -609,80 +287,64 @@ module.exports.addErrorDetailIf = function addErrorDetailIf(
|
|
|
609
287
|
range,
|
|
610
288
|
fixInfo);
|
|
611
289
|
}
|
|
612
|
-
}
|
|
290
|
+
}
|
|
291
|
+
module.exports.addErrorDetailIf = addErrorDetailIf;
|
|
613
292
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Adds an error object with context via the onError callback.
|
|
295
|
+
*
|
|
296
|
+
* @param {RuleOnError} onError RuleOnError instance.
|
|
297
|
+
* @param {number} lineNumber Line number.
|
|
298
|
+
* @param {string} context Error context.
|
|
299
|
+
* @param {boolean} [start] True iff the start of the text is important.
|
|
300
|
+
* @param {boolean} [end] True iff the end of the text is important.
|
|
301
|
+
* @param {number[]} [range] Column and length of error.
|
|
302
|
+
* @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
|
|
303
|
+
* @returns {void}
|
|
304
|
+
*/
|
|
305
|
+
function addErrorContext(
|
|
306
|
+
onError, lineNumber, context, start, end, range, fixInfo) {
|
|
307
|
+
context = ellipsify(context, start, end);
|
|
618
308
|
addError(onError, lineNumber, undefined, context, range, fixInfo);
|
|
619
|
-
}
|
|
309
|
+
}
|
|
310
|
+
module.exports.addErrorContext = addErrorContext;
|
|
620
311
|
|
|
621
312
|
/**
|
|
622
|
-
*
|
|
313
|
+
* Defines a range within a file (start line/column to end line/column, subset of MicromarkToken).
|
|
623
314
|
*
|
|
624
|
-
* @
|
|
625
|
-
* @
|
|
626
|
-
* @
|
|
315
|
+
* @typedef {Object} FileRange
|
|
316
|
+
* @property {number} startLine Start line (1-based).
|
|
317
|
+
* @property {number} startColumn Start column (1-based).
|
|
318
|
+
* @property {number} endLine End line (1-based).
|
|
319
|
+
* @property {number} endColumn End column (1-based).
|
|
627
320
|
*/
|
|
628
|
-
module.exports.codeBlockAndSpanRanges = (params, lineMetadata) => {
|
|
629
|
-
const exclusions = [];
|
|
630
|
-
// Add code block ranges (excludes fences)
|
|
631
|
-
forEachLine(lineMetadata, (line, lineIndex, inCode, onFence) => {
|
|
632
|
-
if (inCode && !onFence) {
|
|
633
|
-
exclusions.push([ lineIndex, 0, line.length ]);
|
|
634
|
-
}
|
|
635
|
-
});
|
|
636
|
-
// Add code span ranges (excludes ticks)
|
|
637
|
-
filterTokens(params, "inline", (token) => {
|
|
638
|
-
if (token.children.some((child) => child.type === "code_inline")) {
|
|
639
|
-
const tokenLines = params.lines.slice(token.map[0], token.map[1]);
|
|
640
|
-
forEachInlineCodeSpan(
|
|
641
|
-
tokenLines.join("\n"),
|
|
642
|
-
(code, lineIndex, columnIndex) => {
|
|
643
|
-
const codeLines = code.split(newLineRe);
|
|
644
|
-
for (const [ i, line ] of codeLines.entries()) {
|
|
645
|
-
exclusions.push([
|
|
646
|
-
token.lineNumber - 1 + lineIndex + i,
|
|
647
|
-
i ? 0 : columnIndex,
|
|
648
|
-
line.length
|
|
649
|
-
]);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
);
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
return exclusions;
|
|
656
|
-
};
|
|
657
321
|
|
|
658
322
|
/**
|
|
659
|
-
*
|
|
323
|
+
* Returns whether line/column A is less than or equal to line/column B.
|
|
660
324
|
*
|
|
661
|
-
* @param {number
|
|
662
|
-
* @param {number}
|
|
663
|
-
* @param {number}
|
|
664
|
-
* @param {number}
|
|
665
|
-
* @returns {boolean} True iff
|
|
666
|
-
*/
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
(index < span[1]) ||
|
|
671
|
-
(index + length > span[1] + span[2])
|
|
672
|
-
))
|
|
325
|
+
* @param {number} lineA Line A.
|
|
326
|
+
* @param {number} columnA Column A.
|
|
327
|
+
* @param {number} lineB Line B.
|
|
328
|
+
* @param {number} columnB Column B.
|
|
329
|
+
* @returns {boolean} True iff A is less than or equal to B.
|
|
330
|
+
*/
|
|
331
|
+
const positionLessThanOrEqual = (lineA, columnA, lineB, columnB) => (
|
|
332
|
+
(lineA < lineB) ||
|
|
333
|
+
((lineA === lineB) && (columnA <= columnB))
|
|
673
334
|
);
|
|
674
|
-
module.exports.withinAnyRange = withinAnyRange;
|
|
675
335
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Returns whether two ranges (or MicromarkTokens) overlap anywhere.
|
|
338
|
+
*
|
|
339
|
+
* @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeA Range A.
|
|
340
|
+
* @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeB Range B.
|
|
341
|
+
* @returns {boolean} True iff the two ranges overlap.
|
|
342
|
+
*/
|
|
343
|
+
module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) {
|
|
344
|
+
const lte = positionLessThanOrEqual(rangeA.startLine, rangeA.startColumn, rangeB.startLine, rangeB.startColumn);
|
|
345
|
+
const first = lte ? rangeA : rangeB;
|
|
346
|
+
const second = lte ? rangeB : rangeA;
|
|
347
|
+
return positionLessThanOrEqual(second.startLine, second.startColumn, first.endLine, first.endColumn);
|
|
686
348
|
};
|
|
687
349
|
|
|
688
350
|
// Determines if the front matter includes a title
|
|
@@ -702,16 +364,28 @@ module.exports.frontMatterHasTitle =
|
|
|
702
364
|
/**
|
|
703
365
|
* Returns an object with information about reference links and images.
|
|
704
366
|
*
|
|
705
|
-
* @param {import("../helpers/micromark.cjs").Token[]} tokens Micromark tokens.
|
|
367
|
+
* @param {import("../helpers/micromark-helpers.cjs").Token[]} tokens Micromark tokens.
|
|
706
368
|
* @returns {Object} Reference link/image data.
|
|
707
369
|
*/
|
|
708
370
|
function getReferenceLinkImageData(tokens) {
|
|
709
371
|
const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
372
|
+
const references = new Map();
|
|
373
|
+
const shortcuts = new Map();
|
|
374
|
+
const addReferenceToDictionary = (token, label, isShortcut) => {
|
|
375
|
+
const referenceDatum = [
|
|
376
|
+
token.startLine - 1,
|
|
377
|
+
token.startColumn - 1,
|
|
378
|
+
token.text.length
|
|
379
|
+
];
|
|
380
|
+
const reference = normalizeReference(label);
|
|
381
|
+
const dictionary = isShortcut ? shortcuts : references;
|
|
382
|
+
const referenceData = dictionary.get(reference) || [];
|
|
383
|
+
referenceData.push(referenceDatum);
|
|
384
|
+
dictionary.set(reference, referenceData);
|
|
385
|
+
};
|
|
710
386
|
const definitions = new Map();
|
|
711
387
|
const definitionLineIndices = [];
|
|
712
388
|
const duplicateDefinitions = [];
|
|
713
|
-
const references = new Map();
|
|
714
|
-
const shortcuts = new Map();
|
|
715
389
|
const filteredTokens =
|
|
716
390
|
micromark.filterByTypes(
|
|
717
391
|
tokens,
|
|
@@ -721,7 +395,9 @@ function getReferenceLinkImageData(tokens) {
|
|
|
721
395
|
// definitions and definitionLineIndices
|
|
722
396
|
"definitionLabelString", "gfmFootnoteDefinitionLabelString",
|
|
723
397
|
// references and shortcuts
|
|
724
|
-
"gfmFootnoteCall", "image", "link"
|
|
398
|
+
"gfmFootnoteCall", "image", "link",
|
|
399
|
+
// undefined link labels
|
|
400
|
+
"undefinedReferenceCollapsed", "undefinedReferenceFull", "undefinedReferenceShortcut"
|
|
725
401
|
]
|
|
726
402
|
);
|
|
727
403
|
for (const token of filteredTokens) {
|
|
@@ -744,15 +420,10 @@ function getReferenceLinkImageData(tokens) {
|
|
|
744
420
|
if (definitions.has(reference)) {
|
|
745
421
|
duplicateDefinitions.push([ reference, token.startLine - 1 ]);
|
|
746
422
|
} else {
|
|
747
|
-
let destinationString = null;
|
|
748
423
|
const parent =
|
|
749
|
-
micromark.
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
micromark.filterByPredicate(parent.children),
|
|
753
|
-
"definitionDestinationString"
|
|
754
|
-
);
|
|
755
|
-
}
|
|
424
|
+
micromark.getParentOfType(token, [ "definition" ]);
|
|
425
|
+
const destinationString = parent &&
|
|
426
|
+
micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
|
|
756
427
|
definitions.set(
|
|
757
428
|
reference,
|
|
758
429
|
[ token.startLine - 1, destinationString ]
|
|
@@ -764,67 +435,38 @@ function getReferenceLinkImageData(tokens) {
|
|
|
764
435
|
case "image":
|
|
765
436
|
case "link":
|
|
766
437
|
{
|
|
767
|
-
|
|
768
|
-
let
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
if
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
);
|
|
778
|
-
isShortcut = (labelText !== null);
|
|
779
|
-
}
|
|
780
|
-
const fullAndCollapsedCandidate =
|
|
781
|
-
micromark.matchAndGetTokensByType(
|
|
782
|
-
token.children, [ "label", "reference" ]
|
|
438
|
+
// Identify if shortcut or full/collapsed
|
|
439
|
+
let isShortcut = (token.children.length === 1);
|
|
440
|
+
const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource");
|
|
441
|
+
const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]);
|
|
442
|
+
const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]);
|
|
443
|
+
let label = labelText?.text;
|
|
444
|
+
// Identify if footnote
|
|
445
|
+
if (!isShortcut && !isFullOrCollapsed) {
|
|
446
|
+
const [ footnoteCallMarker, footnoteCallString ] = token.children.filter(
|
|
447
|
+
(t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type)
|
|
783
448
|
);
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
);
|
|
789
|
-
referenceStringText =
|
|
790
|
-
micromark.getTokenTextByType(
|
|
791
|
-
fullAndCollapsedCandidate[1].children, "referenceString"
|
|
792
|
-
);
|
|
793
|
-
isFullOrCollapsed = (labelText !== null);
|
|
794
|
-
}
|
|
795
|
-
const footnote = micromark.matchAndGetTokensByType(
|
|
796
|
-
token.children,
|
|
797
|
-
[
|
|
798
|
-
"gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
|
|
799
|
-
"gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
|
|
800
|
-
],
|
|
801
|
-
[ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
|
|
802
|
-
);
|
|
803
|
-
if (footnote) {
|
|
804
|
-
const callMarkerText = footnote[0].text;
|
|
805
|
-
const callString = footnote[1].text;
|
|
806
|
-
labelText = `${callMarkerText}${callString}`;
|
|
807
|
-
isShortcut = true;
|
|
449
|
+
if (footnoteCallMarker && footnoteCallString) {
|
|
450
|
+
label = `${footnoteCallMarker.text}${footnoteCallString.text}`;
|
|
451
|
+
isShortcut = true;
|
|
452
|
+
}
|
|
808
453
|
}
|
|
809
|
-
// Track shortcuts separately due to ambiguity in "text [text] text"
|
|
454
|
+
// Track link (handle shortcuts separately due to ambiguity in "text [text] text")
|
|
810
455
|
if (isShortcut || isFullOrCollapsed) {
|
|
811
|
-
|
|
812
|
-
token.startLine - 1,
|
|
813
|
-
token.startColumn - 1,
|
|
814
|
-
token.text.length,
|
|
815
|
-
// @ts-ignore
|
|
816
|
-
labelText.length,
|
|
817
|
-
(referenceStringText || "").length
|
|
818
|
-
];
|
|
819
|
-
const reference =
|
|
820
|
-
normalizeReference(referenceStringText || labelText);
|
|
821
|
-
const dictionary = isShortcut ? shortcuts : references;
|
|
822
|
-
const referenceData = dictionary.get(reference) || [];
|
|
823
|
-
referenceData.push(referenceDatum);
|
|
824
|
-
dictionary.set(reference, referenceData);
|
|
456
|
+
addReferenceToDictionary(token, referenceString?.text || label, isShortcut);
|
|
825
457
|
}
|
|
826
458
|
}
|
|
827
459
|
break;
|
|
460
|
+
case "undefinedReferenceCollapsed":
|
|
461
|
+
case "undefinedReferenceFull":
|
|
462
|
+
case "undefinedReferenceShortcut":
|
|
463
|
+
{
|
|
464
|
+
const undefinedReference = micromark.getDescendantsByType(token, [ "undefinedReference" ])[0];
|
|
465
|
+
const label = undefinedReference.children.map((t) => t.text).join("");
|
|
466
|
+
const isShortcut = (token.type === "undefinedReferenceShortcut");
|
|
467
|
+
addReferenceToDictionary(token, label, isShortcut);
|
|
468
|
+
}
|
|
469
|
+
break;
|
|
828
470
|
}
|
|
829
471
|
}
|
|
830
472
|
return {
|
|
@@ -877,120 +519,6 @@ function getPreferredLineEnding(input, os) {
|
|
|
877
519
|
}
|
|
878
520
|
module.exports.getPreferredLineEnding = getPreferredLineEnding;
|
|
879
521
|
|
|
880
|
-
/**
|
|
881
|
-
* Normalizes the fields of a RuleOnErrorFixInfo instance.
|
|
882
|
-
*
|
|
883
|
-
* @param {Object} fixInfo RuleOnErrorFixInfo instance.
|
|
884
|
-
* @param {number} [lineNumber] Line number.
|
|
885
|
-
* @returns {Object} Normalized RuleOnErrorFixInfo instance.
|
|
886
|
-
*/
|
|
887
|
-
function normalizeFixInfo(fixInfo, lineNumber) {
|
|
888
|
-
return {
|
|
889
|
-
"lineNumber": fixInfo.lineNumber || lineNumber,
|
|
890
|
-
"editColumn": fixInfo.editColumn || 1,
|
|
891
|
-
"deleteCount": fixInfo.deleteCount || 0,
|
|
892
|
-
"insertText": fixInfo.insertText || ""
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
/**
|
|
897
|
-
* Fixes the specified error on a line of Markdown content.
|
|
898
|
-
*
|
|
899
|
-
* @param {string} line Line of Markdown content.
|
|
900
|
-
* @param {Object} fixInfo RuleOnErrorFixInfo instance.
|
|
901
|
-
* @param {string} [lineEnding] Line ending to use.
|
|
902
|
-
* @returns {string | null} Fixed content.
|
|
903
|
-
*/
|
|
904
|
-
function applyFix(line, fixInfo, lineEnding) {
|
|
905
|
-
const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
|
|
906
|
-
const editIndex = editColumn - 1;
|
|
907
|
-
return (deleteCount === -1) ?
|
|
908
|
-
null :
|
|
909
|
-
line.slice(0, editIndex) +
|
|
910
|
-
insertText.replace(/\n/g, lineEnding || "\n") +
|
|
911
|
-
line.slice(editIndex + deleteCount);
|
|
912
|
-
}
|
|
913
|
-
module.exports.applyFix = applyFix;
|
|
914
|
-
|
|
915
|
-
/**
|
|
916
|
-
* Applies as many fixes as possible to Markdown content.
|
|
917
|
-
*
|
|
918
|
-
* @param {string} input Lines of Markdown content.
|
|
919
|
-
* @param {Object[]} errors RuleOnErrorInfo instances.
|
|
920
|
-
* @returns {string} Corrected content.
|
|
921
|
-
*/
|
|
922
|
-
function applyFixes(input, errors) {
|
|
923
|
-
const lineEnding = getPreferredLineEnding(input, require("node:os"));
|
|
924
|
-
const lines = input.split(newLineRe);
|
|
925
|
-
// Normalize fixInfo objects
|
|
926
|
-
let fixInfos = errors
|
|
927
|
-
.filter((error) => error.fixInfo)
|
|
928
|
-
.map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber));
|
|
929
|
-
// Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
|
|
930
|
-
fixInfos.sort((a, b) => {
|
|
931
|
-
const aDeletingLine = (a.deleteCount === -1);
|
|
932
|
-
const bDeletingLine = (b.deleteCount === -1);
|
|
933
|
-
return (
|
|
934
|
-
(b.lineNumber - a.lineNumber) ||
|
|
935
|
-
(aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) ||
|
|
936
|
-
(b.editColumn - a.editColumn) ||
|
|
937
|
-
(b.insertText.length - a.insertText.length)
|
|
938
|
-
);
|
|
939
|
-
});
|
|
940
|
-
// Remove duplicate entries (needed for following collapse step)
|
|
941
|
-
let lastFixInfo = {};
|
|
942
|
-
fixInfos = fixInfos.filter((fixInfo) => {
|
|
943
|
-
const unique = (
|
|
944
|
-
(fixInfo.lineNumber !== lastFixInfo.lineNumber) ||
|
|
945
|
-
(fixInfo.editColumn !== lastFixInfo.editColumn) ||
|
|
946
|
-
(fixInfo.deleteCount !== lastFixInfo.deleteCount) ||
|
|
947
|
-
(fixInfo.insertText !== lastFixInfo.insertText)
|
|
948
|
-
);
|
|
949
|
-
lastFixInfo = fixInfo;
|
|
950
|
-
return unique;
|
|
951
|
-
});
|
|
952
|
-
// Collapse insert/no-delete and no-insert/delete for same line/column
|
|
953
|
-
lastFixInfo = {
|
|
954
|
-
"lineNumber": -1
|
|
955
|
-
};
|
|
956
|
-
for (const fixInfo of fixInfos) {
|
|
957
|
-
if (
|
|
958
|
-
(fixInfo.lineNumber === lastFixInfo.lineNumber) &&
|
|
959
|
-
(fixInfo.editColumn === lastFixInfo.editColumn) &&
|
|
960
|
-
!fixInfo.insertText &&
|
|
961
|
-
(fixInfo.deleteCount > 0) &&
|
|
962
|
-
lastFixInfo.insertText &&
|
|
963
|
-
!lastFixInfo.deleteCount) {
|
|
964
|
-
fixInfo.insertText = lastFixInfo.insertText;
|
|
965
|
-
lastFixInfo.lineNumber = 0;
|
|
966
|
-
}
|
|
967
|
-
lastFixInfo = fixInfo;
|
|
968
|
-
}
|
|
969
|
-
fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber);
|
|
970
|
-
// Apply all (remaining/updated) fixes
|
|
971
|
-
let lastLineIndex = -1;
|
|
972
|
-
let lastEditIndex = -1;
|
|
973
|
-
for (const fixInfo of fixInfos) {
|
|
974
|
-
const { lineNumber, editColumn, deleteCount } = fixInfo;
|
|
975
|
-
const lineIndex = lineNumber - 1;
|
|
976
|
-
const editIndex = editColumn - 1;
|
|
977
|
-
if (
|
|
978
|
-
(lineIndex !== lastLineIndex) ||
|
|
979
|
-
(deleteCount === -1) ||
|
|
980
|
-
((editIndex + deleteCount) <=
|
|
981
|
-
(lastEditIndex - ((deleteCount > 0) ? 0 : 1)))
|
|
982
|
-
) {
|
|
983
|
-
// @ts-ignore
|
|
984
|
-
lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
|
|
985
|
-
}
|
|
986
|
-
lastLineIndex = lineIndex;
|
|
987
|
-
lastEditIndex = editIndex;
|
|
988
|
-
}
|
|
989
|
-
// Return corrected input
|
|
990
|
-
return lines.filter((line) => line !== null).join(lineEnding);
|
|
991
|
-
}
|
|
992
|
-
module.exports.applyFixes = applyFixes;
|
|
993
|
-
|
|
994
522
|
/**
|
|
995
523
|
* Expands a path with a tilde to an absolute path.
|
|
996
524
|
*
|
|
@@ -1003,23 +531,3 @@ function expandTildePath(file, os) {
|
|
|
1003
531
|
return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file;
|
|
1004
532
|
}
|
|
1005
533
|
module.exports.expandTildePath = expandTildePath;
|
|
1006
|
-
|
|
1007
|
-
// Copied from markdownlint.js to avoid TypeScript compiler import() issue.
|
|
1008
|
-
/**
|
|
1009
|
-
* @typedef {Object} MarkdownItToken
|
|
1010
|
-
* @property {string[][]} attrs HTML attributes.
|
|
1011
|
-
* @property {boolean} block Block-level token.
|
|
1012
|
-
* @property {MarkdownItToken[]} children Child nodes.
|
|
1013
|
-
* @property {string} content Tag contents.
|
|
1014
|
-
* @property {boolean} hidden Ignore element.
|
|
1015
|
-
* @property {string} info Fence info.
|
|
1016
|
-
* @property {number} level Nesting level.
|
|
1017
|
-
* @property {number[]} map Beginning/ending line numbers.
|
|
1018
|
-
* @property {string} markup Markup text.
|
|
1019
|
-
* @property {Object} meta Arbitrary data.
|
|
1020
|
-
* @property {number} nesting Level change.
|
|
1021
|
-
* @property {string} tag HTML tag name.
|
|
1022
|
-
* @property {string} type Token type.
|
|
1023
|
-
* @property {number} lineNumber Line number (1-based).
|
|
1024
|
-
* @property {string} line Line content.
|
|
1025
|
-
*/
|