mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
Exclude htmlFlow content by default for filterByTypes, opt in as needed.
This commit is contained in:
parent
ea9659841e
commit
12502f6571
18 changed files with 206 additions and 129 deletions
|
@ -1240,13 +1240,40 @@ const {
|
||||||
} = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark");
|
} = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark");
|
||||||
const { newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
|
const { newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js");
|
||||||
|
|
||||||
const flatTokensSymbol = Symbol("flat-tokens");
|
const flatTokensWithHtmlFlowSymbol = Symbol("flat-tokens-with-html-flow");
|
||||||
|
const flatTokensWithoutHtmlFlowSymbol = Symbol("flat-tokens-without-html-flow");
|
||||||
|
|
||||||
/** @typedef {import("markdownlint-micromark").Event} Event */
|
/** @typedef {import("markdownlint-micromark").Event} Event */
|
||||||
/** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
|
/** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
|
||||||
/** @typedef {import("markdownlint-micromark").TokenType} TokenType */
|
/** @typedef {import("markdownlint-micromark").TokenType} TokenType */
|
||||||
/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
|
/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a Micromark token has an htmlFlow-type parent.
|
||||||
|
*
|
||||||
|
* @param {Token} token Micromark token.
|
||||||
|
* @returns {boolean} True iff the token has an htmlFlow-type parent.
|
||||||
|
*/
|
||||||
|
function inHtmlFlow(token) {
|
||||||
|
return getTokenParentOfType(token, [ "htmlFlow" ]) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
||||||
*
|
*
|
||||||
|
@ -1337,7 +1364,8 @@ function micromarkParseWithOffset(
|
||||||
|
|
||||||
// Create Token objects
|
// Create Token objects
|
||||||
const document = [];
|
const document = [];
|
||||||
let flatTokens = [];
|
let flatTokensWithHtmlFlow = [];
|
||||||
|
const flatTokensWithoutHtmlFlow = [];
|
||||||
/** @type {Token} */
|
/** @type {Token} */
|
||||||
const root = {
|
const root = {
|
||||||
"type": "data",
|
"type": "data",
|
||||||
|
@ -1376,7 +1404,8 @@ function micromarkParseWithOffset(
|
||||||
"parent": ((previous === root) ? (ancestor || null) : previous)
|
"parent": ((previous === root) ? (ancestor || null) : previous)
|
||||||
};
|
};
|
||||||
previous.children.push(current);
|
previous.children.push(current);
|
||||||
flatTokens.push(current);
|
flatTokensWithHtmlFlow.push(current);
|
||||||
|
flatTokensWithoutHtmlFlow.push(current);
|
||||||
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
||||||
skipHtmlFlowChildren = true;
|
skipHtmlFlowChildren = true;
|
||||||
if (!reparseOptions || !lines) {
|
if (!reparseOptions || !lines) {
|
||||||
|
@ -1405,7 +1434,7 @@ function micromarkParseWithOffset(
|
||||||
current.children = tokens;
|
current.children = tokens;
|
||||||
// Avoid stack overflow of Array.push(...spread)
|
// Avoid stack overflow of Array.push(...spread)
|
||||||
// eslint-disable-next-line unicorn/prefer-spread
|
// eslint-disable-next-line unicorn/prefer-spread
|
||||||
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
flatTokensWithHtmlFlow = flatTokensWithHtmlFlow.concat(tokens[flatTokensWithHtmlFlowSymbol]);
|
||||||
}
|
}
|
||||||
} else if (kind === "exit") {
|
} else if (kind === "exit") {
|
||||||
if (type === "htmlFlow") {
|
if (type === "htmlFlow") {
|
||||||
|
@ -1421,7 +1450,8 @@ function micromarkParseWithOffset(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return document
|
// Return document
|
||||||
Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
|
Object.defineProperty(document, flatTokensWithHtmlFlowSymbol, { "value": flatTokensWithHtmlFlow });
|
||||||
|
Object.defineProperty(document, flatTokensWithoutHtmlFlowSymbol, { "value": flatTokensWithoutHtmlFlow });
|
||||||
Object.freeze(document);
|
Object.freeze(document);
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
@ -1507,15 +1537,24 @@ function filterByPredicate(tokens, allowed, transformChildren) {
|
||||||
*
|
*
|
||||||
* @param {Token[]} tokens Micromark tokens.
|
* @param {Token[]} tokens Micromark tokens.
|
||||||
* @param {TokenType[]} types Types to allow.
|
* @param {TokenType[]} types Types to allow.
|
||||||
|
* @param {boolean} [htmlFlow] Whether to include htmlFlow content.
|
||||||
* @returns {Token[]} Filtered tokens.
|
* @returns {Token[]} Filtered tokens.
|
||||||
*/
|
*/
|
||||||
function filterByTypes(tokens, types) {
|
function filterByTypes(tokens, types, htmlFlow) {
|
||||||
const predicate = (token) => types.includes(token.type);
|
const predicate = (token) => types.includes(token.type);
|
||||||
const flatTokens = tokens[flatTokensSymbol];
|
const flatTokens = tokens[
|
||||||
|
htmlFlow ?
|
||||||
|
flatTokensWithHtmlFlowSymbol :
|
||||||
|
flatTokensWithoutHtmlFlowSymbol
|
||||||
|
];
|
||||||
if (flatTokens) {
|
if (flatTokens) {
|
||||||
return flatTokens.filter(predicate);
|
return flatTokens.filter(predicate);
|
||||||
}
|
}
|
||||||
return filterByPredicate(tokens, predicate);
|
const result = filterByPredicate(tokens, predicate);
|
||||||
|
if (htmlFlow) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result.filter((token) => !inHtmlFlow(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1589,22 +1628,6 @@ function getHtmlTagInfo(token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the text of the first match from a list of Micromark tokens by type.
|
* Get the text of the first match from a list of Micromark tokens by type.
|
||||||
*
|
*
|
||||||
|
@ -1617,16 +1640,6 @@ function getTokenTextByType(tokens, type) {
|
||||||
return (filtered.length > 0) ? filtered[0].text : null;
|
return (filtered.length > 0) ? filtered[0].text : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a Micromark token has an htmlFlow-type parent.
|
|
||||||
*
|
|
||||||
* @param {Token} token Micromark token.
|
|
||||||
* @returns {boolean} True iff the token has an htmlFlow-type parent.
|
|
||||||
*/
|
|
||||||
function inHtmlFlow(token) {
|
|
||||||
return getTokenParentOfType(token, [ "htmlFlow" ]) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines a list of Micromark tokens matches and returns a subset.
|
* Determines a list of Micromark tokens matches and returns a subset.
|
||||||
*
|
*
|
||||||
|
@ -3374,7 +3387,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, getHeadingLevel, getHeadingStyle, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel, getHeadingStyle } =
|
||||||
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
|
@ -3395,7 +3408,7 @@ module.exports = {
|
||||||
if (style === "consistent") {
|
if (style === "consistent") {
|
||||||
style = styleForToken;
|
style = styleForToken;
|
||||||
}
|
}
|
||||||
if ((styleForToken !== style) && !inHtmlFlow(heading)) {
|
if (styleForToken !== style) {
|
||||||
const h12 = getHeadingLevel(heading) <= 2;
|
const h12 = getHeadingLevel(heading) <= 2;
|
||||||
const setextWithAtx =
|
const setextWithAtx =
|
||||||
(style === "setext_with_atx") &&
|
(style === "setext_with_atx") &&
|
||||||
|
@ -3529,7 +3542,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -3547,7 +3560,7 @@ module.exports = {
|
||||||
const lists = filterByTypes(
|
const lists = filterByTypes(
|
||||||
micromarkTokens,
|
micromarkTokens,
|
||||||
[ "listOrdered", "listUnordered" ]
|
[ "listOrdered", "listUnordered" ]
|
||||||
).filter((list) => !inHtmlFlow(list));
|
);
|
||||||
for (const list of lists) {
|
for (const list of lists) {
|
||||||
const expectedIndent = list.startColumn - 1;
|
const expectedIndent = list.startColumn - 1;
|
||||||
let expectedEnd = 0;
|
let expectedEnd = 0;
|
||||||
|
@ -3564,8 +3577,8 @@ module.exports = {
|
||||||
lineNumber,
|
lineNumber,
|
||||||
expectedIndent,
|
expectedIndent,
|
||||||
actualIndent,
|
actualIndent,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
range
|
range
|
||||||
// No fixInfo; MD007 handles this scenario better
|
// No fixInfo; MD007 handles this scenario better
|
||||||
);
|
);
|
||||||
|
@ -3621,8 +3634,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, getTokenParentOfType, inHtmlFlow } =
|
const { filterByTypes, getTokenParentOfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("markdownlint-micromark").TokenType[] */
|
/** @type import("markdownlint-micromark").TokenType[] */
|
||||||
|
@ -3675,7 +3687,7 @@ module.exports = {
|
||||||
if (nesting >= 0) {
|
if (nesting >= 0) {
|
||||||
unorderedListNesting.set(token, nesting);
|
unorderedListNesting.set(token, nesting);
|
||||||
}
|
}
|
||||||
} else if (!inHtmlFlow(token)) {
|
} else {
|
||||||
// listItemPrefix
|
// listItemPrefix
|
||||||
const nesting = unorderedListNesting.get(parent);
|
const nesting = unorderedListNesting.get(parent);
|
||||||
if (nesting !== undefined) {
|
if (nesting !== undefined) {
|
||||||
|
@ -4438,8 +4450,7 @@ module.exports = {
|
||||||
|
|
||||||
const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } =
|
const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } =
|
||||||
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, getHeadingLevel, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
const defaultLines = 1;
|
const defaultLines = 1;
|
||||||
|
|
||||||
|
@ -4484,7 +4495,7 @@ module.exports = {
|
||||||
const headings = filterByTypes(
|
const headings = filterByTypes(
|
||||||
micromarkTokens,
|
micromarkTokens,
|
||||||
[ "atxHeading", "setextHeading" ]
|
[ "atxHeading", "setextHeading" ]
|
||||||
).filter((heading) => !inHtmlFlow(heading));
|
);
|
||||||
for (const heading of headings) {
|
for (const heading of headings) {
|
||||||
const { startLine, endLine } = heading;
|
const { startLine, endLine } = heading;
|
||||||
const line = lines[startLine - 1].trim();
|
const line = lines[startLine - 1].trim();
|
||||||
|
@ -4507,7 +4518,7 @@ module.exports = {
|
||||||
actualAbove,
|
actualAbove,
|
||||||
"Above",
|
"Above",
|
||||||
line,
|
line,
|
||||||
null,
|
undefined,
|
||||||
{
|
{
|
||||||
"insertText": getBlockQuote(
|
"insertText": getBlockQuote(
|
||||||
lines[startLine - 2],
|
lines[startLine - 2],
|
||||||
|
@ -4535,7 +4546,7 @@ module.exports = {
|
||||||
actualBelow,
|
actualBelow,
|
||||||
"Below",
|
"Below",
|
||||||
line,
|
line,
|
||||||
null,
|
undefined,
|
||||||
{
|
{
|
||||||
"lineNumber": endLine + 1,
|
"lineNumber": endLine + 1,
|
||||||
"insertText": getBlockQuote(
|
"insertText": getBlockQuote(
|
||||||
|
@ -4672,8 +4683,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, getHeadingLevel, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -4696,7 +4706,7 @@ module.exports = {
|
||||||
);
|
);
|
||||||
for (const heading of headings) {
|
for (const heading of headings) {
|
||||||
const headingLevel = getHeadingLevel(heading);
|
const headingLevel = getHeadingLevel(heading);
|
||||||
if ((headingLevel === level) && !inHtmlFlow(heading)) {
|
if (headingLevel === level) {
|
||||||
if (hasTopLevelHeading || foundFrontMatterTitle) {
|
if (hasTopLevelHeading || foundFrontMatterTitle) {
|
||||||
const headingTexts = filterByTypes(
|
const headingTexts = filterByTypes(
|
||||||
heading.children,
|
heading.children,
|
||||||
|
@ -5223,7 +5233,7 @@ module.exports = {
|
||||||
const micromarkTokens =
|
const micromarkTokens =
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
params.parsers.micromark.tokens;
|
params.parsers.micromark.tokens;
|
||||||
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ])) {
|
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ], true)) {
|
||||||
const htmlTagInfo = getHtmlTagInfo(token);
|
const htmlTagInfo = getHtmlTagInfo(token);
|
||||||
if (
|
if (
|
||||||
htmlTagInfo &&
|
htmlTagInfo &&
|
||||||
|
@ -5352,8 +5362,8 @@ module.exports = {
|
||||||
onError,
|
onError,
|
||||||
token.startLine,
|
token.startLine,
|
||||||
token.text,
|
token.text,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
range,
|
range,
|
||||||
fixInfo
|
fixInfo
|
||||||
);
|
);
|
||||||
|
@ -5590,8 +5600,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { filterByTypes, inHtmlFlow, tokenIfType } =
|
const { filterByTypes, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
||||||
const rightSpaceRe = /[^`]\s$/;
|
const rightSpaceRe = /[^`]\s$/;
|
||||||
|
@ -5619,8 +5628,7 @@ module.exports = {
|
||||||
const micromarkTokens =
|
const micromarkTokens =
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
params.parsers.micromark.tokens;
|
params.parsers.micromark.tokens;
|
||||||
const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ])
|
const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ]);
|
||||||
.filter((codeText) => !inHtmlFlow(codeText));
|
|
||||||
for (const codeText of codeTexts) {
|
for (const codeText of codeTexts) {
|
||||||
const { children } = codeText;
|
const { children } = codeText;
|
||||||
const first = 0;
|
const first = 0;
|
||||||
|
@ -5862,7 +5870,7 @@ module.exports = {
|
||||||
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
||||||
isError = (getHeadingLevel(token) !== level);
|
isError = (getHeadingLevel(token) !== level);
|
||||||
} else if (token.type === "htmlFlow") {
|
} else if (token.type === "htmlFlow") {
|
||||||
const htmlTexts = filterByTypes(token.children, [ "htmlText" ]);
|
const htmlTexts = filterByTypes(token.children, [ "htmlText" ], true);
|
||||||
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
||||||
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
||||||
}
|
}
|
||||||
|
@ -6195,7 +6203,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process HTML images
|
// Process HTML images
|
||||||
const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ]);
|
const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ], true);
|
||||||
for (const htmlText of htmlTexts) {
|
for (const htmlText of htmlTexts) {
|
||||||
const { startColumn, startLine, text } = htmlText;
|
const { startColumn, startLine, text } = htmlText;
|
||||||
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
||||||
|
@ -6596,7 +6604,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process HTML anchors
|
// Process HTML anchors
|
||||||
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ])) {
|
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ], true)) {
|
||||||
const htmlTagInfo = getHtmlTagInfo(token);
|
const htmlTagInfo = getHtmlTagInfo(token);
|
||||||
if (htmlTagInfo && !htmlTagInfo.close) {
|
if (htmlTagInfo && !htmlTagInfo.close) {
|
||||||
const anchorMatch = idRe.exec(token.text) ||
|
const anchorMatch = idRe.exec(token.text) ||
|
||||||
|
|
|
@ -10,13 +10,40 @@ const {
|
||||||
} = require("markdownlint-micromark");
|
} = require("markdownlint-micromark");
|
||||||
const { newLineRe } = require("./shared.js");
|
const { newLineRe } = require("./shared.js");
|
||||||
|
|
||||||
const flatTokensSymbol = Symbol("flat-tokens");
|
const flatTokensWithHtmlFlowSymbol = Symbol("flat-tokens-with-html-flow");
|
||||||
|
const flatTokensWithoutHtmlFlowSymbol = Symbol("flat-tokens-without-html-flow");
|
||||||
|
|
||||||
/** @typedef {import("markdownlint-micromark").Event} Event */
|
/** @typedef {import("markdownlint-micromark").Event} Event */
|
||||||
/** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
|
/** @typedef {import("markdownlint-micromark").ParseOptions} ParseOptions */
|
||||||
/** @typedef {import("markdownlint-micromark").TokenType} TokenType */
|
/** @typedef {import("markdownlint-micromark").TokenType} TokenType */
|
||||||
/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
|
/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a Micromark token has an htmlFlow-type parent.
|
||||||
|
*
|
||||||
|
* @param {Token} token Micromark token.
|
||||||
|
* @returns {boolean} True iff the token has an htmlFlow-type parent.
|
||||||
|
*/
|
||||||
|
function inHtmlFlow(token) {
|
||||||
|
return getTokenParentOfType(token, [ "htmlFlow" ]) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
||||||
*
|
*
|
||||||
|
@ -107,7 +134,8 @@ function micromarkParseWithOffset(
|
||||||
|
|
||||||
// Create Token objects
|
// Create Token objects
|
||||||
const document = [];
|
const document = [];
|
||||||
let flatTokens = [];
|
let flatTokensWithHtmlFlow = [];
|
||||||
|
const flatTokensWithoutHtmlFlow = [];
|
||||||
/** @type {Token} */
|
/** @type {Token} */
|
||||||
const root = {
|
const root = {
|
||||||
"type": "data",
|
"type": "data",
|
||||||
|
@ -146,7 +174,8 @@ function micromarkParseWithOffset(
|
||||||
"parent": ((previous === root) ? (ancestor || null) : previous)
|
"parent": ((previous === root) ? (ancestor || null) : previous)
|
||||||
};
|
};
|
||||||
previous.children.push(current);
|
previous.children.push(current);
|
||||||
flatTokens.push(current);
|
flatTokensWithHtmlFlow.push(current);
|
||||||
|
flatTokensWithoutHtmlFlow.push(current);
|
||||||
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
||||||
skipHtmlFlowChildren = true;
|
skipHtmlFlowChildren = true;
|
||||||
if (!reparseOptions || !lines) {
|
if (!reparseOptions || !lines) {
|
||||||
|
@ -175,7 +204,7 @@ function micromarkParseWithOffset(
|
||||||
current.children = tokens;
|
current.children = tokens;
|
||||||
// Avoid stack overflow of Array.push(...spread)
|
// Avoid stack overflow of Array.push(...spread)
|
||||||
// eslint-disable-next-line unicorn/prefer-spread
|
// eslint-disable-next-line unicorn/prefer-spread
|
||||||
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
flatTokensWithHtmlFlow = flatTokensWithHtmlFlow.concat(tokens[flatTokensWithHtmlFlowSymbol]);
|
||||||
}
|
}
|
||||||
} else if (kind === "exit") {
|
} else if (kind === "exit") {
|
||||||
if (type === "htmlFlow") {
|
if (type === "htmlFlow") {
|
||||||
|
@ -191,7 +220,8 @@ function micromarkParseWithOffset(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return document
|
// Return document
|
||||||
Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
|
Object.defineProperty(document, flatTokensWithHtmlFlowSymbol, { "value": flatTokensWithHtmlFlow });
|
||||||
|
Object.defineProperty(document, flatTokensWithoutHtmlFlowSymbol, { "value": flatTokensWithoutHtmlFlow });
|
||||||
Object.freeze(document);
|
Object.freeze(document);
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
@ -277,15 +307,24 @@ function filterByPredicate(tokens, allowed, transformChildren) {
|
||||||
*
|
*
|
||||||
* @param {Token[]} tokens Micromark tokens.
|
* @param {Token[]} tokens Micromark tokens.
|
||||||
* @param {TokenType[]} types Types to allow.
|
* @param {TokenType[]} types Types to allow.
|
||||||
|
* @param {boolean} [htmlFlow] Whether to include htmlFlow content.
|
||||||
* @returns {Token[]} Filtered tokens.
|
* @returns {Token[]} Filtered tokens.
|
||||||
*/
|
*/
|
||||||
function filterByTypes(tokens, types) {
|
function filterByTypes(tokens, types, htmlFlow) {
|
||||||
const predicate = (token) => types.includes(token.type);
|
const predicate = (token) => types.includes(token.type);
|
||||||
const flatTokens = tokens[flatTokensSymbol];
|
const flatTokens = tokens[
|
||||||
|
htmlFlow ?
|
||||||
|
flatTokensWithHtmlFlowSymbol :
|
||||||
|
flatTokensWithoutHtmlFlowSymbol
|
||||||
|
];
|
||||||
if (flatTokens) {
|
if (flatTokens) {
|
||||||
return flatTokens.filter(predicate);
|
return flatTokens.filter(predicate);
|
||||||
}
|
}
|
||||||
return filterByPredicate(tokens, predicate);
|
const result = filterByPredicate(tokens, predicate);
|
||||||
|
if (htmlFlow) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result.filter((token) => !inHtmlFlow(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -359,22 +398,6 @@ function getHtmlTagInfo(token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the text of the first match from a list of Micromark tokens by type.
|
* Get the text of the first match from a list of Micromark tokens by type.
|
||||||
*
|
*
|
||||||
|
@ -387,16 +410,6 @@ function getTokenTextByType(tokens, type) {
|
||||||
return (filtered.length > 0) ? filtered[0].text : null;
|
return (filtered.length > 0) ? filtered[0].text : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a Micromark token has an htmlFlow-type parent.
|
|
||||||
*
|
|
||||||
* @param {Token} token Micromark token.
|
|
||||||
* @returns {boolean} True iff the token has an htmlFlow-type parent.
|
|
||||||
*/
|
|
||||||
function inHtmlFlow(token) {
|
|
||||||
return getTokenParentOfType(token, [ "htmlFlow" ]) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines a list of Micromark tokens matches and returns a subset.
|
* Determines a list of Micromark tokens matches and returns a subset.
|
||||||
*
|
*
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorDetailIf } = require("../helpers");
|
const { addErrorDetailIf } = require("../helpers");
|
||||||
const { filterByTypes, getHeadingLevel, getHeadingStyle, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel, getHeadingStyle } =
|
||||||
require("../helpers/micromark.cjs");
|
require("../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
|
@ -24,7 +24,7 @@ module.exports = {
|
||||||
if (style === "consistent") {
|
if (style === "consistent") {
|
||||||
style = styleForToken;
|
style = styleForToken;
|
||||||
}
|
}
|
||||||
if ((styleForToken !== style) && !inHtmlFlow(heading)) {
|
if (styleForToken !== style) {
|
||||||
const h12 = getHeadingLevel(heading) <= 2;
|
const h12 = getHeadingLevel(heading) <= 2;
|
||||||
const setextWithAtx =
|
const setextWithAtx =
|
||||||
(style === "setext_with_atx") &&
|
(style === "setext_with_atx") &&
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addError, addErrorDetailIf } = require("../helpers");
|
const { addError, addErrorDetailIf } = require("../helpers");
|
||||||
const { filterByTypes, inHtmlFlow } = require("../helpers/micromark.cjs");
|
const { filterByTypes } = require("../helpers/micromark.cjs");
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -21,7 +21,7 @@ module.exports = {
|
||||||
const lists = filterByTypes(
|
const lists = filterByTypes(
|
||||||
micromarkTokens,
|
micromarkTokens,
|
||||||
[ "listOrdered", "listUnordered" ]
|
[ "listOrdered", "listUnordered" ]
|
||||||
).filter((list) => !inHtmlFlow(list));
|
);
|
||||||
for (const list of lists) {
|
for (const list of lists) {
|
||||||
const expectedIndent = list.startColumn - 1;
|
const expectedIndent = list.startColumn - 1;
|
||||||
let expectedEnd = 0;
|
let expectedEnd = 0;
|
||||||
|
@ -38,8 +38,8 @@ module.exports = {
|
||||||
lineNumber,
|
lineNumber,
|
||||||
expectedIndent,
|
expectedIndent,
|
||||||
actualIndent,
|
actualIndent,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
range
|
range
|
||||||
// No fixInfo; MD007 handles this scenario better
|
// No fixInfo; MD007 handles this scenario better
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorDetailIf } = require("../helpers");
|
const { addErrorDetailIf } = require("../helpers");
|
||||||
const { filterByTypes, getTokenParentOfType, inHtmlFlow } =
|
const { filterByTypes, getTokenParentOfType } = require("../helpers/micromark.cjs");
|
||||||
require("../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("markdownlint-micromark").TokenType[] */
|
/** @type import("markdownlint-micromark").TokenType[] */
|
||||||
|
@ -57,7 +56,7 @@ module.exports = {
|
||||||
if (nesting >= 0) {
|
if (nesting >= 0) {
|
||||||
unorderedListNesting.set(token, nesting);
|
unorderedListNesting.set(token, nesting);
|
||||||
}
|
}
|
||||||
} else if (!inHtmlFlow(token)) {
|
} else {
|
||||||
// listItemPrefix
|
// listItemPrefix
|
||||||
const nesting = unorderedListNesting.get(parent);
|
const nesting = unorderedListNesting.get(parent);
|
||||||
if (nesting !== undefined) {
|
if (nesting !== undefined) {
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } =
|
const { addErrorDetailIf, blockquotePrefixRe, isBlankLine } =
|
||||||
require("../helpers");
|
require("../helpers");
|
||||||
const { filterByTypes, getHeadingLevel, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel } = require("../helpers/micromark.cjs");
|
||||||
require("../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
const defaultLines = 1;
|
const defaultLines = 1;
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ module.exports = {
|
||||||
const headings = filterByTypes(
|
const headings = filterByTypes(
|
||||||
micromarkTokens,
|
micromarkTokens,
|
||||||
[ "atxHeading", "setextHeading" ]
|
[ "atxHeading", "setextHeading" ]
|
||||||
).filter((heading) => !inHtmlFlow(heading));
|
);
|
||||||
for (const heading of headings) {
|
for (const heading of headings) {
|
||||||
const { startLine, endLine } = heading;
|
const { startLine, endLine } = heading;
|
||||||
const line = lines[startLine - 1].trim();
|
const line = lines[startLine - 1].trim();
|
||||||
|
@ -73,7 +72,7 @@ module.exports = {
|
||||||
actualAbove,
|
actualAbove,
|
||||||
"Above",
|
"Above",
|
||||||
line,
|
line,
|
||||||
null,
|
undefined,
|
||||||
{
|
{
|
||||||
"insertText": getBlockQuote(
|
"insertText": getBlockQuote(
|
||||||
lines[startLine - 2],
|
lines[startLine - 2],
|
||||||
|
@ -101,7 +100,7 @@ module.exports = {
|
||||||
actualBelow,
|
actualBelow,
|
||||||
"Below",
|
"Below",
|
||||||
line,
|
line,
|
||||||
null,
|
undefined,
|
||||||
{
|
{
|
||||||
"lineNumber": endLine + 1,
|
"lineNumber": endLine + 1,
|
||||||
"insertText": getBlockQuote(
|
"insertText": getBlockQuote(
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorContext, frontMatterHasTitle } = require("../helpers");
|
const { addErrorContext, frontMatterHasTitle } = require("../helpers");
|
||||||
const { filterByTypes, getHeadingLevel, inHtmlFlow } =
|
const { filterByTypes, getHeadingLevel } = require("../helpers/micromark.cjs");
|
||||||
require("../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -27,7 +26,7 @@ module.exports = {
|
||||||
);
|
);
|
||||||
for (const heading of headings) {
|
for (const heading of headings) {
|
||||||
const headingLevel = getHeadingLevel(heading);
|
const headingLevel = getHeadingLevel(heading);
|
||||||
if ((headingLevel === level) && !inHtmlFlow(heading)) {
|
if (headingLevel === level) {
|
||||||
if (hasTopLevelHeading || foundFrontMatterTitle) {
|
if (hasTopLevelHeading || foundFrontMatterTitle) {
|
||||||
const headingTexts = filterByTypes(
|
const headingTexts = filterByTypes(
|
||||||
heading.children,
|
heading.children,
|
||||||
|
|
|
@ -22,7 +22,7 @@ module.exports = {
|
||||||
const micromarkTokens =
|
const micromarkTokens =
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
params.parsers.micromark.tokens;
|
params.parsers.micromark.tokens;
|
||||||
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ])) {
|
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ], true)) {
|
||||||
const htmlTagInfo = getHtmlTagInfo(token);
|
const htmlTagInfo = getHtmlTagInfo(token);
|
||||||
if (
|
if (
|
||||||
htmlTagInfo &&
|
htmlTagInfo &&
|
||||||
|
|
|
@ -94,8 +94,8 @@ module.exports = {
|
||||||
onError,
|
onError,
|
||||||
token.startLine,
|
token.startLine,
|
||||||
token.text,
|
token.text,
|
||||||
null,
|
undefined,
|
||||||
null,
|
undefined,
|
||||||
range,
|
range,
|
||||||
fixInfo
|
fixInfo
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorContext } = require("../helpers");
|
const { addErrorContext } = require("../helpers");
|
||||||
const { filterByTypes, inHtmlFlow, tokenIfType } =
|
const { filterByTypes, tokenIfType } = require("../helpers/micromark.cjs");
|
||||||
require("../helpers/micromark.cjs");
|
|
||||||
|
|
||||||
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
||||||
const rightSpaceRe = /[^`]\s$/;
|
const rightSpaceRe = /[^`]\s$/;
|
||||||
|
@ -32,8 +31,7 @@ module.exports = {
|
||||||
const micromarkTokens =
|
const micromarkTokens =
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
params.parsers.micromark.tokens;
|
params.parsers.micromark.tokens;
|
||||||
const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ])
|
const codeTexts = filterByTypes(micromarkTokens, [ "codeText" ]);
|
||||||
.filter((codeText) => !inHtmlFlow(codeText));
|
|
||||||
for (const codeText of codeTexts) {
|
for (const codeText of codeTexts) {
|
||||||
const { children } = codeText;
|
const { children } = codeText;
|
||||||
const first = 0;
|
const first = 0;
|
||||||
|
|
|
@ -23,7 +23,7 @@ module.exports = {
|
||||||
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
if ((token.type === "atxHeading") || (token.type === "setextHeading")) {
|
||||||
isError = (getHeadingLevel(token) !== level);
|
isError = (getHeadingLevel(token) !== level);
|
||||||
} else if (token.type === "htmlFlow") {
|
} else if (token.type === "htmlFlow") {
|
||||||
const htmlTexts = filterByTypes(token.children, [ "htmlText" ]);
|
const htmlTexts = filterByTypes(token.children, [ "htmlText" ], true);
|
||||||
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
|
||||||
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process HTML images
|
// Process HTML images
|
||||||
const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ]);
|
const htmlTexts = filterByTypes(micromarkTokens, [ "htmlText" ], true);
|
||||||
for (const htmlText of htmlTexts) {
|
for (const htmlText of htmlTexts) {
|
||||||
const { startColumn, startLine, text } = htmlText;
|
const { startColumn, startLine, text } = htmlText;
|
||||||
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
const htmlTagInfo = getHtmlTagInfo(htmlText);
|
||||||
|
|
|
@ -97,7 +97,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process HTML anchors
|
// Process HTML anchors
|
||||||
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ])) {
|
for (const token of filterByTypes(micromarkTokens, [ "htmlText" ], true)) {
|
||||||
const htmlTagInfo = getHtmlTagInfo(token);
|
const htmlTagInfo = getHtmlTagInfo(token);
|
||||||
if (htmlTagInfo && !htmlTagInfo.close) {
|
if (htmlTagInfo && !htmlTagInfo.close) {
|
||||||
const anchorMatch = idRe.exec(token.text) ||
|
const anchorMatch = idRe.exec(token.text) ||
|
||||||
|
|
|
@ -5,3 +5,9 @@
|
||||||
## Heading 2
|
## Heading 2
|
||||||
|
|
||||||
#### Heading 4 {MD001}
|
#### Heading 4 {MD001}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
###### Not heading
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- markdownlint-disable-file no-inline-html -->
|
||||||
|
|
|
@ -63,15 +63,40 @@ test("getMicromarkEvents/filterByPredicate", async(t) => {
|
||||||
t.deepEqual(tokenTypes, eventTypes);
|
t.deepEqual(tokenTypes, eventTypes);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("filterByTypes", async(t) => {
|
test("filterByTypes, htmlFlow false", async(t) => {
|
||||||
t.plan(8);
|
t.plan(7);
|
||||||
const filtered = filterByTypes(
|
const tokens = await testTokens;
|
||||||
await testTokens,
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
[ "atxHeadingText", "codeText", "htmlText", "setextHeadingText" ]
|
/** @type import("../micromark/micromark.cjs").TokenType[] */
|
||||||
);
|
const types = [ "atxHeadingText", "codeText", "htmlText", "setextHeadingText" ];
|
||||||
|
const filtered = filterByTypes(tokens, types);
|
||||||
|
// Using flat tokens
|
||||||
for (const token of filtered) {
|
for (const token of filtered) {
|
||||||
t.true(token.type.endsWith("Text"));
|
t.true(token.type.endsWith("Text"));
|
||||||
}
|
}
|
||||||
|
// Not using flat tokens
|
||||||
|
t.deepEqual(
|
||||||
|
filtered,
|
||||||
|
filterByTypes([ ...tokens], types)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
test("filterByTypes, htmlFlow true", async(t) => {
|
||||||
|
t.plan(9);
|
||||||
|
const tokens = await testTokens;
|
||||||
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
|
/** @type import("../micromark/micromark.cjs").TokenType[] */
|
||||||
|
const types = [ "atxHeadingText", "codeText", "htmlText", "setextHeadingText" ];
|
||||||
|
// Using flat tokens
|
||||||
|
const filtered = filterByTypes(tokens, types, true);
|
||||||
|
for (const token of filtered) {
|
||||||
|
t.true(token.type.endsWith("Text"));
|
||||||
|
}
|
||||||
|
// Not using flat tokens
|
||||||
|
t.deepEqual(
|
||||||
|
filtered,
|
||||||
|
filterByTypes([ ...tokens], types, true)
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
test("filterByPredicate/filterByTypes", async(t) => {
|
test("filterByPredicate/filterByTypes", async(t) => {
|
||||||
|
@ -79,6 +104,6 @@ test("filterByPredicate/filterByTypes", async(t) => {
|
||||||
const tokens = await testTokens;
|
const tokens = await testTokens;
|
||||||
const byPredicate = filterByPredicate(tokens, () => true);
|
const byPredicate = filterByPredicate(tokens, () => true);
|
||||||
const allTypes = new Set(byPredicate.map(((token) => token.type)));
|
const allTypes = new Set(byPredicate.map(((token) => token.type)));
|
||||||
const byTypes = filterByTypes(tokens, [ ...allTypes.values() ]);
|
const byTypes = filterByTypes(tokens, [ ...allTypes.values() ], true);
|
||||||
t.deepEqual(byPredicate, byTypes);
|
t.deepEqual(byPredicate, byTypes);
|
||||||
});
|
});
|
||||||
|
|
|
@ -64,6 +64,10 @@ Uppercase image tag with alt attribute set
|
||||||
|
|
||||||
Uppercase image tag with no alt set <IMG SRC="cat.png" /> {MD045}
|
Uppercase image tag with no alt set <IMG SRC="cat.png" /> {MD045}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="image.png" /> {MD045}
|
||||||
|
</p>
|
||||||
|
|
||||||
<!-- markdownlint-restore no-inline-html -->
|
<!-- markdownlint-restore no-inline-html -->
|
||||||
|
|
||||||
[notitle]: image.jpg
|
[notitle]: image.jpg
|
||||||
|
|
|
@ -16101,6 +16101,12 @@ Generated by [AVA](https://avajs.dev).
|
||||||
## Heading 2␊
|
## Heading 2␊
|
||||||
␊
|
␊
|
||||||
#### Heading 4 {MD001}␊
|
#### Heading 4 {MD001}␊
|
||||||
|
␊
|
||||||
|
<p>␊
|
||||||
|
###### Not heading␊
|
||||||
|
</p>␊
|
||||||
|
␊
|
||||||
|
<!-- markdownlint-disable-file no-inline-html -->␊
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39577,6 +39583,22 @@ Generated by [AVA](https://avajs.dev).
|
||||||
'no-alt-text',
|
'no-alt-text',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
errorContext: null,
|
||||||
|
errorDetail: null,
|
||||||
|
errorRange: [
|
||||||
|
3,
|
||||||
|
23,
|
||||||
|
],
|
||||||
|
fixInfo: null,
|
||||||
|
lineNumber: 68,
|
||||||
|
ruleDescription: 'Images should have alternate text (alt text)',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md045.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD045',
|
||||||
|
'no-alt-text',
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
fixed: `# Images with and without alternate text␊
|
fixed: `# Images with and without alternate text␊
|
||||||
␊
|
␊
|
||||||
|
@ -39644,6 +39666,10 @@ Generated by [AVA](https://avajs.dev).
|
||||||
␊
|
␊
|
||||||
Uppercase image tag with no alt set <IMG SRC="cat.png" /> {MD045}␊
|
Uppercase image tag with no alt set <IMG SRC="cat.png" /> {MD045}␊
|
||||||
␊
|
␊
|
||||||
|
<p>␊
|
||||||
|
<img src="image.png" /> {MD045}␊
|
||||||
|
</p>␊
|
||||||
|
␊
|
||||||
<!-- markdownlint-restore no-inline-html -->␊
|
<!-- markdownlint-restore no-inline-html -->␊
|
||||||
␊
|
␊
|
||||||
[notitle]: image.jpg␊
|
[notitle]: image.jpg␊
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue