markdownlint/lib/md026.js

53 lines
1.6 KiB
JavaScript
Raw Normal View History

// @ts-check
"use strict";
const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe,
endOfLineHtmlEntityRe, escapeForRegExp } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = {
"names": [ "MD026", "no-trailing-punctuation" ],
"description": "Trailing punctuation in heading",
"tags": [ "headings" ],
"function": function MD026(params, onError) {
let punctuation = params.config.punctuation;
punctuation = String(
(punctuation === undefined) ? allPunctuationNoQuestion : punctuation
);
const trailingPunctuationRe =
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
const headings = filterByTypes(
// eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "atxHeadingText", "setextHeadingText" ]
);
for (const heading of headings) {
const { endColumn, endLine, text } = heading;
const match = trailingPunctuationRe.exec(text);
if (
match &&
!endOfLineHtmlEntityRe.test(text) &&
!endOfLineGemojiCodeRe.test(text)
) {
const fullMatch = match[0];
const length = fullMatch.length;
const column = endColumn - length;
addError(
onError,
endLine,
`Punctuation: '${fullMatch}'`,
undefined,
[ column, length ],
{
"editColumn": column,
"deleteCount": length
}
);
}
}
}
};