markdownlint 0.34.0 → 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.
Files changed (76) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +25 -10
  3. package/demo/markdownlint-browser.js +1144 -1166
  4. package/doc/CustomRules.md +11 -6
  5. package/doc/Rules.md +66 -0
  6. package/doc/md034.md +5 -0
  7. package/doc/md044.md +10 -0
  8. package/doc/md058.md +48 -0
  9. package/helpers/README.md +3 -29
  10. package/helpers/helpers.js +56 -288
  11. package/helpers/micromark.cjs +111 -12
  12. package/helpers/package.json +1 -1
  13. package/lib/cache.js +62 -13
  14. package/lib/configuration-strict.d.ts +1185 -0
  15. package/lib/configuration.d.ts +3 -1173
  16. package/lib/constants.js +3 -2
  17. package/lib/markdownlint.d.ts +65 -56
  18. package/lib/markdownlint.js +59 -37
  19. package/lib/md001.js +15 -9
  20. package/lib/md003.js +14 -9
  21. package/lib/md004.js +55 -48
  22. package/lib/md005.js +4 -13
  23. package/lib/md007.js +5 -9
  24. package/lib/md009.js +50 -44
  25. package/lib/md010.js +48 -33
  26. package/lib/md011.js +16 -8
  27. package/lib/md012.js +17 -9
  28. package/lib/md013.js +44 -38
  29. package/lib/md014.js +35 -38
  30. package/lib/md018.js +17 -9
  31. package/lib/md019-md021.js +80 -0
  32. package/lib/md020.js +13 -7
  33. package/lib/md022.js +6 -16
  34. package/lib/md023.js +22 -23
  35. package/lib/md024.js +12 -9
  36. package/lib/md025.js +15 -10
  37. package/lib/md026.js +2 -7
  38. package/lib/md027.js +5 -10
  39. package/lib/md028.js +3 -8
  40. package/lib/md029.js +40 -34
  41. package/lib/md030.js +4 -10
  42. package/lib/md031.js +43 -23
  43. package/lib/md032.js +16 -26
  44. package/lib/md033.js +3 -8
  45. package/lib/md034.js +5 -10
  46. package/lib/md035.js +2 -7
  47. package/lib/md036.js +3 -2
  48. package/lib/md037.js +2 -7
  49. package/lib/md038.js +3 -9
  50. package/lib/md039.js +66 -54
  51. package/lib/md040.js +3 -8
  52. package/lib/md041.js +1 -1
  53. package/lib/md042.js +48 -38
  54. package/lib/md043.js +20 -14
  55. package/lib/md044.js +3 -8
  56. package/lib/md045.js +3 -8
  57. package/lib/md046.js +2 -8
  58. package/lib/md048.js +3 -7
  59. package/lib/md049-md050.js +2 -7
  60. package/lib/md051.js +6 -12
  61. package/lib/md052.js +2 -2
  62. package/lib/md053.js +2 -2
  63. package/lib/md054.js +8 -13
  64. package/lib/md055.js +7 -8
  65. package/lib/md056.js +15 -11
  66. package/lib/md058.js +43 -0
  67. package/lib/rules.js +11 -4
  68. package/package.json +19 -17
  69. package/schema/.markdownlint.jsonc +54 -51
  70. package/schema/.markdownlint.yaml +53 -50
  71. package/schema/ValidatingConfiguration.md +6 -8
  72. package/schema/markdownlint-config-schema-strict.json +1819 -0
  73. package/schema/markdownlint-config-schema.json +115 -105
  74. package/style/prettier.json +1 -0
  75. package/lib/md019.js +0 -42
  76. package/lib/md021.js +0 -65
@@ -11,12 +11,23 @@ const {
11
11
  const { newLineRe } = require("./shared.js");
12
12
 
13
13
  const flatTokensSymbol = Symbol("flat-tokens");
14
+ const reparseSymbol = Symbol("reparse");
14
15
 
15
16
  /** @typedef {import("markdownlint-micromark").Event} Event */
16
17
  /** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
17
18
  /** @typedef {import("markdownlint-micromark").TokenType} TokenType */
18
19
  /** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
19
20
 
21
+ /**
22
+ * Determines if a Micromark token is within an htmlFlow.
23
+ *
24
+ * @param {Token} token Micromark token.
25
+ * @returns {boolean} True iff the token is within an htmlFlow.
26
+ */
27
+ function inHtmlFlow(token) {
28
+ return token[reparseSymbol];
29
+ }
30
+
20
31
  /**
21
32
  * Returns whether a token is an htmlFlow type containing an HTML comment.
22
33
  *
@@ -145,6 +156,9 @@ function micromarkParseWithOffset(
145
156
  "children": [],
146
157
  "parent": ((previous === root) ? (ancestor || null) : previous)
147
158
  };
159
+ if (ancestor) {
160
+ Object.defineProperty(current, reparseSymbol, { "value": true });
161
+ }
148
162
  previous.children.push(current);
149
163
  flatTokens.push(current);
150
164
  if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
@@ -217,6 +231,20 @@ function micromarkParse(
217
231
  );
218
232
  }
219
233
 
234
+ /**
235
+ * Adds a range of numbers to a set.
236
+ *
237
+ * @param {Set<number>} set Set of numbers.
238
+ * @param {number} start Starting number.
239
+ * @param {number} end Ending number.
240
+ * @returns {void}
241
+ */
242
+ function addRangeToSet(set, start, end) {
243
+ for (let i = start; i <= end; i++) {
244
+ set.add(i);
245
+ }
246
+ }
247
+
220
248
  /**
221
249
  * @callback AllowedPredicate
222
250
  * @param {Token} token Micromark token.
@@ -277,10 +305,12 @@ function filterByPredicate(tokens, allowed, transformChildren) {
277
305
  *
278
306
  * @param {Token[]} tokens Micromark tokens.
279
307
  * @param {TokenType[]} types Types to allow.
308
+ * @param {boolean} [htmlFlow] Whether to include htmlFlow content.
280
309
  * @returns {Token[]} Filtered tokens.
281
310
  */
282
- function filterByTypes(tokens, types) {
283
- const predicate = (token) => types.includes(token.type);
311
+ function filterByTypes(tokens, types, htmlFlow) {
312
+ const predicate = (token) =>
313
+ (htmlFlow || !inHtmlFlow(token)) && types.includes(token.type);
284
314
  const flatTokens = tokens[flatTokensSymbol];
285
315
  if (flatTokens) {
286
316
  return flatTokens.filter(predicate);
@@ -288,6 +318,46 @@ function filterByTypes(tokens, types) {
288
318
  return filterByPredicate(tokens, predicate);
289
319
  }
290
320
 
321
+ /**
322
+ * Gets a list of nested Micromark token descendants by type path.
323
+ *
324
+ * @param {Token|Token[]} parent Micromark token parent or parents.
325
+ * @param {TokenType[]} typePath Micromark token type path.
326
+ * @returns {Token[]} Micromark token descendants.
327
+ */
328
+ function getDescendantsByType(parent, typePath) {
329
+ let tokens = Array.isArray(parent) ? parent : [ parent ];
330
+ for (const type of typePath) {
331
+ tokens = tokens.flatMap((t) => t.children).filter((t) => t.type === type);
332
+ }
333
+ return tokens;
334
+ }
335
+
336
+ // eslint-disable-next-line jsdoc/valid-types
337
+ /** @typedef {readonly string[]} ReadonlyStringArray */
338
+
339
+ /**
340
+ * Gets the line/column/length exclusions for a Micromark token.
341
+ *
342
+ * @param {ReadonlyStringArray} lines File/string lines.
343
+ * @param {Token} token Micromark token.
344
+ * @returns {number[][]} Exclusions (line number, start column, length).
345
+ */
346
+ function getExclusionsForToken(lines, token) {
347
+ const exclusions = [];
348
+ const { endColumn, endLine, startColumn, startLine } = token;
349
+ for (let lineNumber = startLine; lineNumber <= endLine; lineNumber++) {
350
+ const start = (lineNumber === startLine) ? startColumn : 1;
351
+ const end = (lineNumber === endLine) ? endColumn : lines[lineNumber - 1].length;
352
+ exclusions.push([
353
+ lineNumber,
354
+ start,
355
+ end - start + 1
356
+ ]);
357
+ }
358
+ return exclusions;
359
+ }
360
+
291
361
  /**
292
362
  * Gets the heading level of a Micromark heading tokan.
293
363
  *
@@ -309,6 +379,40 @@ function getHeadingLevel(heading) {
309
379
  return level;
310
380
  }
311
381
 
382
+ /**
383
+ * Gets the heading style of a Micromark heading tokan.
384
+ *
385
+ * @param {Token} heading Micromark heading token.
386
+ * @returns {"atx" | "atx_closed" | "setext"} Heading style.
387
+ */
388
+ function getHeadingStyle(heading) {
389
+ if (heading.type === "setextHeading") {
390
+ return "setext";
391
+ }
392
+ const atxHeadingSequenceLength = filterByTypes(
393
+ heading.children,
394
+ [ "atxHeadingSequence" ]
395
+ ).length;
396
+ if (atxHeadingSequenceLength === 1) {
397
+ return "atx";
398
+ }
399
+ return "atx_closed";
400
+ }
401
+
402
+ /**
403
+ * Gets the heading text of a Micromark heading token.
404
+ *
405
+ * @param {Token} heading Micromark heading token.
406
+ * @returns {string} Heading text.
407
+ */
408
+ function getHeadingText(heading) {
409
+ const headingTexts = filterByTypes(
410
+ heading.children,
411
+ [ "atxHeadingText", "setextHeadingText" ]
412
+ );
413
+ return headingTexts[0]?.text.replace(/[\r\n]+/g, " ") || "";
414
+ }
415
+
312
416
  /**
313
417
  * HTML tag information.
314
418
  *
@@ -367,16 +471,6 @@ function getTokenTextByType(tokens, type) {
367
471
  return (filtered.length > 0) ? filtered[0].text : null;
368
472
  }
369
473
 
370
- /**
371
- * Determines if a Micromark token has an htmlFlow-type parent.
372
- *
373
- * @param {Token} token Micromark token.
374
- * @returns {boolean} True iff the token has an htmlFlow-type parent.
375
- */
376
- function inHtmlFlow(token) {
377
- return getTokenParentOfType(token, [ "htmlFlow" ]) !== null;
378
- }
379
-
380
474
  /**
381
475
  * Determines a list of Micromark tokens matches and returns a subset.
382
476
  *
@@ -430,9 +524,14 @@ const nonContentTokens = new Set([
430
524
 
431
525
  module.exports = {
432
526
  "parse": micromarkParse,
527
+ addRangeToSet,
433
528
  filterByPredicate,
434
529
  filterByTypes,
530
+ getDescendantsByType,
531
+ getExclusionsForToken,
435
532
  getHeadingLevel,
533
+ getHeadingStyle,
534
+ getHeadingText,
436
535
  getHtmlTagInfo,
437
536
  getMicromarkEvents,
438
537
  getTokenParentOfType,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint-rule-helpers",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "A collection of markdownlint helper functions for custom rules",
5
5
  "main": "./helpers.js",
6
6
  "exports": "./helpers.js",
package/lib/cache.js CHANGED
@@ -2,20 +2,69 @@
2
2
 
3
3
  "use strict";
4
4
 
5
+ const helpers = require("../helpers");
6
+ const { filterByTypes } = require("../helpers/micromark.cjs");
7
+
8
+ /** @type {Map<string, object>} */
5
9
  const map = new Map();
10
+ // eslint-disable-next-line no-undef-init
11
+ let params = undefined;
12
+
13
+ /**
14
+ * Initializes (resets) the cache.
15
+ *
16
+ * @param {import("./markdownlint").RuleParams} [p] Rule parameters object.
17
+ * @returns {void}
18
+ */
19
+ function initialize(p) {
20
+ map.clear();
21
+ params = p;
22
+ }
6
23
 
7
- module.exports.set = (keyValuePairs) => {
8
- for (const [ key, value ] of Object.entries(keyValuePairs)) {
9
- map.set(key, value);
24
+ /**
25
+ * Gets a cached object value - computes it and caches it.
26
+ *
27
+ * @param {string} name Cache object name.
28
+ * @param {Function} getValue Getter for object value.
29
+ * @returns {Object} Object value.
30
+ */
31
+ function getCached(name, getValue) {
32
+ if (map.has(name)) {
33
+ return map.get(name);
10
34
  }
35
+ const value = getValue();
36
+ map.set(name, value);
37
+ return value;
38
+ }
39
+
40
+ /**
41
+ * Filters a list of Micromark tokens by type and caches the result.
42
+ *
43
+ * @param {import("./markdownlint").MicromarkTokenType[]} types Types to allow.
44
+ * @param {boolean} [htmlFlow] Whether to include htmlFlow content.
45
+ * @returns {import("./markdownlint").MicromarkToken[]} Filtered tokens.
46
+ */
47
+ function filterByTypesCached(types, htmlFlow) {
48
+ return getCached(
49
+ types.join("|"),
50
+ () => filterByTypes(params.parsers.micromark.tokens, types, htmlFlow)
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Gets a reference link and image data object.
56
+ *
57
+ * @returns {Object} Reference link and image data object.
58
+ */
59
+ function getReferenceLinkImageData() {
60
+ return getCached(
61
+ getReferenceLinkImageData.name,
62
+ () => helpers.getReferenceLinkImageData(params.parsers.micromark.tokens)
63
+ );
64
+ }
65
+
66
+ module.exports = {
67
+ initialize,
68
+ filterByTypesCached,
69
+ getReferenceLinkImageData
11
70
  };
12
- module.exports.clear = () => map.clear();
13
-
14
- module.exports.codeBlockAndSpanRanges =
15
- () => map.get("codeBlockAndSpanRanges");
16
- module.exports.flattenedLists =
17
- () => map.get("flattenedLists");
18
- module.exports.lineMetadata =
19
- () => map.get("lineMetadata");
20
- module.exports.referenceLinkImageData =
21
- () => map.get("referenceLinkImageData");