mirror of
https://github.com/theoludwig/markdownlint-rule-relative-links.git
synced 2025-05-27 11:37:24 +02:00
feat: html anchor support
This commit is contained in:
@ -7,6 +7,7 @@ const {
|
||||
filterTokens,
|
||||
convertHeadingToHTMLFragment,
|
||||
getMarkdownHeadings,
|
||||
getMarkdownAnchorHTMLFragments,
|
||||
} = require("./utils.js")
|
||||
|
||||
/** @typedef {import('markdownlint').Rule} MarkdownLintRule */
|
||||
@ -63,6 +64,8 @@ const customRule = {
|
||||
if (type === "link_open" && url.hash !== "") {
|
||||
const fileContent = fs.readFileSync(url, { encoding: "utf8" })
|
||||
const headings = getMarkdownHeadings(fileContent)
|
||||
const anchorHTMLFragments =
|
||||
getMarkdownAnchorHTMLFragments(fileContent)
|
||||
|
||||
/** @type {Map<string, number>} */
|
||||
const fragments = new Map()
|
||||
@ -77,6 +80,8 @@ const customRule = {
|
||||
return fragment
|
||||
})
|
||||
|
||||
headingsHTMLFragments.push(...anchorHTMLFragments)
|
||||
|
||||
if (!headingsHTMLFragments.includes(url.hash)) {
|
||||
onError({
|
||||
lineNumber,
|
||||
|
49
src/utils.js
49
src/utils.js
@ -1,4 +1,6 @@
|
||||
const MarkdownIt = require("markdown-it")
|
||||
// @ts-ignore
|
||||
const { getHtmlAttributeRe } = require("markdownlint-rule-helpers")
|
||||
|
||||
/** @typedef {import('markdownlint').RuleParams} MarkdownLintRuleParams */
|
||||
/** @typedef {import('markdownlint').MarkdownItToken} MarkdownItToken */
|
||||
@ -94,8 +96,55 @@ const getMarkdownHeadings = (content) => {
|
||||
return headings
|
||||
}
|
||||
|
||||
const anchorNameRe = getHtmlAttributeRe("name")
|
||||
const anchorIdRe = getHtmlAttributeRe("id")
|
||||
|
||||
/**
|
||||
* Gets the anchor HTML fragments from a Markdown string.
|
||||
* @param {string} content
|
||||
* @returns {string[]}
|
||||
*/
|
||||
const getMarkdownAnchorHTMLFragments = (content) => {
|
||||
const markdownIt = new MarkdownIt({ html: true })
|
||||
const tokens = markdownIt.parse(content, {})
|
||||
|
||||
/** @type {string[]} */
|
||||
const result = []
|
||||
|
||||
for (const token of tokens) {
|
||||
if (token.type === "inline") {
|
||||
if (!token.children) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (const child of token.children) {
|
||||
if (child.type === "html_inline") {
|
||||
const anchorMatch =
|
||||
anchorIdRe.exec(token.content) || anchorNameRe.exec(token.content)
|
||||
if (!anchorMatch || anchorMatch.length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
const anchorIdOrName = anchorMatch[1]
|
||||
if (anchorMatch[1] === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
const anchorHTMLFragment = "#" + anchorIdOrName
|
||||
if (!result.includes(anchorHTMLFragment)) {
|
||||
result.push(anchorHTMLFragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
filterTokens,
|
||||
convertHeadingToHTMLFragment,
|
||||
getMarkdownHeadings,
|
||||
getMarkdownAnchorHTMLFragments,
|
||||
}
|
||||
|
Reference in New Issue
Block a user