mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-22 05:40:48 +02:00
Refactor to remove micromark helper matchAndGetTokensByType.
This commit is contained in:
parent
2ea3f95fd1
commit
87daa5b06c
4 changed files with 66 additions and 184 deletions
|
@ -483,60 +483,33 @@ function getReferenceLinkImageData(tokens) {
|
||||||
case "image":
|
case "image":
|
||||||
case "link":
|
case "link":
|
||||||
{
|
{
|
||||||
let isShortcut = false;
|
// Identify if shortcut or full/collapsed
|
||||||
let isFullOrCollapsed = false;
|
let isShortcut = (token.children.length === 1);
|
||||||
let labelText = null;
|
const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource");
|
||||||
let referenceStringText = null;
|
const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]);
|
||||||
const shortcutCandidate =
|
const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]);
|
||||||
micromark.matchAndGetTokensByType(token.children, [ "label" ]);
|
let label = labelText?.text;
|
||||||
if (shortcutCandidate) {
|
// Identify if footnote
|
||||||
labelText =
|
if (!isShortcut && !isFullOrCollapsed) {
|
||||||
micromark.getTokenTextByType(
|
const [ footnoteCallMarker, footnoteCallString ] = token.children.filter(
|
||||||
shortcutCandidate[0].children, "labelText"
|
(t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type)
|
||||||
);
|
|
||||||
isShortcut = (labelText !== null);
|
|
||||||
}
|
|
||||||
const fullAndCollapsedCandidate =
|
|
||||||
micromark.matchAndGetTokensByType(
|
|
||||||
token.children, [ "label", "reference" ]
|
|
||||||
);
|
);
|
||||||
if (fullAndCollapsedCandidate) {
|
if (footnoteCallMarker && footnoteCallString) {
|
||||||
labelText =
|
label = `${footnoteCallMarker.text}${footnoteCallString.text}`;
|
||||||
micromark.getTokenTextByType(
|
isShortcut = true;
|
||||||
fullAndCollapsedCandidate[0].children, "labelText"
|
}
|
||||||
);
|
|
||||||
referenceStringText =
|
|
||||||
micromark.getTokenTextByType(
|
|
||||||
fullAndCollapsedCandidate[1].children, "referenceString"
|
|
||||||
);
|
|
||||||
isFullOrCollapsed = (labelText !== null);
|
|
||||||
}
|
}
|
||||||
const footnote = micromark.matchAndGetTokensByType(
|
// Track link (handle shortcuts separately due to ambiguity in "text [text] text")
|
||||||
token.children,
|
|
||||||
[
|
|
||||||
"gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
|
|
||||||
"gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
|
|
||||||
],
|
|
||||||
[ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
|
|
||||||
);
|
|
||||||
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) {
|
if (isShortcut || isFullOrCollapsed) {
|
||||||
const referenceDatum = [
|
const referenceDatum = [
|
||||||
token.startLine - 1,
|
token.startLine - 1,
|
||||||
token.startColumn - 1,
|
token.startColumn - 1,
|
||||||
token.text.length,
|
token.text.length,
|
||||||
// @ts-ignore
|
label.length,
|
||||||
labelText.length,
|
(referenceString?.text || "").length
|
||||||
(referenceStringText || "").length
|
|
||||||
];
|
];
|
||||||
const reference =
|
const reference =
|
||||||
normalizeReference(referenceStringText || labelText);
|
normalizeReference(referenceString?.text || label);
|
||||||
const dictionary = isShortcut ? shortcuts : references;
|
const dictionary = isShortcut ? shortcuts : references;
|
||||||
const referenceData = dictionary.get(reference) || [];
|
const referenceData = dictionary.get(reference) || [];
|
||||||
referenceData.push(referenceDatum);
|
referenceData.push(referenceDatum);
|
||||||
|
@ -1360,31 +1333,6 @@ function getTokenTextByType(tokens, type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines a list of Micromark tokens matches and returns a subset.
|
|
||||||
*
|
|
||||||
* @param {Token[]} tokens Micromark tokens.
|
|
||||||
* @param {TokenType[]} matchTypes Types to match.
|
|
||||||
* @param {TokenType[]} [resultTypes] Types to return.
|
|
||||||
* @returns {Token[] | null} Matching tokens.
|
|
||||||
*/
|
|
||||||
function matchAndGetTokensByType(tokens, matchTypes, resultTypes) {
|
|
||||||
if (tokens.length !== matchTypes.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
resultTypes = resultTypes || matchTypes;
|
|
||||||
const result = [];
|
|
||||||
// eslint-disable-next-line unicorn/no-for-loop
|
|
||||||
for (let i = 0; i < matchTypes.length; i++) {
|
|
||||||
if (tokens[i].type !== matchTypes[i]) {
|
|
||||||
return null;
|
|
||||||
} else if (resultTypes.includes(matchTypes[i])) {
|
|
||||||
result.push(tokens[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set containing token types that do not contain content.
|
* Set containing token types that do not contain content.
|
||||||
*
|
*
|
||||||
|
@ -1416,7 +1364,6 @@ module.exports = {
|
||||||
getTokenTextByType,
|
getTokenTextByType,
|
||||||
inHtmlFlow,
|
inHtmlFlow,
|
||||||
isHtmlFlowComment,
|
isHtmlFlowComment,
|
||||||
matchAndGetTokensByType,
|
|
||||||
nonContentTokens
|
nonContentTokens
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5273,15 +5220,15 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
|
||||||
const { matchAndGetTokensByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
|
||||||
const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
|
||||||
|
|
||||||
/** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
|
/** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
|
||||||
/** @type {Map<TokenType, TokenType[]>} */
|
/** @type {TokenType[][]} */
|
||||||
const emphasisAndChildrenTypes = new Map([
|
const emphasisTypes = [
|
||||||
[ "emphasis", [ "emphasisSequence", "emphasisText", "emphasisSequence" ] ],
|
[ "emphasis", "emphasisText" ],
|
||||||
[ "strong", [ "strongSequence", "strongText", "strongSequence" ] ]
|
[ "strong", "strongText" ]
|
||||||
]);
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -5299,21 +5246,15 @@ module.exports = {
|
||||||
.filter((token) =>
|
.filter((token) =>
|
||||||
(token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
|
(token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
|
||||||
);
|
);
|
||||||
for (const paragraphToken of paragraphTokens) {
|
for (const emphasisType of emphasisTypes) {
|
||||||
const childToken = paragraphToken.children[0];
|
const textTokens = getDescendantsByType(paragraphTokens, emphasisType);
|
||||||
for (const [ emphasisType, emphasisChildrenTypes ] of emphasisAndChildrenTypes) {
|
for (const textToken of textTokens) {
|
||||||
if (childToken.type === emphasisType) {
|
if (
|
||||||
const matchingTokens = matchAndGetTokensByType(childToken.children, emphasisChildrenTypes);
|
(textToken.children.length === 1) &&
|
||||||
if (matchingTokens) {
|
(textToken.children[0].type === "data") &&
|
||||||
const textToken = matchingTokens[1];
|
!punctuationRe.test(textToken.text)
|
||||||
if (
|
) {
|
||||||
(textToken.children.length === 1) &&
|
addErrorContext(onError, textToken.startLine, textToken.text);
|
||||||
(textToken.children[0].type === "data") &&
|
|
||||||
!punctuationRe.test(textToken.text)
|
|
||||||
) {
|
|
||||||
addErrorContext(onError, textToken.startLine, textToken.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,60 +471,33 @@ function getReferenceLinkImageData(tokens) {
|
||||||
case "image":
|
case "image":
|
||||||
case "link":
|
case "link":
|
||||||
{
|
{
|
||||||
let isShortcut = false;
|
// Identify if shortcut or full/collapsed
|
||||||
let isFullOrCollapsed = false;
|
let isShortcut = (token.children.length === 1);
|
||||||
let labelText = null;
|
const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource");
|
||||||
let referenceStringText = null;
|
const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]);
|
||||||
const shortcutCandidate =
|
const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]);
|
||||||
micromark.matchAndGetTokensByType(token.children, [ "label" ]);
|
let label = labelText?.text;
|
||||||
if (shortcutCandidate) {
|
// Identify if footnote
|
||||||
labelText =
|
if (!isShortcut && !isFullOrCollapsed) {
|
||||||
micromark.getTokenTextByType(
|
const [ footnoteCallMarker, footnoteCallString ] = token.children.filter(
|
||||||
shortcutCandidate[0].children, "labelText"
|
(t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type)
|
||||||
);
|
|
||||||
isShortcut = (labelText !== null);
|
|
||||||
}
|
|
||||||
const fullAndCollapsedCandidate =
|
|
||||||
micromark.matchAndGetTokensByType(
|
|
||||||
token.children, [ "label", "reference" ]
|
|
||||||
);
|
);
|
||||||
if (fullAndCollapsedCandidate) {
|
if (footnoteCallMarker && footnoteCallString) {
|
||||||
labelText =
|
label = `${footnoteCallMarker.text}${footnoteCallString.text}`;
|
||||||
micromark.getTokenTextByType(
|
isShortcut = true;
|
||||||
fullAndCollapsedCandidate[0].children, "labelText"
|
}
|
||||||
);
|
|
||||||
referenceStringText =
|
|
||||||
micromark.getTokenTextByType(
|
|
||||||
fullAndCollapsedCandidate[1].children, "referenceString"
|
|
||||||
);
|
|
||||||
isFullOrCollapsed = (labelText !== null);
|
|
||||||
}
|
}
|
||||||
const footnote = micromark.matchAndGetTokensByType(
|
// Track link (handle shortcuts separately due to ambiguity in "text [text] text")
|
||||||
token.children,
|
|
||||||
[
|
|
||||||
"gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
|
|
||||||
"gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
|
|
||||||
],
|
|
||||||
[ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
|
|
||||||
);
|
|
||||||
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) {
|
if (isShortcut || isFullOrCollapsed) {
|
||||||
const referenceDatum = [
|
const referenceDatum = [
|
||||||
token.startLine - 1,
|
token.startLine - 1,
|
||||||
token.startColumn - 1,
|
token.startColumn - 1,
|
||||||
token.text.length,
|
token.text.length,
|
||||||
// @ts-ignore
|
label.length,
|
||||||
labelText.length,
|
(referenceString?.text || "").length
|
||||||
(referenceStringText || "").length
|
|
||||||
];
|
];
|
||||||
const reference =
|
const reference =
|
||||||
normalizeReference(referenceStringText || labelText);
|
normalizeReference(referenceString?.text || label);
|
||||||
const dictionary = isShortcut ? shortcuts : references;
|
const dictionary = isShortcut ? shortcuts : references;
|
||||||
const referenceData = dictionary.get(reference) || [];
|
const referenceData = dictionary.get(reference) || [];
|
||||||
referenceData.push(referenceDatum);
|
referenceData.push(referenceDatum);
|
||||||
|
|
|
@ -475,31 +475,6 @@ function getTokenTextByType(tokens, type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines a list of Micromark tokens matches and returns a subset.
|
|
||||||
*
|
|
||||||
* @param {Token[]} tokens Micromark tokens.
|
|
||||||
* @param {TokenType[]} matchTypes Types to match.
|
|
||||||
* @param {TokenType[]} [resultTypes] Types to return.
|
|
||||||
* @returns {Token[] | null} Matching tokens.
|
|
||||||
*/
|
|
||||||
function matchAndGetTokensByType(tokens, matchTypes, resultTypes) {
|
|
||||||
if (tokens.length !== matchTypes.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
resultTypes = resultTypes || matchTypes;
|
|
||||||
const result = [];
|
|
||||||
// eslint-disable-next-line unicorn/no-for-loop
|
|
||||||
for (let i = 0; i < matchTypes.length; i++) {
|
|
||||||
if (tokens[i].type !== matchTypes[i]) {
|
|
||||||
return null;
|
|
||||||
} else if (resultTypes.includes(matchTypes[i])) {
|
|
||||||
result.push(tokens[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set containing token types that do not contain content.
|
* Set containing token types that do not contain content.
|
||||||
*
|
*
|
||||||
|
@ -531,6 +506,5 @@ module.exports = {
|
||||||
getTokenTextByType,
|
getTokenTextByType,
|
||||||
inHtmlFlow,
|
inHtmlFlow,
|
||||||
isHtmlFlowComment,
|
isHtmlFlowComment,
|
||||||
matchAndGetTokensByType,
|
|
||||||
nonContentTokens
|
nonContentTokens
|
||||||
};
|
};
|
||||||
|
|
36
lib/md036.js
36
lib/md036.js
|
@ -3,15 +3,15 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { addErrorContext, allPunctuation } = require("../helpers");
|
const { addErrorContext, allPunctuation } = require("../helpers");
|
||||||
const { matchAndGetTokensByType } = require("../helpers/micromark.cjs");
|
const { getDescendantsByType } = require("../helpers/micromark.cjs");
|
||||||
const { filterByTypesCached } = require("./cache");
|
const { filterByTypesCached } = require("./cache");
|
||||||
|
|
||||||
/** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
|
/** @typedef {import("../helpers/micromark.cjs").TokenType} TokenType */
|
||||||
/** @type {Map<TokenType, TokenType[]>} */
|
/** @type {TokenType[][]} */
|
||||||
const emphasisAndChildrenTypes = new Map([
|
const emphasisTypes = [
|
||||||
[ "emphasis", [ "emphasisSequence", "emphasisText", "emphasisSequence" ] ],
|
[ "emphasis", "emphasisText" ],
|
||||||
[ "strong", [ "strongSequence", "strongText", "strongSequence" ] ]
|
[ "strong", "strongText" ]
|
||||||
]);
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/valid-types
|
// eslint-disable-next-line jsdoc/valid-types
|
||||||
/** @type import("./markdownlint").Rule */
|
/** @type import("./markdownlint").Rule */
|
||||||
|
@ -29,21 +29,15 @@ module.exports = {
|
||||||
.filter((token) =>
|
.filter((token) =>
|
||||||
(token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
|
(token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1)
|
||||||
);
|
);
|
||||||
for (const paragraphToken of paragraphTokens) {
|
for (const emphasisType of emphasisTypes) {
|
||||||
const childToken = paragraphToken.children[0];
|
const textTokens = getDescendantsByType(paragraphTokens, emphasisType);
|
||||||
for (const [ emphasisType, emphasisChildrenTypes ] of emphasisAndChildrenTypes) {
|
for (const textToken of textTokens) {
|
||||||
if (childToken.type === emphasisType) {
|
if (
|
||||||
const matchingTokens = matchAndGetTokensByType(childToken.children, emphasisChildrenTypes);
|
(textToken.children.length === 1) &&
|
||||||
if (matchingTokens) {
|
(textToken.children[0].type === "data") &&
|
||||||
const textToken = matchingTokens[1];
|
!punctuationRe.test(textToken.text)
|
||||||
if (
|
) {
|
||||||
(textToken.children.length === 1) &&
|
addErrorContext(onError, textToken.startLine, textToken.text);
|
||||||
(textToken.children[0].type === "data") &&
|
|
||||||
!punctuationRe.test(textToken.text)
|
|
||||||
) {
|
|
||||||
addErrorContext(onError, textToken.startLine, textToken.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue