2024-03-20 20:44:38 -07:00
|
|
|
|
/*! markdownlint 0.34.0 https://github.com/DavidAnson/markdownlint @license MIT */
|
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
|
|
|
|
var markdownlint;
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/ (() => { // webpackBootstrap
|
|
|
|
|
|
/******/ var __webpack_modules__ = ({
|
2019-10-02 20:10:42 -07:00
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../helpers/helpers.js":
|
|
|
|
|
|
/*!*****************************!*\
|
|
|
|
|
|
!*** ../helpers/helpers.js ***!
|
|
|
|
|
|
\*****************************/
|
2022-05-04 22:09:11 -07:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
2019-10-02 20:10:42 -07:00
|
|
|
|
|
|
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const micromark = __webpack_require__(/*! ./micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
const { newLineRe, nextLinesRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports.newLineRe = newLineRe;
|
2023-10-18 23:20:19 -07:00
|
|
|
|
module.exports.nextLinesRe = nextLinesRe;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Regular expression for matching common front matter (YAML and TOML)
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.frontMatterRe =
|
|
|
|
|
|
/((^---\s*$[\s\S]+?^---\s*)|(^\+\+\+\s*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{\s*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-02-12 17:46:46 -08:00
|
|
|
|
// Regular expression for matching the start of inline disable/enable comments
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const inlineCommentStartRe =
|
|
|
|
|
|
/(<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file|disable-line|disable-next-line|configure-file))(?:\s|-->)/gi;
|
2022-02-12 17:46:46 -08:00
|
|
|
|
module.exports.inlineCommentStartRe = inlineCommentStartRe;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Regular expressions for range matching
|
2019-12-14 13:50:48 -08:00
|
|
|
|
module.exports.listItemMarkerRe = /^([\s>]*)(?:[*+-]|\d+[.)])\s+/;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-08-01 18:48:01 -07:00
|
|
|
|
// Regular expression for blockquote prefixes
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const blockquotePrefixRe = /^[>\s]*/;
|
2022-08-01 18:48:01 -07:00
|
|
|
|
module.exports.blockquotePrefixRe = blockquotePrefixRe;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
// Regular expression for link reference definitions
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
|
2022-06-01 20:23:08 -07:00
|
|
|
|
module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-06-24 15:45:51 -07:00
|
|
|
|
// Regular expression for identifying an HTML entity at the end of a line
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.endOfLineHtmlEntityRe =
|
|
|
|
|
|
/&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/;
|
2023-06-24 15:45:51 -07:00
|
|
|
|
|
|
|
|
|
|
// Regular expression for identifying a GitHub emoji code at the end of a line
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.endOfLineGemojiCodeRe =
|
|
|
|
|
|
/:(?:[abmovx]|[-+]1|100|1234|(?:1st|2nd|3rd)_place_medal|8ball|clock\d{1,4}|e-mail|non-potable_water|o2|t-rex|u5272|u5408|u55b6|u6307|u6708|u6709|u6e80|u7121|u7533|u7981|u7a7a|[a-z]{2,15}2?|[a-z]{1,14}(?:_[a-z\d]{1,16})+):$/;
|
2023-06-24 15:45:51 -07:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// All punctuation characters (normal and full-width)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const allPunctuation = ".,;:!?。,;:!?";
|
2020-11-24 16:37:11 -08:00
|
|
|
|
module.exports.allPunctuation = allPunctuation;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-11-24 16:37:11 -08:00
|
|
|
|
// All punctuation characters without question mark (normal and full-width)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
module.exports.allPunctuationNoQuestion = allPunctuation.replace(/[??]/gu, "");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-07-12 21:58:36 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input is a Number.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} obj Object of unknown type.
|
|
|
|
|
|
* @returns {boolean} True iff obj is a Number.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isNumber(obj) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return typeof obj === "number";
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isNumber = isNumber;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-07-12 21:58:36 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input is a String.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} obj Object of unknown type.
|
|
|
|
|
|
* @returns {boolean} True iff obj is a String.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isString(obj) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return typeof obj === "string";
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isString = isString;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-07-12 21:58:36 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input String is empty.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} str String of unknown length.
|
|
|
|
|
|
* @returns {boolean} True iff the input String is empty.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isEmptyString(str) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return str.length === 0;
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isEmptyString = isEmptyString;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-07-12 21:58:36 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input is an Object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} obj Object of unknown type.
|
|
|
|
|
|
* @returns {boolean} True iff obj is an Object.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isObject(obj) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return !!obj && (typeof obj === "object") && !Array.isArray(obj);
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isObject = isObject;
|
2023-07-11 21:44:45 -07:00
|
|
|
|
|
2023-07-12 21:58:36 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input is a URL.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} obj Object of unknown type.
|
|
|
|
|
|
* @returns {boolean} True iff obj is a URL.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isUrl(obj) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return !!obj && (Object.getPrototypeOf(obj) === URL.prototype);
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isUrl = isUrl;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Clones the input if it is an Array.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} arr Object of unknown type.
|
|
|
|
|
|
* @returns {Object} Clone of obj iff obj is an Array.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function cloneIfArray(arr) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return Array.isArray(arr) ? [ ...arr ] : arr;
|
2023-07-12 21:58:36 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.cloneIfArray = cloneIfArray;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Clones the input if it is a URL.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} url Object of unknown type.
|
|
|
|
|
|
* @returns {Object} Clone of obj iff obj is a URL.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function cloneIfUrl(url) {
|
|
|
|
|
|
return isUrl(url) ? new URL(url) : url;
|
|
|
|
|
|
}
|
|
|
|
|
|
module.exports.cloneIfUrl = cloneIfUrl;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-10-18 23:45:39 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets a Regular Expression for matching the specified HTML attribute.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} name HTML attribute name.
|
|
|
|
|
|
* @returns {RegExp} Regular Expression for matching.
|
|
|
|
|
|
*/
|
|
|
|
|
|
module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
return new RegExp(`\\s${name}\\s*=\\s*['"]?([^'"\\s>]*)`, "iu");
|
2023-10-18 23:45:39 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2022-02-11 21:54:43 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns true iff the input line is blank (contains nothing, whitespace, or
|
|
|
|
|
|
* comments (unclosed start/end comments allowed)).
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} line Input line.
|
|
|
|
|
|
* @returns {boolean} True iff line is blank.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isBlankLine(line) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const startComment = "<!--";
|
|
|
|
|
|
const endComment = "-->";
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const removeComments = (s) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while (true) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const start = s.indexOf(startComment);
|
|
|
|
|
|
const end = s.indexOf(endComment);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((end !== -1) && ((start === -1) || (end < start))) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Unmatched end comment is first
|
|
|
|
|
|
s = s.slice(end + endComment.length);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((start !== -1) && (end !== -1)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Start comment is before end comment
|
|
|
|
|
|
s = s.slice(0, start) + s.slice(end + endComment.length);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((start !== -1) && (end === -1)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Unmatched start comment is last
|
|
|
|
|
|
s = s.slice(0, start);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// No more comments to remove
|
|
|
|
|
|
return s;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (
|
|
|
|
|
|
!line ||
|
|
|
|
|
|
!line.trim() ||
|
|
|
|
|
|
!removeComments(line).replace(/>/g, "").trim()
|
|
|
|
|
|
);
|
2022-02-11 21:54:43 -08:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.isBlankLine = isBlankLine;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Compare function for Array.prototype.sort for ascending order of numbers.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {number} a First number.
|
|
|
|
|
|
* @param {number} b Second number.
|
|
|
|
|
|
* @returns {number} Positive value if a>b, negative value if b<a, 0 otherwise.
|
|
|
|
|
|
*/
|
|
|
|
|
|
module.exports.numericSortAscending = function numericSortAscending(a, b) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return a - b;
|
2020-01-27 19:19:34 -08:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Returns true iff the sorted array contains the specified element
|
|
|
|
|
|
module.exports.includesSorted = function includesSorted(array, element) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let left = 0;
|
|
|
|
|
|
let right = array.length - 1;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while (left <= right) {
|
|
|
|
|
|
// eslint-disable-next-line no-bitwise
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const mid = (left + right) >> 1;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (array[mid] < element) {
|
|
|
|
|
|
left = mid + 1;
|
|
|
|
|
|
} else if (array[mid] > element) {
|
|
|
|
|
|
right = mid - 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return true;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-01-30 14:36:11 -08:00
|
|
|
|
// Replaces the content of properly-formatted CommonMark comments with "."
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// This preserves the line/column information for the rest of the document
|
2021-01-30 13:08:57 -08:00
|
|
|
|
// https://spec.commonmark.org/0.29/#html-blocks
|
|
|
|
|
|
// https://spec.commonmark.org/0.29/#html-comment
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlCommentBegin = "<!--";
|
|
|
|
|
|
const htmlCommentEnd = "-->";
|
|
|
|
|
|
const safeCommentCharacter = ".";
|
|
|
|
|
|
const startsWithPipeRe = /^ *\|/;
|
|
|
|
|
|
const notCrLfRe = /[^\r\n]/g;
|
|
|
|
|
|
const notSpaceCrLfRe = /[^ \r\n]/g;
|
|
|
|
|
|
const trailingSpaceRe = / +[\r\n]/g;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const replaceTrailingSpace = (s) => s.replace(notCrLfRe, safeCommentCharacter);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let i = 0;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const j = text.indexOf(htmlCommentEnd, i + 2);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (j === -1) {
|
|
|
|
|
|
// Un-terminated comments are treated as text
|
|
|
|
|
|
break;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// If the comment has content...
|
|
|
|
|
|
if (j > i + htmlCommentBegin.length) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const content = text.slice(i + htmlCommentBegin.length, j);
|
|
|
|
|
|
const lastLf = text.lastIndexOf("\n", i) + 1;
|
|
|
|
|
|
const preText = text.slice(lastLf, i);
|
|
|
|
|
|
const isBlock = preText.trim().length === 0;
|
|
|
|
|
|
const couldBeTable = startsWithPipeRe.test(preText);
|
|
|
|
|
|
const spansTableCells = couldBeTable && content.includes("\n");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const isValid =
|
|
|
|
|
|
isBlock ||
|
|
|
|
|
|
!(
|
|
|
|
|
|
spansTableCells ||
|
|
|
|
|
|
content.startsWith(">") ||
|
|
|
|
|
|
content.startsWith("->") ||
|
|
|
|
|
|
content.endsWith("-") ||
|
|
|
|
|
|
content.includes("--")
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// If a valid block/inline comment...
|
|
|
|
|
|
if (isValid) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const clearedContent = content
|
|
|
|
|
|
.replace(notSpaceCrLfRe, safeCommentCharacter)
|
|
|
|
|
|
.replace(trailingSpaceRe, replaceTrailingSpace);
|
|
|
|
|
|
text =
|
|
|
|
|
|
text.slice(0, i + htmlCommentBegin.length) +
|
|
|
|
|
|
clearedContent +
|
|
|
|
|
|
text.slice(j);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
i = j + htmlCommentEnd.length;
|
|
|
|
|
|
}
|
|
|
|
|
|
return text;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Escapes a string for use in a RegExp
|
|
|
|
|
|
module.exports.escapeForRegExp = function escapeForRegExp(str) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Return the string representation of a fence markup character.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} markup Fence string.
|
|
|
|
|
|
* @returns {string} String representation.
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.fencedCodeBlockStyleFor =
|
|
|
|
|
|
function fencedCodeBlockStyleFor(markup) {
|
|
|
|
|
|
switch (markup[0]) {
|
|
|
|
|
|
case "~":
|
|
|
|
|
|
return "tilde";
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "backtick";
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-10-21 06:42:48 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Return the string representation of a emphasis or strong markup character.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} markup Emphasis or strong string.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @returns {"asterisk" | "underscore"} String representation.
|
2021-10-21 06:42:48 +02:00
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.emphasisOrStrongStyleFor =
|
|
|
|
|
|
function emphasisOrStrongStyleFor(markup) {
|
|
|
|
|
|
switch (markup[0]) {
|
|
|
|
|
|
case "*":
|
|
|
|
|
|
return "asterisk";
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "underscore";
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Return the number of characters of indent for a token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} token MarkdownItToken instance.
|
|
|
|
|
|
* @returns {number} Characters of indent.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function indentFor(token) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const line = token.line.replace(/^[\s>]*(> |>)/, "");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return line.length - line.trimStart().length;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.indentFor = indentFor;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Return the string representation of an unordered list marker.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} token MarkdownItToken instance.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @returns {"asterisk" | "dash" | "plus"} String representation.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
*/
|
|
|
|
|
|
module.exports.unorderedListStyleFor = function unorderedListStyleFor(token) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
switch (token.markup) {
|
|
|
|
|
|
case "-":
|
|
|
|
|
|
return "dash";
|
|
|
|
|
|
case "+":
|
|
|
|
|
|
return "plus";
|
|
|
|
|
|
// case "*":
|
|
|
|
|
|
default:
|
|
|
|
|
|
return "asterisk";
|
|
|
|
|
|
}
|
2020-01-27 19:19:34 -08:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* @callback TokenCallback
|
|
|
|
|
|
* @param {MarkdownItToken} token Current token.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Calls the provided function for each matching token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} params RuleParams instance.
|
|
|
|
|
|
* @param {string} type Token type identifier.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {TokenCallback} handler Callback function.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function filterTokens(params, type, handler) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of params.parsers.markdownit.tokens) {
|
|
|
|
|
|
if (token.type === type) {
|
|
|
|
|
|
handler(token);
|
2022-06-07 22:59:48 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.filterTokens = filterTokens;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* @typedef {Array} LineMetadata
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Gets a line metadata array.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} params RuleParams instance.
|
|
|
|
|
|
* @returns {LineMetadata} Line metadata.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getLineMetadata(params) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const lineMetadata = params.lines.map(
|
2024-07-20 13:38:45 +08:00
|
|
|
|
(line, index) => [ line, index, false, 0, false, false, false, false ]
|
2024-02-17 15:46:13 -08:00
|
|
|
|
);
|
|
|
|
|
|
filterTokens(params, "fence", (token) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[token.map[0]][3] = 1;
|
|
|
|
|
|
lineMetadata[token.map[1] - 1][3] = -1;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[i][2] = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "code_block", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[i][2] = true;
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "table_open", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[i][4] = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "list_item_open", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let count = 1;
|
|
|
|
|
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[i][5] = count;
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "hr", (token) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineMetadata[token.map[0]][6] = true;
|
|
|
|
|
|
});
|
2024-07-20 13:38:45 +08:00
|
|
|
|
filterTokens(params, "html_block", (token) => {
|
|
|
|
|
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
|
|
|
|
lineMetadata[i][7] = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return lineMetadata;
|
2023-09-04 21:41:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.getLineMetadata = getLineMetadata;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @callback EachLineCallback
|
|
|
|
|
|
* @param {string} line Line content.
|
|
|
|
|
|
* @param {number} lineIndex Line index (0-based).
|
|
|
|
|
|
* @param {boolean} inCode Iff in a code block.
|
|
|
|
|
|
* @param {number} onFence + if open, - if closed, 0 otherwise.
|
|
|
|
|
|
* @param {boolean} inTable Iff in a table.
|
|
|
|
|
|
* @param {boolean} inItem Iff in a list item.
|
|
|
|
|
|
* @param {boolean} inBreak Iff in semantic break.
|
2024-07-20 13:38:45 +08:00
|
|
|
|
* @param {boolean} inHtml Iff in HTML block.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-11-23 04:40:05 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Calls the provided function for each line.
|
|
|
|
|
|
*
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {LineMetadata} lineMetadata Line metadata object.
|
|
|
|
|
|
* @param {EachLineCallback} handler Function taking (line, lineIndex, inCode,
|
|
|
|
|
|
* onFence, inTable, inItem, inBreak).
|
2021-11-23 04:40:05 +00:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function forEachLine(lineMetadata, handler) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const metadata of lineMetadata) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
handler(...metadata);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2021-11-23 04:40:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.forEachLine = forEachLine;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Returns (nested) lists as a flat array (in order)
|
2021-06-17 22:01:27 -07:00
|
|
|
|
module.exports.flattenLists = function flattenLists(tokens) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const flattenedLists = [];
|
|
|
|
|
|
const stack = [];
|
|
|
|
|
|
let current = null;
|
|
|
|
|
|
let nesting = 0;
|
|
|
|
|
|
const nestingStack = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
let lastWithMap = { "map": [ 0, 1 ] };
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of tokens) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((token.type === "bullet_list_open") ||
|
|
|
|
|
|
(token.type === "ordered_list_open")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Save current context and start a new one
|
|
|
|
|
|
stack.push(current);
|
|
|
|
|
|
current = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"unordered": (token.type === "bullet_list_open"),
|
|
|
|
|
|
"parentsUnordered": !current ||
|
|
|
|
|
|
(current.unordered && current.parentsUnordered),
|
2024-01-06 20:47:01 -08:00
|
|
|
|
"open": token,
|
|
|
|
|
|
"indent": indentFor(token),
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"parentIndent": (current && current.indent) || 0,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
"items": [],
|
|
|
|
|
|
"nesting": nesting,
|
|
|
|
|
|
"lastLineIndex": -1,
|
|
|
|
|
|
"insert": flattenedLists.length
|
|
|
|
|
|
};
|
|
|
|
|
|
nesting++;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((token.type === "bullet_list_close") ||
|
|
|
|
|
|
(token.type === "ordered_list_close")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Finalize current context and restore previous
|
|
|
|
|
|
current.lastLineIndex = lastWithMap.map[1];
|
|
|
|
|
|
flattenedLists.splice(current.insert, 0, current);
|
|
|
|
|
|
delete current.insert;
|
|
|
|
|
|
current = stack.pop();
|
|
|
|
|
|
nesting--;
|
|
|
|
|
|
} else if (token.type === "list_item_open") {
|
|
|
|
|
|
// Add list item
|
|
|
|
|
|
current.items.push(token);
|
|
|
|
|
|
} else if (token.type === "blockquote_open") {
|
|
|
|
|
|
nestingStack.push(nesting);
|
|
|
|
|
|
nesting = 0;
|
|
|
|
|
|
} else if (token.type === "blockquote_close") {
|
|
|
|
|
|
nesting = nestingStack.pop() || 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (token.map) {
|
|
|
|
|
|
// Track last token with map
|
|
|
|
|
|
lastWithMap = token;
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return flattenedLists;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Calls the provided function for each heading's content
|
|
|
|
|
|
module.exports.forEachHeading = function forEachHeading(params, handler) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let heading = null;
|
|
|
|
|
|
for (const token of params.parsers.markdownit.tokens) {
|
|
|
|
|
|
if (token.type === "heading_open") {
|
|
|
|
|
|
heading = token;
|
|
|
|
|
|
} else if (token.type === "heading_close") {
|
|
|
|
|
|
heading = null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((token.type === "inline") && heading) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
handler(heading, token.content, token);
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* @callback InlineCodeSpanCallback
|
|
|
|
|
|
* @param {string} code Code content.
|
|
|
|
|
|
* @param {number} lineIndex Line index (0-based).
|
|
|
|
|
|
* @param {number} columnIndex Column index (0-based).
|
|
|
|
|
|
* @param {number} ticks Count of backticks.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2020-04-25 21:15:13 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Calls the provided function for each inline code span's content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} input Markdown content.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {InlineCodeSpanCallback} handler Callback function taking (code,
|
|
|
|
|
|
* lineIndex, columnIndex, ticks).
|
2020-04-25 21:15:13 -07:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function forEachInlineCodeSpan(input, handler) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const backtickRe = /`+/g;
|
|
|
|
|
|
let match = null;
|
|
|
|
|
|
const backticksLengthAndIndex = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while ((match = backtickRe.exec(input)) !== null) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
backticksLengthAndIndex.push([ match[0].length, match.index ]);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const newLinesIndex = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while ((match = newLineRe.exec(input)) !== null) {
|
|
|
|
|
|
newLinesIndex.push(match.index);
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let lineIndex = 0;
|
|
|
|
|
|
let lineStartIndex = 0;
|
|
|
|
|
|
let k = 0;
|
|
|
|
|
|
for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ startLength, startIndex ] = backticksLengthAndIndex[i];
|
|
|
|
|
|
if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let j = i + 1; j < backticksLengthAndIndex.length; j++) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ endLength, endIndex ] = backticksLengthAndIndex[j];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (startLength === endLength) {
|
|
|
|
|
|
for (; k < newLinesIndex.length; k++) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const newLineIndex = newLinesIndex[k];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (startIndex < newLineIndex) {
|
|
|
|
|
|
break;
|
2020-04-25 21:15:13 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lineIndex++;
|
|
|
|
|
|
lineStartIndex = newLineIndex + 1;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const columnIndex = startIndex - lineStartIndex + startLength;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
handler(
|
|
|
|
|
|
input.slice(startIndex + startLength, endIndex),
|
|
|
|
|
|
lineIndex,
|
|
|
|
|
|
columnIndex,
|
|
|
|
|
|
startLength
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
i = j;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-04-25 21:15:13 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2020-04-25 21:15:13 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.forEachInlineCodeSpan = forEachInlineCodeSpan;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Adds ellipsis to the left/right/middle of the specified text.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} text Text to ellipsify.
|
|
|
|
|
|
* @param {boolean} [start] True iff the start of the text is important.
|
|
|
|
|
|
* @param {boolean} [end] True iff the end of the text is important.
|
|
|
|
|
|
* @returns {string} Ellipsified text.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function ellipsify(text, start, end) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (text.length <= 30) {
|
|
|
|
|
|
// Nothing to do
|
|
|
|
|
|
} else if (start && end) {
|
|
|
|
|
|
text = text.slice(0, 15) + "..." + text.slice(-15);
|
|
|
|
|
|
} else if (end) {
|
|
|
|
|
|
text = "..." + text.slice(-30);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
text = text.slice(0, 30) + "...";
|
|
|
|
|
|
}
|
|
|
|
|
|
return text;
|
2022-06-01 20:23:08 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.ellipsify = ellipsify;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Adds a generic error object via the onError callback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} onError RuleOnError instance.
|
|
|
|
|
|
* @param {number} lineNumber Line number.
|
|
|
|
|
|
* @param {string} [detail] Error details.
|
|
|
|
|
|
* @param {string} [context] Error context.
|
|
|
|
|
|
* @param {number[]} [range] Column and length of error.
|
|
|
|
|
|
* @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function addError(onError, lineNumber, detail, context, range, fixInfo) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
onError({
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lineNumber,
|
|
|
|
|
|
detail,
|
|
|
|
|
|
context,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.addError = addError;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2024-06-01 21:32:10 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Adds an error object with details conditionally via the onError callback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} onError RuleOnError instance.
|
|
|
|
|
|
* @param {number} lineNumber Line number.
|
|
|
|
|
|
* @param {Object} expected Expected value.
|
|
|
|
|
|
* @param {Object} actual Actual value.
|
|
|
|
|
|
* @param {string} [detail] Error details.
|
|
|
|
|
|
* @param {string} [context] Error context.
|
|
|
|
|
|
* @param {number[]} [range] Column and length of error.
|
|
|
|
|
|
* @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function addErrorDetailIf(
|
2024-02-17 15:46:13 -08:00
|
|
|
|
onError, lineNumber, expected, actual, detail, context, range, fixInfo) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (expected !== actual) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
"Expected: " + expected + "; Actual: " + actual +
|
|
|
|
|
|
(detail ? "; " + detail : ""),
|
|
|
|
|
|
context,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-01 21:32:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.addErrorDetailIf = addErrorDetailIf;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2024-06-01 21:32:10 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Adds an error object with context via the onError callback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} onError RuleOnError instance.
|
|
|
|
|
|
* @param {number} lineNumber Line number.
|
|
|
|
|
|
* @param {string} context Error context.
|
|
|
|
|
|
* @param {boolean} [start] True iff the start of the text is important.
|
|
|
|
|
|
* @param {boolean} [end] True iff the end of the text is important.
|
|
|
|
|
|
* @param {number[]} [range] Column and length of error.
|
|
|
|
|
|
* @param {Object} [fixInfo] RuleOnErrorFixInfo instance.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function addErrorContext(
|
|
|
|
|
|
onError, lineNumber, context, start, end, range, fixInfo) {
|
|
|
|
|
|
context = ellipsify(context, start, end);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
addError(onError, lineNumber, undefined, context, range, fixInfo);
|
2024-06-01 21:32:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.addErrorContext = addErrorContext;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Adds an error object with context for a construct missing a blank line.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} onError RuleOnError instance.
|
|
|
|
|
|
* @param {string[]} lines Lines of Markdown content.
|
|
|
|
|
|
* @param {number} lineIndex Line index of line.
|
|
|
|
|
|
* @param {number} [lineNumber] Line number for override.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function addErrorContextForLine(onError, lines, lineIndex, lineNumber) {
|
|
|
|
|
|
const line = lines[lineIndex];
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const quotePrefix = line.match(blockquotePrefixRe)[0].trimEnd();
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
line.trim(),
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
{
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
"insertText": `${quotePrefix}\n`
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
module.exports.addErrorContextForLine = addErrorContextForLine;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-06-17 21:50:03 -07:00
|
|
|
|
/**
|
2021-11-23 04:40:05 +00:00
|
|
|
|
* Returns an array of code block and span content ranges.
|
2021-06-17 21:50:03 -07:00
|
|
|
|
*
|
2021-11-23 04:40:05 +00:00
|
|
|
|
* @param {Object} params RuleParams instance.
|
|
|
|
|
|
* @param {Object} lineMetadata Line metadata object.
|
|
|
|
|
|
* @returns {number[][]} Array of ranges (lineIndex, columnIndex, length).
|
2021-06-17 21:50:03 -07:00
|
|
|
|
*/
|
2024-01-06 20:47:01 -08:00
|
|
|
|
module.exports.codeBlockAndSpanRanges = (params, lineMetadata) => {
|
|
|
|
|
|
const exclusions = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Add code block ranges (excludes fences)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
forEachLine(lineMetadata, (line, lineIndex, inCode, onFence) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (inCode && !onFence) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
exclusions.push([ lineIndex, 0, line.length ]);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// Add code span ranges (excludes ticks)
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "inline", (token) => {
|
|
|
|
|
|
if (token.children.some((child) => child.type === "code_inline")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const tokenLines = params.lines.slice(token.map[0], token.map[1]);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
forEachInlineCodeSpan(
|
|
|
|
|
|
tokenLines.join("\n"),
|
|
|
|
|
|
(code, lineIndex, columnIndex) => {
|
|
|
|
|
|
const codeLines = code.split(newLineRe);
|
|
|
|
|
|
for (const [ i, line ] of codeLines.entries()) {
|
|
|
|
|
|
exclusions.push([
|
|
|
|
|
|
token.lineNumber - 1 + lineIndex + i,
|
|
|
|
|
|
i ? 0 : columnIndex,
|
|
|
|
|
|
line.length
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return exclusions;
|
2021-06-17 21:50:03 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Determines whether the specified range is within another range.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {number[][]} ranges Array of ranges (line, index, length).
|
|
|
|
|
|
* @param {number} lineIndex Line index to check.
|
|
|
|
|
|
* @param {number} index Index to check.
|
|
|
|
|
|
* @param {number} length Length to check.
|
|
|
|
|
|
* @returns {boolean} True iff the specified range is within.
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const withinAnyRange = (ranges, lineIndex, index, length) => (
|
|
|
|
|
|
!ranges.every((span) => (
|
|
|
|
|
|
(lineIndex !== span[0]) ||
|
|
|
|
|
|
(index < span[1]) ||
|
|
|
|
|
|
(index + length > span[1] + span[2])
|
|
|
|
|
|
))
|
|
|
|
|
|
);
|
2022-06-02 22:17:32 -07:00
|
|
|
|
module.exports.withinAnyRange = withinAnyRange;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Returns a range object for a line by applying a RegExp
|
|
|
|
|
|
module.exports.rangeFromRegExp = function rangeFromRegExp(line, regexp) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let range = null;
|
|
|
|
|
|
const match = line.match(regexp);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (match) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const column = match.index + 1;
|
|
|
|
|
|
const length = match[0].length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ column, length ];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return range;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// Determines if the front matter includes a title
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.frontMatterHasTitle =
|
|
|
|
|
|
function frontMatterHasTitle(frontMatterLines, frontMatterTitlePattern) {
|
|
|
|
|
|
const ignoreFrontMatter =
|
|
|
|
|
|
(frontMatterTitlePattern !== undefined) && !frontMatterTitlePattern;
|
|
|
|
|
|
const frontMatterTitleRe =
|
|
|
|
|
|
new RegExp(
|
|
|
|
|
|
String(frontMatterTitlePattern || "^\\s*\"?title\"?\\s*[:=]"),
|
|
|
|
|
|
"i"
|
|
|
|
|
|
);
|
|
|
|
|
|
return !ignoreFrontMatter &&
|
|
|
|
|
|
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns an object with information about reference links and images.
|
|
|
|
|
|
*
|
2024-03-09 16:17:50 -08:00
|
|
|
|
* @param {import("../helpers/micromark.cjs").Token[]} tokens Micromark tokens.
|
2022-06-01 20:23:08 -07:00
|
|
|
|
* @returns {Object} Reference link/image data.
|
|
|
|
|
|
*/
|
2024-03-09 16:17:50 -08:00
|
|
|
|
function getReferenceLinkImageData(tokens) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const definitions = new Map();
|
|
|
|
|
|
const definitionLineIndices = [];
|
|
|
|
|
|
const duplicateDefinitions = [];
|
|
|
|
|
|
const references = new Map();
|
|
|
|
|
|
const shortcuts = new Map();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const filteredTokens =
|
|
|
|
|
|
micromark.filterByTypes(
|
2024-03-09 16:17:50 -08:00
|
|
|
|
tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[
|
|
|
|
|
|
// definitionLineIndices
|
|
|
|
|
|
"definition", "gfmFootnoteDefinition",
|
|
|
|
|
|
// definitions and definitionLineIndices
|
|
|
|
|
|
"definitionLabelString", "gfmFootnoteDefinitionLabelString",
|
|
|
|
|
|
// references and shortcuts
|
|
|
|
|
|
"gfmFootnoteCall", "image", "link"
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of filteredTokens) {
|
|
|
|
|
|
let labelPrefix = "";
|
|
|
|
|
|
// eslint-disable-next-line default-case
|
|
|
|
|
|
switch (token.type) {
|
|
|
|
|
|
case "definition":
|
|
|
|
|
|
case "gfmFootnoteDefinition":
|
|
|
|
|
|
// definitionLineIndices
|
|
|
|
|
|
for (let i = token.startLine; i <= token.endLine; i++) {
|
|
|
|
|
|
definitionLineIndices.push(i - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "gfmFootnoteDefinitionLabelString":
|
|
|
|
|
|
labelPrefix = "^";
|
2024-02-17 15:46:13 -08:00
|
|
|
|
case "definitionLabelString": // eslint-disable-line no-fallthrough
|
2024-01-06 20:47:01 -08:00
|
|
|
|
{
|
|
|
|
|
|
// definitions and definitionLineIndices
|
|
|
|
|
|
const reference = normalizeReference(`${labelPrefix}${token.text}`);
|
|
|
|
|
|
if (definitions.has(reference)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
duplicateDefinitions.push([ reference, token.startLine - 1 ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} else {
|
|
|
|
|
|
let destinationString = null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const parent =
|
|
|
|
|
|
micromark.getTokenParentOfType(token, [ "definition" ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (parent) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
destinationString = micromark.getTokenTextByType(
|
|
|
|
|
|
micromark.filterByPredicate(parent.children),
|
|
|
|
|
|
"definitionDestinationString"
|
|
|
|
|
|
);
|
2023-01-29 20:36:53 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
definitions.set(
|
|
|
|
|
|
reference,
|
|
|
|
|
|
[ token.startLine - 1, destinationString ]
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "gfmFootnoteCall":
|
|
|
|
|
|
case "image":
|
|
|
|
|
|
case "link":
|
|
|
|
|
|
{
|
|
|
|
|
|
let isShortcut = false;
|
|
|
|
|
|
let isFullOrCollapsed = false;
|
|
|
|
|
|
let labelText = null;
|
|
|
|
|
|
let referenceStringText = null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const shortcutCandidate =
|
|
|
|
|
|
micromark.matchAndGetTokensByType(token.children, [ "label" ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (shortcutCandidate) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
labelText =
|
|
|
|
|
|
micromark.getTokenTextByType(
|
|
|
|
|
|
shortcutCandidate[0].children, "labelText"
|
|
|
|
|
|
);
|
|
|
|
|
|
isShortcut = (labelText !== null);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const fullAndCollapsedCandidate =
|
|
|
|
|
|
micromark.matchAndGetTokensByType(
|
|
|
|
|
|
token.children, [ "label", "reference" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (fullAndCollapsedCandidate) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
labelText =
|
|
|
|
|
|
micromark.getTokenTextByType(
|
|
|
|
|
|
fullAndCollapsedCandidate[0].children, "labelText"
|
|
|
|
|
|
);
|
|
|
|
|
|
referenceStringText =
|
|
|
|
|
|
micromark.getTokenTextByType(
|
|
|
|
|
|
fullAndCollapsedCandidate[1].children, "referenceString"
|
|
|
|
|
|
);
|
|
|
|
|
|
isFullOrCollapsed = (labelText !== null);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const footnote = micromark.matchAndGetTokensByType(
|
|
|
|
|
|
token.children,
|
|
|
|
|
|
[
|
|
|
|
|
|
"gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
|
|
|
|
|
|
"gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
|
|
|
|
|
|
],
|
|
|
|
|
|
[ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (footnote) {
|
|
|
|
|
|
const callMarkerText = footnote[0].text;
|
|
|
|
|
|
const callString = footnote[1].text;
|
|
|
|
|
|
labelText = `${callMarkerText}${callString}`;
|
|
|
|
|
|
isShortcut = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Track shortcuts separately due to ambiguity in "text [text] text"
|
|
|
|
|
|
if (isShortcut || isFullOrCollapsed) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const referenceDatum = [
|
|
|
|
|
|
token.startLine - 1,
|
|
|
|
|
|
token.startColumn - 1,
|
|
|
|
|
|
token.text.length,
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
labelText.length,
|
|
|
|
|
|
(referenceStringText || "").length
|
|
|
|
|
|
];
|
|
|
|
|
|
const reference =
|
|
|
|
|
|
normalizeReference(referenceStringText || labelText);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const dictionary = isShortcut ? shortcuts : references;
|
|
|
|
|
|
const referenceData = dictionary.get(reference) || [];
|
|
|
|
|
|
referenceData.push(referenceDatum);
|
|
|
|
|
|
dictionary.set(reference, referenceData);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2022-06-01 20:23:08 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
references,
|
|
|
|
|
|
shortcuts,
|
|
|
|
|
|
definitions,
|
|
|
|
|
|
duplicateDefinitions,
|
|
|
|
|
|
definitionLineIndices
|
2023-01-17 04:19:40 +00:00
|
|
|
|
};
|
2022-06-01 20:23:08 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.getReferenceLinkImageData = getReferenceLinkImageData;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the most common line ending, falling back to the platform default.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} input Markdown content to analyze.
|
2022-05-06 21:04:34 -07:00
|
|
|
|
* @param {Object} [os] Node.js "os" module.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {string} Preferred line ending.
|
|
|
|
|
|
*/
|
2022-05-06 21:04:34 -07:00
|
|
|
|
function getPreferredLineEnding(input, os) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let cr = 0;
|
|
|
|
|
|
let lf = 0;
|
|
|
|
|
|
let crlf = 0;
|
|
|
|
|
|
const endings = input.match(newLineRe) || [];
|
|
|
|
|
|
for (const ending of endings) {
|
|
|
|
|
|
// eslint-disable-next-line default-case
|
|
|
|
|
|
switch (ending) {
|
|
|
|
|
|
case "\r":
|
|
|
|
|
|
cr++;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "\n":
|
|
|
|
|
|
lf++;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "\r\n":
|
|
|
|
|
|
crlf++;
|
|
|
|
|
|
break;
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let preferredLineEnding = null;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!cr && !lf && !crlf) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
preferredLineEnding = (os && os.EOL) || "\n";
|
|
|
|
|
|
} else if ((lf >= crlf) && (lf >= cr)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
preferredLineEnding = "\n";
|
|
|
|
|
|
} else if (crlf >= cr) {
|
|
|
|
|
|
preferredLineEnding = "\r\n";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
preferredLineEnding = "\r";
|
|
|
|
|
|
}
|
|
|
|
|
|
return preferredLineEnding;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.getPreferredLineEnding = getPreferredLineEnding;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Normalizes the fields of a RuleOnErrorFixInfo instance.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} fixInfo RuleOnErrorFixInfo instance.
|
|
|
|
|
|
* @param {number} [lineNumber] Line number.
|
|
|
|
|
|
* @returns {Object} Normalized RuleOnErrorFixInfo instance.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function normalizeFixInfo(fixInfo, lineNumber) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return {
|
|
|
|
|
|
"lineNumber": fixInfo.lineNumber || lineNumber,
|
|
|
|
|
|
"editColumn": fixInfo.editColumn || 1,
|
|
|
|
|
|
"deleteCount": fixInfo.deleteCount || 0,
|
|
|
|
|
|
"insertText": fixInfo.insertText || ""
|
|
|
|
|
|
};
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Fixes the specified error on a line of Markdown content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} line Line of Markdown content.
|
|
|
|
|
|
* @param {Object} fixInfo RuleOnErrorFixInfo instance.
|
2022-02-09 22:44:49 -08:00
|
|
|
|
* @param {string} [lineEnding] Line ending to use.
|
2022-06-12 17:51:47 -07:00
|
|
|
|
* @returns {string | null} Fixed content.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function applyFix(line, fixInfo, lineEnding) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const editIndex = editColumn - 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (deleteCount === -1) ?
|
|
|
|
|
|
null :
|
|
|
|
|
|
line.slice(0, editIndex) +
|
|
|
|
|
|
insertText.replace(/\n/g, lineEnding || "\n") +
|
|
|
|
|
|
line.slice(editIndex + deleteCount);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.applyFix = applyFix;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-02-09 22:44:49 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Applies as many fixes as possible to Markdown content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} input Lines of Markdown content.
|
|
|
|
|
|
* @param {Object[]} errors RuleOnErrorInfo instances.
|
|
|
|
|
|
* @returns {string} Corrected content.
|
|
|
|
|
|
*/
|
2022-05-05 23:14:18 -07:00
|
|
|
|
function applyFixes(input, errors) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lineEnding = getPreferredLineEnding(input, __webpack_require__(/*! node:os */ "?0176"));
|
|
|
|
|
|
const lines = input.split(newLineRe);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Normalize fixInfo objects
|
2024-02-17 15:46:13 -08:00
|
|
|
|
let fixInfos = errors
|
|
|
|
|
|
.filter((error) => error.fixInfo)
|
|
|
|
|
|
.map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfos.sort((a, b) => {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const aDeletingLine = (a.deleteCount === -1);
|
|
|
|
|
|
const bDeletingLine = (b.deleteCount === -1);
|
|
|
|
|
|
return (
|
|
|
|
|
|
(b.lineNumber - a.lineNumber) ||
|
|
|
|
|
|
(aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) ||
|
|
|
|
|
|
(b.editColumn - a.editColumn) ||
|
|
|
|
|
|
(b.insertText.length - a.insertText.length)
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
|
|
|
|
|
// Remove duplicate entries (needed for following collapse step)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let lastFixInfo = {};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
fixInfos = fixInfos.filter((fixInfo) => {
|
|
|
|
|
|
const unique = (
|
|
|
|
|
|
(fixInfo.lineNumber !== lastFixInfo.lineNumber) ||
|
|
|
|
|
|
(fixInfo.editColumn !== lastFixInfo.editColumn) ||
|
|
|
|
|
|
(fixInfo.deleteCount !== lastFixInfo.deleteCount) ||
|
|
|
|
|
|
(fixInfo.insertText !== lastFixInfo.insertText)
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lastFixInfo = fixInfo;
|
|
|
|
|
|
return unique;
|
|
|
|
|
|
});
|
|
|
|
|
|
// Collapse insert/no-delete and no-insert/delete for same line/column
|
|
|
|
|
|
lastFixInfo = {
|
|
|
|
|
|
"lineNumber": -1
|
|
|
|
|
|
};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const fixInfo of fixInfos) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
(fixInfo.lineNumber === lastFixInfo.lineNumber) &&
|
|
|
|
|
|
(fixInfo.editColumn === lastFixInfo.editColumn) &&
|
|
|
|
|
|
!fixInfo.insertText &&
|
|
|
|
|
|
(fixInfo.deleteCount > 0) &&
|
|
|
|
|
|
lastFixInfo.insertText &&
|
|
|
|
|
|
!lastFixInfo.deleteCount) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo.insertText = lastFixInfo.insertText;
|
|
|
|
|
|
lastFixInfo.lineNumber = 0;
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lastFixInfo = fixInfo;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Apply all (remaining/updated) fixes
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let lastLineIndex = -1;
|
|
|
|
|
|
let lastEditIndex = -1;
|
|
|
|
|
|
for (const fixInfo of fixInfos) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { lineNumber, editColumn, deleteCount } = fixInfo;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lineIndex = lineNumber - 1;
|
|
|
|
|
|
const editIndex = editColumn - 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
(lineIndex !== lastLineIndex) ||
|
|
|
|
|
|
(deleteCount === -1) ||
|
|
|
|
|
|
((editIndex + deleteCount) <=
|
|
|
|
|
|
(lastEditIndex - ((deleteCount > 0) ? 0 : 1)))
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding);
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lastLineIndex = lineIndex;
|
|
|
|
|
|
lastEditIndex = editIndex;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Return corrected input
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return lines.filter((line) => line !== null).join(lineEnding);
|
2022-02-09 22:44:49 -08:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.applyFixes = applyFixes;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-05-16 22:57:11 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Expands a path with a tilde to an absolute path.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} file Path that may begin with a tilde.
|
|
|
|
|
|
* @param {Object} os Node.js "os" module.
|
|
|
|
|
|
* @returns {string} Absolute path (or original path).
|
|
|
|
|
|
*/
|
|
|
|
|
|
function expandTildePath(file, os) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const homedir = os && os.homedir && os.homedir();
|
|
|
|
|
|
return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file;
|
2022-05-16 22:57:11 -07:00
|
|
|
|
}
|
|
|
|
|
|
module.exports.expandTildePath = expandTildePath;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
// Copied from markdownlint.js to avoid TypeScript compiler import() issue.
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @typedef {Object} MarkdownItToken
|
|
|
|
|
|
* @property {string[][]} attrs HTML attributes.
|
|
|
|
|
|
* @property {boolean} block Block-level token.
|
|
|
|
|
|
* @property {MarkdownItToken[]} children Child nodes.
|
|
|
|
|
|
* @property {string} content Tag contents.
|
|
|
|
|
|
* @property {boolean} hidden Ignore element.
|
|
|
|
|
|
* @property {string} info Fence info.
|
|
|
|
|
|
* @property {number} level Nesting level.
|
|
|
|
|
|
* @property {number[]} map Beginning/ending line numbers.
|
|
|
|
|
|
* @property {string} markup Markup text.
|
|
|
|
|
|
* @property {Object} meta Arbitrary data.
|
|
|
|
|
|
* @property {number} nesting Level change.
|
|
|
|
|
|
* @property {string} tag HTML tag name.
|
|
|
|
|
|
* @property {string} type Token type.
|
|
|
|
|
|
* @property {number} lineNumber Line number (1-based).
|
|
|
|
|
|
* @property {string} line Line content.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2022-04-21 21:09:07 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2023-07-21 22:49:08 -07:00
|
|
|
|
/***/ "../helpers/shared.js":
|
|
|
|
|
|
/*!****************************!*\
|
|
|
|
|
|
!*** ../helpers/shared.js ***!
|
|
|
|
|
|
\****************************/
|
|
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Regular expression for matching common newline characters
|
|
|
|
|
|
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
|
|
|
|
|
|
module.exports.newLineRe = /\r\n?|\n/g;
|
|
|
|
|
|
|
2023-10-18 23:20:19 -07:00
|
|
|
|
// Regular expression for matching next lines
|
|
|
|
|
|
module.exports.nextLinesRe = /[\r\n][\s\S]*$/;
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib sync recursive":
|
|
|
|
|
|
/*!********************!*\
|
|
|
|
|
|
!*** ../lib/ sync ***!
|
|
|
|
|
|
\********************/
|
|
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
|
|
|
|
|
function webpackEmptyContext(req) {
|
|
|
|
|
|
var e = new Error("Cannot find module '" + req + "'");
|
|
|
|
|
|
e.code = 'MODULE_NOT_FOUND';
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
}
|
|
|
|
|
|
webpackEmptyContext.keys = () => ([]);
|
|
|
|
|
|
webpackEmptyContext.resolve = webpackEmptyContext;
|
|
|
|
|
|
webpackEmptyContext.id = "../lib sync recursive";
|
|
|
|
|
|
module.exports = webpackEmptyContext;
|
|
|
|
|
|
|
2023-07-21 22:49:08 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-04-21 21:09:07 -07:00
|
|
|
|
/***/ "markdown-it":
|
|
|
|
|
|
/*!*****************************!*\
|
|
|
|
|
|
!*** external "markdownit" ***!
|
|
|
|
|
|
\*****************************/
|
|
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = markdownit;
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2023-02-08 20:50:28 -08:00
|
|
|
|
/***/ "markdownlint-micromark":
|
|
|
|
|
|
/*!***********************************!*\
|
|
|
|
|
|
!*** external "micromarkBrowser" ***!
|
|
|
|
|
|
\***********************************/
|
|
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = micromarkBrowser;
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-08-16 04:01:53 +00:00
|
|
|
|
/***/ "?0176":
|
|
|
|
|
|
/*!*************************!*\
|
|
|
|
|
|
!*** node:os (ignored) ***!
|
|
|
|
|
|
\*************************/
|
2022-05-04 22:09:11 -07:00
|
|
|
|
/***/ (() => {
|
|
|
|
|
|
|
|
|
|
|
|
/* (ignored) */
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-08-16 04:01:53 +00:00
|
|
|
|
/***/ "?d0ee":
|
|
|
|
|
|
/*!*************************!*\
|
|
|
|
|
|
!*** node:fs (ignored) ***!
|
|
|
|
|
|
\*************************/
|
2022-04-21 21:09:07 -07:00
|
|
|
|
/***/ (() => {
|
|
|
|
|
|
|
|
|
|
|
|
/* (ignored) */
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-08-16 04:01:53 +00:00
|
|
|
|
/***/ "?e6c4":
|
|
|
|
|
|
/*!*************************!*\
|
|
|
|
|
|
!*** node:os (ignored) ***!
|
|
|
|
|
|
\*************************/
|
2022-05-16 22:57:11 -07:00
|
|
|
|
/***/ (() => {
|
|
|
|
|
|
|
|
|
|
|
|
/* (ignored) */
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-08-16 04:01:53 +00:00
|
|
|
|
/***/ "?9a52":
|
|
|
|
|
|
/*!***************************!*\
|
|
|
|
|
|
!*** node:path (ignored) ***!
|
|
|
|
|
|
\***************************/
|
2022-04-21 21:09:07 -07:00
|
|
|
|
/***/ (() => {
|
|
|
|
|
|
|
|
|
|
|
|
/* (ignored) */
|
|
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-08-16 04:01:53 +00:00
|
|
|
|
/***/ "?39e5":
|
|
|
|
|
|
/*!***************************!*\
|
|
|
|
|
|
!*** node:util (ignored) ***!
|
|
|
|
|
|
\***************************/
|
2022-04-21 21:09:07 -07:00
|
|
|
|
/***/ (() => {
|
|
|
|
|
|
|
|
|
|
|
|
/* (ignored) */
|
|
|
|
|
|
|
2022-12-29 00:43:53 +00:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "./markdownlint-exports.js":
|
|
|
|
|
|
/*!*********************************!*\
|
|
|
|
|
|
!*** ./markdownlint-exports.js ***!
|
|
|
|
|
|
\*********************************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2022-12-29 00:43:53 +00:00
|
|
|
|
module.exports = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"library": __webpack_require__(/*! .. */ "../lib/markdownlint.js"),
|
|
|
|
|
|
"helpers": __webpack_require__(/*! ../helpers */ "../helpers/helpers.js")
|
2022-12-29 00:43:53 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2023-01-20 04:10:18 +00:00
|
|
|
|
/***/ "../helpers/micromark.cjs":
|
|
|
|
|
|
/*!********************************!*\
|
|
|
|
|
|
!*** ../helpers/micromark.cjs ***!
|
|
|
|
|
|
\********************************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const {
|
2024-03-04 21:38:18 -08:00
|
|
|
|
directive, gfmAutolinkLiteral, gfmFootnote, gfmTable, math,
|
|
|
|
|
|
parse, postprocess, preprocess
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
} = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
|
|
|
|
|
|
|
2024-06-10 22:16:20 -07:00
|
|
|
|
const flatTokensSymbol = Symbol("flat-tokens");
|
|
|
|
|
|
const reparseSymbol = Symbol("reparse");
|
2023-01-20 04:10:18 +00:00
|
|
|
|
|
2024-03-04 21:38:18 -08:00
|
|
|
|
/** @typedef {import("markdownlint-micromark").Event} Event */
|
|
|
|
|
|
/** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
|
|
|
|
|
|
/** @typedef {import("markdownlint-micromark").TokenType} TokenType */
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
|
2023-01-20 04:10:18 +00:00
|
|
|
|
|
2024-06-09 17:09:03 -07:00
|
|
|
|
/**
|
2024-06-10 22:16:20 -07:00
|
|
|
|
* Determines if a Micromark token is within an htmlFlow.
|
2024-06-09 17:09:03 -07:00
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
2024-06-10 22:16:20 -07:00
|
|
|
|
* @returns {boolean} True iff the token is within an htmlFlow.
|
2024-06-09 17:09:03 -07:00
|
|
|
|
*/
|
|
|
|
|
|
function inHtmlFlow(token) {
|
2024-06-10 22:16:20 -07:00
|
|
|
|
return token[reparseSymbol];
|
2024-06-09 17:09:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-02 12:07:14 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
|
|
|
|
|
* @returns {boolean} True iff token is htmlFlow containing a comment.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function isHtmlFlowComment(token) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { text, type } = token;
|
|
|
|
|
|
if (
|
|
|
|
|
|
(type === "htmlFlow") &&
|
|
|
|
|
|
text.startsWith("<!--") &&
|
|
|
|
|
|
text.endsWith("-->")
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const comment = text.slice(4, -3);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (
|
|
|
|
|
|
!comment.startsWith(">") &&
|
|
|
|
|
|
!comment.startsWith("->") &&
|
|
|
|
|
|
!comment.endsWith("-")
|
|
|
|
|
|
// The following condition from the CommonMark specification is commented
|
|
|
|
|
|
// to avoid parsing HTML comments that include "--" because that is NOT a
|
|
|
|
|
|
// condition of the HTML specification.
|
|
|
|
|
|
// https://spec.commonmark.org/0.30/#raw-html
|
|
|
|
|
|
// https://html.spec.whatwg.org/multipage/syntax.html#comments
|
|
|
|
|
|
// && !comment.includes("--")
|
|
|
|
|
|
);
|
2023-09-02 12:07:14 -07:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-20 04:10:18 +00:00
|
|
|
|
/**
|
2023-02-10 20:37:32 -08:00
|
|
|
|
* Parses a Markdown document and returns Micromark events.
|
2023-01-20 04:10:18 +00:00
|
|
|
|
*
|
|
|
|
|
|
* @param {string} markdown Markdown document.
|
2024-03-04 21:38:18 -08:00
|
|
|
|
* @param {ParseOptions} [micromarkOptions] Options for micromark.
|
2023-07-21 22:49:08 -07:00
|
|
|
|
* @param {boolean} [referencesDefined] Treat references as defined.
|
2024-03-04 21:38:18 -08:00
|
|
|
|
* @returns {Event[]} Micromark events.
|
2023-01-20 04:10:18 +00:00
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function getMicromarkEvents(
|
|
|
|
|
|
markdown,
|
|
|
|
|
|
micromarkOptions = {},
|
|
|
|
|
|
referencesDefined = true
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
2023-01-29 20:36:53 -08:00
|
|
|
|
// Customize options object to add useful extensions
|
2023-07-21 22:49:08 -07:00
|
|
|
|
micromarkOptions.extensions = micromarkOptions.extensions || [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
micromarkOptions.extensions.push(
|
|
|
|
|
|
directive(),
|
|
|
|
|
|
gfmAutolinkLiteral(),
|
|
|
|
|
|
gfmFootnote(),
|
|
|
|
|
|
gfmTable(),
|
|
|
|
|
|
math()
|
|
|
|
|
|
);
|
2023-01-29 20:36:53 -08:00
|
|
|
|
|
2023-01-20 04:10:18 +00:00
|
|
|
|
// Use micromark to parse document into Events
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const encoding = undefined;
|
|
|
|
|
|
const eol = true;
|
|
|
|
|
|
const parseContext = parse(micromarkOptions);
|
2023-07-21 22:49:08 -07:00
|
|
|
|
if (referencesDefined) {
|
2023-05-23 04:01:55 +00:00
|
|
|
|
// Customize ParseContext to treat all references as defined
|
2024-02-17 15:46:13 -08:00
|
|
|
|
parseContext.defined.includes = (searchElement) => searchElement.length > 0;
|
2023-05-23 04:01:55 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const chunks = preprocess()(markdown, encoding, eol);
|
|
|
|
|
|
const events = postprocess(parseContext.document().write(chunks));
|
2023-02-10 20:37:32 -08:00
|
|
|
|
return events;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Parses a Markdown document and returns (frozen) tokens.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} markdown Markdown document.
|
2024-03-04 21:38:18 -08:00
|
|
|
|
* @param {ParseOptions} micromarkOptions Options for micromark.
|
2023-07-21 22:49:08 -07:00
|
|
|
|
* @param {boolean} referencesDefined Treat references as defined.
|
|
|
|
|
|
* @param {number} lineDelta Offset to apply to start/end line.
|
2023-10-19 23:01:31 -07:00
|
|
|
|
* @param {Token} [ancestor] Parent of top-most tokens.
|
2023-02-10 20:37:32 -08:00
|
|
|
|
* @returns {Token[]} Micromark tokens (frozen).
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function micromarkParseWithOffset(
|
|
|
|
|
|
markdown,
|
|
|
|
|
|
micromarkOptions,
|
|
|
|
|
|
referencesDefined,
|
|
|
|
|
|
lineDelta,
|
|
|
|
|
|
ancestor
|
|
|
|
|
|
) {
|
2023-02-10 20:37:32 -08:00
|
|
|
|
// Use micromark to parse document into Events
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const events = getMicromarkEvents(
|
|
|
|
|
|
markdown, micromarkOptions, referencesDefined
|
|
|
|
|
|
);
|
2023-01-20 04:10:18 +00:00
|
|
|
|
|
|
|
|
|
|
// Create Token objects
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const document = [];
|
2024-06-10 22:16:20 -07:00
|
|
|
|
let flatTokens = [];
|
2023-10-19 23:01:31 -07:00
|
|
|
|
/** @type {Token} */
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const root = {
|
2024-02-29 23:05:27 -08:00
|
|
|
|
"type": "data",
|
2023-10-19 23:01:31 -07:00
|
|
|
|
"startLine": -1,
|
|
|
|
|
|
"startColumn": -1,
|
|
|
|
|
|
"endLine": -1,
|
|
|
|
|
|
"endColumn": -1,
|
|
|
|
|
|
"text": "ROOT",
|
|
|
|
|
|
"children": document,
|
|
|
|
|
|
"parent": null
|
2023-01-20 04:10:18 +00:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const history = [ root ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let current = root;
|
2024-03-04 21:38:18 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type ParseOptions | null */
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let reparseOptions = null;
|
|
|
|
|
|
let lines = null;
|
|
|
|
|
|
let skipHtmlFlowChildren = false;
|
|
|
|
|
|
for (const event of events) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ kind, token, context ] = event;
|
|
|
|
|
|
const { type, start, end } = token;
|
|
|
|
|
|
const { "column": startColumn, "line": startLine } = start;
|
|
|
|
|
|
const { "column": endColumn, "line": endLine } = end;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const text = context.sliceSerialize(token);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((kind === "enter") && !skipHtmlFlowChildren) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const previous = current;
|
|
|
|
|
|
history.push(previous);
|
|
|
|
|
|
current = {
|
|
|
|
|
|
type,
|
|
|
|
|
|
"startLine": startLine + lineDelta,
|
|
|
|
|
|
startColumn,
|
|
|
|
|
|
"endLine": endLine + lineDelta,
|
|
|
|
|
|
endColumn,
|
|
|
|
|
|
text,
|
|
|
|
|
|
"children": [],
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"parent": ((previous === root) ? (ancestor || null) : previous)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
};
|
2024-06-10 22:16:20 -07:00
|
|
|
|
if (ancestor) {
|
|
|
|
|
|
Object.defineProperty(current, reparseSymbol, { "value": true });
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
previous.children.push(current);
|
2024-06-10 22:16:20 -07:00
|
|
|
|
flatTokens.push(current);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
skipHtmlFlowChildren = true;
|
|
|
|
|
|
if (!reparseOptions || !lines) {
|
|
|
|
|
|
reparseOptions = {
|
|
|
|
|
|
...micromarkOptions,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"extensions": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"disable": {
|
|
|
|
|
|
"null": [ "codeIndented", "htmlFlow" ]
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
]
|
2024-01-06 20:47:01 -08:00
|
|
|
|
};
|
|
|
|
|
|
lines = markdown.split(newLineRe);
|
2023-09-02 12:07:14 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const reparseMarkdown = lines
|
|
|
|
|
|
.slice(current.startLine - 1, current.endLine)
|
|
|
|
|
|
.join("\n");
|
|
|
|
|
|
const tokens = micromarkParseWithOffset(
|
|
|
|
|
|
reparseMarkdown,
|
|
|
|
|
|
reparseOptions,
|
|
|
|
|
|
referencesDefined,
|
|
|
|
|
|
current.startLine - 1,
|
|
|
|
|
|
current
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
current.children = tokens;
|
|
|
|
|
|
// Avoid stack overflow of Array.push(...spread)
|
|
|
|
|
|
// eslint-disable-next-line unicorn/prefer-spread
|
2024-06-10 22:16:20 -07:00
|
|
|
|
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
} else if (kind === "exit") {
|
|
|
|
|
|
if (type === "htmlFlow") {
|
|
|
|
|
|
skipHtmlFlowChildren = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!skipHtmlFlowChildren) {
|
|
|
|
|
|
Object.freeze(current.children);
|
|
|
|
|
|
Object.freeze(current);
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
current = history.pop();
|
2023-01-20 04:10:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
|
|
|
|
|
|
// Return document
|
2024-06-10 22:16:20 -07:00
|
|
|
|
Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
|
2023-01-20 04:10:18 +00:00
|
|
|
|
Object.freeze(document);
|
|
|
|
|
|
return document;
|
|
|
|
|
|
}
|
2023-01-21 15:41:03 -08:00
|
|
|
|
|
2023-07-21 22:49:08 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Parses a Markdown document and returns (frozen) tokens.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} markdown Markdown document.
|
2024-03-04 21:38:18 -08:00
|
|
|
|
* @param {ParseOptions} [micromarkOptions] Options for micromark.
|
2023-07-21 22:49:08 -07:00
|
|
|
|
* @param {boolean} [referencesDefined] Treat references as defined.
|
|
|
|
|
|
* @returns {Token[]} Micromark tokens (frozen).
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function micromarkParse(
|
|
|
|
|
|
markdown,
|
|
|
|
|
|
micromarkOptions = {},
|
|
|
|
|
|
referencesDefined = true
|
|
|
|
|
|
) {
|
|
|
|
|
|
return micromarkParseWithOffset(
|
|
|
|
|
|
markdown,
|
|
|
|
|
|
micromarkOptions,
|
|
|
|
|
|
referencesDefined,
|
|
|
|
|
|
0
|
|
|
|
|
|
);
|
2023-07-21 22:49:08 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* @callback AllowedPredicate
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
|
|
|
|
|
* @returns {boolean} True iff allowed.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @callback TransformPredicate
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
|
|
|
|
|
* @returns {Token[]} Child tokens.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2023-01-21 15:41:03 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Filter a list of Micromark tokens by predicate.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token[]} tokens Micromark tokens.
|
2023-10-25 20:05:19 -07:00
|
|
|
|
* @param {AllowedPredicate} [allowed] Allowed token predicate.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {TransformPredicate} [transformChildren] Transform predicate.
|
2023-01-21 15:41:03 -08:00
|
|
|
|
* @returns {Token[]} Filtered tokens.
|
|
|
|
|
|
*/
|
2023-03-14 21:03:07 -07:00
|
|
|
|
function filterByPredicate(tokens, allowed, transformChildren) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
allowed = allowed || (() => true);
|
|
|
|
|
|
const result = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const queue = [
|
|
|
|
|
|
{
|
|
|
|
|
|
"array": tokens,
|
|
|
|
|
|
"index": 0
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
2023-09-02 21:30:43 -07:00
|
|
|
|
while (queue.length > 0) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const current = queue[queue.length - 1];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { array, index } = current;
|
2023-09-02 21:30:43 -07:00
|
|
|
|
if (index < array.length) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const token = array[current.index++];
|
2023-09-02 21:30:43 -07:00
|
|
|
|
if (allowed(token)) {
|
|
|
|
|
|
result.push(token);
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { children } = token;
|
2023-09-02 21:30:43 -07:00
|
|
|
|
if (children.length > 0) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const transformed =
|
|
|
|
|
|
transformChildren ? transformChildren(token) : children;
|
|
|
|
|
|
queue.push(
|
|
|
|
|
|
{
|
|
|
|
|
|
"array": transformed,
|
|
|
|
|
|
"index": 0
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-09-02 21:30:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
queue.pop();
|
2023-03-10 22:22:54 -08:00
|
|
|
|
}
|
2023-01-21 15:41:03 -08:00
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Filter a list of Micromark tokens by type.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token[]} tokens Micromark tokens.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {TokenType[]} types Types to allow.
|
2024-06-09 17:09:03 -07:00
|
|
|
|
* @param {boolean} [htmlFlow] Whether to include htmlFlow content.
|
2023-01-21 15:41:03 -08:00
|
|
|
|
* @returns {Token[]} Filtered tokens.
|
|
|
|
|
|
*/
|
2024-06-09 17:09:03 -07:00
|
|
|
|
function filterByTypes(tokens, types, htmlFlow) {
|
2024-06-10 22:16:20 -07:00
|
|
|
|
const predicate = (token) =>
|
|
|
|
|
|
(htmlFlow || !inHtmlFlow(token)) && types.includes(token.type);
|
|
|
|
|
|
const flatTokens = tokens[flatTokensSymbol];
|
2023-08-28 22:00:43 -07:00
|
|
|
|
if (flatTokens) {
|
|
|
|
|
|
return flatTokens.filter(predicate);
|
|
|
|
|
|
}
|
2024-06-10 22:16:20 -07:00
|
|
|
|
return filterByPredicate(tokens, predicate);
|
2023-01-21 15:41:03 -08:00
|
|
|
|
}
|
2023-01-29 20:36:53 -08:00
|
|
|
|
|
2024-06-29 16:45:40 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets a list of nested Micromark token descendants by type path.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token|Token[]} parent Micromark token parent or parents.
|
|
|
|
|
|
* @param {TokenType[]} typePath Micromark token type path.
|
|
|
|
|
|
* @returns {Token[]} Micromark token descendants.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getDescendantsByType(parent, typePath) {
|
|
|
|
|
|
let tokens = Array.isArray(parent) ? parent : [ parent ];
|
|
|
|
|
|
for (const type of typePath) {
|
|
|
|
|
|
tokens = tokens.flatMap((t) => t.children).filter((t) => t.type === type);
|
|
|
|
|
|
}
|
|
|
|
|
|
return tokens;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-08 22:56:47 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the heading level of a Micromark heading tokan.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} heading Micromark heading token.
|
|
|
|
|
|
* @returns {number} Heading level.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getHeadingLevel(heading) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const headingSequence = filterByTypes(
|
|
|
|
|
|
heading.children,
|
|
|
|
|
|
[ "atxHeadingSequence", "setextHeadingLineSequence" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let level = 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { text } = headingSequence[0];
|
2023-08-08 22:56:47 -07:00
|
|
|
|
if (text[0] === "#") {
|
|
|
|
|
|
level = Math.min(text.length, 6);
|
|
|
|
|
|
} else if (text[0] === "-") {
|
|
|
|
|
|
level = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
return level;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-08 14:44:49 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the heading style of a Micromark heading tokan.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} heading Micromark heading token.
|
|
|
|
|
|
* @returns {"atx" | "atx_closed" | "setext"} Heading style.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getHeadingStyle(heading) {
|
|
|
|
|
|
if (heading.type === "setextHeading") {
|
|
|
|
|
|
return "setext";
|
|
|
|
|
|
}
|
|
|
|
|
|
const atxHeadingSequenceLength = filterByTypes(
|
|
|
|
|
|
heading.children,
|
|
|
|
|
|
[ "atxHeadingSequence" ]
|
|
|
|
|
|
).length;
|
|
|
|
|
|
if (atxHeadingSequenceLength === 1) {
|
|
|
|
|
|
return "atx";
|
|
|
|
|
|
}
|
|
|
|
|
|
return "atx_closed";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-19 21:05:31 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the heading text of a Micromark heading token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} heading Micromark heading token.
|
|
|
|
|
|
* @returns {string} Heading text.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getHeadingText(heading) {
|
|
|
|
|
|
const headingTexts = filterByTypes(
|
|
|
|
|
|
heading.children,
|
|
|
|
|
|
[ "atxHeadingText", "setextHeadingText" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
return headingTexts[0]?.text.replace(/[\r\n]+/g, " ") || "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-18 20:48:22 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* HTML tag information.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} HtmlTagInfo
|
|
|
|
|
|
* @property {boolean} close True iff close tag.
|
|
|
|
|
|
* @property {string} name Tag name.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2023-02-05 16:58:06 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets information about the tag in an HTML token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
2024-03-18 20:48:22 -07:00
|
|
|
|
* @returns {HtmlTagInfo | null} HTML tag information.
|
2023-02-05 16:58:06 -08:00
|
|
|
|
*/
|
|
|
|
|
|
function getHtmlTagInfo(token) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlTagNameRe = /^<([^!>][^/\s>]*)/;
|
2023-02-05 16:58:06 -08:00
|
|
|
|
if (token.type === "htmlText") {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const match = htmlTagNameRe.exec(token.text);
|
2023-02-05 16:58:06 -08:00
|
|
|
|
if (match) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const name = match[1];
|
|
|
|
|
|
const close = name.startsWith("/");
|
2023-02-05 16:58:06 -08:00
|
|
|
|
return {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
close,
|
2023-02-05 16:58:06 -08:00
|
|
|
|
"name": close ? name.slice(1) : name
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-10 22:16:20 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the nearest parent of the specified type for a Micromark token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} token Micromark token.
|
|
|
|
|
|
* @param {TokenType[]} types Types to allow.
|
|
|
|
|
|
* @returns {Token | null} Parent token.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getTokenParentOfType(token, types) {
|
|
|
|
|
|
/** @type {Token | null} */
|
|
|
|
|
|
let current = token;
|
|
|
|
|
|
while ((current = current.parent) && !types.includes(current.type)) {
|
|
|
|
|
|
// Empty
|
|
|
|
|
|
}
|
|
|
|
|
|
return current;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-29 20:36:53 -08:00
|
|
|
|
/**
|
2023-10-25 20:05:19 -07:00
|
|
|
|
* Get the text of the first match from a list of Micromark tokens by type.
|
2023-01-29 20:36:53 -08:00
|
|
|
|
*
|
|
|
|
|
|
* @param {Token[]} tokens Micromark tokens.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {TokenType} type Type to match.
|
2023-01-29 20:36:53 -08:00
|
|
|
|
* @returns {string | null} Text of token.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getTokenTextByType(tokens, type) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const filtered = tokens.filter((token) => token.type === type);
|
|
|
|
|
|
return (filtered.length > 0) ? filtered[0].text : null;
|
2023-01-29 20:36:53 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Determines a list of Micromark tokens matches and returns a subset.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token[]} tokens Micromark tokens.
|
2024-03-19 21:20:44 -07:00
|
|
|
|
* @param {TokenType[]} matchTypes Types to match.
|
|
|
|
|
|
* @param {TokenType[]} [resultTypes] Types to return.
|
2023-02-23 22:14:44 -08:00
|
|
|
|
* @returns {Token[] | null} Matching tokens.
|
2023-01-29 20:36:53 -08:00
|
|
|
|
*/
|
|
|
|
|
|
function matchAndGetTokensByType(tokens, matchTypes, resultTypes) {
|
|
|
|
|
|
if (tokens.length !== matchTypes.length) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2023-02-25 16:24:24 -08:00
|
|
|
|
resultTypes = resultTypes || matchTypes;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const result = [];
|
2023-02-23 22:14:44 -08:00
|
|
|
|
// eslint-disable-next-line unicorn/no-for-loop
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = 0; i < matchTypes.length; i++) {
|
2023-01-29 20:36:53 -08:00
|
|
|
|
if (tokens[i].type !== matchTypes[i]) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
} else if (resultTypes.includes(matchTypes[i])) {
|
2023-02-23 22:14:44 -08:00
|
|
|
|
result.push(tokens[i]);
|
2023-01-29 20:36:53 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2023-05-25 03:47:34 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Returns the specified token iff it is of the desired type.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Token} token Micromark token candidate.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {TokenType} type Desired type.
|
2023-05-25 03:47:34 +00:00
|
|
|
|
* @returns {Token | null} Token instance.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function tokenIfType(token, type) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (token && (token.type === type)) ? token : null;
|
2023-05-25 03:47:34 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-03-18 20:48:22 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Set containing token types that do not contain content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @type {Set<TokenType>}
|
|
|
|
|
|
*/
|
|
|
|
|
|
const nonContentTokens = new Set([
|
|
|
|
|
|
"blockQuoteMarker",
|
|
|
|
|
|
"blockQuotePrefix",
|
|
|
|
|
|
"blockQuotePrefixWhitespace",
|
|
|
|
|
|
"lineEnding",
|
|
|
|
|
|
"lineEndingBlank",
|
|
|
|
|
|
"linePrefix",
|
|
|
|
|
|
"listItemIndent"
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2023-01-20 04:10:18 +00:00
|
|
|
|
module.exports = {
|
2023-02-05 16:58:06 -08:00
|
|
|
|
"parse": micromarkParse,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
filterByPredicate,
|
|
|
|
|
|
filterByTypes,
|
2024-06-29 16:45:40 -07:00
|
|
|
|
getDescendantsByType,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
getHeadingLevel,
|
2024-06-08 14:44:49 -07:00
|
|
|
|
getHeadingStyle,
|
2024-06-19 21:05:31 -07:00
|
|
|
|
getHeadingText,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
getHtmlTagInfo,
|
|
|
|
|
|
getMicromarkEvents,
|
|
|
|
|
|
getTokenParentOfType,
|
|
|
|
|
|
getTokenTextByType,
|
|
|
|
|
|
inHtmlFlow,
|
2024-03-18 20:48:22 -07:00
|
|
|
|
isHtmlFlowComment,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
matchAndGetTokensByType,
|
2024-03-18 20:48:22 -07:00
|
|
|
|
nonContentTokens,
|
2024-01-06 20:47:01 -08:00
|
|
|
|
tokenIfType
|
2023-01-20 04:10:18 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2023-01-20 04:10:18 +00:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/cache.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/cache.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const map = new Map();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
module.exports.set = (keyValuePairs) => {
|
|
|
|
|
|
for (const [ key, value ] of Object.entries(keyValuePairs)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
map.set(key, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
module.exports.clear = () => map.clear();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
module.exports.codeBlockAndSpanRanges =
|
|
|
|
|
|
() => map.get("codeBlockAndSpanRanges");
|
|
|
|
|
|
module.exports.flattenedLists =
|
|
|
|
|
|
() => map.get("flattenedLists");
|
|
|
|
|
|
module.exports.lineMetadata =
|
|
|
|
|
|
() => map.get("lineMetadata");
|
|
|
|
|
|
module.exports.referenceLinkImageData =
|
|
|
|
|
|
() => map.get("referenceLinkImageData");
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-11-10 21:48:15 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib/constants.js":
|
|
|
|
|
|
/*!***************************!*\
|
|
|
|
|
|
!*** ../lib/constants.js ***!
|
|
|
|
|
|
\***************************/
|
|
|
|
|
|
/***/ ((module) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 19:47:15 -08:00
|
|
|
|
module.exports.deprecatedRuleNames = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports.fixableRuleNames = [
|
|
|
|
|
|
"MD004", "MD005", "MD007", "MD009", "MD010", "MD011",
|
|
|
|
|
|
"MD012", "MD014", "MD018", "MD019", "MD020", "MD021",
|
|
|
|
|
|
"MD022", "MD023", "MD026", "MD027", "MD030", "MD031",
|
|
|
|
|
|
"MD032", "MD034", "MD037", "MD038", "MD039", "MD044",
|
2024-06-01 21:32:10 -07:00
|
|
|
|
"MD047", "MD049", "MD050", "MD051", "MD053", "MD054",
|
|
|
|
|
|
"MD058"
|
2024-02-17 15:46:13 -08:00
|
|
|
|
];
|
2021-11-10 21:48:15 -08:00
|
|
|
|
module.exports.homepage = "https://github.com/DavidAnson/markdownlint";
|
2024-03-20 20:44:38 -07:00
|
|
|
|
module.exports.version = "0.34.0";
|
2021-11-10 21:48:15 -08:00
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/markdownlint.js":
|
|
|
|
|
|
/*!******************************!*\
|
|
|
|
|
|
!*** ../lib/markdownlint.js ***!
|
|
|
|
|
|
\******************************/
|
2022-06-02 21:42:48 -07:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
2021-01-05 20:55:09 -08:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const path = __webpack_require__(/*! node:path */ "?9a52");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { promisify } = __webpack_require__(/*! node:util */ "?39e5");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const markdownit = __webpack_require__(/*! markdown-it */ "markdown-it");
|
|
|
|
|
|
const micromark = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2023-11-09 19:47:15 -08:00
|
|
|
|
// const { deprecatedRuleNames } = require("./constants");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const rules = __webpack_require__(/*! ./rules */ "../lib/rules.js");
|
|
|
|
|
|
const helpers = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const cache = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-02-11 22:16:07 -08:00
|
|
|
|
// @ts-ignore
|
2023-11-05 20:13:12 -08:00
|
|
|
|
// eslint-disable-next-line camelcase, no-inline-comments, no-undef
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const dynamicRequire = (typeof require === "undefined") ? __webpack_require__("../lib sync recursive") : /* c8 ignore next */ require;
|
2021-02-11 22:16:07 -08:00
|
|
|
|
// Capture native require implementation for dynamic loading of modules
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Validate the list of rules for structure and reuse.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
2021-12-11 21:44:25 -08:00
|
|
|
|
* @param {boolean} synchronous Whether to execute synchronously.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @returns {Error | null} Error message if validation fails.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
*/
|
2021-12-11 21:44:25 -08:00
|
|
|
|
function validateRuleList(ruleList, synchronous) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let result = null;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (ruleList.length === rules.length) {
|
|
|
|
|
|
// No need to validate if only using built-in rules
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const allIds = {};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const [ index, rule ] of ruleList.entries()) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const customIndex = index - rules.length;
|
2024-04-20 21:23:06 -07:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
2024-03-09 16:17:50 -08:00
|
|
|
|
function newError(property, value) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return new Error(
|
2024-03-09 16:17:50 -08:00
|
|
|
|
`Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const property of [ "names", "tags" ]) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const value = rule[property];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (!result &&
|
|
|
|
|
|
(!value || !Array.isArray(value) || (value.length === 0) ||
|
|
|
|
|
|
!value.every(helpers.isString) || value.some(helpers.isEmptyString))) {
|
2024-03-09 16:17:50 -08:00
|
|
|
|
result = newError(property, value);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const propertyInfo of [
|
|
|
|
|
|
[ "description", "string" ],
|
|
|
|
|
|
[ "function", "function" ]
|
|
|
|
|
|
]) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const property = propertyInfo[0];
|
|
|
|
|
|
const value = rule[property];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (!result && (!value || (typeof value !== propertyInfo[1]))) {
|
2024-03-09 16:17:50 -08:00
|
|
|
|
result = newError(property, value);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-03-09 16:17:50 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!result &&
|
|
|
|
|
|
(rule.parser !== undefined) &&
|
|
|
|
|
|
(rule.parser !== "markdownit") &&
|
|
|
|
|
|
!((customIndex < 0) && (rule.parser === "micromark")) &&
|
|
|
|
|
|
(rule.parser !== "none")
|
|
|
|
|
|
) {
|
|
|
|
|
|
result = newError("parser", rule.parser);
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!result &&
|
|
|
|
|
|
rule.information &&
|
|
|
|
|
|
!helpers.isUrl(rule.information)
|
|
|
|
|
|
) {
|
2024-03-09 16:17:50 -08:00
|
|
|
|
result = newError("information", rule.information);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!result &&
|
|
|
|
|
|
(rule.asynchronous !== undefined) &&
|
|
|
|
|
|
(typeof rule.asynchronous !== "boolean")
|
|
|
|
|
|
) {
|
2024-03-09 16:17:50 -08:00
|
|
|
|
result = newError("asynchronous", rule.asynchronous);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
if (!result && rule.asynchronous && synchronous) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
result = new Error(
|
|
|
|
|
|
"Custom rule " + rule.names.join("/") + " at index " + customIndex +
|
|
|
|
|
|
" is asynchronous and can not be used in a synchronous context."
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
if (!result) {
|
|
|
|
|
|
for (const name of rule.names) {
|
|
|
|
|
|
const nameUpper = name.toUpperCase();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (!result && (allIds[nameUpper] !== undefined)) {
|
|
|
|
|
|
result = new Error("Name '" + name + "' of custom rule at index " +
|
|
|
|
|
|
customIndex + " is already used as a name or tag.");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
allIds[nameUpper] = true;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const tag of rule.tags) {
|
|
|
|
|
|
const tagUpper = tag.toUpperCase();
|
|
|
|
|
|
if (!result && allIds[tagUpper]) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
result = new Error("Tag '" + tag + "' of custom rule at index " +
|
|
|
|
|
|
customIndex + " is already used as a name.");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
allIds[tagUpper] = false;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return result;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Creates a LintResults instance with toString for pretty display.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
|
|
|
|
|
* @returns {LintResults} New LintResults instance.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function newResults(ruleList) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lintResults = {};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function toString(useAlias) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let ruleNameToRule = null;
|
|
|
|
|
|
const results = [];
|
|
|
|
|
|
const keys = Object.keys(lintResults);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
keys.sort();
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const file of keys) {
|
|
|
|
|
|
const fileResults = lintResults[file];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (Array.isArray(fileResults)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const result of fileResults) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const ruleMoniker = result.ruleNames ?
|
|
|
|
|
|
result.ruleNames.join("/") :
|
|
|
|
|
|
(result.ruleName + "/" + result.ruleAlias);
|
|
|
|
|
|
results.push(
|
|
|
|
|
|
file + ": " +
|
|
|
|
|
|
result.lineNumber + ": " +
|
|
|
|
|
|
ruleMoniker + " " +
|
|
|
|
|
|
result.ruleDescription +
|
|
|
|
|
|
(result.errorDetail ?
|
|
|
|
|
|
" [" + result.errorDetail + "]" :
|
|
|
|
|
|
"") +
|
|
|
|
|
|
(result.errorContext ?
|
|
|
|
|
|
" [Context: \"" + result.errorContext + "\"]" :
|
|
|
|
|
|
""));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (!ruleNameToRule) {
|
|
|
|
|
|
ruleNameToRule = {};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const rule of ruleList) {
|
|
|
|
|
|
const ruleName = rule.names[0].toUpperCase();
|
|
|
|
|
|
ruleNameToRule[ruleName] = rule;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const [ ruleName, ruleResults ] of Object.entries(fileResults)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const rule = ruleNameToRule[ruleName.toUpperCase()];
|
|
|
|
|
|
for (const lineNumber of ruleResults) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const nameIndex = Math.min(useAlias ? 1 : 0, rule.names.length - 1);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const result =
|
|
|
|
|
|
file + ": " +
|
|
|
|
|
|
lineNumber + ": " +
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
rule.names[nameIndex] + " " +
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
rule.description;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
results.push(result);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-09-13 21:15:11 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return results.join("\n");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
Object.defineProperty(lintResults, "toString", { "value": toString });
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return lintResults;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Remove front matter (if present at beginning of content).
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} content Markdown content.
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {RegExp | null} frontMatter Regular expression to match front matter.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {Object} Trimmed content and front matter lines.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function removeFrontMatter(content, frontMatter) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let frontMatterLines = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (frontMatter) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const frontMatterMatch = content.match(frontMatter);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (frontMatterMatch && !frontMatterMatch.index) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const contentMatched = frontMatterMatch[0];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
content = content.slice(contentMatched.length);
|
|
|
|
|
|
frontMatterLines = contentMatched.split(helpers.newLineRe);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((frontMatterLines.length > 0) &&
|
|
|
|
|
|
(frontMatterLines[frontMatterLines.length - 1] === "")) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
frontMatterLines.length--;
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
"content": content,
|
|
|
|
|
|
"frontMatterLines": frontMatterLines
|
|
|
|
|
|
};
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
2022-06-09 23:56:44 -07:00
|
|
|
|
* Freeze all freeze-able members of a token and its children.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {MarkdownItToken} token A markdown-it token.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function freezeToken(token) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (token.attrs) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const attr of token.attrs) {
|
|
|
|
|
|
Object.freeze(attr);
|
2022-06-09 23:56:44 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
Object.freeze(token.attrs);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (token.children) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const child of token.children) {
|
|
|
|
|
|
freezeToken(child);
|
2022-06-09 23:56:44 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
Object.freeze(token.children);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (token.map) {
|
|
|
|
|
|
Object.freeze(token.map);
|
|
|
|
|
|
}
|
|
|
|
|
|
Object.freeze(token);
|
2022-06-09 23:56:44 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-09 23:56:44 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Annotate tokens with line/lineNumber and freeze them.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
*
|
|
|
|
|
|
* @param {MarkdownItToken[]} tokens Array of markdown-it tokens.
|
|
|
|
|
|
* @param {string[]} lines Lines of Markdown content.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2022-06-09 23:56:44 -07:00
|
|
|
|
function annotateAndFreezeTokens(tokens, lines) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let trMap = null;
|
|
|
|
|
|
for (const token of tokens) {
|
|
|
|
|
|
// Provide missing maps for table content
|
|
|
|
|
|
if (token.type === "tr_open") {
|
|
|
|
|
|
trMap = token.map;
|
|
|
|
|
|
} else if (token.type === "tr_close") {
|
|
|
|
|
|
trMap = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!token.map && trMap) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
token.map = [ ...trMap ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
// Update token metadata
|
|
|
|
|
|
if (token.map) {
|
|
|
|
|
|
token.line = lines[token.map[0]];
|
|
|
|
|
|
token.lineNumber = token.map[0] + 1;
|
|
|
|
|
|
// Trim bottom of token to exclude whitespace lines
|
2024-02-17 15:46:13 -08:00
|
|
|
|
while (token.map[1] && !((lines[token.map[1] - 1] || "").trim())) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
token.map[1]--;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
// Annotate children with lineNumber
|
|
|
|
|
|
if (token.children) {
|
|
|
|
|
|
const codeSpanExtraLines = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (token.children.some((child) => child.type === "code_inline")) {
|
|
|
|
|
|
helpers.forEachInlineCodeSpan(token.content, (code) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
codeSpanExtraLines.push(code.split(helpers.newLineRe).length - 1);
|
|
|
|
|
|
});
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let lineNumber = token.lineNumber;
|
|
|
|
|
|
for (const child of token.children) {
|
|
|
|
|
|
child.lineNumber = lineNumber;
|
|
|
|
|
|
child.line = lines[lineNumber - 1];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lineNumber++;
|
|
|
|
|
|
} else if (child.type === "code_inline") {
|
|
|
|
|
|
lineNumber += codeSpanExtraLines.shift();
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
freezeToken(token);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
Object.freeze(tokens);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Map rule names/tags to canonical rule name.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
|
|
|
|
|
* @returns {Object.<string, string[]>} Map of alias to rule name.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function mapAliasToRuleNames(ruleList) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const aliasToRuleNames = {};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// const tagToRuleNames = {};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const rule of ruleList) {
|
|
|
|
|
|
const ruleName = rule.names[0].toUpperCase();
|
2019-10-02 20:10:42 -07:00
|
|
|
|
// The following is useful for updating README.md:
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// console.log(
|
|
|
|
|
|
// "* **[" + ruleName + "](doc/Rules.md#" + ruleName.toLowerCase() +
|
|
|
|
|
|
// ")** *" + rule.names.slice(1).join("/") + "* - " + rule.description);
|
|
|
|
|
|
for (const name of rule.names) {
|
|
|
|
|
|
const nameUpper = name.toUpperCase();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
aliasToRuleNames[nameUpper] = [ ruleName ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
for (const tag of rule.tags) {
|
|
|
|
|
|
const tagUpper = tag.toUpperCase();
|
|
|
|
|
|
const ruleNames = aliasToRuleNames[tagUpper] || [];
|
|
|
|
|
|
ruleNames.push(ruleName);
|
|
|
|
|
|
aliasToRuleNames[tagUpper] = ruleNames;
|
|
|
|
|
|
// tagToRuleNames[tag] = ruleName;
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// The following is useful for updating README.md:
|
|
|
|
|
|
// Object.keys(tagToRuleNames).sort().forEach(function forTag(tag) {
|
|
|
|
|
|
// console.log("* **" + tag + "** - " +
|
|
|
|
|
|
// aliasToRuleNames[tag.toUpperCase()].join(", "));
|
|
|
|
|
|
// });
|
|
|
|
|
|
// @ts-ignore
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return aliasToRuleNames;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Apply (and normalize) configuration object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
|
|
|
|
|
* @param {Configuration} config Configuration object.
|
|
|
|
|
|
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
|
|
|
|
* names.
|
|
|
|
|
|
* @returns {Configuration} Effective configuration.
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const defaultKey = Object.keys(config).filter(
|
|
|
|
|
|
(key) => key.toUpperCase() === "DEFAULT"
|
|
|
|
|
|
);
|
|
|
|
|
|
const ruleDefault = (defaultKey.length === 0) || !!config[defaultKey[0]];
|
2023-11-08 19:49:02 -08:00
|
|
|
|
/** @type {Configuration} */
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const effectiveConfig = {};
|
|
|
|
|
|
for (const rule of ruleList) {
|
|
|
|
|
|
const ruleName = rule.names[0].toUpperCase();
|
|
|
|
|
|
effectiveConfig[ruleName] = ruleDefault;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// for (const ruleName of deprecatedRuleNames) {
|
|
|
|
|
|
// effectiveConfig[ruleName] = false;
|
|
|
|
|
|
// }
|
|
|
|
|
|
for (const key of Object.keys(config)) {
|
|
|
|
|
|
let value = config[key];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (value) {
|
|
|
|
|
|
if (!(value instanceof Object)) {
|
|
|
|
|
|
value = {};
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value = false;
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const keyUpper = key.toUpperCase();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const ruleName of (aliasToRuleNames[keyUpper] || [])) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
effectiveConfig[ruleName] = value;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return effectiveConfig;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-06-05 22:32:22 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Parse the content of a configuration file.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} name Name of the configuration file.
|
|
|
|
|
|
* @param {string} content Configuration content.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @param {ConfigurationParser[] | null} [parsers] Parsing function(s).
|
2022-06-05 22:32:22 -07:00
|
|
|
|
* @returns {Object} Configuration object and error message.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function parseConfiguration(name, content, parsers) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let config = null;
|
|
|
|
|
|
let message = "";
|
|
|
|
|
|
const errors = [];
|
|
|
|
|
|
let index = 0;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Try each parser
|
2024-02-17 15:46:13 -08:00
|
|
|
|
(parsers || [ JSON.parse ]).every((parser) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
try {
|
|
|
|
|
|
config = parser(content);
|
|
|
|
|
|
} catch (error) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
errors.push(`Parser ${index++}: ${error.message}`);
|
2022-06-05 22:32:22 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return !config;
|
|
|
|
|
|
});
|
|
|
|
|
|
// Message if unable to parse
|
|
|
|
|
|
if (!config) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
errors.unshift(`Unable to parse '${name}'`);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
message = errors.join("; ");
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
config,
|
|
|
|
|
|
message
|
2023-01-17 04:19:40 +00:00
|
|
|
|
};
|
2022-06-05 22:32:22 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Create a mapping of enabled rules per line.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
|
|
|
|
|
* @param {string[]} lines List of content lines.
|
|
|
|
|
|
* @param {string[]} frontMatterLines List of front matter lines.
|
|
|
|
|
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
2020-04-11 13:54:46 -07:00
|
|
|
|
* @param {Configuration} config Configuration object.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @param {ConfigurationParser[] | null} configParsers Configuration parsers.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
|
|
|
|
* names.
|
2020-04-11 13:54:46 -07:00
|
|
|
|
* @returns {Object} Effective configuration and enabled rules per line number.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function getEnabledRulesPerLineNumber(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
lines,
|
|
|
|
|
|
frontMatterLines,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
aliasToRuleNames) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Shared variables
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let enabledRules = {};
|
|
|
|
|
|
let capturedRules = {};
|
|
|
|
|
|
const allRuleNames = [];
|
|
|
|
|
|
const enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Helper functions
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function handleInlineConfig(input, forEachMatch, forEachLine) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const [ lineIndex, line ] of input.entries()) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (!noInlineConfig) {
|
|
|
|
|
|
let match = null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
while ((match = helpers.inlineCommentStartRe.exec(line))) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const action = match[2].toUpperCase();
|
|
|
|
|
|
const startIndex = match.index + match[1].length;
|
|
|
|
|
|
const endIndex = line.indexOf("-->", startIndex);
|
|
|
|
|
|
if (endIndex === -1) {
|
|
|
|
|
|
break;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const parameter = line.slice(startIndex, endIndex);
|
|
|
|
|
|
forEachMatch(action, parameter, lineIndex + 1);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (forEachLine) {
|
|
|
|
|
|
forEachLine();
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function configureFile(action, parameter) {
|
|
|
|
|
|
if (action === "CONFIGURE-FILE") {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { "config": parsed } = parseConfiguration(
|
|
|
|
|
|
"CONFIGURE-FILE", parameter, configParsers
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (parsed) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
config = {
|
|
|
|
|
|
...config,
|
|
|
|
|
|
...parsed
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2020-04-11 13:54:46 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function applyEnableDisable(action, parameter, state) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
state = { ...state };
|
|
|
|
|
|
const enabled = (action.startsWith("ENABLE"));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const trimmed = parameter && parameter.trim();
|
|
|
|
|
|
const items = trimmed ? trimmed.toUpperCase().split(/\s+/) : allRuleNames;
|
|
|
|
|
|
for (const nameUpper of items) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const ruleName of (aliasToRuleNames[nameUpper] || [])) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
state[ruleName] = enabled;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2020-04-11 13:54:46 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return state;
|
|
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function enableDisableFile(action, parameter) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
enabledRules = applyEnableDisable(action, parameter, enabledRules);
|
2020-04-11 13:54:46 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function captureRestoreEnableDisable(action, parameter) {
|
|
|
|
|
|
if (action === "CAPTURE") {
|
|
|
|
|
|
capturedRules = enabledRules;
|
|
|
|
|
|
} else if (action === "RESTORE") {
|
|
|
|
|
|
enabledRules = capturedRules;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((action === "ENABLE") || (action === "DISABLE")) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
enabledRules = applyEnableDisable(action, parameter, enabledRules);
|
2020-04-11 13:54:46 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function updateLineState() {
|
|
|
|
|
|
enabledRulesPerLineNumber.push(enabledRules);
|
|
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function disableLineNextLine(action, parameter, lineNumber) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const disableLine = (action === "DISABLE-LINE");
|
|
|
|
|
|
const disableNextLine = (action === "DISABLE-NEXT-LINE");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (disableLine || disableNextLine) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const nextLineNumber =
|
|
|
|
|
|
frontMatterLines.length + lineNumber + (disableNextLine ? 1 : 0);
|
|
|
|
|
|
enabledRulesPerLineNumber[nextLineNumber] =
|
|
|
|
|
|
applyEnableDisable(
|
|
|
|
|
|
action,
|
|
|
|
|
|
parameter,
|
|
|
|
|
|
enabledRulesPerLineNumber[nextLineNumber]
|
|
|
|
|
|
);
|
2020-11-24 16:37:11 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// Handle inline comments
|
2024-02-17 15:46:13 -08:00
|
|
|
|
handleInlineConfig([ lines.join("\n") ], configureFile);
|
|
|
|
|
|
const effectiveConfig = getEffectiveConfig(
|
|
|
|
|
|
ruleList, config, aliasToRuleNames);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const rule of ruleList) {
|
|
|
|
|
|
const ruleName = rule.names[0].toUpperCase();
|
|
|
|
|
|
allRuleNames.push(ruleName);
|
|
|
|
|
|
enabledRules[ruleName] = !!effectiveConfig[ruleName];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
capturedRules = enabledRules;
|
|
|
|
|
|
handleInlineConfig(lines, enableDisableFile);
|
|
|
|
|
|
handleInlineConfig(lines, captureRestoreEnableDisable, updateLineState);
|
|
|
|
|
|
handleInlineConfig(lines, disableLineNextLine);
|
|
|
|
|
|
// Return results
|
|
|
|
|
|
return {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
effectiveConfig,
|
|
|
|
|
|
enabledRulesPerLineNumber
|
2023-01-17 04:19:40 +00:00
|
|
|
|
};
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Lints a string containing Markdown content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
2023-03-12 20:49:41 -07:00
|
|
|
|
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
|
|
|
|
* names.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {string} name Identifier for the content.
|
2020-11-24 16:37:11 -08:00
|
|
|
|
* @param {string} content Markdown content.
|
|
|
|
|
|
* @param {Object} md Instance of markdown-it.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {Configuration} config Configuration object.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @param {ConfigurationParser[] | null} configParsers Configuration parsers.
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {RegExp | null} frontMatter Regular expression for front matter.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
|
|
|
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
|
|
|
|
* @param {number} resultVersion Version of the LintResults object to return.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {LintContentCallback} callback Callback (err, result) function.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function lintContent(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
aliasToRuleNames,
|
|
|
|
|
|
name,
|
|
|
|
|
|
content,
|
|
|
|
|
|
md,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
frontMatter,
|
|
|
|
|
|
handleRuleFailures,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
resultVersion,
|
|
|
|
|
|
callback) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Remove UTF-8 byte order marker (if present)
|
|
|
|
|
|
content = content.replace(/^\uFEFF/, "");
|
|
|
|
|
|
// Remove front matter
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const removeFrontMatterResult = removeFrontMatter(content, frontMatter);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { frontMatterLines } = removeFrontMatterResult;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
content = removeFrontMatterResult.content;
|
|
|
|
|
|
// Get enabled rules per line (with HTML comments present)
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { effectiveConfig, enabledRulesPerLineNumber } =
|
|
|
|
|
|
getEnabledRulesPerLineNumber(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
content.split(helpers.newLineRe),
|
|
|
|
|
|
frontMatterLines,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
aliasToRuleNames
|
|
|
|
|
|
);
|
2023-01-15 21:41:22 -08:00
|
|
|
|
// Parse content into parser tokens
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const markdownitTokens = md.parse(content, {});
|
|
|
|
|
|
const micromarkTokens = micromark.parse(content);
|
2023-01-15 21:41:22 -08:00
|
|
|
|
// Hide the content of HTML comments from rules
|
2023-01-17 04:19:40 +00:00
|
|
|
|
content = helpers.clearHtmlCommentText(content);
|
2023-01-15 21:41:22 -08:00
|
|
|
|
// Parse content into lines and update markdown-it tokens
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lines = content.split(helpers.newLineRe);
|
2023-01-15 21:41:22 -08:00
|
|
|
|
annotateAndFreezeTokens(markdownitTokens, lines);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Create (frozen) parameters for rules
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/** @type {MarkdownParsers} */
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const parsersMarkdownIt = Object.freeze({
|
2023-01-21 19:16:07 -08:00
|
|
|
|
"markdownit": Object.freeze({
|
|
|
|
|
|
"tokens": markdownitTokens
|
2024-03-09 16:17:50 -08:00
|
|
|
|
})
|
|
|
|
|
|
});
|
|
|
|
|
|
/** @type {MarkdownParsers} */
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const parsersMicromark = Object.freeze({
|
2023-01-21 19:16:07 -08:00
|
|
|
|
"micromark": Object.freeze({
|
|
|
|
|
|
"tokens": micromarkTokens
|
|
|
|
|
|
})
|
2023-01-15 21:41:22 -08:00
|
|
|
|
});
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/** @type {MarkdownParsers} */
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const parsersNone = Object.freeze({});
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const paramsBase = {
|
|
|
|
|
|
name,
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parsers": parsersMarkdownIt,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"lines": Object.freeze(lines),
|
|
|
|
|
|
"frontMatterLines": Object.freeze(frontMatterLines)
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const lineMetadata =
|
|
|
|
|
|
helpers.getLineMetadata(paramsBase);
|
|
|
|
|
|
const codeBlockAndSpanRanges =
|
|
|
|
|
|
helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata);
|
|
|
|
|
|
const flattenedLists =
|
2024-03-09 16:17:50 -08:00
|
|
|
|
helpers.flattenLists(markdownitTokens);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const referenceLinkImageData =
|
2024-03-09 16:17:50 -08:00
|
|
|
|
helpers.getReferenceLinkImageData(micromarkTokens);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
cache.set({
|
2024-01-06 20:47:01 -08:00
|
|
|
|
codeBlockAndSpanRanges,
|
|
|
|
|
|
flattenedLists,
|
|
|
|
|
|
lineMetadata,
|
|
|
|
|
|
referenceLinkImageData
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
|
|
|
|
|
// Function to run for each rule
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let results = [];
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param {Rule} rule Rule.
|
|
|
|
|
|
* @returns {Promise<void> | null} Promise.
|
|
|
|
|
|
*/
|
|
|
|
|
|
const forRule = (rule) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Configure rule
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const ruleName = rule.names[0].toUpperCase();
|
2024-03-09 16:17:50 -08:00
|
|
|
|
const tokens = {};
|
|
|
|
|
|
let parsers = parsersNone;
|
|
|
|
|
|
if (rule.parser === undefined) {
|
|
|
|
|
|
tokens.tokens = markdownitTokens;
|
|
|
|
|
|
parsers = parsersMarkdownIt;
|
|
|
|
|
|
} else if (rule.parser === "markdownit") {
|
|
|
|
|
|
parsers = parsersMarkdownIt;
|
|
|
|
|
|
} else if (rule.parser === "micromark") {
|
|
|
|
|
|
parsers = parsersMicromark;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const params = {
|
|
|
|
|
|
...paramsBase,
|
2024-03-09 16:17:50 -08:00
|
|
|
|
...tokens,
|
|
|
|
|
|
parsers,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"config": effectiveConfig[ruleName]
|
2024-01-06 20:47:01 -08:00
|
|
|
|
};
|
2020-01-27 19:19:34 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
2023-01-17 04:19:40 +00:00
|
|
|
|
function throwError(property) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
throw new Error(
|
|
|
|
|
|
`Value of '${property}' passed to onError by '${ruleName}' is incorrect for '${name}'.`);
|
2021-12-11 21:44:25 -08:00
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
2023-01-17 04:19:40 +00:00
|
|
|
|
function onError(errorInfo) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (!errorInfo ||
|
|
|
|
|
|
!helpers.isNumber(errorInfo.lineNumber) ||
|
|
|
|
|
|
(errorInfo.lineNumber < 1) ||
|
|
|
|
|
|
(errorInfo.lineNumber > lines.length)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("lineNumber");
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lineNumber = errorInfo.lineNumber + frontMatterLines.length;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!enabledRulesPerLineNumber[lineNumber][ruleName]) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (errorInfo.detail &&
|
|
|
|
|
|
!helpers.isString(errorInfo.detail)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("detail");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (errorInfo.context &&
|
|
|
|
|
|
!helpers.isString(errorInfo.context)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("context");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (errorInfo.information &&
|
|
|
|
|
|
!helpers.isUrl(errorInfo.information)) {
|
2023-07-11 21:44:45 -07:00
|
|
|
|
throwError("information");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (errorInfo.range &&
|
|
|
|
|
|
(!Array.isArray(errorInfo.range) ||
|
|
|
|
|
|
(errorInfo.range.length !== 2) ||
|
|
|
|
|
|
!helpers.isNumber(errorInfo.range[0]) ||
|
|
|
|
|
|
(errorInfo.range[0] < 1) ||
|
|
|
|
|
|
!helpers.isNumber(errorInfo.range[1]) ||
|
|
|
|
|
|
(errorInfo.range[1] < 1) ||
|
|
|
|
|
|
((errorInfo.range[0] + errorInfo.range[1] - 1) >
|
|
|
|
|
|
lines[errorInfo.lineNumber - 1].length))) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("range");
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fixInfo = errorInfo.fixInfo;
|
|
|
|
|
|
const cleanFixInfo = {};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (fixInfo) {
|
|
|
|
|
|
if (!helpers.isObject(fixInfo)) {
|
|
|
|
|
|
throwError("fixInfo");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (fixInfo.lineNumber !== undefined) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((!helpers.isNumber(fixInfo.lineNumber) ||
|
|
|
|
|
|
(fixInfo.lineNumber < 1) ||
|
|
|
|
|
|
(fixInfo.lineNumber > lines.length))) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("fixInfo.lineNumber");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
cleanFixInfo.lineNumber =
|
|
|
|
|
|
fixInfo.lineNumber + frontMatterLines.length;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const effectiveLineNumber = fixInfo.lineNumber || errorInfo.lineNumber;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (fixInfo.editColumn !== undefined) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((!helpers.isNumber(fixInfo.editColumn) ||
|
|
|
|
|
|
(fixInfo.editColumn < 1) ||
|
|
|
|
|
|
(fixInfo.editColumn >
|
|
|
|
|
|
lines[effectiveLineNumber - 1].length + 1))) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("fixInfo.editColumn");
|
|
|
|
|
|
}
|
|
|
|
|
|
cleanFixInfo.editColumn = fixInfo.editColumn;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (fixInfo.deleteCount !== undefined) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((!helpers.isNumber(fixInfo.deleteCount) ||
|
|
|
|
|
|
(fixInfo.deleteCount < -1) ||
|
|
|
|
|
|
(fixInfo.deleteCount >
|
|
|
|
|
|
lines[effectiveLineNumber - 1].length))) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
throwError("fixInfo.deleteCount");
|
|
|
|
|
|
}
|
|
|
|
|
|
cleanFixInfo.deleteCount = fixInfo.deleteCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (fixInfo.insertText !== undefined) {
|
|
|
|
|
|
if (!helpers.isString(fixInfo.insertText)) {
|
|
|
|
|
|
throwError("fixInfo.insertText");
|
|
|
|
|
|
}
|
|
|
|
|
|
cleanFixInfo.insertText = fixInfo.insertText;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const information = errorInfo.information || rule.information;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
results.push({
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lineNumber,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"ruleName": rule.names[0],
|
|
|
|
|
|
"ruleNames": rule.names,
|
|
|
|
|
|
"ruleDescription": rule.description,
|
2023-07-11 21:44:45 -07:00
|
|
|
|
"ruleInformation": information ? information.href : null,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"errorDetail": errorInfo.detail || null,
|
|
|
|
|
|
"errorContext": errorInfo.context || null,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"errorRange": errorInfo.range ? [ ...errorInfo.range ] : null,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"fixInfo": fixInfo ? cleanFixInfo : null
|
|
|
|
|
|
});
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Call (possibly external) rule function to report errors
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const catchCallsOnError = (error) => onError({
|
2024-01-06 20:47:01 -08:00
|
|
|
|
"lineNumber": 1,
|
|
|
|
|
|
"detail": `This rule threw an exception: ${error.message || error}`
|
|
|
|
|
|
});
|
|
|
|
|
|
const invokeRuleFunction = () => rule.function(params, onError);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (rule.asynchronous) {
|
|
|
|
|
|
// Asynchronous rule, ensure it returns a Promise
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const ruleFunctionPromise =
|
|
|
|
|
|
Promise.resolve().then(invokeRuleFunction);
|
|
|
|
|
|
return handleRuleFailures ?
|
|
|
|
|
|
ruleFunctionPromise.catch(catchCallsOnError) :
|
|
|
|
|
|
ruleFunctionPromise;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// Synchronous rule
|
2019-10-02 20:10:42 -07:00
|
|
|
|
try {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
invokeRuleFunction();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
if (handleRuleFailures) {
|
|
|
|
|
|
catchCallsOnError(error);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return null;
|
2024-03-20 20:24:55 -07:00
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function formatResults() {
|
|
|
|
|
|
// Sort results by rule name by line number
|
2024-02-17 15:46:13 -08:00
|
|
|
|
results.sort((a, b) => (
|
|
|
|
|
|
a.ruleName.localeCompare(b.ruleName) ||
|
|
|
|
|
|
a.lineNumber - b.lineNumber
|
|
|
|
|
|
));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (resultVersion < 3) {
|
|
|
|
|
|
// Remove fixInfo and multiple errors for the same rule and line number
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const noPrevious = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"ruleName": null,
|
|
|
|
|
|
"lineNumber": -1
|
|
|
|
|
|
};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
results = results.filter((error, index, array) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
delete error.fixInfo;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const previous = array[index - 1] || noPrevious;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (
|
|
|
|
|
|
(error.ruleName !== previous.ruleName) ||
|
|
|
|
|
|
(error.lineNumber !== previous.lineNumber)
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
2021-12-04 17:02:11 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (resultVersion === 0) {
|
|
|
|
|
|
// Return a dictionary of rule->[line numbers]
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const dictionary = {};
|
|
|
|
|
|
for (const error of results) {
|
|
|
|
|
|
const ruleLines = dictionary[error.ruleName] || [];
|
|
|
|
|
|
ruleLines.push(error.lineNumber);
|
|
|
|
|
|
dictionary[error.ruleName] = ruleLines;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// @ts-ignore
|
2023-01-17 04:19:40 +00:00
|
|
|
|
results = dictionary;
|
|
|
|
|
|
} else if (resultVersion === 1) {
|
|
|
|
|
|
// Use ruleAlias instead of ruleNames
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const error of results) {
|
|
|
|
|
|
error.ruleAlias = error.ruleNames[1] || error.ruleName;
|
|
|
|
|
|
delete error.ruleNames;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// resultVersion 2 or 3: Remove unwanted ruleName
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const error of results) {
|
|
|
|
|
|
delete error.ruleName;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2021-12-04 17:02:11 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return results;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Run all rules
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const ruleListAsync = ruleList.filter((rule) => rule.asynchronous);
|
|
|
|
|
|
const ruleListSync = ruleList.filter((rule) => !rule.asynchronous);
|
|
|
|
|
|
const ruleListAsyncFirst = [
|
|
|
|
|
|
...ruleListAsync,
|
|
|
|
|
|
...ruleListSync
|
|
|
|
|
|
];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const callbackSuccess = () => callback(null, formatResults());
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const callbackError =
|
|
|
|
|
|
(error) => callback(error instanceof Error ? error : new Error(error));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
try {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const ruleResults = ruleListAsyncFirst.map(forRule);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (ruleListAsync.length > 0) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
Promise.all(ruleResults.slice(0, ruleListAsync.length))
|
|
|
|
|
|
.then(callbackSuccess)
|
|
|
|
|
|
.catch(callbackError);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
callbackSuccess();
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
callbackError(error);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
cache.clear();
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Lints a file containing Markdown content.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Rule[]} ruleList List of rules.
|
2023-03-12 20:49:41 -07:00
|
|
|
|
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
|
|
|
|
* names.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {string} file Path of file to lint.
|
2020-11-24 16:37:11 -08:00
|
|
|
|
* @param {Object} md Instance of markdown-it.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {Configuration} config Configuration object.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @param {ConfigurationParser[] | null} configParsers Configuration parsers.
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {RegExp | null} frontMatter Regular expression for front matter.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
|
|
|
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
|
|
|
|
* @param {number} resultVersion Version of the LintResults object to return.
|
2021-08-12 19:38:03 -07:00
|
|
|
|
* @param {Object} fs File system implementation.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {boolean} synchronous Whether to execute synchronously.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {LintContentCallback} callback Callback (err, result) function.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
function lintFile(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
aliasToRuleNames,
|
|
|
|
|
|
file,
|
|
|
|
|
|
md,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
frontMatter,
|
|
|
|
|
|
handleRuleFailures,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
resultVersion,
|
|
|
|
|
|
fs,
|
|
|
|
|
|
synchronous,
|
|
|
|
|
|
callback) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function lintContentWrapper(err, content) {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
return callback(err);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return lintContent(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
aliasToRuleNames,
|
|
|
|
|
|
file,
|
|
|
|
|
|
content,
|
|
|
|
|
|
md,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
frontMatter,
|
|
|
|
|
|
handleRuleFailures,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
resultVersion,
|
|
|
|
|
|
callback
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
// Make a/synchronous call to read file
|
|
|
|
|
|
if (synchronous) {
|
|
|
|
|
|
lintContentWrapper(null, fs.readFileSync(file, "utf8"));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
fs.readFile(file, "utf8", lintContentWrapper);
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-01-27 19:19:34 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Lint files and strings specified in the Options object.
|
|
|
|
|
|
*
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {Options | null} options Options object.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {boolean} synchronous Whether to execute synchronously.
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {LintCallback} callback Callback (err, result) function.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2019-10-02 20:10:42 -07:00
|
|
|
|
function lintInput(options, synchronous, callback) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Normalize inputs
|
|
|
|
|
|
options = options || {};
|
|
|
|
|
|
callback = callback || function noop() {};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const customRuleList =
|
|
|
|
|
|
[ options.customRules || [] ]
|
|
|
|
|
|
.flat()
|
|
|
|
|
|
.map((rule) => ({
|
|
|
|
|
|
"names": helpers.cloneIfArray(rule.names),
|
|
|
|
|
|
"description": rule.description,
|
|
|
|
|
|
"information": helpers.cloneIfUrl(rule.information),
|
|
|
|
|
|
"tags": helpers.cloneIfArray(rule.tags),
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": rule.parser,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"asynchronous": rule.asynchronous,
|
|
|
|
|
|
"function": rule.function
|
|
|
|
|
|
}));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// eslint-disable-next-line unicorn/prefer-spread
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const ruleList = rules.concat(customRuleList);
|
|
|
|
|
|
const ruleErr = validateRuleList(ruleList, synchronous);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (ruleErr) {
|
|
|
|
|
|
callback(ruleErr);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let files = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (Array.isArray(options.files)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
files = [ ...options.files ];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
} else if (options.files) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
files = [ String(options.files) ];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const strings = options.strings || {};
|
|
|
|
|
|
const stringsKeys = Object.keys(strings);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const config = options.config || { "default": true };
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const configParsers = options.configParsers || null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const frontMatter = (options.frontMatter === undefined) ?
|
|
|
|
|
|
helpers.frontMatterRe : options.frontMatter;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const handleRuleFailures = !!options.handleRuleFailures;
|
|
|
|
|
|
const noInlineConfig = !!options.noInlineConfig;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const resultVersion = (options.resultVersion === undefined) ?
|
|
|
|
|
|
3 : options.resultVersion;
|
|
|
|
|
|
const md = markdownit({ "html": true });
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const markdownItPlugins = options.markdownItPlugins || [];
|
|
|
|
|
|
for (const plugin of markdownItPlugins) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
md.use(...plugin);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fs = options.fs || __webpack_require__(/*! node:fs */ "?d0ee");
|
|
|
|
|
|
const aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
|
|
|
|
|
const results = newResults(ruleList);
|
|
|
|
|
|
let done = false;
|
|
|
|
|
|
let concurrency = 0;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
|
|
|
|
function lintWorker() {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let currentItem = null;
|
2020-09-13 21:15:11 -07:00
|
|
|
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
2023-01-17 04:19:40 +00:00
|
|
|
|
function lintWorkerCallback(err, result) {
|
|
|
|
|
|
concurrency--;
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
done = true;
|
|
|
|
|
|
return callback(err);
|
|
|
|
|
|
}
|
|
|
|
|
|
results[currentItem] = result;
|
|
|
|
|
|
if (!synchronous) {
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
2020-09-13 21:15:11 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (done) {
|
|
|
|
|
|
// Abort for error or nothing left to do
|
|
|
|
|
|
} else if (files.length > 0) {
|
|
|
|
|
|
// Lint next file
|
|
|
|
|
|
concurrency++;
|
|
|
|
|
|
currentItem = files.shift();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
lintFile(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
aliasToRuleNames,
|
|
|
|
|
|
currentItem,
|
|
|
|
|
|
md,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
frontMatter,
|
|
|
|
|
|
handleRuleFailures,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
resultVersion,
|
|
|
|
|
|
fs,
|
|
|
|
|
|
synchronous,
|
|
|
|
|
|
lintWorkerCallback
|
|
|
|
|
|
);
|
|
|
|
|
|
} else if ((currentItem = stringsKeys.shift())) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Lint next string
|
|
|
|
|
|
concurrency++;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
lintContent(
|
|
|
|
|
|
ruleList,
|
|
|
|
|
|
aliasToRuleNames,
|
|
|
|
|
|
currentItem,
|
|
|
|
|
|
strings[currentItem] || "",
|
|
|
|
|
|
md,
|
|
|
|
|
|
config,
|
|
|
|
|
|
configParsers,
|
|
|
|
|
|
frontMatter,
|
|
|
|
|
|
handleRuleFailures,
|
|
|
|
|
|
noInlineConfig,
|
|
|
|
|
|
resultVersion,
|
|
|
|
|
|
lintWorkerCallback
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
} else if (concurrency === 0) {
|
|
|
|
|
|
// Finish
|
|
|
|
|
|
done = true;
|
|
|
|
|
|
return callback(null, results);
|
2021-12-03 22:43:58 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (synchronous) {
|
|
|
|
|
|
while (!done) {
|
|
|
|
|
|
lintWorker();
|
2021-12-03 22:43:58 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
// Testing on a Raspberry Pi 4 Model B with an artificial 5ms file access
|
|
|
|
|
|
// delay suggests that a concurrency factor of 8 can eliminate the impact
|
|
|
|
|
|
// of that delay (i.e., total time is the same as with no delay).
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
lintWorker();
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Lint specified Markdown files.
|
|
|
|
|
|
*
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {Options | null} options Configuration options.
|
2019-12-14 13:50:48 -08:00
|
|
|
|
* @param {LintCallback} callback Callback (err, result) function.
|
2019-10-02 20:10:42 -07:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function markdownlint(options, callback) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return lintInput(options, false, callback);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const markdownlintPromisify = promisify && promisify(markdownlint);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-09-13 21:15:11 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Lint specified Markdown files.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Options} options Configuration options.
|
|
|
|
|
|
* @returns {Promise<LintResults>} Results object.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function markdownlintPromise(options) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return markdownlintPromisify(options);
|
2020-09-13 21:15:11 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Lint specified Markdown files synchronously.
|
|
|
|
|
|
*
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @param {Options | null} options Configuration options.
|
2019-12-14 13:50:48 -08:00
|
|
|
|
* @returns {LintResults} Results object.
|
2019-10-02 20:10:42 -07:00
|
|
|
|
*/
|
|
|
|
|
|
function markdownlintSync(options) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let results = null;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
lintInput(options, true, function callback(error, res) {
|
|
|
|
|
|
if (error) {
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
results = res;
|
|
|
|
|
|
});
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return results;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2021-08-12 20:43:18 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Resolve referenced "extends" path in a configuration file
|
|
|
|
|
|
* using path.resolve() with require.resolve() as a fallback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} configFile Configuration file name.
|
|
|
|
|
|
* @param {string} referenceId Referenced identifier to resolve.
|
|
|
|
|
|
* @param {Object} fs File system implementation.
|
2022-06-11 22:40:45 -07:00
|
|
|
|
* @param {ResolveConfigExtendsCallback} callback Callback (err, result)
|
2021-08-12 20:43:18 -07:00
|
|
|
|
* function.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const configFileDirname = path.dirname(configFile);
|
|
|
|
|
|
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
fs.access(resolvedExtendsFile, (err) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (err) {
|
|
|
|
|
|
// Not a file, try require.resolve
|
|
|
|
|
|
try {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return callback(null, dynamicRequire.resolve(
|
|
|
|
|
|
referenceId,
|
|
|
|
|
|
{ "paths": [ configFileDirname ] }
|
|
|
|
|
|
));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} catch {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Unable to resolve, use resolvedExtendsFile
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return callback(null, resolvedExtendsFile);
|
|
|
|
|
|
});
|
2021-08-12 20:43:18 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-11-24 16:37:11 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Resolve referenced "extends" path in a configuration file
|
|
|
|
|
|
* using path.resolve() with require.resolve() as a fallback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} configFile Configuration file name.
|
|
|
|
|
|
* @param {string} referenceId Referenced identifier to resolve.
|
2021-08-12 19:38:03 -07:00
|
|
|
|
* @param {Object} fs File system implementation.
|
2020-11-24 16:37:11 -08:00
|
|
|
|
* @returns {string} Resolved path to file.
|
|
|
|
|
|
*/
|
2021-08-12 20:43:18 -07:00
|
|
|
|
function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const configFileDirname = path.dirname(configFile);
|
|
|
|
|
|
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
try {
|
|
|
|
|
|
fs.accessSync(resolvedExtendsFile);
|
2020-11-24 16:37:11 -08:00
|
|
|
|
return resolvedExtendsFile;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} catch {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Not a file, try require.resolve
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return dynamicRequire.resolve(
|
|
|
|
|
|
referenceId,
|
|
|
|
|
|
{ "paths": [ configFileDirname ] }
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} catch {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Unable to resolve, return resolvedExtendsFile
|
|
|
|
|
|
}
|
|
|
|
|
|
return resolvedExtendsFile;
|
2020-11-24 16:37:11 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-04-03 22:59:06 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Extend specified configuration object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Configuration} config Configuration object.
|
|
|
|
|
|
* @param {string} file Configuration file name.
|
|
|
|
|
|
* @param {ConfigurationParser[]} parsers Parsing
|
|
|
|
|
|
* function(s).
|
|
|
|
|
|
* @param {Object} fs File system implementation.
|
|
|
|
|
|
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function extendConfig(config, file, parsers, fs, callback) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const configExtends = config.extends;
|
2023-04-03 22:59:06 -07:00
|
|
|
|
if (configExtends) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return resolveConfigExtends(
|
|
|
|
|
|
file,
|
|
|
|
|
|
helpers.expandTildePath(configExtends, __webpack_require__(/*! node:os */ "?e6c4")),
|
|
|
|
|
|
fs,
|
|
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
|
|
|
|
(_, resolvedExtends) => readConfig(
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
resolvedExtends,
|
|
|
|
|
|
parsers,
|
|
|
|
|
|
fs,
|
|
|
|
|
|
(err, extendsConfig) => {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
return callback(err);
|
|
|
|
|
|
}
|
|
|
|
|
|
const result = {
|
|
|
|
|
|
...extendsConfig,
|
|
|
|
|
|
...config
|
|
|
|
|
|
};
|
|
|
|
|
|
delete result.extends;
|
|
|
|
|
|
return callback(null, result);
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
2023-04-03 22:59:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
return callback(null, config);
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const extendConfigPromisify = promisify && promisify(extendConfig);
|
2023-04-03 22:59:06 -07:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Extend specified configuration object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {Configuration} config Configuration object.
|
|
|
|
|
|
* @param {string} file Configuration file name.
|
|
|
|
|
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
|
|
|
|
* @param {Object} [fs] File system implementation.
|
|
|
|
|
|
* @returns {Promise<Configuration>} Configuration object.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function extendConfigPromise(config, file, parsers, fs) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return extendConfigPromisify(config, file, parsers, fs);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Read specified configuration file.
|
|
|
|
|
|
*
|
2019-12-14 13:50:48 -08:00
|
|
|
|
* @param {string} file Configuration file name.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
|
|
|
|
|
* function(s).
|
2021-08-12 19:38:03 -07:00
|
|
|
|
* @param {Object} [fs] File system implementation.
|
2020-01-27 19:19:34 -08:00
|
|
|
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
2019-10-02 20:10:42 -07:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2021-08-12 19:38:03 -07:00
|
|
|
|
function readConfig(file, parsers, fs, callback) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!callback) {
|
|
|
|
|
|
if (fs) {
|
|
|
|
|
|
callback = fs;
|
|
|
|
|
|
fs = null;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
callback = parsers;
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
parsers = null;
|
2021-08-12 19:38:03 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (!fs) {
|
|
|
|
|
|
fs = __webpack_require__(/*! node:fs */ "?d0ee");
|
|
|
|
|
|
}
|
|
|
|
|
|
// Read file
|
2023-04-03 22:59:06 -07:00
|
|
|
|
file = helpers.expandTildePath(file, __webpack_require__(/*! node:os */ "?e6c4"));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fs.readFile(file, "utf8", (err, content) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (err) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return callback(err);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Try to parse file
|
|
|
|
|
|
// @ts-ignore
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { config, message } = parseConfiguration(file, content, parsers);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!config) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return callback(new Error(message));
|
|
|
|
|
|
}
|
|
|
|
|
|
// Extend configuration
|
|
|
|
|
|
// @ts-ignore
|
2023-04-03 22:59:06 -07:00
|
|
|
|
return extendConfig(config, file, parsers, fs, callback);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const readConfigPromisify = promisify && promisify(readConfig);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-09-13 21:15:11 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Read specified configuration file.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} file Configuration file name.
|
|
|
|
|
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
2021-08-12 19:38:03 -07:00
|
|
|
|
* @param {Object} [fs] File system implementation.
|
2020-09-13 21:15:11 -07:00
|
|
|
|
* @returns {Promise<Configuration>} Configuration object.
|
|
|
|
|
|
*/
|
2021-08-12 19:38:03 -07:00
|
|
|
|
function readConfigPromise(file, parsers, fs) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
return readConfigPromisify(file, parsers, fs);
|
2020-09-13 21:15:11 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Read specified configuration file synchronously.
|
|
|
|
|
|
*
|
2019-12-14 13:50:48 -08:00
|
|
|
|
* @param {string} file Configuration file name.
|
|
|
|
|
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
2021-08-12 19:38:03 -07:00
|
|
|
|
* @param {Object} [fs] File system implementation.
|
2019-12-14 13:50:48 -08:00
|
|
|
|
* @returns {Configuration} Configuration object.
|
2021-08-22 18:03:26 -07:00
|
|
|
|
* @throws An Error if processing fails.
|
2019-10-02 20:10:42 -07:00
|
|
|
|
*/
|
2021-08-12 19:38:03 -07:00
|
|
|
|
function readConfigSync(file, parsers, fs) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!fs) {
|
|
|
|
|
|
fs = __webpack_require__(/*! node:fs */ "?d0ee");
|
|
|
|
|
|
}
|
|
|
|
|
|
// Read file
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const os = __webpack_require__(/*! node:os */ "?e6c4");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
file = helpers.expandTildePath(file, os);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const content = fs.readFileSync(file, "utf8");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Try to parse file
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { config, message } = parseConfiguration(file, content, parsers);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!config) {
|
|
|
|
|
|
throw new Error(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
// Extend configuration
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const configExtends = config.extends;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (configExtends) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
delete config.extends;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const resolvedExtends = resolveConfigExtendsSync(
|
|
|
|
|
|
file,
|
|
|
|
|
|
helpers.expandTildePath(configExtends, os),
|
|
|
|
|
|
fs
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
return {
|
|
|
|
|
|
...readConfigSync(resolvedExtends, parsers, fs),
|
|
|
|
|
|
...config
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return config;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-10-20 20:16:49 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Gets the (semantic) version of the library.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @returns {string} SemVer string.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getVersion() {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
return (__webpack_require__(/*! ./constants */ "../lib/constants.js").version);
|
2020-10-20 20:16:49 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2020-09-13 21:15:11 -07:00
|
|
|
|
// Export a/synchronous/Promise APIs
|
2019-10-02 20:10:42 -07:00
|
|
|
|
markdownlint.sync = markdownlintSync;
|
|
|
|
|
|
markdownlint.readConfig = readConfig;
|
|
|
|
|
|
markdownlint.readConfigSync = readConfigSync;
|
2020-10-20 20:16:49 -07:00
|
|
|
|
markdownlint.getVersion = getVersion;
|
2020-09-13 21:15:11 -07:00
|
|
|
|
markdownlint.promises = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"markdownlint": markdownlintPromise,
|
2023-04-03 22:59:06 -07:00
|
|
|
|
"extendConfig": extendConfigPromise,
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"readConfig": readConfigPromise
|
2020-09-13 21:15:11 -07:00
|
|
|
|
};
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = markdownlint;
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Type declarations
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Function to implement rule logic.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback RuleFunction
|
|
|
|
|
|
* @param {RuleParams} params Rule parameters.
|
|
|
|
|
|
* @param {RuleOnError} onError Error-reporting callback.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/* eslint-disable jsdoc/valid-types */
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Rule parameters.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} RuleParams
|
|
|
|
|
|
* @property {string} name File/string name.
|
2024-02-27 20:42:09 -08:00
|
|
|
|
* @property {MarkdownParsers} parsers Markdown parser data.
|
2024-03-09 16:17:50 -08:00
|
|
|
|
* @property {readonly string[]} lines File/string lines.
|
|
|
|
|
|
* @property {readonly string[]} frontMatterLines Front matter lines.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* @property {RuleConfiguration} config Rule configuration.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/* eslint-enable jsdoc/valid-types */
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
/**
|
2024-02-27 20:42:09 -08:00
|
|
|
|
* Markdown parser data.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} MarkdownParsers
|
2024-03-09 16:17:50 -08:00
|
|
|
|
* @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it (only present when Rule.parser is "markdownit").
|
|
|
|
|
|
* @property {ParserMicromark} micromark Markdown parser data from micromark (only present when Rule.parser is "micromark").
|
2024-02-27 20:42:09 -08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Markdown parser data from markdown-it.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} ParserMarkdownIt
|
|
|
|
|
|
* @property {MarkdownItToken[]} tokens Token objects from markdown-it.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Markdown parser data from micromark.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} ParserMicromark
|
|
|
|
|
|
* @property {MicromarkToken[]} tokens Token objects from micromark.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* markdown-it token.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} MarkdownItToken
|
|
|
|
|
|
* @property {string[][]} attrs HTML attributes.
|
|
|
|
|
|
* @property {boolean} block Block-level token.
|
|
|
|
|
|
* @property {MarkdownItToken[]} children Child nodes.
|
|
|
|
|
|
* @property {string} content Tag contents.
|
|
|
|
|
|
* @property {boolean} hidden Ignore element.
|
|
|
|
|
|
* @property {string} info Fence info.
|
|
|
|
|
|
* @property {number} level Nesting level.
|
|
|
|
|
|
* @property {number[]} map Beginning/ending line numbers.
|
|
|
|
|
|
* @property {string} markup Markup text.
|
|
|
|
|
|
* @property {Object} meta Arbitrary data.
|
|
|
|
|
|
* @property {number} nesting Level change.
|
|
|
|
|
|
* @property {string} tag HTML tag name.
|
|
|
|
|
|
* @property {string} type Token type.
|
|
|
|
|
|
* @property {number} lineNumber Line number (1-based).
|
|
|
|
|
|
* @property {string} line Line content.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2024-03-09 16:17:50 -08:00
|
|
|
|
/** @typedef {import("markdownlint-micromark").TokenType} MicromarkTokenType */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* micromark token.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} MicromarkToken
|
|
|
|
|
|
* @property {MicromarkTokenType} type Token type.
|
|
|
|
|
|
* @property {number} startLine Start line (1-based).
|
|
|
|
|
|
* @property {number} startColumn Start column (1-based).
|
|
|
|
|
|
* @property {number} endLine End line (1-based).
|
|
|
|
|
|
* @property {number} endColumn End column (1-based).
|
|
|
|
|
|
* @property {string} text Token text.
|
|
|
|
|
|
* @property {MicromarkToken[]} children Child tokens.
|
|
|
|
|
|
* @property {MicromarkToken | null} parent Parent token.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Error-reporting callback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback RuleOnError
|
|
|
|
|
|
* @param {RuleOnErrorInfo} onErrorInfo Error information.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Fix information for RuleOnError callback.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} RuleOnErrorInfo
|
|
|
|
|
|
* @property {number} lineNumber Line number (1-based).
|
|
|
|
|
|
* @property {string} [detail] Detail about the error.
|
|
|
|
|
|
* @property {string} [context] Context for the error.
|
2023-07-11 21:44:45 -07:00
|
|
|
|
* @property {URL} [information] Link to more information.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* @property {number[]} [range] Column number (1-based) and length.
|
|
|
|
|
|
* @property {RuleOnErrorFixInfo} [fixInfo] Fix information.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Fix information for RuleOnErrorInfo.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} RuleOnErrorFixInfo
|
|
|
|
|
|
* @property {number} [lineNumber] Line number (1-based).
|
|
|
|
|
|
* @property {number} [editColumn] Column of the fix (1-based).
|
|
|
|
|
|
* @property {number} [deleteCount] Count of characters to delete.
|
|
|
|
|
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Rule definition.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} Rule
|
|
|
|
|
|
* @property {string[]} names Rule name(s).
|
|
|
|
|
|
* @property {string} description Rule description.
|
|
|
|
|
|
* @property {URL} [information] Link to more information.
|
|
|
|
|
|
* @property {string[]} tags Rule tag(s).
|
2024-03-09 16:17:50 -08:00
|
|
|
|
* @property {"markdownit" | "micromark" | "none"} parser Parser used.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* @property {boolean} [asynchronous] True if asynchronous.
|
|
|
|
|
|
* @property {RuleFunction} function Rule implementation.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Configuration options.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} Options
|
|
|
|
|
|
* @property {Configuration} [config] Configuration object.
|
|
|
|
|
|
* @property {ConfigurationParser[]} [configParsers] Configuration parsers.
|
|
|
|
|
|
* @property {Rule[] | Rule} [customRules] Custom rules.
|
|
|
|
|
|
* @property {string[] | string} [files] Files to lint.
|
2023-01-29 21:13:17 -08:00
|
|
|
|
* @property {RegExp | null} [frontMatter] Front matter pattern.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* @property {Object} [fs] File system implementation.
|
|
|
|
|
|
* @property {boolean} [handleRuleFailures] True to catch exceptions.
|
|
|
|
|
|
* @property {Plugin[]} [markdownItPlugins] Additional plugins.
|
|
|
|
|
|
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
|
|
|
|
|
* @property {number} [resultVersion] Results object version.
|
|
|
|
|
|
* @property {Object.<string, string>} [strings] Strings to lint.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* A markdown-it plugin.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Array} Plugin
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Function to pretty-print lint results.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback ToStringCallback
|
|
|
|
|
|
* @param {boolean} [ruleAliases] True to use rule aliases.
|
|
|
|
|
|
* @returns {string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Lint results (for resultVersion 3).
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object.<string, LintError[]>} LintResults
|
|
|
|
|
|
* @property {ToStringCallback} toString String representation.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Lint error.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} LintError
|
|
|
|
|
|
* @property {number} lineNumber Line number (1-based).
|
|
|
|
|
|
* @property {string[]} ruleNames Rule name(s).
|
|
|
|
|
|
* @property {string} ruleDescription Rule description.
|
|
|
|
|
|
* @property {string} ruleInformation Link to more information.
|
|
|
|
|
|
* @property {string} errorDetail Detail about the error.
|
|
|
|
|
|
* @property {string} errorContext Context for the error.
|
|
|
|
|
|
* @property {number[]} errorRange Column number (1-based) and length.
|
|
|
|
|
|
* @property {FixInfo} [fixInfo] Fix information.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Fix information.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {Object} FixInfo
|
|
|
|
|
|
* @property {number} [lineNumber] Line number (1-based).
|
|
|
|
|
|
* @property {number} [editColumn] Column of the fix (1-based).
|
|
|
|
|
|
* @property {number} [deleteCount] Count of characters to delete.
|
|
|
|
|
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2023-09-04 21:41:16 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Called with the result of linting a string or document.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback LintContentCallback
|
|
|
|
|
|
* @param {Error | null} error Error iff failed.
|
|
|
|
|
|
* @param {LintError[]} [result] Result iff successful.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* Called with the result of the lint function.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback LintCallback
|
2023-09-04 21:41:16 -07:00
|
|
|
|
* @param {Error | null} error Error object iff failed.
|
|
|
|
|
|
* @param {LintResults} [results] Lint results iff succeeded.
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2023-11-08 19:49:02 -08:00
|
|
|
|
* Configuration object for linting rules. For the JSON schema, see
|
2023-01-17 04:19:40 +00:00
|
|
|
|
* {@link ../schema/markdownlint-config-schema.json}.
|
|
|
|
|
|
*
|
2023-11-08 19:49:02 -08:00
|
|
|
|
* @typedef {import("./configuration").Configuration} Configuration
|
2023-01-17 04:19:40 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Rule configuration object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @typedef {boolean | Object} RuleConfiguration Rule configuration.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Parses a configuration string and returns a configuration object.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback ConfigurationParser
|
|
|
|
|
|
* @param {string} text Configuration string.
|
|
|
|
|
|
* @returns {Configuration}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Called with the result of the readConfig function.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback ReadConfigCallback
|
|
|
|
|
|
* @param {Error | null} err Error object or null.
|
|
|
|
|
|
* @param {Configuration} [config] Configuration object.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Called with the result of the resolveConfigExtends function.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @callback ResolveConfigExtendsCallback
|
|
|
|
|
|
* @param {Error | null} err Error object or null.
|
|
|
|
|
|
* @param {string} [path] Resolved path to file.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md001.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md001.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-06 21:19:14 -07:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD001", "heading-increment" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Heading levels should only increment by one level at a time",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-06-06 21:19:14 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD001(params, onError) {
|
2024-06-06 21:19:14 -07:00
|
|
|
|
let prevLevel = Number.MAX_SAFE_INTEGER;
|
|
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const heading of headings) {
|
|
|
|
|
|
const level = getHeadingLevel(heading);
|
|
|
|
|
|
if (level > prevLevel) {
|
|
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
heading.startLine,
|
|
|
|
|
|
`h${prevLevel + 1}`,
|
|
|
|
|
|
`h${level}`
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
prevLevel = level;
|
2024-06-06 21:19:14 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md003.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md003.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-08 14:44:49 -07:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const { filterByTypes, getHeadingLevel, getHeadingStyle } =
|
2024-06-08 14:44:49 -07:00
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD003", "heading-style" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Heading style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-06-08 14:44:49 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD003(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let style = String(params.config.style || "consistent");
|
2024-06-08 14:44:49 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const heading of headings) {
|
|
|
|
|
|
const styleForToken = getHeadingStyle(heading);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (style === "consistent") {
|
|
|
|
|
|
style = styleForToken;
|
|
|
|
|
|
}
|
2024-06-09 17:09:03 -07:00
|
|
|
|
if (styleForToken !== style) {
|
2024-06-08 14:44:49 -07:00
|
|
|
|
const h12 = getHeadingLevel(heading) <= 2;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const setextWithAtx =
|
|
|
|
|
|
(style === "setext_with_atx") &&
|
|
|
|
|
|
((h12 && (styleForToken === "setext")) ||
|
|
|
|
|
|
(!h12 && (styleForToken === "atx")));
|
|
|
|
|
|
const setextWithAtxClosed =
|
|
|
|
|
|
(style === "setext_with_atx_closed") &&
|
|
|
|
|
|
((h12 && (styleForToken === "setext")) ||
|
|
|
|
|
|
(!h12 && (styleForToken === "atx_closed")));
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!setextWithAtx && !setextWithAtxClosed) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let expected = style;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (style === "setext_with_atx") {
|
|
|
|
|
|
expected = h12 ? "setext" : "atx";
|
|
|
|
|
|
} else if (style === "setext_with_atx_closed") {
|
|
|
|
|
|
expected = h12 ? "setext" : "atx_closed";
|
|
|
|
|
|
}
|
2024-06-08 14:44:49 -07:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
heading.startLine,
|
|
|
|
|
|
expected,
|
|
|
|
|
|
styleForToken
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-08 14:44:49 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md004.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md004.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, listItemMarkerRe, unorderedListStyleFor } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { flattenedLists } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const expectedStyleToMarker = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"dash": "-",
|
|
|
|
|
|
"plus": "+",
|
|
|
|
|
|
"asterisk": "*"
|
2021-02-06 15:49:02 -08:00
|
|
|
|
};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const differentItemStyle = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"dash": "plus",
|
|
|
|
|
|
"plus": "asterisk",
|
|
|
|
|
|
"asterisk": "dash"
|
2021-02-06 15:49:02 -08:00
|
|
|
|
};
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const validStyles = Object.keys(expectedStyleToMarker);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD004", "ul-style" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Unordered list style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "bullet", "ul" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD004(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const style = String(params.config.style || "consistent");
|
|
|
|
|
|
let expectedStyle = style;
|
|
|
|
|
|
const nestingStyles = [];
|
|
|
|
|
|
for (const list of flattenedLists()) {
|
|
|
|
|
|
if (list.unordered) {
|
|
|
|
|
|
if (expectedStyle === "consistent") {
|
|
|
|
|
|
expectedStyle = unorderedListStyleFor(list.items[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
for (const item of list.items) {
|
|
|
|
|
|
const itemStyle = unorderedListStyleFor(item);
|
|
|
|
|
|
if (style === "sublist") {
|
|
|
|
|
|
const nesting = list.nesting;
|
|
|
|
|
|
if (!nestingStyles[nesting]) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
nestingStyles[nesting] =
|
|
|
|
|
|
(itemStyle === nestingStyles[nesting - 1]) ?
|
|
|
|
|
|
differentItemStyle[itemStyle] :
|
|
|
|
|
|
itemStyle;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
expectedStyle = nestingStyles[nesting];
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!validStyles.includes(expectedStyle)) {
|
|
|
|
|
|
expectedStyle = validStyles[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
let range = null;
|
|
|
|
|
|
let fixInfo = null;
|
|
|
|
|
|
const match = item.line.match(listItemMarkerRe);
|
|
|
|
|
|
if (match) {
|
|
|
|
|
|
const column = match.index + 1;
|
|
|
|
|
|
const length = match[0].length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ column, length ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": match[1].length + 1,
|
|
|
|
|
|
"deleteCount": 1,
|
|
|
|
|
|
"insertText": expectedStyleToMarker[expectedStyle]
|
|
|
|
|
|
};
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
item.lineNumber,
|
|
|
|
|
|
expectedStyle,
|
|
|
|
|
|
itemStyle,
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md005.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md005.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD005", "list-indent" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Inconsistent indentation for list items at the same level",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "bullet", "ul", "indentation" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD005(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const lists = filterByTypes(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
params.parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ "listOrdered", "listUnordered" ]
|
2024-06-09 17:09:03 -07:00
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const list of lists) {
|
|
|
|
|
|
const expectedIndent = list.startColumn - 1;
|
|
|
|
|
|
let expectedEnd = 0;
|
|
|
|
|
|
let endMatching = false;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const listItemPrefixes =
|
|
|
|
|
|
list.children.filter((token) => (token.type === "listItemPrefix"));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const listItemPrefix of listItemPrefixes) {
|
|
|
|
|
|
const lineNumber = listItemPrefix.startLine;
|
|
|
|
|
|
const actualIndent = listItemPrefix.startColumn - 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const range = [ 1, listItemPrefix.endColumn - 1 ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (list.type === "listUnordered") {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
expectedIndent,
|
|
|
|
|
|
actualIndent,
|
2024-06-09 17:09:03 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range
|
|
|
|
|
|
// No fixInfo; MD007 handles this scenario better
|
2024-01-06 20:47:01 -08:00
|
|
|
|
);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const markerLength = listItemPrefix.text.trim().length;
|
|
|
|
|
|
const actualEnd = listItemPrefix.startColumn + markerLength - 1;
|
|
|
|
|
|
expectedEnd = expectedEnd || actualEnd;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if ((expectedIndent !== actualIndent) || endMatching) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (expectedEnd === actualEnd) {
|
|
|
|
|
|
endMatching = true;
|
2023-10-12 21:43:31 -07:00
|
|
|
|
} else {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const detail = endMatching ?
|
|
|
|
|
|
`Expected: (${expectedEnd}); Actual: (${actualEnd})` :
|
|
|
|
|
|
`Expected: ${expectedIndent}; Actual: ${actualIndent}`;
|
|
|
|
|
|
const expected = endMatching ?
|
|
|
|
|
|
expectedEnd - markerLength :
|
|
|
|
|
|
expectedIndent;
|
|
|
|
|
|
const actual = endMatching ?
|
|
|
|
|
|
actualEnd - markerLength :
|
|
|
|
|
|
actualIndent;
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
detail,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
range,
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": Math.min(actual, expected) + 1,
|
|
|
|
|
|
"deleteCount": Math.max(actual - expected, 0),
|
|
|
|
|
|
"insertText": "".padEnd(Math.max(expected - actual, 0))
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md007.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md007.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const { filterByTypes, getTokenParentOfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2023-10-19 23:01:31 -07:00
|
|
|
|
|
2024-02-29 23:05:27 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
2024-03-04 21:38:18 -08:00
|
|
|
|
/** @type import("markdownlint-micromark").TokenType[] */
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const unorderedListTypes =
|
|
|
|
|
|
[ "blockQuotePrefix", "listItemPrefix", "listUnordered" ];
|
2024-02-29 23:05:27 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
2024-03-04 21:38:18 -08:00
|
|
|
|
/** @type import("markdownlint-micromark").TokenType[] */
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const unorderedParentTypes =
|
|
|
|
|
|
[ "blockQuote", "listOrdered", "listUnordered" ];
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD007", "ul-indent" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Unordered list indentation",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "bullet", "ul", "indentation" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD007(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const indent = Number(params.config.indent || 2);
|
|
|
|
|
|
const startIndented = !!params.config.start_indented;
|
|
|
|
|
|
const startIndent = Number(params.config.start_indent || indent);
|
|
|
|
|
|
const unorderedListNesting = new Map();
|
|
|
|
|
|
let lastBlockQuotePrefix = null;
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const tokens = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
unorderedListTypes
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of tokens) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { endColumn, parent, startColumn, startLine, type } = token;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (type === "blockQuotePrefix") {
|
|
|
|
|
|
lastBlockQuotePrefix = token;
|
|
|
|
|
|
} else if (type === "listUnordered") {
|
|
|
|
|
|
let nesting = 0;
|
2024-02-29 23:05:27 -08:00
|
|
|
|
/** @type {import("../helpers/micromark.cjs").Token | null} */
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let current = token;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
while (
|
|
|
|
|
|
(current = getTokenParentOfType(current, unorderedParentTypes))
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (current.type === "listUnordered") {
|
|
|
|
|
|
nesting++;
|
|
|
|
|
|
// eslint-disable-next-line no-continue
|
|
|
|
|
|
continue;
|
|
|
|
|
|
} else if (current.type === "listOrdered") {
|
|
|
|
|
|
nesting = -1;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nesting >= 0) {
|
|
|
|
|
|
unorderedListNesting.set(token, nesting);
|
|
|
|
|
|
}
|
2024-06-09 17:09:03 -07:00
|
|
|
|
} else {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// listItemPrefix
|
|
|
|
|
|
const nesting = unorderedListNesting.get(parent);
|
|
|
|
|
|
if (nesting !== undefined) {
|
|
|
|
|
|
// listItemPrefix for listUnordered
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const expectedIndent =
|
|
|
|
|
|
(startIndented ? startIndent : 0) + (nesting * indent);
|
|
|
|
|
|
const blockQuoteAdjustment =
|
|
|
|
|
|
(lastBlockQuotePrefix?.endLine === startLine) ?
|
|
|
|
|
|
(lastBlockQuotePrefix.endColumn - 1) :
|
|
|
|
|
|
0;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const actualIndent = startColumn - 1 - blockQuoteAdjustment;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const range = [ 1, endColumn - 1 ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fixInfo = {
|
|
|
|
|
|
"editColumn": startColumn - actualIndent,
|
|
|
|
|
|
"deleteCount": Math.max(actualIndent - expectedIndent, 0),
|
|
|
|
|
|
"insertText": "".padEnd(Math.max(expectedIndent - actualIndent, 0))
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
expectedIndent,
|
|
|
|
|
|
actualIndent,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md009.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md009.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, filterTokens, forEachLine, includesSorted,
|
|
|
|
|
|
numericSortAscending } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD009", "no-trailing-spaces" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Trailing spaces",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "markdownit",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD009(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let brSpaces = params.config.br_spaces;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
brSpaces = Number((brSpaces === undefined) ? 2 : brSpaces);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const listItemEmptyLines = !!params.config.list_item_empty_lines;
|
|
|
|
|
|
const strict = !!params.config.strict;
|
|
|
|
|
|
const listItemLineNumbers = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (listItemEmptyLines) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "list_item_open", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
listItemLineNumbers.push(i + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
listItemLineNumbers.sort(numericSortAscending);
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const paragraphLineNumbers = [];
|
|
|
|
|
|
const codeInlineLineNumbers = [];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (strict) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "paragraph_open", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0]; i < token.map[1] - 1; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
paragraphLineNumbers.push(i + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const addLineNumberRange = (start, end) => {
|
|
|
|
|
|
for (let i = start; i < end; i++) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
codeInlineLineNumbers.push(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "inline", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let start = 0;
|
|
|
|
|
|
for (const child of token.children) {
|
|
|
|
|
|
if (start > 0) {
|
|
|
|
|
|
addLineNumberRange(start, child.lineNumber);
|
|
|
|
|
|
start = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (child.type === "code_inline") {
|
|
|
|
|
|
start = child.lineNumber;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-12-14 13:50:48 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (start > 0) {
|
|
|
|
|
|
addLineNumberRange(start, token.map[1]);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
});
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
|
|
|
|
|
const lineNumber = lineIndex + 1;
|
|
|
|
|
|
const trailingSpaces = line.length - line.trimEnd().length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
trailingSpaces &&
|
|
|
|
|
|
!inCode &&
|
|
|
|
|
|
!includesSorted(listItemLineNumbers, lineNumber) &&
|
|
|
|
|
|
(
|
|
|
|
|
|
(expected !== trailingSpaces) ||
|
|
|
|
|
|
(strict &&
|
|
|
|
|
|
(!includesSorted(paragraphLineNumbers, lineNumber) ||
|
|
|
|
|
|
includesSorted(codeInlineLineNumbers, lineNumber)))
|
|
|
|
|
|
)
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const column = line.length - trailingSpaces + 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
"Expected: " + (expected === 0 ? "" : "0 or ") +
|
|
|
|
|
|
expected + "; Actual: " + trailingSpaces,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ column, trailingSpaces ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": trailingSpaces
|
|
|
|
|
|
});
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md010.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md010.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, filterTokens, forEachLine, withinAnyRange } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { codeBlockAndSpanRanges, lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const tabRe = /\t+/g;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD010", "no-hard-tabs" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Hard tabs",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace", "hard_tab" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "markdownit",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD010(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const codeBlocks = params.config.code_blocks;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
|
|
|
|
const ignoreCodeLanguages = new Set(
|
|
|
|
|
|
(params.config.ignore_code_languages || [])
|
|
|
|
|
|
.map((language) => language.toLowerCase())
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const spacesPerTab = params.config.spaces_per_tab;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const spaceMultiplier = (spacesPerTab === undefined) ?
|
|
|
|
|
|
1 :
|
|
|
|
|
|
Math.max(0, Number(spacesPerTab));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const exclusions = includeCode ? [] : codeBlockAndSpanRanges();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "fence", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const language = token.info.trim().toLowerCase();
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (ignoreCodeLanguages.has(language)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = token.map[0] + 1; i < token.map[1] - 1; i++) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
exclusions.push([ i, 0, params.lines[i].length ]);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-01-06 20:47:01 -08:00
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (includeCode || !inCode) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let match = null;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while ((match = tabRe.exec(line)) !== null) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { index } = match;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const column = index + 1;
|
|
|
|
|
|
const length = match[0].length;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!withinAnyRange(exclusions, lineIndex, index, length)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
"Column: " + column,
|
2024-02-27 20:42:09 -08:00
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ column, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": length,
|
|
|
|
|
|
"insertText": "".padEnd(length * spaceMultiplier)
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md011.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md011.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, forEachLine, withinAnyRange } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { codeBlockAndSpanRanges, lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
|
|
|
|
|
const reversedLinkRe =
|
|
|
|
|
|
/(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD011", "no-reversed-links" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Reversed link syntax",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD011(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const exclusions = codeBlockAndSpanRanges();
|
|
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!inCode && !onFence) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let match = null;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while ((match = reversedLinkRe.exec(line)) !== null) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ reversedLink, preChar, linkText, linkDestination ] = match;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const index = match.index + preChar.length;
|
|
|
|
|
|
const length = match[0].length - preChar.length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!linkText.endsWith("\\") &&
|
|
|
|
|
|
!linkDestination.endsWith("\\") &&
|
|
|
|
|
|
!withinAnyRange(exclusions, lineIndex, index, length)
|
|
|
|
|
|
) {
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
reversedLink.slice(preChar.length),
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ index + 1, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": index + 1,
|
|
|
|
|
|
"deleteCount": length,
|
|
|
|
|
|
"insertText": `[${linkText}](${linkDestination})`
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md012.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md012.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD012", "no-multiple-blanks" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Multiple consecutive blank lines",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace", "blank_lines" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD012(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const maximum = Number(params.config.maximum || 1);
|
|
|
|
|
|
let count = 0;
|
|
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
count = (inCode || (line.trim().length > 0)) ? 0 : count + 1;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (maximum < count) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
maximum,
|
|
|
|
|
|
count,
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
{
|
|
|
|
|
|
"deleteCount": -1
|
|
|
|
|
|
});
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md013.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md013.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
|
|
|
|
|
includesSorted } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata, referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const longLineRePrefix = "^.{";
|
|
|
|
|
|
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
|
|
|
|
|
const longLineRePostfixStrict = "}.+$";
|
|
|
|
|
|
const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/;
|
|
|
|
|
|
const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
|
|
|
|
|
|
const tokenTypeMap = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"em_open": "e",
|
|
|
|
|
|
"em_close": "E",
|
|
|
|
|
|
"image": "I",
|
|
|
|
|
|
"link_open": "l",
|
|
|
|
|
|
"link_close": "L",
|
|
|
|
|
|
"strong_open": "s",
|
|
|
|
|
|
"strong_close": "S",
|
|
|
|
|
|
"text": "T"
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD013", "line-length" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Line length",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "line_length" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "markdownit",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD013(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lineLength = Number(params.config.line_length || 80);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const headingLineLength =
|
|
|
|
|
|
Number(params.config.heading_line_length || lineLength);
|
|
|
|
|
|
const codeLineLength =
|
|
|
|
|
|
Number(params.config.code_block_line_length || lineLength);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const strict = !!params.config.strict;
|
|
|
|
|
|
const stern = !!params.config.stern;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const longLineRePostfix =
|
|
|
|
|
|
(strict || stern) ? longLineRePostfixStrict : longLineRePostfixRelaxed;
|
|
|
|
|
|
const longLineRe =
|
|
|
|
|
|
new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
|
|
|
|
|
|
const longHeadingLineRe =
|
|
|
|
|
|
new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
|
|
|
|
|
|
const longCodeLineRe =
|
|
|
|
|
|
new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const codeBlocks = params.config.code_blocks;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const tables = params.config.tables;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeTables = (tables === undefined) ? true : !!tables;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const headings = params.config.headings;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeHeadings = (headings === undefined) ? true : !!headings;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const headingLineNumbers = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
forEachHeading(params, (heading) => {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
headingLineNumbers.push(heading.lineNumber);
|
|
|
|
|
|
});
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const linkOnlyLineNumbers = [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "inline", (token) => {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let childTokenTypes = "";
|
|
|
|
|
|
for (const child of token.children) {
|
|
|
|
|
|
if (child.type !== "text" || child.content !== "") {
|
|
|
|
|
|
childTokenTypes += tokenTypeMap[child.type] || "x";
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (linkOrImageOnlyLineRe.test(childTokenTypes)) {
|
|
|
|
|
|
linkOnlyLineNumbers.push(token.lineNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { definitionLineIndices } = referenceLinkImageData();
|
2024-01-06 20:47:01 -08:00
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
|
|
|
|
|
|
const lineNumber = lineIndex + 1;
|
|
|
|
|
|
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const length = inCode ?
|
|
|
|
|
|
codeLineLength :
|
|
|
|
|
|
(isHeading ? headingLineLength : lineLength);
|
|
|
|
|
|
const lengthRe = inCode ?
|
|
|
|
|
|
longCodeLineRe :
|
|
|
|
|
|
(isHeading ? longHeadingLineRe : longLineRe);
|
|
|
|
|
|
if ((includeCodeBlocks || !inCode) &&
|
|
|
|
|
|
(includeTables || !inTable) &&
|
|
|
|
|
|
(includeHeadings || !isHeading) &&
|
|
|
|
|
|
!includesSorted(definitionLineIndices, lineIndex) &&
|
|
|
|
|
|
(strict ||
|
|
|
|
|
|
(!(stern && sternModeRe.test(line)) &&
|
|
|
|
|
|
!includesSorted(linkOnlyLineNumbers, lineNumber))) &&
|
|
|
|
|
|
lengthRe.test(line)) {
|
|
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
length,
|
|
|
|
|
|
line.length,
|
2024-06-08 14:44:49 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ length + 1, line.length - length ]);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md014.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md014.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-22 15:12:37 -07:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const dollarCommandRe = /^(\s*)(\$\s+)/;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD014", "commands-show-output" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Dollar signs used before commands without showing output",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "code" ],
|
2024-06-22 15:12:37 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD014(params, onError) {
|
2024-06-22 15:12:37 -07:00
|
|
|
|
const codeBlocks = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "codeFenced", "codeIndented" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const codeBlock of codeBlocks) {
|
|
|
|
|
|
const codeFlowValues = filterByTypes(
|
|
|
|
|
|
codeBlock.children,
|
|
|
|
|
|
[ "codeFlowValue" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
const dollarMatches = codeFlowValues.
|
|
|
|
|
|
map((codeFlowValue) => ({
|
|
|
|
|
|
"result": codeFlowValue.text.match(dollarCommandRe),
|
|
|
|
|
|
"startColumn": codeFlowValue.startColumn,
|
|
|
|
|
|
"startLine": codeFlowValue.startLine,
|
|
|
|
|
|
"text": codeFlowValue.text
|
|
|
|
|
|
})).
|
|
|
|
|
|
filter((dollarMatch) => dollarMatch.result);
|
|
|
|
|
|
if (dollarMatches.length === codeFlowValues.length) {
|
|
|
|
|
|
for (const dollarMatch of dollarMatches) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const column = dollarMatch.startColumn + dollarMatch.result[1].length;
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const length = dollarMatch.result[2].length;
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
dollarMatch.startLine,
|
|
|
|
|
|
dollarMatch.text,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ column, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": length
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-22 15:12:37 -07:00
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-22 15:12:37 -07:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md018.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md018.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD018", "no-missing-space-atx" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "No space after hash on atx style heading",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings", "atx", "spaces" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD018(params, onError) {
|
2024-07-20 13:38:45 +08:00
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, inFence, inTable, inItem, inBreak, inHtml) => {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (!inCode &&
|
2024-07-20 13:38:45 +08:00
|
|
|
|
!inHtml &&
|
2024-02-17 15:46:13 -08:00
|
|
|
|
/^#+[^# \t]/.test(line) &&
|
|
|
|
|
|
!/#\s*$/.test(line) &&
|
|
|
|
|
|
!line.startsWith("#️⃣")) {
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// @ts-ignore
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const hashCount = /^#+/.exec(line)[0].length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
line.trim(),
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
[ 1, hashCount + 1 ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": hashCount + 1,
|
|
|
|
|
|
"insertText": " "
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2024-06-16 20:25:07 -07:00
|
|
|
|
/***/ "../lib/md019-md021.js":
|
|
|
|
|
|
/*!*****************************!*\
|
|
|
|
|
|
!*** ../lib/md019-md021.js ***!
|
|
|
|
|
|
\*****************************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-16 20:25:07 -07:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers/helpers */ "../helpers/helpers.js");
|
2024-06-11 21:37:09 -07:00
|
|
|
|
const { filterByTypes, getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-06-16 20:25:07 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Validate heading sequence and whitespace length at start or end.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
|
|
|
|
|
* @param {import("./markdownlint").MicromarkToken} heading ATX heading token.
|
|
|
|
|
|
* @param {number} delta Direction to scan.
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
function validateHeadingSpaces(onError, heading, delta) {
|
|
|
|
|
|
const { children, startLine, text } = heading;
|
|
|
|
|
|
let index = (delta > 0) ? 0 : (children.length - 1);
|
|
|
|
|
|
while (
|
|
|
|
|
|
children[index] &&
|
|
|
|
|
|
(children[index].type !== "atxHeadingSequence")
|
|
|
|
|
|
) {
|
|
|
|
|
|
index += delta;
|
|
|
|
|
|
}
|
|
|
|
|
|
const headingSequence = children[index];
|
|
|
|
|
|
const whitespace = children[index + delta];
|
|
|
|
|
|
if (
|
|
|
|
|
|
(headingSequence?.type === "atxHeadingSequence") &&
|
|
|
|
|
|
(whitespace?.type === "whitespace") &&
|
|
|
|
|
|
(whitespace.text.length > 1)
|
|
|
|
|
|
) {
|
|
|
|
|
|
const column = whitespace.startColumn + 1;
|
|
|
|
|
|
const length = whitespace.endColumn - column;
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
text.trim(),
|
|
|
|
|
|
delta > 0,
|
|
|
|
|
|
delta < 0,
|
|
|
|
|
|
[ column, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": length
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
2024-06-16 20:25:07 -07:00
|
|
|
|
/** @type import("./markdownlint").Rule[] */
|
|
|
|
|
|
module.exports = [
|
|
|
|
|
|
{
|
|
|
|
|
|
"names": [ "MD019", "no-multiple-space-atx" ],
|
|
|
|
|
|
"description": "Multiple spaces after hash on atx style heading",
|
|
|
|
|
|
"tags": [ "headings", "atx", "spaces" ],
|
|
|
|
|
|
"parser": "micromark",
|
|
|
|
|
|
"function": function MD019(params, onError) {
|
|
|
|
|
|
const atxHeadings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading" ]
|
|
|
|
|
|
).filter((heading) => getHeadingStyle(heading) === "atx");
|
|
|
|
|
|
for (const atxHeading of atxHeadings) {
|
|
|
|
|
|
validateHeadingSpaces(onError, atxHeading, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"names": [ "MD021", "no-multiple-space-closed-atx" ],
|
|
|
|
|
|
"description": "Multiple spaces inside hashes on closed atx style heading",
|
|
|
|
|
|
"tags": [ "headings", "atx_closed", "spaces" ],
|
|
|
|
|
|
"parser": "micromark",
|
|
|
|
|
|
"function": function MD021(params, onError) {
|
|
|
|
|
|
const atxClosedHeadings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading" ]
|
|
|
|
|
|
).filter((heading) => getHeadingStyle(heading) === "atx_closed");
|
|
|
|
|
|
for (const atxClosedHeading of atxClosedHeadings) {
|
|
|
|
|
|
validateHeadingSpaces(onError, atxClosedHeading, 1);
|
|
|
|
|
|
validateHeadingSpaces(onError, atxClosedHeading, -1);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-11 21:37:09 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-16 20:25:07 -07:00
|
|
|
|
];
|
2019-10-02 20:10:42 -07:00
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md020.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md020.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD020", "no-missing-space-closed-atx" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "No space inside hashes on closed atx style heading",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings", "atx_closed", "spaces" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD020(params, onError) {
|
2024-07-20 13:38:45 +08:00
|
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, inFence, inTable, inItem, inBreak, inHtml) => {
|
|
|
|
|
|
if (!inCode &&
|
|
|
|
|
|
!inHtml) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const match =
|
|
|
|
|
|
/^(#+)([ \t]*)([^#]*?[^#\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (match) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [
|
|
|
|
|
|
,
|
|
|
|
|
|
leftHash,
|
|
|
|
|
|
{ "length": leftSpaceLength },
|
|
|
|
|
|
content,
|
|
|
|
|
|
{ "length": rightSpaceLength },
|
|
|
|
|
|
rightEscape,
|
|
|
|
|
|
rightHash,
|
|
|
|
|
|
{ "length": trailSpaceLength }
|
|
|
|
|
|
] = match;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const leftHashLength = leftHash.length;
|
|
|
|
|
|
const rightHashLength = rightHash.length;
|
|
|
|
|
|
const left = !leftSpaceLength;
|
2024-06-01 21:32:10 -07:00
|
|
|
|
const right = !rightSpaceLength || !!rightEscape;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const rightEscapeReplacement = rightEscape ? `${rightEscape} ` : "";
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (left || right) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const range = left ?
|
|
|
|
|
|
[
|
|
|
|
|
|
1,
|
|
|
|
|
|
leftHashLength + 1
|
|
|
|
|
|
] :
|
|
|
|
|
|
[
|
|
|
|
|
|
line.length - trailSpaceLength - rightHashLength,
|
|
|
|
|
|
rightHashLength + 1
|
|
|
|
|
|
];
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
line.trim(),
|
|
|
|
|
|
left,
|
|
|
|
|
|
right,
|
|
|
|
|
|
range,
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": 1,
|
|
|
|
|
|
"deleteCount": line.length,
|
|
|
|
|
|
"insertText":
|
|
|
|
|
|
`${leftHash} ${content} ${rightEscapeReplacement}${rightHash}`
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md022.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md022.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const { filterByTypes, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const defaultLines = 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
const getLinesFunction = (linesParam) => {
|
2023-08-08 22:56:47 -07:00
|
|
|
|
if (Array.isArray(linesParam)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const linesArray = new Array(6).fill(defaultLines);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const [ index, value ] of [ ...linesParam.entries() ].slice(0, 6)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
linesArray[index] = value;
|
2023-08-08 22:56:47 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return (heading) => linesArray[getHeadingLevel(heading) - 1];
|
2023-08-08 22:56:47 -07:00
|
|
|
|
}
|
|
|
|
|
|
// Coerce linesParam to a number
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const lines = (linesParam === undefined) ? defaultLines : Number(linesParam);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
return () => lines;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
const getBlockQuote = (str, count) => (
|
|
|
|
|
|
(str || "")
|
|
|
|
|
|
.match(blockquotePrefixRe)[0]
|
|
|
|
|
|
.trimEnd()
|
|
|
|
|
|
// eslint-disable-next-line unicorn/prefer-spread
|
|
|
|
|
|
.concat("\n")
|
|
|
|
|
|
.repeat(count)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD022", "blanks-around-headings" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Headings should be surrounded by blank lines",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings", "blank_lines" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD022(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const getLinesAbove = getLinesFunction(params.config.lines_above);
|
|
|
|
|
|
const getLinesBelow = getLinesFunction(params.config.lines_below);
|
2024-02-28 21:01:23 -08:00
|
|
|
|
const { lines } = params;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const headings = filterByTypes(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
2024-06-09 17:09:03 -07:00
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const heading of headings) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { startLine, endLine } = heading;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const line = lines[startLine - 1].trim();
|
|
|
|
|
|
|
|
|
|
|
|
// Check lines above
|
|
|
|
|
|
const linesAbove = getLinesAbove(heading);
|
|
|
|
|
|
if (linesAbove >= 0) {
|
|
|
|
|
|
let actualAbove = 0;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (
|
|
|
|
|
|
let i = 0;
|
|
|
|
|
|
(i < linesAbove) && isBlankLine(lines[startLine - 2 - i]);
|
|
|
|
|
|
i++
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
actualAbove++;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
linesAbove,
|
|
|
|
|
|
actualAbove,
|
|
|
|
|
|
"Above",
|
|
|
|
|
|
line,
|
2024-06-09 17:09:03 -07:00
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
{
|
|
|
|
|
|
"insertText": getBlockQuote(
|
|
|
|
|
|
lines[startLine - 2],
|
|
|
|
|
|
linesAbove - actualAbove
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2023-08-06 15:24:35 -07:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Check lines below
|
|
|
|
|
|
const linesBelow = getLinesBelow(heading);
|
|
|
|
|
|
if (linesBelow >= 0) {
|
|
|
|
|
|
let actualBelow = 0;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (
|
|
|
|
|
|
let i = 0;
|
|
|
|
|
|
(i < linesBelow) && isBlankLine(lines[endLine + i]);
|
|
|
|
|
|
i++
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
actualBelow++;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
linesBelow,
|
|
|
|
|
|
actualBelow,
|
|
|
|
|
|
"Below",
|
|
|
|
|
|
line,
|
2024-06-09 17:09:03 -07:00
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
{
|
|
|
|
|
|
"lineNumber": endLine + 1,
|
|
|
|
|
|
"insertText": getBlockQuote(
|
|
|
|
|
|
lines[endLine],
|
|
|
|
|
|
linesBelow - actualBelow
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-08-05 23:09:07 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md023.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md023.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-17 22:18:58 -07:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD023", "heading-start-left" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Headings must start at the beginning of the line",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings", "spaces" ],
|
2024-06-17 22:18:58 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD023(params, onError) {
|
2024-06-17 22:18:58 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "linePrefix", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (let i = 0; i < headings.length - 1; i++) {
|
|
|
|
|
|
if (
|
|
|
|
|
|
(headings[i].type === "linePrefix") &&
|
|
|
|
|
|
(headings[i + 1].type !== "linePrefix") &&
|
|
|
|
|
|
(headings[i].startLine === headings[i + 1].startLine)
|
|
|
|
|
|
) {
|
|
|
|
|
|
const { endColumn, startColumn, startLine } = headings[i];
|
|
|
|
|
|
const length = endColumn - startColumn;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
2024-06-17 22:18:58 -07:00
|
|
|
|
startLine,
|
|
|
|
|
|
params.lines[startLine - 1],
|
|
|
|
|
|
true,
|
|
|
|
|
|
false,
|
|
|
|
|
|
[ startColumn, length ],
|
2024-02-17 15:46:13 -08:00
|
|
|
|
{
|
2024-06-17 22:18:58 -07:00
|
|
|
|
"editColumn": startColumn,
|
|
|
|
|
|
"deleteCount": length
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-17 22:18:58 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md024.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md024.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-19 21:05:31 -07:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD024", "no-duplicate-heading" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Multiple headings with the same content",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-06-19 21:05:31 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD024(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const siblingsOnly = !!params.config.siblings_only || false;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const knownContents = [ null, [] ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let lastLevel = 1;
|
|
|
|
|
|
let knownContent = knownContents[lastLevel];
|
2024-06-19 21:05:31 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const heading of headings) {
|
|
|
|
|
|
const headingText = getHeadingText(heading);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (siblingsOnly) {
|
2024-06-19 21:05:31 -07:00
|
|
|
|
const newLevel = getHeadingLevel(heading);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
while (lastLevel < newLevel) {
|
|
|
|
|
|
lastLevel++;
|
|
|
|
|
|
knownContents[lastLevel] = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
while (lastLevel > newLevel) {
|
|
|
|
|
|
knownContents[lastLevel] = [];
|
|
|
|
|
|
lastLevel--;
|
|
|
|
|
|
}
|
|
|
|
|
|
knownContent = knownContents[newLevel];
|
|
|
|
|
|
}
|
2023-12-05 19:23:17 -08:00
|
|
|
|
// @ts-ignore
|
2024-06-19 21:05:31 -07:00
|
|
|
|
if (knownContent.includes(headingText)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
2024-06-19 21:05:31 -07:00
|
|
|
|
heading.startLine,
|
|
|
|
|
|
headingText.trim()
|
2024-02-17 15:46:13 -08:00
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
} else {
|
2023-12-05 19:23:17 -08:00
|
|
|
|
// @ts-ignore
|
2024-06-19 21:05:31 -07:00
|
|
|
|
knownContent.push(headingText);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-19 21:05:31 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md025.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md025.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-08 20:41:40 -07:00
|
|
|
|
const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-19 21:05:31 -07:00
|
|
|
|
const { filterByTypes, getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD025", "single-title", "single-h1" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Multiple top-level headings in the same document",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-06-08 20:41:40 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD025(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const level = Number(params.config.level || 1);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const foundFrontMatterTitle =
|
|
|
|
|
|
frontMatterHasTitle(
|
|
|
|
|
|
params.frontMatterLines,
|
|
|
|
|
|
params.config.front_matter_title
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let hasTopLevelHeading = false;
|
2024-06-08 20:41:40 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const heading of headings) {
|
|
|
|
|
|
const headingLevel = getHeadingLevel(heading);
|
2024-06-09 17:09:03 -07:00
|
|
|
|
if (headingLevel === level) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (hasTopLevelHeading || foundFrontMatterTitle) {
|
2024-06-19 21:05:31 -07:00
|
|
|
|
const headingText = getHeadingText(heading);
|
2024-06-08 20:41:40 -07:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
heading.startLine,
|
|
|
|
|
|
headingText
|
|
|
|
|
|
);
|
|
|
|
|
|
} else if (heading.startLine === 1) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
hasTopLevelHeading = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-08 20:41:40 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md026.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md026.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe,
|
|
|
|
|
|
endOfLineHtmlEntityRe, escapeForRegExp } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD026", "no-trailing-punctuation" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Trailing punctuation in heading",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD026(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let punctuation = params.config.punctuation;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
punctuation = String(
|
|
|
|
|
|
(punctuation === undefined) ? allPunctuationNoQuestion : punctuation
|
|
|
|
|
|
);
|
|
|
|
|
|
const trailingPunctuationRe =
|
|
|
|
|
|
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeadingText", "setextHeadingText" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const heading of headings) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { endColumn, endLine, text } = heading;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const match = trailingPunctuationRe.exec(text);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
match &&
|
|
|
|
|
|
!endOfLineHtmlEntityRe.test(text) &&
|
|
|
|
|
|
!endOfLineGemojiCodeRe.test(text)
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fullMatch = match[0];
|
|
|
|
|
|
const length = fullMatch.length;
|
|
|
|
|
|
const column = endColumn - length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
endLine,
|
|
|
|
|
|
`Punctuation: '${fullMatch}'`,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ column, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": length
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-06-24 15:45:51 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md027.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md027.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-25 15:06:28 -08:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-02-26 21:07:24 -08:00
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-25 15:06:28 -08:00
|
|
|
|
"names": ["MD027", "no-multiple-space-blockquote"],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Multiple spaces after blockquote symbol",
|
2024-02-25 15:06:28 -08:00
|
|
|
|
"tags": ["blockquote", "whitespace", "indentation"],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD027(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const micromarkTokens = params.parsers.micromark.tokens;
|
2024-02-28 21:01:23 -08:00
|
|
|
|
for (const token of filterByTypes(micromarkTokens, [ "linePrefix" ])) {
|
|
|
|
|
|
const siblings = token.parent?.children || micromarkTokens;
|
2024-02-26 21:07:24 -08:00
|
|
|
|
if (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") {
|
|
|
|
|
|
const { startColumn, startLine, text } = token;
|
|
|
|
|
|
const { length } = text;
|
|
|
|
|
|
const line = params.lines[startLine - 1];
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
line,
|
2024-06-21 21:03:30 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-26 21:07:24 -08:00
|
|
|
|
[ startColumn, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": startColumn,
|
|
|
|
|
|
"deleteCount": length
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md028.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md028.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-02-26 21:07:24 -08:00
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD028", "no-blanks-blockquote" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Blank line inside blockquote",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "blockquote", "whitespace" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD028(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const micromarkTokens = params.parsers.micromark.tokens;
|
2024-02-28 21:01:23 -08:00
|
|
|
|
for (const token of filterByTypes(micromarkTokens, [ "blockQuote" ])) {
|
2024-02-26 21:07:24 -08:00
|
|
|
|
const errorLineNumbers = [];
|
2024-02-28 21:01:23 -08:00
|
|
|
|
const siblings = token.parent?.children || micromarkTokens;
|
2024-02-26 21:07:24 -08:00
|
|
|
|
for (let i = siblings.indexOf(token) + 1; i < siblings.length; i++) {
|
|
|
|
|
|
const sibling = siblings[i];
|
|
|
|
|
|
const { startLine, type } = sibling;
|
|
|
|
|
|
if (type === "lineEndingBlank") {
|
|
|
|
|
|
// Possible blank between blockquotes
|
|
|
|
|
|
errorLineNumbers.push(startLine);
|
|
|
|
|
|
} else if (ignoreTypes.has(type)) {
|
|
|
|
|
|
// Ignore invisible formatting
|
|
|
|
|
|
} else if (type === "blockQuote") {
|
|
|
|
|
|
// Blockquote followed by blockquote
|
|
|
|
|
|
for (const lineNumber of errorLineNumbers) {
|
|
|
|
|
|
addError(onError, lineNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Blockquote not followed by blockquote
|
|
|
|
|
|
break;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md029.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md029.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, listItemMarkerRe, orderedListItemMarkerRe,
|
|
|
|
|
|
rangeFromRegExp } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { flattenedLists } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const listStyleExamples = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"one": "1/1/1",
|
|
|
|
|
|
"ordered": "1/2/3",
|
|
|
|
|
|
"zero": "0/0/0"
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD029", "ol-prefix" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Ordered list item prefix",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "ol" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD029(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const style = String(params.config.style || "one_or_ordered");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const filteredLists = flattenedLists().filter((list) => !list.unordered);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const list of filteredLists) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { items } = list;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let current = 1;
|
|
|
|
|
|
let incrementing = false;
|
|
|
|
|
|
// Check for incrementing number pattern 1/2/3 or 0/1/2
|
|
|
|
|
|
if (items.length >= 2) {
|
|
|
|
|
|
const first = orderedListItemMarkerRe.exec(items[0].line);
|
|
|
|
|
|
const second = orderedListItemMarkerRe.exec(items[1].line);
|
|
|
|
|
|
if (first && second) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ , firstNumber ] = first;
|
|
|
|
|
|
const [ , secondNumber ] = second;
|
|
|
|
|
|
if ((secondNumber !== "1") || (firstNumber === "0")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
incrementing = true;
|
|
|
|
|
|
if (firstNumber === "0") {
|
|
|
|
|
|
current = 0;
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
// Determine effective style
|
|
|
|
|
|
let listStyle = style;
|
|
|
|
|
|
if (listStyle === "one_or_ordered") {
|
|
|
|
|
|
listStyle = incrementing ? "ordered" : "one";
|
|
|
|
|
|
}
|
|
|
|
|
|
// Force expected value for 0/0/0 and 1/1/1 patterns
|
|
|
|
|
|
if (listStyle === "zero") {
|
|
|
|
|
|
current = 0;
|
|
|
|
|
|
} else if (listStyle === "one") {
|
|
|
|
|
|
current = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Validate each list item marker
|
|
|
|
|
|
for (const item of items) {
|
|
|
|
|
|
const match = orderedListItemMarkerRe.exec(item.line);
|
|
|
|
|
|
if (match) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(onError, item.lineNumber,
|
|
|
|
|
|
String(current), match[1],
|
|
|
|
|
|
"Style: " + listStyleExamples[listStyle], null,
|
|
|
|
|
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (listStyle === "ordered") {
|
|
|
|
|
|
current++;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md030.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md030.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2023-01-17 04:19:40 +00:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD030", "list-marker-space" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Spaces after list markers",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "ol", "ul", "whitespace" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD030(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const ulSingle = Number(params.config.ul_single || 1);
|
|
|
|
|
|
const olSingle = Number(params.config.ol_single || 1);
|
|
|
|
|
|
const ulMulti = Number(params.config.ul_multi || 1);
|
|
|
|
|
|
const olMulti = Number(params.config.ol_multi || 1);
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const lists = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "listOrdered", "listUnordered" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const list of lists) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const ordered = (list.type === "listOrdered");
|
|
|
|
|
|
const listItemPrefixes =
|
|
|
|
|
|
list.children.filter((token) => (token.type === "listItemPrefix"));
|
|
|
|
|
|
const allSingleLine =
|
|
|
|
|
|
(list.endLine - list.startLine + 1) === listItemPrefixes.length;
|
|
|
|
|
|
const expectedSpaces = ordered ?
|
|
|
|
|
|
(allSingleLine ? olSingle : olMulti) :
|
|
|
|
|
|
(allSingleLine ? ulSingle : ulMulti);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const listItemPrefix of listItemPrefixes) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const range = [
|
|
|
|
|
|
listItemPrefix.startColumn,
|
|
|
|
|
|
listItemPrefix.endColumn - listItemPrefix.startColumn
|
|
|
|
|
|
];
|
|
|
|
|
|
const listItemPrefixWhitespaces = listItemPrefix.children.filter(
|
|
|
|
|
|
(token) => (token.type === "listItemPrefixWhitespace")
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const listItemPrefixWhitespace of listItemPrefixWhitespaces) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { endColumn, startColumn, startLine } =
|
|
|
|
|
|
listItemPrefixWhitespace;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const actualSpaces = endColumn - startColumn;
|
|
|
|
|
|
const fixInfo = {
|
|
|
|
|
|
"editColumn": startColumn,
|
|
|
|
|
|
"deleteCount": actualSpaces,
|
|
|
|
|
|
"insertText": "".padEnd(expectedSpaces)
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
expectedSpaces,
|
|
|
|
|
|
actualSpaces,
|
2024-06-21 21:03:30 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md031.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md031.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, forEachLine, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const codeFencePrefixRe = /^(.*?)[`~]/;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD031", "blanks-around-fences" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Fenced code blocks should be surrounded by blank lines",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "code", "blank_lines" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD031(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const listItems = params.config.list_items;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeListItems = (listItems === undefined) ? true : !!listItems;
|
|
|
|
|
|
const { lines } = params;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
forEachLine(lineMetadata(), (line, i, inCode, onFence, inTable, inItem) => {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const onTopFence = (onFence > 0);
|
|
|
|
|
|
const onBottomFence = (onFence < 0);
|
|
|
|
|
|
if ((includeListItems || !inItem) &&
|
|
|
|
|
|
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
|
|
|
|
|
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
|
|
|
|
|
const [ , prefix ] = line.match(codeFencePrefixRe) || [];
|
|
|
|
|
|
const fixInfo = (prefix === undefined) ? null : {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"lineNumber": i + (onTopFence ? 1 : 2),
|
2024-01-06 20:47:01 -08:00
|
|
|
|
"insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n`
|
2023-01-17 04:19:40 +00:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
i + 1,
|
|
|
|
|
|
lines[i].trim(),
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
null,
|
|
|
|
|
|
fixInfo);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md032.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md032.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-01 21:32:10 -07:00
|
|
|
|
const { addErrorContextForLine, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-03-18 20:48:22 -07:00
|
|
|
|
const { filterByPredicate, nonContentTokens } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
|
|
|
|
|
const isList = (token) => (
|
|
|
|
|
|
(token.type === "listOrdered") || (token.type === "listUnordered")
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD032", "blanks-around-lists" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Lists should be surrounded by blank lines",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD032(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const { lines, parsers } = params;
|
2023-07-18 22:33:57 -07:00
|
|
|
|
|
|
|
|
|
|
// For every top-level list...
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const topLevelLists = filterByPredicate(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
isList,
|
|
|
|
|
|
(token) => (
|
|
|
|
|
|
(isList(token) || (token.type === "htmlFlow")) ? [] : token.children
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const list of topLevelLists) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Look for a blank line above the list
|
|
|
|
|
|
const firstIndex = list.startLine - 1;
|
|
|
|
|
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
2024-06-01 21:32:10 -07:00
|
|
|
|
addErrorContextForLine(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
lines,
|
|
|
|
|
|
firstIndex
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2023-07-18 22:33:57 -07:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Find the "visual" end of the list
|
|
|
|
|
|
let endLine = list.endLine;
|
|
|
|
|
|
const flattenedChildren = filterByPredicate(list.children);
|
|
|
|
|
|
for (const child of flattenedChildren.reverse()) {
|
|
|
|
|
|
if (!nonContentTokens.has(child.type)) {
|
|
|
|
|
|
endLine = child.endLine;
|
|
|
|
|
|
break;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
|
|
|
|
|
|
// Look for a blank line below the list
|
|
|
|
|
|
const lastIndex = endLine - 1;
|
|
|
|
|
|
if (!isBlankLine(lines[lastIndex + 1])) {
|
2024-06-01 21:32:10 -07:00
|
|
|
|
addErrorContextForLine(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
lines,
|
|
|
|
|
|
lastIndex,
|
|
|
|
|
|
lastIndex + 2
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md033.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md033.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getHtmlTagInfo } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD033", "no-inline-html" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Inline HTML",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "html" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD033(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let allowedElements = params.config.allowed_elements;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
2024-06-21 21:03:30 -07:00
|
|
|
|
for (const token of filterByTypes(params.parsers.micromark.tokens, [ "htmlText" ], true)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlTagInfo = getHtmlTagInfo(token);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
htmlTagInfo &&
|
|
|
|
|
|
!htmlTagInfo.close &&
|
|
|
|
|
|
!allowedElements.includes(htmlTagInfo.name.toLowerCase())
|
|
|
|
|
|
) {
|
|
|
|
|
|
const range = [
|
|
|
|
|
|
token.startColumn,
|
|
|
|
|
|
token.text.replace(nextLinesRe, "").length
|
|
|
|
|
|
];
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
token.startLine,
|
|
|
|
|
|
"Element: " + htmlTagInfo.name,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
range
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md034.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md034.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByPredicate, filterByTypes, getHtmlTagInfo, inHtmlFlow, parse } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD034", "no-bare-urls" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Bare URL used",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "links", "url" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD034(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const literalAutolinks = (tokens) => (
|
|
|
|
|
|
filterByPredicate(
|
|
|
|
|
|
tokens,
|
2024-03-03 19:06:14 -08:00
|
|
|
|
(token) => {
|
|
|
|
|
|
if ((token.type === "literalAutolink") && !inHtmlFlow(token)) {
|
|
|
|
|
|
// Detect and ignore https://github.com/micromark/micromark/issues/164
|
|
|
|
|
|
const siblings = token.parent?.children;
|
|
|
|
|
|
// Commented-out due to not being able to exercise in test/code coverage
|
|
|
|
|
|
// || micromarkTokens;
|
|
|
|
|
|
const index = siblings?.indexOf(token);
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const prev = siblings?.at(index - 1);
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const next = siblings?.at(index + 1);
|
|
|
|
|
|
return !(
|
|
|
|
|
|
prev &&
|
|
|
|
|
|
next &&
|
|
|
|
|
|
(prev.type === "data") &&
|
|
|
|
|
|
(next.type === "data") &&
|
|
|
|
|
|
prev.text.endsWith("<") &&
|
|
|
|
|
|
next.text.startsWith(">")
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
},
|
2024-02-17 15:46:13 -08:00
|
|
|
|
(token) => {
|
|
|
|
|
|
const { children } = token;
|
|
|
|
|
|
const result = [];
|
|
|
|
|
|
for (let i = 0; i < children.length; i++) {
|
|
|
|
|
|
const current = children[i];
|
|
|
|
|
|
const openTagInfo = getHtmlTagInfo(current);
|
|
|
|
|
|
if (openTagInfo && !openTagInfo.close) {
|
|
|
|
|
|
let count = 1;
|
|
|
|
|
|
for (let j = i + 1; j < children.length; j++) {
|
|
|
|
|
|
const candidate = children[j];
|
|
|
|
|
|
const closeTagInfo = getHtmlTagInfo(candidate);
|
|
|
|
|
|
if (closeTagInfo && (openTagInfo.name === closeTagInfo.name)) {
|
|
|
|
|
|
if (closeTagInfo.close) {
|
|
|
|
|
|
count--;
|
|
|
|
|
|
if (count === 0) {
|
|
|
|
|
|
i = j;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
2023-02-05 16:58:06 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else {
|
|
|
|
|
|
result.push(current);
|
2023-02-05 16:58:06 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return result;
|
2023-02-05 16:58:06 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
)
|
|
|
|
|
|
);
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const autoLinks = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "literalAutolink" ]
|
|
|
|
|
|
);
|
2023-09-13 22:44:15 -07:00
|
|
|
|
if (autoLinks.length > 0) {
|
2023-05-23 04:01:55 +00:00
|
|
|
|
// Re-parse with correct link/image reference definition handling
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const document = params.lines.join("\n");
|
|
|
|
|
|
const tokens = parse(document, undefined, false);
|
|
|
|
|
|
for (const token of literalAutolinks(tokens)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const range = [
|
|
|
|
|
|
token.startColumn,
|
|
|
|
|
|
token.endColumn - token.startColumn
|
|
|
|
|
|
];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fixInfo = {
|
|
|
|
|
|
"editColumn": range[0],
|
|
|
|
|
|
"deleteCount": range[1],
|
|
|
|
|
|
"insertText": `<${token.text}>`
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
token.startLine,
|
|
|
|
|
|
token.text,
|
2024-06-09 17:09:03 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md035.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md035.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD035", "hr-style" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Horizontal rule style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "hr" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD035(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let style = String(params.config.style || "consistent").trim();
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const thematicBreaks = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "thematicBreak" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of thematicBreaks) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { startLine, text } = token;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (style === "consistent") {
|
|
|
|
|
|
style = text;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
addErrorDetailIf(onError, startLine, style, text);
|
2023-03-06 21:38:40 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md036.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md036.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-03-19 21:20:44 -07:00
|
|
|
|
const { filterByTypes, matchAndGetTokensByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
/** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
|
|
|
|
|
|
/** @type {Map<TokenType, TokenType[]>} */
|
|
|
|
|
|
const emphasisAndChildrenTypes = new Map([
|
|
|
|
|
|
[ "emphasis", [ "emphasisSequence", "emphasisText", "emphasisSequence" ] ],
|
|
|
|
|
|
[ "strong", [ "strongSequence", "strongText", "strongSequence" ] ]
|
|
|
|
|
|
]);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD036", "no-emphasis-as-heading" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Emphasis used instead of a heading",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings", "emphasis" ],
|
2024-03-19 21:20:44 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD036(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let punctuation = params.config.punctuation;
|
2024-03-19 21:20:44 -07:00
|
|
|
|
punctuation = String((punctuation === undefined) ? allPunctuation : punctuation);
|
|
|
|
|
|
const punctuationRe = new RegExp("[" + punctuation + "]$");
|
|
|
|
|
|
const paragraphTokens =
|
|
|
|
|
|
filterByTypes(params.parsers.micromark.tokens, [ "paragraph" ]).
|
|
|
|
|
|
filter((token) =>
|
|
|
|
|
|
(token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const paragraphToken of paragraphTokens) {
|
|
|
|
|
|
const childToken = paragraphToken.children[0];
|
|
|
|
|
|
for (const [ emphasisType, emphasisChildrenTypes ] of emphasisAndChildrenTypes) {
|
|
|
|
|
|
if (childToken.type === emphasisType) {
|
|
|
|
|
|
const matchingTokens = matchAndGetTokensByType(childToken.children, emphasisChildrenTypes);
|
|
|
|
|
|
if (matchingTokens) {
|
|
|
|
|
|
const textToken = matchingTokens[1];
|
|
|
|
|
|
if (
|
|
|
|
|
|
(textToken.children.length === 1) &&
|
|
|
|
|
|
(textToken.children[0].type === "data") &&
|
|
|
|
|
|
!punctuationRe.test(textToken.text)
|
|
|
|
|
|
) {
|
|
|
|
|
|
addErrorContext(onError, textToken.startLine, textToken.text);
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-03-19 21:20:44 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md037.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md037.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD037", "no-space-in-emphasis" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Spaces inside emphasis markers",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace", "emphasis" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD037(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2023-07-24 21:36:55 -07:00
|
|
|
|
// Initialize variables
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const { lines, parsers } = params;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const emphasisTokensByMarker = new Map();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
for (const marker of [ "_", "__", "___", "*", "**", "***" ]) {
|
2023-07-24 21:36:55 -07:00
|
|
|
|
emphasisTokensByMarker.set(marker, []);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const tokens = filterByPredicate(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
(token) => token.children.some((child) => child.type === "data")
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of tokens) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Build lists of bare tokens for each emphasis marker type
|
|
|
|
|
|
for (const emphasisTokens of emphasisTokensByMarker.values()) {
|
|
|
|
|
|
emphasisTokens.length = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (const child of token.children) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { text, type } = child;
|
|
|
|
|
|
if ((type === "data") && (text.length <= 3)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const emphasisTokens = emphasisTokensByMarker.get(text);
|
|
|
|
|
|
if (emphasisTokens && !inHtmlFlow(child)) {
|
|
|
|
|
|
emphasisTokens.push(child);
|
2023-09-02 12:07:14 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2023-07-24 21:36:55 -07:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Process bare tokens for each emphasis marker type
|
|
|
|
|
|
for (const entry of emphasisTokensByMarker.entries()) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ marker, emphasisTokens ] = entry;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (let i = 0; i + 1 < emphasisTokens.length; i += 2) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Process start token of start/end pair
|
|
|
|
|
|
const startToken = emphasisTokens[i];
|
|
|
|
|
|
const startLine = lines[startToken.startLine - 1];
|
|
|
|
|
|
const startSlice = startLine.slice(startToken.endColumn - 1);
|
|
|
|
|
|
const startMatch = startSlice.match(/^\s+\S/);
|
|
|
|
|
|
if (startMatch) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ startSpaceCharacter ] = startMatch;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const startContext = `${marker}${startSpaceCharacter}`;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startToken.startLine,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
startContext,
|
|
|
|
|
|
[ startToken.startColumn, startContext.length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": startToken.endColumn,
|
|
|
|
|
|
"deleteCount": startSpaceCharacter.length - 1
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
2023-07-24 21:36:55 -07:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Process end token of start/end pair
|
|
|
|
|
|
const endToken = emphasisTokens[i + 1];
|
|
|
|
|
|
const endLine = lines[endToken.startLine - 1];
|
|
|
|
|
|
const endSlice = endLine.slice(0, endToken.startColumn - 1);
|
|
|
|
|
|
const endMatch = endSlice.match(/\S\s+$/);
|
|
|
|
|
|
if (endMatch) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ endSpaceCharacter ] = endMatch;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const endContext = `${endSpaceCharacter}${marker}`;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
endToken.startLine,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
endContext,
|
|
|
|
|
|
[ endToken.endColumn - endContext.length, endContext.length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn":
|
|
|
|
|
|
endToken.startColumn - (endSpaceCharacter.length - 1),
|
|
|
|
|
|
"deleteCount": endSpaceCharacter.length - 1
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-07-24 21:36:55 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md038.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md038.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const { filterByTypes, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
|
|
|
|
|
const rightSpaceRe = /[^`]\s$/;
|
|
|
|
|
|
const trimCodeText = (text, start, end) => {
|
2023-02-23 22:20:27 -08:00
|
|
|
|
text = text.replace(/^\s+$/, "");
|
|
|
|
|
|
if (start) {
|
|
|
|
|
|
text = text.replace(/^\s+?(\s`|\S)/, "$1");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (end) {
|
|
|
|
|
|
text = text.replace(/(`\s|\S)\s+$/, "$1");
|
|
|
|
|
|
}
|
|
|
|
|
|
return text;
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD038", "no-space-in-code" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Spaces inside code span elements",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace", "code" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD038(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const codeTexts = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "codeText" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const codeText of codeTexts) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { children } = codeText;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const first = 0;
|
|
|
|
|
|
const last = children.length - 1;
|
|
|
|
|
|
const startSequence = tokenIfType(children[first], "codeTextSequence");
|
|
|
|
|
|
const endSequence = tokenIfType(children[last], "codeTextSequence");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const startData =
|
|
|
|
|
|
tokenIfType(children[first + 1], "codeTextData") ||
|
|
|
|
|
|
tokenIfType(children[first + 2], "codeTextData");
|
|
|
|
|
|
const endData =
|
|
|
|
|
|
tokenIfType(children[last - 1], "codeTextData") ||
|
|
|
|
|
|
tokenIfType(children[last - 2], "codeTextData");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (startSequence && endSequence && startData && endData) {
|
|
|
|
|
|
const spaceLeft = leftSpaceRe.test(startData.text);
|
|
|
|
|
|
const spaceRight = rightSpaceRe.test(endData.text);
|
|
|
|
|
|
if (spaceLeft || spaceRight) {
|
|
|
|
|
|
let lineNumber = startSequence.startLine;
|
|
|
|
|
|
let range = null;
|
|
|
|
|
|
let fixInfo = null;
|
|
|
|
|
|
if (startSequence.startLine === endSequence.endLine) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [
|
|
|
|
|
|
startSequence.startColumn,
|
|
|
|
|
|
endSequence.endColumn - startSequence.startColumn
|
|
|
|
|
|
];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": startSequence.endColumn,
|
|
|
|
|
|
"deleteCount": endSequence.startColumn - startSequence.endColumn,
|
|
|
|
|
|
"insertText": trimCodeText(startData.text, true, true)
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if (spaceLeft && (startSequence.endLine === startData.startLine)) {
|
|
|
|
|
|
range = [
|
|
|
|
|
|
startSequence.startColumn,
|
|
|
|
|
|
startData.endColumn - startSequence.startColumn
|
|
|
|
|
|
];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": startSequence.endColumn,
|
|
|
|
|
|
"deleteCount": startData.endColumn - startData.startColumn,
|
|
|
|
|
|
"insertText": trimCodeText(startData.text, true, false)
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if (spaceRight && (endData.text.trim().length > 0)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lineNumber = endSequence.endLine;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [
|
|
|
|
|
|
endData.startColumn,
|
|
|
|
|
|
endSequence.endColumn - endData.startColumn
|
|
|
|
|
|
];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": endData.startColumn,
|
|
|
|
|
|
"deleteCount": endData.endColumn - endData.startColumn,
|
|
|
|
|
|
"insertText": trimCodeText(endData.text, false, true)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
if (range) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const context = params
|
|
|
|
|
|
.lines[lineNumber - 1]
|
|
|
|
|
|
.substring(range[0] - 1, range[0] - 1 + range[1]);
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
context,
|
|
|
|
|
|
spaceLeft,
|
|
|
|
|
|
spaceRight,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-02-23 22:20:27 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-02-23 22:20:27 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md039.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md039.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
|
|
|
|
|
|
const spaceInLinkRe =
|
|
|
|
|
|
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD039", "no-space-in-links" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Spaces inside link text",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "whitespace", "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "markdownit",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD039(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
filterTokens(params, "inline", (token) => {
|
|
|
|
|
|
const { children } = token;
|
|
|
|
|
|
let { lineNumber } = token;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let inLink = false;
|
|
|
|
|
|
let linkText = "";
|
|
|
|
|
|
let lineIndex = 0;
|
|
|
|
|
|
for (const child of children) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { content, markup, type } = child;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (type === "link_open") {
|
|
|
|
|
|
inLink = true;
|
|
|
|
|
|
linkText = "";
|
|
|
|
|
|
} else if (type === "link_close") {
|
|
|
|
|
|
inLink = false;
|
|
|
|
|
|
const left = linkText.trimStart().length !== linkText.length;
|
|
|
|
|
|
const right = linkText.trimEnd().length !== linkText.length;
|
|
|
|
|
|
if (left || right) {
|
|
|
|
|
|
const line = params.lines[lineNumber - 1];
|
|
|
|
|
|
let range = null;
|
|
|
|
|
|
let fixInfo = null;
|
|
|
|
|
|
const match = line.slice(lineIndex).match(spaceInLinkRe);
|
|
|
|
|
|
if (match) {
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// @ts-ignore
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const column = match.index + lineIndex + 1;
|
|
|
|
|
|
const length = match[0].length;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ column, length ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": column + 1,
|
|
|
|
|
|
"deleteCount": length - 2,
|
|
|
|
|
|
"insertText": linkText.trim()
|
|
|
|
|
|
};
|
|
|
|
|
|
lineIndex = column + length - 1;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineNumber,
|
|
|
|
|
|
`[${linkText}]`,
|
|
|
|
|
|
left,
|
|
|
|
|
|
right,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
} else if ((type === "softbreak") || (type === "hardbreak")) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
lineNumber++;
|
|
|
|
|
|
lineIndex = 0;
|
|
|
|
|
|
} else if (inLink) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
linkText += type.endsWith("_inline") ?
|
|
|
|
|
|
`${markup}${content}${markup}` :
|
|
|
|
|
|
(content || markup);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md040.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md040.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-18 17:22:32 -08:00
|
|
|
|
const { addError, addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getTokenTextByType, tokenIfType } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD040", "fenced-code-language" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Fenced code blocks should have a language specified",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "code", "language" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD040(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let allowed = params.config.allowed_languages;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
allowed = Array.isArray(allowed) ? allowed : [];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const languageOnly = !!params.config.language_only;
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const fencedCodes = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "codeFenced" ]
|
|
|
|
|
|
);
|
2024-02-18 17:22:32 -08:00
|
|
|
|
for (const fencedCode of fencedCodes) {
|
|
|
|
|
|
const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
|
|
|
|
|
|
if (openingFence) {
|
|
|
|
|
|
const { children, startLine, text } = openingFence;
|
2024-03-20 20:24:55 -07:00
|
|
|
|
const info = getTokenTextByType(children, "codeFencedFenceInfo");
|
2024-02-18 17:22:32 -08:00
|
|
|
|
if (!info) {
|
|
|
|
|
|
addErrorContext(onError, startLine, text);
|
|
|
|
|
|
} else if ((allowed.length > 0) && !allowed.includes(info)) {
|
|
|
|
|
|
addError(onError, startLine, `"${info}" is not allowed`);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (languageOnly && getTokenTextByType(children, "codeFencedFenceMeta")) {
|
|
|
|
|
|
addError(onError, startLine, `Info string contains more than language: "${text}"`);
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-18 17:22:32 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md041.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md041.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-03-18 20:48:22 -07:00
|
|
|
|
const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD041", "first-line-heading", "first-line-h1" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "First line in a file should be a top-level heading",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-03-18 20:48:22 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD041(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const level = Number(params.config.level || 1);
|
2024-03-18 20:48:22 -07:00
|
|
|
|
if (!frontMatterHasTitle(params.frontMatterLines, params.config.front_matter_title)) {
|
|
|
|
|
|
params.parsers.micromark.tokens.
|
|
|
|
|
|
filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token)).
|
|
|
|
|
|
every((token) => {
|
|
|
|
|
|
let isError = true;
|
|
|
|
|
|
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
|
|
|
|
|
isError = (getHeadingLevel(token) !== level);
|
|
|
|
|
|
} else if (token.type === "htmlFlow") {
|
2024-06-09 17:09:03 -07:00
|
|
|
|
const htmlTexts = filterByTypes(token.children, [ "htmlText" ], true);
|
2024-03-18 20:48:22 -07:00
|
|
|
|
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
|
|
|
|
|
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-03-18 20:48:22 -07:00
|
|
|
|
if (isError) {
|
|
|
|
|
|
addErrorContext(onError, token.startLine, params.lines[token.startLine - 1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md042.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md042.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-29 16:45:40 -07:00
|
|
|
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { getDescendantsByType, filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD042", "no-empty-links" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "No empty links",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "links" ],
|
2024-06-29 16:45:40 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD042(params, onError) {
|
2024-06-29 16:45:40 -07:00
|
|
|
|
const { definitions } = referenceLinkImageData();
|
|
|
|
|
|
const isReferenceDefinitionHash = (token) => {
|
|
|
|
|
|
const definition = definitions.get(token.text.trim());
|
|
|
|
|
|
return (definition && (definition[1] === "#"));
|
|
|
|
|
|
};
|
|
|
|
|
|
const links = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "link" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const link of links) {
|
|
|
|
|
|
const labelText = getDescendantsByType(link, [ "label", "labelText" ]);
|
|
|
|
|
|
const reference = getDescendantsByType(link, [ "reference" ]);
|
|
|
|
|
|
const resource = getDescendantsByType(link, [ "resource" ]);
|
|
|
|
|
|
const referenceString = getDescendantsByType(reference, [ "referenceString" ]);
|
|
|
|
|
|
const resourceDestination = getDescendantsByType(resource, [ "resourceDestination" ]);
|
|
|
|
|
|
const resourceDestinationString = [
|
|
|
|
|
|
...getDescendantsByType(resourceDestination, [ "resourceDestinationRaw", "resourceDestinationString" ]),
|
|
|
|
|
|
...getDescendantsByType(resourceDestination, [ "resourceDestinationLiteral", "resourceDestinationString" ])
|
|
|
|
|
|
];
|
|
|
|
|
|
const hasLabelText = labelText.length > 0;
|
|
|
|
|
|
const hasReference = reference.length > 0;
|
|
|
|
|
|
const hasResource = resource.length > 0;
|
|
|
|
|
|
const hasReferenceString = referenceString.length > 0;
|
|
|
|
|
|
const hasResourceDestinationString = resourceDestinationString.length > 0;
|
|
|
|
|
|
let error = false;
|
|
|
|
|
|
if (
|
|
|
|
|
|
hasLabelText &&
|
|
|
|
|
|
((!hasReference && !hasResource) || (hasReference && !hasReferenceString))
|
|
|
|
|
|
) {
|
|
|
|
|
|
error = isReferenceDefinitionHash(labelText[0]);
|
|
|
|
|
|
} else if (hasReferenceString && !hasResourceDestinationString) {
|
|
|
|
|
|
error = isReferenceDefinitionHash(referenceString[0]);
|
|
|
|
|
|
} else if (!hasReferenceString && hasResourceDestinationString) {
|
|
|
|
|
|
error = (resourceDestinationString[0].text.trim() === "#");
|
|
|
|
|
|
} else if (!hasReferenceString && !hasResourceDestinationString) {
|
|
|
|
|
|
error = true;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-06-29 16:45:40 -07:00
|
|
|
|
if (error) {
|
|
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
link.startLine,
|
|
|
|
|
|
link.text,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ link.startColumn, link.endColumn - link.startColumn ]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md043.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md043.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-06-22 14:37:32 -07:00
|
|
|
|
const { addErrorContext, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD043", "required-headings" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Required heading structure",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "headings" ],
|
2024-06-22 14:37:32 -07:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD043(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const requiredHeadings = params.config.headings;
|
2023-08-29 23:00:27 -07:00
|
|
|
|
if (!Array.isArray(requiredHeadings)) {
|
|
|
|
|
|
// Nothing to check; avoid doing any work
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const matchCase = params.config.match_case || false;
|
|
|
|
|
|
let i = 0;
|
|
|
|
|
|
let matchAny = false;
|
|
|
|
|
|
let hasError = false;
|
|
|
|
|
|
let anyHeadings = false;
|
|
|
|
|
|
const getExpected = () => requiredHeadings[i++] || "[None]";
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const handleCase = (str) => (matchCase ? str : str.toLowerCase());
|
2024-06-22 14:37:32 -07:00
|
|
|
|
const headings = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "atxHeading", "setextHeading" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const heading of headings) {
|
2023-08-29 23:00:27 -07:00
|
|
|
|
if (!hasError) {
|
2024-06-22 14:37:32 -07:00
|
|
|
|
const headingText = getHeadingText(heading);
|
|
|
|
|
|
const headingLevel = getHeadingLevel(heading);
|
2023-08-29 23:00:27 -07:00
|
|
|
|
anyHeadings = true;
|
2024-06-22 14:37:32 -07:00
|
|
|
|
const actual = `${"".padEnd(headingLevel, "#")} ${headingText}`;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const expected = getExpected();
|
2023-08-29 23:00:27 -07:00
|
|
|
|
if (expected === "*") {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const nextExpected = getExpected();
|
2023-08-29 23:00:27 -07:00
|
|
|
|
if (handleCase(nextExpected) !== handleCase(actual)) {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
matchAny = true;
|
|
|
|
|
|
i--;
|
|
|
|
|
|
}
|
2023-08-29 23:00:27 -07:00
|
|
|
|
} else if (expected === "+") {
|
|
|
|
|
|
matchAny = true;
|
|
|
|
|
|
} else if (handleCase(expected) === handleCase(actual)) {
|
|
|
|
|
|
matchAny = false;
|
|
|
|
|
|
} else if (matchAny) {
|
|
|
|
|
|
i--;
|
|
|
|
|
|
} else {
|
2024-06-22 14:37:32 -07:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
heading.startLine,
|
|
|
|
|
|
expected,
|
|
|
|
|
|
actual
|
|
|
|
|
|
);
|
2023-08-29 23:00:27 -07:00
|
|
|
|
hasError = true;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-22 14:37:32 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const extraHeadings = requiredHeadings.length - i;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!hasError &&
|
|
|
|
|
|
((extraHeadings > 1) ||
|
|
|
|
|
|
((extraHeadings === 1) && (requiredHeadings[i] !== "*"))) &&
|
|
|
|
|
|
(anyHeadings || !requiredHeadings.every((heading) => heading === "*"))
|
|
|
|
|
|
) {
|
2024-06-22 14:37:32 -07:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
params.lines.length,
|
|
|
|
|
|
requiredHeadings[i]
|
|
|
|
|
|
);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md044.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md044.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, escapeForRegExp, withinAnyRange } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByPredicate, filterByTypes, parse } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
const ignoredChildTypes = new Set(
|
|
|
|
|
|
[ "codeFencedFence", "definition", "reference", "resource" ]
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD044", "proper-names" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Proper names should have the correct capitalization",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "spelling" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD044(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let names = params.config.names;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
names = Array.isArray(names) ? names : [];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
names.sort((a, b) => (b.length - a.length) || a.localeCompare(b));
|
2023-08-27 23:35:00 -07:00
|
|
|
|
if (names.length === 0) {
|
|
|
|
|
|
// Nothing to check; avoid doing any work
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const codeBlocks = params.config.code_blocks;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeCodeBlocks =
|
|
|
|
|
|
(codeBlocks === undefined) ? true : !!codeBlocks;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlElements = params.config.html_elements;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const includeHtmlElements =
|
|
|
|
|
|
(htmlElements === undefined) ? true : !!htmlElements;
|
|
|
|
|
|
const scannedTypes = new Set([ "data" ]);
|
2023-03-14 21:03:07 -07:00
|
|
|
|
if (includeCodeBlocks) {
|
|
|
|
|
|
scannedTypes.add("codeFlowValue");
|
|
|
|
|
|
scannedTypes.add("codeTextData");
|
|
|
|
|
|
}
|
2023-09-02 12:07:14 -07:00
|
|
|
|
if (includeHtmlElements) {
|
|
|
|
|
|
scannedTypes.add("htmlFlowData");
|
|
|
|
|
|
scannedTypes.add("htmlTextData");
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const contentTokens =
|
|
|
|
|
|
filterByPredicate(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
params.parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
(token) => scannedTypes.has(token.type),
|
|
|
|
|
|
(token) => (
|
|
|
|
|
|
token.children.filter((t) => !ignoredChildTypes.has(t.type))
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const exclusions = [];
|
|
|
|
|
|
const autoLinked = new Set();
|
|
|
|
|
|
for (const name of names) {
|
|
|
|
|
|
const escapedName = escapeForRegExp(name);
|
|
|
|
|
|
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
|
|
|
|
|
|
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const namePattern =
|
|
|
|
|
|
`(${startNamePattern})(${escapedName})${endNamePattern}`;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const nameRe = new RegExp(namePattern, "gi");
|
|
|
|
|
|
for (const token of contentTokens) {
|
|
|
|
|
|
let match = null;
|
|
|
|
|
|
while ((match = nameRe.exec(token.text)) !== null) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ , leftMatch, nameMatch ] = match;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const index = token.startColumn - 1 + match.index + leftMatch.length;
|
|
|
|
|
|
const length = nameMatch.length;
|
|
|
|
|
|
const lineIndex = token.startLine - 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
!withinAnyRange(exclusions, lineIndex, index, length) &&
|
|
|
|
|
|
!names.includes(nameMatch)
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let urlRanges = [];
|
|
|
|
|
|
if (!autoLinked.has(token)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
urlRanges = filterByTypes(
|
|
|
|
|
|
parse(token.text),
|
|
|
|
|
|
[ "literalAutolink" ]
|
|
|
|
|
|
).map(
|
|
|
|
|
|
(t) => [
|
|
|
|
|
|
lineIndex,
|
|
|
|
|
|
token.startColumn - 1 + t.startColumn - 1,
|
|
|
|
|
|
t.endColumn - t.startColumn
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
exclusions.push(...urlRanges);
|
|
|
|
|
|
autoLinked.add(token);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!withinAnyRange(urlRanges, lineIndex, index, length)) {
|
|
|
|
|
|
const column = index + 1;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
token.startLine,
|
|
|
|
|
|
name,
|
|
|
|
|
|
nameMatch,
|
2024-06-21 21:03:30 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ column, length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": column,
|
|
|
|
|
|
"deleteCount": length,
|
|
|
|
|
|
"insertText": name
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2021-06-13 13:07:03 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
exclusions.push([ lineIndex, index, length ]);
|
2023-03-14 21:03:07 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md045.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md045.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, getHtmlAttributeRe, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const altRe = getHtmlAttributeRe("alt");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD045", "no-alt-text" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Images should have alternate text (alt text)",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "accessibility", "images" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD045(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const micromarkTokens = params.parsers.micromark.tokens;
|
2023-10-18 23:20:19 -07:00
|
|
|
|
|
|
|
|
|
|
// Process Markdown images
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const images = filterByTypes(
|
|
|
|
|
|
micromarkTokens,
|
|
|
|
|
|
[ "image" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const image of images) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const labelTexts = filterByTypes(image.children, [ "labelText" ]);
|
|
|
|
|
|
if (labelTexts.some((labelText) => labelText.text.length === 0)) {
|
|
|
|
|
|
const range = (image.startLine === image.endLine) ?
|
|
|
|
|
|
[ image.startColumn, image.endColumn - image.startColumn ] :
|
|
|
|
|
|
undefined;
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
image.startLine,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
range
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-07-28 20:19:30 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
|
|
|
|
|
|
// Process HTML images
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const htmlTexts = filterByTypes(
|
|
|
|
|
|
micromarkTokens,
|
|
|
|
|
|
[ "htmlText" ],
|
|
|
|
|
|
true
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const htmlText of htmlTexts) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { startColumn, startLine, text } = htmlText;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
htmlTagInfo &&
|
|
|
|
|
|
!htmlTagInfo.close &&
|
|
|
|
|
|
(htmlTagInfo.name.toLowerCase() === "img") &&
|
|
|
|
|
|
!altRe.test(text)
|
|
|
|
|
|
) {
|
|
|
|
|
|
const range = [
|
|
|
|
|
|
startColumn,
|
|
|
|
|
|
text.replace(nextLinesRe, "").length
|
|
|
|
|
|
];
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
range
|
|
|
|
|
|
);
|
2023-10-18 23:20:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md046.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md046.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-02-19 20:30:35 -08:00
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const tokenTypeToStyle = {
|
2024-02-19 20:30:35 -08:00
|
|
|
|
"codeFenced": "fenced",
|
|
|
|
|
|
"codeIndented": "indented"
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD046", "code-block-style" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Code block style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "code" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD046(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let expectedStyle = String(params.config.style || "consistent");
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const codeBlocksAndFences = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "codeFenced", "codeIndented" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const token of codeBlocksAndFences) {
|
2024-02-19 20:30:35 -08:00
|
|
|
|
const { startLine, type } = token;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (expectedStyle === "consistent") {
|
|
|
|
|
|
expectedStyle = tokenTypeToStyle[type];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
2024-02-19 20:30:35 -08:00
|
|
|
|
startLine,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
expectedStyle,
|
|
|
|
|
|
tokenTypeToStyle[type]);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md047.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md047.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD047", "single-trailing-newline" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Files should end with a single newline character",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "blank_lines" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD047(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lastLineNumber = params.lines.length;
|
|
|
|
|
|
const lastLine = params.lines[lastLineNumber - 1];
|
2023-01-17 04:19:40 +00:00
|
|
|
|
if (!isBlankLine(lastLine)) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lastLineNumber,
|
2024-02-27 20:42:09 -08:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
[ lastLine.length, 1 ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"insertText": "\n",
|
|
|
|
|
|
"editColumn": lastLine.length + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2019-10-02 20:10:42 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/md048.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md048.js ***!
|
|
|
|
|
|
\***********************/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
2019-10-02 20:10:42 -07:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf, fencedCodeBlockStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
2024-02-19 20:42:12 -08:00
|
|
|
|
const { filterByTypes, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2019-12-14 13:50:48 -08:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD048", "code-fence-style" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Code fence style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "code" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD048(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const style = String(params.config.style || "consistent");
|
|
|
|
|
|
let expectedStyle = style;
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const codeFenceds = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "codeFenced" ]
|
|
|
|
|
|
);
|
2024-02-19 20:42:12 -08:00
|
|
|
|
for (const codeFenced of codeFenceds) {
|
|
|
|
|
|
const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
|
|
|
|
|
|
if (codeFencedFence) {
|
|
|
|
|
|
const codeFencedFenceSequence = tokenIfType(codeFencedFence.children[0], "codeFencedFenceSequence");
|
|
|
|
|
|
if (codeFencedFenceSequence) {
|
|
|
|
|
|
const { startLine, text } = codeFencedFenceSequence;
|
|
|
|
|
|
if (expectedStyle === "consistent") {
|
|
|
|
|
|
expectedStyle = fencedCodeBlockStyleFor(text);
|
|
|
|
|
|
}
|
|
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
expectedStyle,
|
|
|
|
|
|
fencedCodeBlockStyleFor(text)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-12-14 13:50:48 -08:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2019-12-14 13:50:48 -08:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-10-24 06:54:58 +02:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2022-05-03 21:37:30 -07:00
|
|
|
|
/***/ "../lib/md049-md050.js":
|
|
|
|
|
|
/*!*****************************!*\
|
|
|
|
|
|
!*** ../lib/md049-md050.js ***!
|
|
|
|
|
|
\*****************************/
|
2021-10-24 06:54:58 +02:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2021-10-21 06:42:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, emphasisOrStrongStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByPredicate, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
2024-02-19 15:41:10 -08:00
|
|
|
|
const intrawordRe = /^\w$/;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-29 23:05:27 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* @param {import("./markdownlint").RuleParams} params Rule parameters.
|
|
|
|
|
|
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
2024-03-04 21:38:18 -08:00
|
|
|
|
* @param {import("markdownlint-micromark").TokenType} type Token type.
|
|
|
|
|
|
* @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type.
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {"*" | "**"} asterisk Asterisk kind.
|
|
|
|
|
|
* @param {"_" | "__"} underline Underline kind.
|
|
|
|
|
|
* @param {"asterisk" | "consistent" | "underscore"} style Style string.
|
|
|
|
|
|
*/
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const impl =
|
2024-02-29 23:05:27 -08:00
|
|
|
|
(params, onError, type, typeSequence, asterisk, underline, style = "consistent") => {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const { lines, parsers } = params;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const emphasisTokens = filterByPredicate(
|
2024-06-21 21:03:30 -07:00
|
|
|
|
parsers.micromark.tokens,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
(token) => token.type === type,
|
|
|
|
|
|
(token) => ((token.type === "htmlFlow") ? [] : token.children)
|
|
|
|
|
|
);
|
|
|
|
|
|
for (const token of emphasisTokens) {
|
|
|
|
|
|
const { children } = token;
|
2024-02-29 23:05:27 -08:00
|
|
|
|
const startSequence = tokenIfType(children[0], typeSequence);
|
|
|
|
|
|
const endSequence = tokenIfType(children[children.length - 1], typeSequence);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (startSequence && endSequence) {
|
|
|
|
|
|
const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
|
|
|
|
|
|
if (style === "consistent") {
|
|
|
|
|
|
style = markupStyle;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (style !== markupStyle) {
|
|
|
|
|
|
const underscoreIntraword = (style === "underscore") && (
|
|
|
|
|
|
intrawordRe.test(
|
|
|
|
|
|
lines[startSequence.startLine - 1][startSequence.startColumn - 2]
|
|
|
|
|
|
) ||
|
|
|
|
|
|
intrawordRe.test(
|
|
|
|
|
|
lines[endSequence.endLine - 1][endSequence.endColumn - 1]
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
if (!underscoreIntraword) {
|
|
|
|
|
|
for (const sequence of [ startSequence, endSequence ]) {
|
|
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
sequence.startLine,
|
|
|
|
|
|
`Expected: ${style}; Actual: ${markupStyle}`,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
[ sequence.startColumn, sequence.text.length ],
|
|
|
|
|
|
{
|
|
|
|
|
|
"editColumn": sequence.startColumn,
|
|
|
|
|
|
"deleteCount": sequence.text.length,
|
|
|
|
|
|
"insertText": (style === "asterisk") ? asterisk : underline
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2023-05-25 03:47:34 +00:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-29 23:05:27 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule[] */
|
2024-02-17 15:46:13 -08:00
|
|
|
|
module.exports = [
|
|
|
|
|
|
{
|
|
|
|
|
|
"names": [ "MD049", "emphasis-style" ],
|
|
|
|
|
|
"description": "Emphasis style",
|
|
|
|
|
|
"tags": [ "emphasis" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"function": function MD049(params, onError) {
|
|
|
|
|
|
return impl(
|
|
|
|
|
|
params,
|
|
|
|
|
|
onError,
|
|
|
|
|
|
"emphasis",
|
2024-02-29 23:05:27 -08:00
|
|
|
|
"emphasisSequence",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"*",
|
|
|
|
|
|
"_",
|
|
|
|
|
|
params.config.style || undefined
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"names": [ "MD050", "strong-style" ],
|
|
|
|
|
|
"description": "Strong style",
|
|
|
|
|
|
"tags": [ "emphasis" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"function": function MD050(params, onError) {
|
|
|
|
|
|
return impl(
|
|
|
|
|
|
params,
|
|
|
|
|
|
onError,
|
|
|
|
|
|
"strong",
|
2024-02-29 23:05:27 -08:00
|
|
|
|
"strongSequence",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"**",
|
|
|
|
|
|
"__",
|
|
|
|
|
|
params.config.style || undefined
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2023-05-25 03:47:34 +00:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
];
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-01-26 00:21:08 +01:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib/md051.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md051.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, addErrorDetailIf, getHtmlAttributeRe } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByPredicate, filterByTypes, getHtmlTagInfo } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2022-04-10 05:37:57 +00:00
|
|
|
|
// Regular expression for identifying HTML anchor names
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const idRe = getHtmlAttributeRe("id");
|
|
|
|
|
|
const nameRe = getHtmlAttributeRe("name");
|
|
|
|
|
|
const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu;
|
2024-02-10 15:36:12 -08:00
|
|
|
|
const lineFragmentRe = /^#(?:L\d+(?:C\d+)?-L\d+(?:C\d+)?|L\d+)$/;
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
2023-09-04 12:26:38 -07:00
|
|
|
|
// Sets for filtering heading tokens during conversion
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const childrenExclude = new Set([ "image", "reference", "resource" ]);
|
|
|
|
|
|
const tokensInclude = new Set(
|
2024-03-17 14:31:49 -07:00
|
|
|
|
[ "characterEscapeValue", "codeTextData", "data", "mathTextData" ]
|
2024-02-17 15:46:13 -08:00
|
|
|
|
);
|
2023-09-04 12:26:38 -07:00
|
|
|
|
|
2022-01-26 00:21:08 +01:00
|
|
|
|
/**
|
2022-04-10 05:37:57 +00:00
|
|
|
|
* Converts a Markdown heading into an HTML fragment according to the rules
|
|
|
|
|
|
* used by GitHub.
|
2022-01-26 00:21:08 +01:00
|
|
|
|
*
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {import("../helpers/micromark.cjs").Token} headingText Heading text token.
|
2022-04-10 05:37:57 +00:00
|
|
|
|
* @returns {string} Fragment string for heading.
|
2022-01-26 00:21:08 +01:00
|
|
|
|
*/
|
2023-08-04 20:53:38 -07:00
|
|
|
|
function convertHeadingToHTMLFragment(headingText) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const inlineText =
|
|
|
|
|
|
filterByPredicate(
|
|
|
|
|
|
headingText.children,
|
|
|
|
|
|
(token) => tokensInclude.has(token.type),
|
|
|
|
|
|
(token) => (childrenExclude.has(token.type) ? [] : token.children)
|
|
|
|
|
|
)
|
|
|
|
|
|
.map((token) => token.text)
|
|
|
|
|
|
.join("");
|
|
|
|
|
|
return "#" + encodeURIComponent(
|
|
|
|
|
|
inlineText
|
|
|
|
|
|
.toLowerCase()
|
|
|
|
|
|
// RegExp source with Ruby's \p{Word} expanded into its General Categories
|
|
|
|
|
|
// https://github.com/gjtorikian/html-pipeline/blob/main/lib/html/pipeline/toc_filter.rb
|
|
|
|
|
|
// https://ruby-doc.org/core-3.0.2/Regexp.html
|
|
|
|
|
|
.replace(
|
|
|
|
|
|
/[^\p{Letter}\p{Mark}\p{Number}\p{Connector_Punctuation}\- ]/gu,
|
|
|
|
|
|
""
|
|
|
|
|
|
)
|
|
|
|
|
|
.replace(/ /gu, "-")
|
|
|
|
|
|
);
|
2022-01-26 00:21:08 +01:00
|
|
|
|
}
|
2023-09-06 21:25:00 -07:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Unescapes the text of a String-type micromark Token.
|
|
|
|
|
|
*
|
2024-02-29 23:05:27 -08:00
|
|
|
|
* @param {import("../helpers/micromark.cjs").Token} token String-type micromark Token.
|
2023-09-06 21:25:00 -07:00
|
|
|
|
* @returns {string} Unescaped token text.
|
|
|
|
|
|
*/
|
|
|
|
|
|
function unescapeStringTokenText(token) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
return filterByTypes(token.children, [ "characterEscapeValue", "data" ])
|
|
|
|
|
|
.map((child) => child.text)
|
|
|
|
|
|
.join("");
|
2023-09-06 21:25:00 -07:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2022-01-26 00:21:08 +01:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD051", "link-fragments" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Link fragments should be valid",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD051(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const micromarkTokens = params.parsers.micromark.tokens;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const fragments = new Map();
|
2023-08-04 20:53:38 -07:00
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Process headings
|
2024-02-28 21:01:23 -08:00
|
|
|
|
const headingTexts = filterByTypes(micromarkTokens, [ "atxHeadingText", "setextHeadingText" ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const headingText of headingTexts) {
|
|
|
|
|
|
const fragment = convertHeadingToHTMLFragment(headingText);
|
|
|
|
|
|
if (fragment !== "#") {
|
|
|
|
|
|
const count = fragments.get(fragment) || 0;
|
|
|
|
|
|
if (count) {
|
|
|
|
|
|
fragments.set(`${fragment}-${count}`, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
fragments.set(fragment, count + 1);
|
|
|
|
|
|
let match = null;
|
|
|
|
|
|
while ((match = anchorRe.exec(headingText.text)) !== null) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ , anchor ] = match;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (!fragments.has(anchor)) {
|
|
|
|
|
|
fragments.set(anchor, 1);
|
2023-08-04 20:53:38 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-08-04 20:53:38 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
|
|
|
|
|
|
// Process HTML anchors
|
2024-06-09 17:09:03 -07:00
|
|
|
|
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ], true)) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const htmlTagInfo = getHtmlTagInfo(token);
|
|
|
|
|
|
if (htmlTagInfo && !htmlTagInfo.close) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const anchorMatch = idRe.exec(token.text) ||
|
|
|
|
|
|
(htmlTagInfo.name.toLowerCase() === "a" && nameRe.exec(token.text));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (anchorMatch && anchorMatch.length > 0) {
|
|
|
|
|
|
fragments.set(`#${anchorMatch[1]}`, 0);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2023-08-04 20:53:38 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
|
|
|
|
|
|
// Process link and definition fragments
|
2024-02-29 23:05:27 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("../helpers/micromark.cjs").TokenType[][] */
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const parentChilds = [
|
|
|
|
|
|
[ "link", "resourceDestinationString" ],
|
|
|
|
|
|
[ "definition", "definitionDestinationString" ]
|
|
|
|
|
|
];
|
|
|
|
|
|
for (const [ parentType, definitionType ] of parentChilds) {
|
2024-02-28 21:01:23 -08:00
|
|
|
|
const links = filterByTypes(micromarkTokens, [ parentType ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const link of links) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const definitions = filterByTypes(link.children, [ definitionType ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const definition of definitions) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { endColumn, startColumn } = definition;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const text = unescapeStringTokenText(definition);
|
2024-02-07 20:45:56 +01:00
|
|
|
|
const encodedText = `#${encodeURIComponent(text.slice(1))}`;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
if (
|
|
|
|
|
|
(text.length > 1) &&
|
|
|
|
|
|
text.startsWith("#") &&
|
|
|
|
|
|
!fragments.has(encodedText) &&
|
|
|
|
|
|
!lineFragmentRe.test(encodedText)
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let context = undefined;
|
|
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let range = undefined;
|
|
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let fixInfo = undefined;
|
|
|
|
|
|
if (link.startLine === link.endLine) {
|
|
|
|
|
|
context = link.text;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ link.startColumn, link.endColumn - link.startColumn ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": startColumn,
|
|
|
|
|
|
"deleteCount": endColumn - startColumn
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
const textLower = text.toLowerCase();
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const mixedCaseKey = [ ...fragments.keys() ]
|
|
|
|
|
|
.find((key) => textLower === key.toLowerCase());
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (mixedCaseKey) {
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
(fixInfo || {}).insertText = mixedCaseKey;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
link.startLine,
|
|
|
|
|
|
mixedCaseKey,
|
|
|
|
|
|
text,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
context,
|
|
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} else {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
link.startLine,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
context,
|
|
|
|
|
|
range
|
|
|
|
|
|
);
|
2023-08-04 20:53:38 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-08-04 20:53:38 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2022-01-26 00:21:08 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib/md052.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md052.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2022-06-01 20:23:08 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD052", "reference-links-images" ],
|
|
|
|
|
|
"description":
|
|
|
|
|
|
"Reference links and images should use a label that is defined",
|
|
|
|
|
|
"tags": [ "images", "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD052(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { config, lines } = params;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const shortcutSyntax = config.shortcut_syntax || false;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { definitions, references, shortcuts } = referenceLinkImageData();
|
|
|
|
|
|
const entries = shortcutSyntax ?
|
|
|
|
|
|
[ ...references.entries(), ...shortcuts.entries() ] :
|
|
|
|
|
|
references.entries();
|
2023-01-17 04:19:40 +00:00
|
|
|
|
// Look for links/images that use an undefined link reference
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const reference of entries) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ label, datas ] = reference;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (!definitions.has(label)) {
|
|
|
|
|
|
for (const data of datas) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ lineIndex, index, length ] = data;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Context will be incomplete if reporting for a multi-line link
|
|
|
|
|
|
const context = lines[lineIndex].slice(index, index + length);
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
`Missing link or image reference definition: "${label}"`,
|
|
|
|
|
|
context,
|
|
|
|
|
|
[ index + 1, context.length ]
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-06-01 20:23:08 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2022-06-01 20:23:08 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2022-06-01 20:23:08 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib/md053.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md053.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addError, ellipsify, linkReferenceDefinitionRe } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2022-06-01 20:23:08 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD053", "link-image-reference-definitions" ],
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"description": "Link and image reference definitions should be needed",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "images", "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "none",
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"function": function MD053(params, onError) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const ignored = new Set(params.config.ignored_definitions || [ "//" ]);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lines = params.lines;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { references, shortcuts, definitions, duplicateDefinitions } =
|
|
|
|
|
|
referenceLinkImageData();
|
|
|
|
|
|
const singleLineDefinition = (line) => (
|
|
|
|
|
|
line.replace(linkReferenceDefinitionRe, "").trim().length > 0
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const deleteFixInfo = {
|
2023-01-17 04:19:40 +00:00
|
|
|
|
"deleteCount": -1
|
|
|
|
|
|
};
|
|
|
|
|
|
// Look for unused link references (unreferenced by any link/image)
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const definition of definitions.entries()) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ label, [ lineIndex ] ] = definition;
|
|
|
|
|
|
if (
|
|
|
|
|
|
!ignored.has(label) &&
|
|
|
|
|
|
!references.has(label) &&
|
|
|
|
|
|
!shortcuts.has(label)
|
|
|
|
|
|
) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const line = lines[lineIndex];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
`Unused link or image reference definition: "${label}"`,
|
|
|
|
|
|
ellipsify(line),
|
|
|
|
|
|
[ 1, line.length ],
|
|
|
|
|
|
singleLineDefinition(line) ? deleteFixInfo : 0
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// Look for duplicate link references (defined more than once)
|
|
|
|
|
|
for (const duplicateDefinition of duplicateDefinitions) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const [ label, lineIndex ] = duplicateDefinition;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (!ignored.has(label)) {
|
|
|
|
|
|
const line = lines[lineIndex];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addError(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lineIndex + 1,
|
|
|
|
|
|
`Duplicate link or image reference definition: "${label}"`,
|
|
|
|
|
|
ellipsify(line),
|
|
|
|
|
|
[ 1, line.length ],
|
|
|
|
|
|
singleLineDefinition(line) ? deleteFixInfo : 0
|
|
|
|
|
|
);
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2022-06-01 20:23:08 -07:00
|
|
|
|
}
|
2023-01-17 04:19:40 +00:00
|
|
|
|
}
|
2022-06-01 20:23:08 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2023-10-25 20:05:19 -07:00
|
|
|
|
/***/ "../lib/md054.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md054.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorContext, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes, filterByPredicate, getTokenTextByType } =
|
|
|
|
|
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
|
|
|
|
|
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const removeBackslashEscapes = (text) => text.replace(backslashEscapeRe, "$1");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const autolinkDisallowedRe = /[ <>]/;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const autolinkAble = (destination) => {
|
2023-10-25 20:05:19 -07:00
|
|
|
|
try {
|
|
|
|
|
|
// eslint-disable-next-line no-new
|
|
|
|
|
|
new URL(destination);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} catch {
|
2023-10-25 20:05:19 -07:00
|
|
|
|
// Not an absolute URL
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return !autolinkDisallowedRe.test(destination);
|
|
|
|
|
|
};
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2023-10-25 20:05:19 -07:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD054", "link-image-style" ],
|
2023-10-25 20:05:19 -07:00
|
|
|
|
"description": "Link and image style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "images", "links" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2024-01-06 20:47:01 -08:00
|
|
|
|
"function": (params, onError) => {
|
2024-02-28 21:01:23 -08:00
|
|
|
|
const config = params.config;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const autolink = (config.autolink === undefined) || !!config.autolink;
|
|
|
|
|
|
const inline = (config.inline === undefined) || !!config.inline;
|
|
|
|
|
|
const full = (config.full === undefined) || !!config.full;
|
|
|
|
|
|
const collapsed = (config.collapsed === undefined) || !!config.collapsed;
|
|
|
|
|
|
const shortcut = (config.shortcut === undefined) || !!config.shortcut;
|
|
|
|
|
|
const urlInline = (config.url_inline === undefined) || !!config.url_inline;
|
2023-11-12 22:42:02 -08:00
|
|
|
|
if (autolink && inline && full && collapsed && shortcut && urlInline) {
|
2023-10-25 20:05:19 -07:00
|
|
|
|
// Everything allowed, nothing to check
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { definitions } = referenceLinkImageData();
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const links = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "autolink", "image", "link" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const link of links) {
|
|
|
|
|
|
let label = null;
|
|
|
|
|
|
let destination = null;
|
|
|
|
|
|
const {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
children, endColumn, endLine, startColumn, startLine, text, type
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} = link;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const image = (type === "image");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let isError = false;
|
|
|
|
|
|
if (type === "autolink") {
|
|
|
|
|
|
// link kind is an autolink
|
|
|
|
|
|
destination = getTokenTextByType(children, "autolinkProtocol");
|
|
|
|
|
|
label = destination;
|
|
|
|
|
|
isError = !autolink;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// link type is "image" or "link"
|
|
|
|
|
|
const descendents = filterByPredicate(children);
|
|
|
|
|
|
label = getTokenTextByType(descendents, "labelText");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
destination =
|
|
|
|
|
|
getTokenTextByType(descendents, "resourceDestinationString");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (destination) {
|
|
|
|
|
|
// link kind is an inline link
|
|
|
|
|
|
const title = getTokenTextByType(descendents, "resourceTitleString");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
isError = !inline || (
|
|
|
|
|
|
!urlInline &&
|
|
|
|
|
|
autolink &&
|
|
|
|
|
|
!image &&
|
|
|
|
|
|
!title &&
|
|
|
|
|
|
(label === destination) &&
|
|
|
|
|
|
autolinkAble(destination)
|
|
|
|
|
|
);
|
2023-10-25 20:05:19 -07:00
|
|
|
|
} else {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// link kind is a full/collapsed/shortcut reference link
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const isShortcut = !children.some((t) => t.type === "reference");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const referenceString = getTokenTextByType(descendents, "referenceString");
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const isCollapsed = (referenceString === null);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const definition = definitions.get(referenceString || label);
|
|
|
|
|
|
destination = definition && definition[1];
|
2024-02-17 15:46:13 -08:00
|
|
|
|
isError = destination &&
|
|
|
|
|
|
(isShortcut ? !shortcut : (isCollapsed ? !collapsed : !full));
|
2023-10-25 20:05:19 -07:00
|
|
|
|
}
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
if (isError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let range = undefined;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let fixInfo = null;
|
|
|
|
|
|
if (startLine === endLine) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ startColumn, endColumn - startColumn ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let insertText = null;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const canInline = (inline && label);
|
|
|
|
|
|
const canAutolink = (autolink && !image && autolinkAble(destination));
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (canInline && (urlInline || !canAutolink)) {
|
|
|
|
|
|
// Most useful form
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const prefix = (image ? "!" : "");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const escapedLabel = label.replace(/[[\]]/g, "\\$&");
|
|
|
|
|
|
const escapedDestination = destination.replace(/[()]/g, "\\$&");
|
|
|
|
|
|
insertText = `${prefix}[${escapedLabel}](${escapedDestination})`;
|
|
|
|
|
|
} else if (canAutolink) {
|
|
|
|
|
|
// Simplest form
|
|
|
|
|
|
insertText = `<${removeBackslashEscapes(destination)}>`;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (insertText) {
|
|
|
|
|
|
fixInfo = {
|
|
|
|
|
|
"editColumn": range[0],
|
|
|
|
|
|
insertText,
|
|
|
|
|
|
"deleteCount": range[1]
|
|
|
|
|
|
};
|
2023-10-25 20:05:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorContext(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
startLine,
|
|
|
|
|
|
text.replace(nextLinesRe, ""),
|
2024-06-21 21:03:30 -07:00
|
|
|
|
undefined,
|
|
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range,
|
|
|
|
|
|
fixInfo
|
|
|
|
|
|
);
|
2023-10-25 20:05:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2023-10-25 20:05:19 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2023-12-30 18:15:38 -08:00
|
|
|
|
/***/ "../lib/md055.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md055.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
|
|
|
|
|
const ignoreWhitespace = (tokens) => tokens.filter(
|
|
|
|
|
|
(token) => !whitespaceTypes.has(token.type)
|
|
|
|
|
|
);
|
|
|
|
|
|
const firstOrNothing = (items) => items[0];
|
|
|
|
|
|
const lastOrNothing = (items) => items[items.length - 1];
|
|
|
|
|
|
const makeRange = (start, end) => [ start, end - start + 1 ];
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2023-12-30 18:15:38 -08:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD055", "table-pipe-style" ],
|
2023-12-30 18:15:38 -08:00
|
|
|
|
"description": "Table pipe style",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "table" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2023-12-30 18:15:38 -08:00
|
|
|
|
"function": function MD055(params, onError) {
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const style = String(params.config.style || "consistent");
|
|
|
|
|
|
let expectedStyle = style;
|
2024-02-17 15:46:13 -08:00
|
|
|
|
let expectedLeadingPipe =
|
|
|
|
|
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
|
|
|
|
|
|
let expectedTrailingPipe =
|
|
|
|
|
|
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const tables = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "table" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const table of tables) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const rows = filterByTypes(
|
|
|
|
|
|
table.children,
|
|
|
|
|
|
[ "tableDelimiterRow", "tableRow" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const row of rows) {
|
|
|
|
|
|
// The following uses of first/lastOrNothing lack fallback handling
|
|
|
|
|
|
// because it seems not to be possible (i.e., 0% coverage)
|
|
|
|
|
|
const firstCell = firstOrNothing(row.children);
|
|
|
|
|
|
const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children));
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const actualLeadingPipe = (leadingToken.type === "tableCellDivider");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const lastCell = lastOrNothing(row.children);
|
|
|
|
|
|
const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children));
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const actualTrailingPipe = (trailingToken.type === "tableCellDivider");
|
|
|
|
|
|
const actualStyle = actualLeadingPipe ?
|
|
|
|
|
|
(actualTrailingPipe ? "leading_and_trailing" : "leading_only") :
|
|
|
|
|
|
(actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing");
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (expectedStyle === "consistent") {
|
|
|
|
|
|
expectedStyle = actualStyle;
|
|
|
|
|
|
expectedLeadingPipe = actualLeadingPipe;
|
|
|
|
|
|
expectedTrailingPipe = actualTrailingPipe;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (actualLeadingPipe !== expectedLeadingPipe) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
firstCell.startLine,
|
|
|
|
|
|
expectedStyle,
|
|
|
|
|
|
actualStyle,
|
|
|
|
|
|
`${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
makeRange(row.startColumn, firstCell.startColumn)
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
}
|
|
|
|
|
|
if (actualTrailingPipe !== expectedTrailingPipe) {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
lastCell.endLine,
|
|
|
|
|
|
expectedStyle,
|
|
|
|
|
|
actualStyle,
|
|
|
|
|
|
`${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`,
|
|
|
|
|
|
undefined,
|
|
|
|
|
|
makeRange(lastCell.endColumn - 1, row.endColumn - 1)
|
|
|
|
|
|
);
|
2023-12-30 18:15:38 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-30 18:15:38 -08:00
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2024-01-04 23:07:55 -08:00
|
|
|
|
/***/ "../lib/md056.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md056.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
const makeRange = (start, end) => [ start, end - start + 1 ];
|
|
|
|
|
|
|
2024-02-27 20:42:09 -08:00
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
2024-01-04 23:07:55 -08:00
|
|
|
|
module.exports = {
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"names": [ "MD056", "table-column-count" ],
|
2024-01-04 23:07:55 -08:00
|
|
|
|
"description": "Table column count",
|
2024-02-17 15:46:13 -08:00
|
|
|
|
"tags": [ "table" ],
|
2024-03-09 16:17:50 -08:00
|
|
|
|
"parser": "micromark",
|
2024-01-04 23:07:55 -08:00
|
|
|
|
"function": function MD056(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const tables = filterByTypes(
|
|
|
|
|
|
params.parsers.micromark.tokens,
|
|
|
|
|
|
[ "table" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
for (const table of tables) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const rows = filterByTypes(
|
|
|
|
|
|
table.children,
|
|
|
|
|
|
[ "tableDelimiterRow", "tableRow" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
let expectedCount = 0;
|
|
|
|
|
|
for (const row of rows) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const cells = filterByTypes(
|
|
|
|
|
|
row.children,
|
|
|
|
|
|
[ "tableData", "tableDelimiter", "tableHeader" ]
|
|
|
|
|
|
);
|
2024-01-06 20:47:01 -08:00
|
|
|
|
const actualCount = cells.length;
|
|
|
|
|
|
expectedCount ||= actualCount;
|
2024-06-21 21:03:30 -07:00
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let detail = undefined;
|
|
|
|
|
|
// eslint-disable-next-line no-undef-init
|
|
|
|
|
|
let range = undefined;
|
2024-01-06 20:47:01 -08:00
|
|
|
|
if (actualCount < expectedCount) {
|
|
|
|
|
|
detail = "Too few cells, row will be missing data";
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range = [ row.endColumn - 1, 1 ];
|
2024-01-06 20:47:01 -08:00
|
|
|
|
} else if (expectedCount < actualCount) {
|
|
|
|
|
|
detail = "Too many cells, extra data will be missing";
|
|
|
|
|
|
range = makeRange(cells[expectedCount].startColumn, row.endColumn - 1);
|
2024-01-04 23:07:55 -08:00
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
addErrorDetailIf(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
row.endLine,
|
|
|
|
|
|
expectedCount,
|
|
|
|
|
|
actualCount,
|
|
|
|
|
|
detail,
|
2024-06-21 21:03:30 -07:00
|
|
|
|
undefined,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
range
|
|
|
|
|
|
);
|
2024-01-04 23:07:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-02-17 15:46:13 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-04 23:07:55 -08:00
|
|
|
|
|
2024-06-01 21:32:10 -07:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
|
|
|
|
|
/***/ "../lib/md058.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/md058.js ***!
|
|
|
|
|
|
\***********************/
|
|
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { addErrorContextForLine, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
|
|
|
|
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line jsdoc/valid-types
|
|
|
|
|
|
/** @type import("./markdownlint").Rule */
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
|
"names": [ "MD058", "blanks-around-tables" ],
|
|
|
|
|
|
"description": "Tables should be surrounded by blank lines",
|
|
|
|
|
|
"tags": [ "table" ],
|
|
|
|
|
|
"parser": "micromark",
|
|
|
|
|
|
"function": function MD058(params, onError) {
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const { lines, parsers } = params;
|
2024-06-01 21:32:10 -07:00
|
|
|
|
// For every table...
|
2024-06-21 21:03:30 -07:00
|
|
|
|
const tables = filterByTypes(
|
|
|
|
|
|
parsers.micromark.tokens,
|
|
|
|
|
|
[ "table" ]
|
|
|
|
|
|
);
|
2024-06-01 21:32:10 -07:00
|
|
|
|
for (const table of tables) {
|
|
|
|
|
|
// Look for a blank line above the table
|
|
|
|
|
|
const firstIndex = table.startLine - 1;
|
|
|
|
|
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
|
|
|
|
addErrorContextForLine(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
lines,
|
|
|
|
|
|
firstIndex
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
// Look for a blank line below the table
|
|
|
|
|
|
const lastIndex = table.endLine - 1;
|
|
|
|
|
|
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
|
|
|
|
addErrorContextForLine(
|
|
|
|
|
|
onError,
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
lines,
|
|
|
|
|
|
lastIndex,
|
|
|
|
|
|
lastIndex + 2
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-01-04 23:07:55 -08:00
|
|
|
|
/***/ }),
|
|
|
|
|
|
|
2021-01-06 19:45:15 -08:00
|
|
|
|
/***/ "../lib/rules.js":
|
|
|
|
|
|
/*!***********************!*\
|
|
|
|
|
|
!*** ../lib/rules.js ***!
|
|
|
|
|
|
\***********************/
|
2022-06-02 21:42:48 -07:00
|
|
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
2021-01-05 20:55:09 -08:00
|
|
|
|
|
2019-12-14 13:50:48 -08:00
|
|
|
|
"use strict";
|
2021-01-05 20:55:09 -08:00
|
|
|
|
// @ts-check
|
|
|
|
|
|
|
2023-01-17 04:19:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const { homepage, version } = __webpack_require__(/*! ./constants */ "../lib/constants.js");
|
|
|
|
|
|
|
2024-06-16 20:25:07 -07:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const [ md019, md021 ] = __webpack_require__(/*! ./md019-md021 */ "../lib/md019-md021.js");
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
const [ md049, md050 ] = __webpack_require__(/*! ./md049-md050 */ "../lib/md049-md050.js");
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
const rules = [
|
|
|
|
|
|
__webpack_require__(/*! ./md001 */ "../lib/md001.js"),
|
|
|
|
|
|
// md002: Deprecated and removed
|
|
|
|
|
|
__webpack_require__(/*! ./md003 */ "../lib/md003.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md004 */ "../lib/md004.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md005 */ "../lib/md005.js"),
|
|
|
|
|
|
// md006: Deprecated and removed
|
|
|
|
|
|
__webpack_require__(/*! ./md007 */ "../lib/md007.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md009 */ "../lib/md009.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md010 */ "../lib/md010.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md011 */ "../lib/md011.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md012 */ "../lib/md012.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md013 */ "../lib/md013.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md014 */ "../lib/md014.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md018 */ "../lib/md018.js"),
|
2024-06-16 20:25:07 -07:00
|
|
|
|
md019,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
__webpack_require__(/*! ./md020 */ "../lib/md020.js"),
|
2024-06-16 20:25:07 -07:00
|
|
|
|
md021,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
__webpack_require__(/*! ./md022 */ "../lib/md022.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md023 */ "../lib/md023.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md024 */ "../lib/md024.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md025 */ "../lib/md025.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md026 */ "../lib/md026.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md027 */ "../lib/md027.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md028 */ "../lib/md028.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md029 */ "../lib/md029.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md030 */ "../lib/md030.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md031 */ "../lib/md031.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md032 */ "../lib/md032.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md033 */ "../lib/md033.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md034 */ "../lib/md034.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md035 */ "../lib/md035.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md036 */ "../lib/md036.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md037 */ "../lib/md037.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md038 */ "../lib/md038.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md039 */ "../lib/md039.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md040 */ "../lib/md040.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md041 */ "../lib/md041.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md042 */ "../lib/md042.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md043 */ "../lib/md043.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md044 */ "../lib/md044.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md045 */ "../lib/md045.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md046 */ "../lib/md046.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md047 */ "../lib/md047.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md048 */ "../lib/md048.js"),
|
2024-06-16 20:25:07 -07:00
|
|
|
|
md049,
|
|
|
|
|
|
md050,
|
2024-02-17 15:46:13 -08:00
|
|
|
|
__webpack_require__(/*! ./md051 */ "../lib/md051.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md052 */ "../lib/md052.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md053 */ "../lib/md053.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md054 */ "../lib/md054.js"),
|
|
|
|
|
|
__webpack_require__(/*! ./md055 */ "../lib/md055.js"),
|
2024-06-01 21:32:10 -07:00
|
|
|
|
__webpack_require__(/*! ./md056 */ "../lib/md056.js"),
|
2024-02-17 15:46:13 -08:00
|
|
|
|
// md057: See https://github.com/markdownlint/markdownlint
|
2024-06-01 21:32:10 -07:00
|
|
|
|
__webpack_require__(/*! ./md058 */ "../lib/md058.js")
|
2024-01-06 20:47:01 -08:00
|
|
|
|
];
|
|
|
|
|
|
for (const rule of rules) {
|
|
|
|
|
|
const name = rule.names[0].toLowerCase();
|
|
|
|
|
|
// eslint-disable-next-line dot-notation
|
2024-02-17 15:46:13 -08:00
|
|
|
|
rule["information"] =
|
|
|
|
|
|
new URL(`${homepage}/blob/v${version}/doc/${name}.md`);
|
2022-06-08 22:10:27 -07:00
|
|
|
|
}
|
2019-10-02 20:10:42 -07:00
|
|
|
|
module.exports = rules;
|
|
|
|
|
|
|
2024-02-17 15:46:13 -08:00
|
|
|
|
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/***/ })
|
|
|
|
|
|
|
|
|
|
|
|
/******/ });
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
/******/ // The module cache
|
|
|
|
|
|
/******/ var __webpack_module_cache__ = {};
|
|
|
|
|
|
/******/
|
|
|
|
|
|
/******/ // The require function
|
|
|
|
|
|
/******/ function __webpack_require__(moduleId) {
|
|
|
|
|
|
/******/ // Check if module is in cache
|
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
|
|
|
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
|
|
|
|
/******/ if (cachedModule !== undefined) {
|
|
|
|
|
|
/******/ return cachedModule.exports;
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/ }
|
|
|
|
|
|
/******/ // Create a new module (and put it into the cache)
|
|
|
|
|
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
|
|
|
|
/******/ // no module.id needed
|
|
|
|
|
|
/******/ // no module.loaded needed
|
|
|
|
|
|
/******/ exports: {}
|
|
|
|
|
|
/******/ };
|
|
|
|
|
|
/******/
|
|
|
|
|
|
/******/ // Execute the module function
|
2022-06-02 21:42:48 -07:00
|
|
|
|
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/
|
|
|
|
|
|
/******/ // Return the exports of the module
|
|
|
|
|
|
/******/ return module.exports;
|
|
|
|
|
|
/******/ }
|
|
|
|
|
|
/******/
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
|
|
|
|
/******/ (() => {
|
2021-02-06 19:23:55 -08:00
|
|
|
|
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/ })();
|
|
|
|
|
|
/******/
|
|
|
|
|
|
/************************************************************************/
|
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
|
|
|
|
/******/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/ // startup
|
|
|
|
|
|
/******/ // Load entry module and return exports
|
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
|
|
|
|
/******/ // This entry module is referenced by other modules so it can't be inlined
|
2022-12-29 00:43:53 +00:00
|
|
|
|
/******/ var __webpack_exports__ = __webpack_require__("./markdownlint-exports.js");
|
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
|
|
|
|
/******/ markdownlint = __webpack_exports__;
|
|
|
|
|
|
/******/
|
2021-01-05 20:55:09 -08:00
|
|
|
|
/******/ })()
|
|
|
|
|
|
;
|