Update MD051/link-fragments to handle backslash-escaped content in link and definition destinations (fixes #956).

This commit is contained in:
David Anson 2023-09-06 21:25:00 -07:00
parent 1ddee6b195
commit ba260b9b1e
5 changed files with 81 additions and 28 deletions

View file

@ -15,11 +15,15 @@ const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu;
const childrenExclude = new Set([ "image", "reference", "resource" ]);
const tokensInclude = new Set([ "codeTextData", "data" ]);
/**
* @typedef {import("../helpers/micromark.cjs").Token} Token
*/
/**
* Converts a Markdown heading into an HTML fragment according to the rules
* used by GitHub.
*
* @param {Object} headingText Heading text token.
* @param {Token} headingText Heading text token.
* @returns {string} Fragment string for heading.
*/
function convertHeadingToHTMLFragment(headingText) {
@ -46,6 +50,18 @@ function convertHeadingToHTMLFragment(headingText) {
);
}
/**
* Unescapes the text of a String-type micromark Token.
*
* @param {Token} token String-type micromark Token.
* @returns {string} Unescaped token text.
*/
function unescapeStringTokenText(token) {
return filterByTypes(token.children, [ "characterEscapeValue", "data" ])
.map((child) => child.text)
.join("");
}
module.exports = {
"names": [ "MD051", "link-fragments" ],
"description": "Link fragments should be valid",
@ -99,7 +115,8 @@ module.exports = {
for (const link of links) {
const definitions = filterByTypes(link.children, [ definitionType ]);
for (const definition of definitions) {
const { endColumn, startColumn, text } = definition;
const { endColumn, startColumn } = definition;
const text = unescapeStringTokenText(definition);
if (
(text.length > 1) &&
text.startsWith("#") &&