mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-16 14:00:13 +01:00
Reimplement MD044/proper-names using micromark tokens.
This commit is contained in:
parent
e8a85c91f2
commit
5bff33d41b
9 changed files with 182 additions and 495 deletions
11
lib/md034.js
11
lib/md034.js
|
|
@ -15,15 +15,16 @@ module.exports = {
|
|||
filterByPredicate(
|
||||
params.parsers.micromark.tokens,
|
||||
(token) => token.type === "literalAutolink",
|
||||
(tokens) => {
|
||||
(token) => {
|
||||
const { children } = token;
|
||||
const result = [];
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
const openToken = tokens[i];
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const openToken = children[i];
|
||||
const openTagInfo = getHtmlTagInfo(openToken);
|
||||
if (openTagInfo && !openTagInfo.close) {
|
||||
let count = 1;
|
||||
for (let j = i + 1; j < tokens.length; j++) {
|
||||
const closeToken = tokens[j];
|
||||
for (let j = i + 1; j < children.length; j++) {
|
||||
const closeToken = children[j];
|
||||
const closeTagInfo = getHtmlTagInfo(closeToken);
|
||||
if (closeTagInfo && (openTagInfo.name === closeTagInfo.name)) {
|
||||
if (closeTagInfo.close) {
|
||||
|
|
|
|||
102
lib/md044.js
102
lib/md044.js
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { addErrorDetailIf, escapeForRegExp, forEachLine, forEachLink,
|
||||
funcExpExec, linkReferenceDefinitionRe, urlFe, withinAnyRange } =
|
||||
const { addErrorDetailIf, escapeForRegExp, withinAnyRange } =
|
||||
require("../helpers");
|
||||
const { codeBlockAndSpanRanges, htmlElementRanges, lineMetadata } =
|
||||
require("./cache");
|
||||
const { filterByPredicate, filterByTypes, parse } =
|
||||
require("../helpers/micromark.cjs");
|
||||
|
||||
const ignoredChildTypes = new Set(
|
||||
[ "codeFencedFence", "definition", "reference", "resource" ]
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
"names": [ "MD044", "proper-names" ],
|
||||
|
|
@ -22,31 +25,25 @@ module.exports = {
|
|||
const htmlElements = params.config.html_elements;
|
||||
const includeHtmlElements =
|
||||
(htmlElements === undefined) ? true : !!htmlElements;
|
||||
const exclusions = [];
|
||||
forEachLine(lineMetadata(), (line, lineIndex) => {
|
||||
if (linkReferenceDefinitionRe.test(line)) {
|
||||
exclusions.push([ lineIndex, 0, line.length ]);
|
||||
} else {
|
||||
let match = null;
|
||||
while ((match = funcExpExec(urlFe, line)) !== null) {
|
||||
// @ts-ignore
|
||||
exclusions.push([ lineIndex, match.index, match[0].length ]);
|
||||
}
|
||||
forEachLink(line, (index, _, text, destination) => {
|
||||
if (destination) {
|
||||
exclusions.push(
|
||||
[ lineIndex, index + text.length, destination.length ]
|
||||
);
|
||||
const scannedTypes = new Set([ "data", "htmlFlowData" ]);
|
||||
if (includeCodeBlocks) {
|
||||
scannedTypes.add("codeFlowValue");
|
||||
scannedTypes.add("codeTextData");
|
||||
}
|
||||
const contentTokens =
|
||||
filterByPredicate(
|
||||
params.parsers.micromark.tokens,
|
||||
(token) => scannedTypes.has(token.type),
|
||||
(token) => {
|
||||
let { children } = token;
|
||||
if (!includeHtmlElements && (token.type === "htmlFlow")) {
|
||||
children = children.slice(1, -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (!includeCodeBlocks) {
|
||||
exclusions.push(...codeBlockAndSpanRanges());
|
||||
}
|
||||
if (!includeHtmlElements) {
|
||||
exclusions.push(...htmlElementRanges());
|
||||
}
|
||||
return children.filter((t) => !ignoredChildTypes.has(t.type));
|
||||
}
|
||||
);
|
||||
const exclusions = [];
|
||||
const autoLinked = new Set();
|
||||
for (const name of names) {
|
||||
const escapedName = escapeForRegExp(name);
|
||||
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
|
||||
|
|
@ -54,36 +51,53 @@ module.exports = {
|
|||
const namePattern =
|
||||
`(${startNamePattern})(${escapedName})${endNamePattern}`;
|
||||
const nameRe = new RegExp(namePattern, "gi");
|
||||
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence) => {
|
||||
if (includeCodeBlocks || (!inCode && !onFence)) {
|
||||
let match = null;
|
||||
while ((match = nameRe.exec(line)) !== null) {
|
||||
const [ , leftMatch, nameMatch ] = match;
|
||||
const index = match.index + leftMatch.length;
|
||||
const length = nameMatch.length;
|
||||
if (
|
||||
!withinAnyRange(exclusions, lineIndex, index, length) &&
|
||||
!names.includes(nameMatch)
|
||||
) {
|
||||
for (const token of contentTokens) {
|
||||
let match = null;
|
||||
while ((match = nameRe.exec(token.text)) !== null) {
|
||||
const [ , leftMatch, nameMatch ] = match;
|
||||
const index = token.startColumn - 1 + match.index + leftMatch.length;
|
||||
const length = nameMatch.length;
|
||||
const lineIndex = token.startLine - 1;
|
||||
if (
|
||||
!withinAnyRange(exclusions, lineIndex, index, length) &&
|
||||
!names.includes(nameMatch)
|
||||
) {
|
||||
let urlRanges = [];
|
||||
if (!autoLinked.has(token)) {
|
||||
urlRanges = filterByTypes(
|
||||
parse(token.text),
|
||||
[ "literalAutolink" ]
|
||||
).map(
|
||||
(t) => [
|
||||
lineIndex,
|
||||
token.startColumn - 1 + t.startColumn - 1,
|
||||
t.endColumn - t.startColumn
|
||||
]
|
||||
);
|
||||
exclusions.push(...urlRanges);
|
||||
autoLinked.add(token);
|
||||
}
|
||||
if (!withinAnyRange(urlRanges, lineIndex, index, length)) {
|
||||
const column = index + 1;
|
||||
addErrorDetailIf(
|
||||
onError,
|
||||
lineIndex + 1,
|
||||
token.startLine,
|
||||
name,
|
||||
nameMatch,
|
||||
null,
|
||||
null,
|
||||
[ index + 1, length ],
|
||||
[ column, length ],
|
||||
{
|
||||
"editColumn": index + 1,
|
||||
"editColumn": column,
|
||||
"deleteCount": length,
|
||||
"insertText": name
|
||||
}
|
||||
);
|
||||
}
|
||||
exclusions.push([ lineIndex, index, length ]);
|
||||
}
|
||||
exclusions.push([ lineIndex, index, length ]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue