Skip to content

Commit

Permalink
Update MD051/link-fragments to support id attributes on non-a ele…
Browse files Browse the repository at this point in the history
…ments (fixes #538).

The `name` is only an anchor on `a` elements, but `id` is a universal
attribute on all elements.

Also fix match on id/name to be complete, not just a suffix.
  • Loading branch information
MarkLodato authored Jul 28, 2022
1 parent cba2ca0 commit 6c8ef48
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 18 deletions.
12 changes: 6 additions & 6 deletions demo/markdownlint-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4601,7 +4601,8 @@ module.exports = [

const { addError, escapeForRegExp, filterTokens, forEachInlineChild, forEachHeading, htmlElementRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// Regular expression for identifying HTML anchor names
const identifierRe = /(?:id|name)\s*=\s*['"]?([^'"\s>]+)/iu;
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
const nameRe = /\sname\s*=\s*['"]?([^'"\s>]+)/iu;
/**
* Converts a Markdown heading into an HTML fragment according to the rules
* used by GitHub.
Expand Down Expand Up @@ -4643,11 +4644,10 @@ module.exports = {
let match = null;
while ((match = htmlElementRe.exec(token.content)) !== null) {
const [tag, , element] = match;
if (element.toLowerCase() === "a") {
const idMatch = identifierRe.exec(tag);
if (idMatch) {
fragments.set(`#${idMatch[1]}`, 0);
}
const anchorMatch = idRe.exec(tag) ||
(element.toLowerCase() === "a" && nameRe.exec(tag));
if (anchorMatch) {
fragments.set(`#${anchorMatch[1]}`, 0);
}
}
};
Expand Down
12 changes: 6 additions & 6 deletions lib/md051.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const { addError, escapeForRegExp, filterTokens, forEachInlineChild,
forEachHeading, htmlElementRe } = require("../helpers");

// Regular expression for identifying HTML anchor names
const identifierRe = /(?:id|name)\s*=\s*['"]?([^'"\s>]+)/iu;
const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu;
const nameRe = /\sname\s*=\s*['"]?([^'"\s>]+)/iu;

/**
* Converts a Markdown heading into an HTML fragment according to the rules
Expand Down Expand Up @@ -55,11 +56,10 @@ module.exports = {
let match = null;
while ((match = htmlElementRe.exec(token.content)) !== null) {
const [ tag, , element ] = match;
if (element.toLowerCase() === "a") {
const idMatch = identifierRe.exec(tag);
if (idMatch) {
fragments.set(`#${idMatch[1]}`, 0);
}
const anchorMatch = idRe.exec(tag) ||
(element.toLowerCase() === "a" && nameRe.exec(tag));
if (anchorMatch) {
fragments.set(`#${anchorMatch[1]}`, 0);
}
}
};
Expand Down
18 changes: 18 additions & 0 deletions test/link-fragments.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@

[Valid](#HREFandID)

[Valid](#id-for-other-element)

[Valid](#id-after-name)

[Valid][goodref]

### Valid H3 Heading
Expand Down Expand Up @@ -125,6 +129,14 @@ Text

<A href="https://example.com" id="HREFandID">Text</A>

<p id="id-for-other-element"></p>

<p name="name-for-other-element"></p>

<input name="name-should-be-ignored" id="id-after-name">

<a data-id="not-an-id-should-be-ignored">

[goodref]: #namedlink

## Invalid Fragments
Expand All @@ -139,6 +151,12 @@ Text

[Invalid](#hrefandid) {MD051}

[Invalid](#name-for-other-element) {MD051}

[Invalid](#name-should-be-ignored) {MD051}

[Invalid](#not-an-id-should-be-ignored) {MD051}

[Invalid][badref] {MD051}

[badref]: #missing
Expand Down
78 changes: 72 additions & 6 deletions test/snapshots/markdownlint-test-scenarios.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -20950,7 +20950,7 @@ Generated by [AVA](https://avajs.dev).
31,
],
fixInfo: null,
lineNumber: 132,
lineNumber: 144,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand All @@ -20966,7 +20966,7 @@ Generated by [AVA](https://avajs.dev).
36,
],
fixInfo: null,
lineNumber: 134,
lineNumber: 146,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand All @@ -20982,7 +20982,7 @@ Generated by [AVA](https://avajs.dev).
28,
],
fixInfo: null,
lineNumber: 136,
lineNumber: 148,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand All @@ -20998,7 +20998,7 @@ Generated by [AVA](https://avajs.dev).
18,
],
fixInfo: null,
lineNumber: 138,
lineNumber: 150,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand All @@ -21014,7 +21014,55 @@ Generated by [AVA](https://avajs.dev).
21,
],
fixInfo: null,
lineNumber: 140,
lineNumber: 152,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
'MD051',
'link-fragments',
],
},
{
errorContext: '[Invalid](#name-for-other-element)',
errorDetail: null,
errorRange: [
1,
34,
],
fixInfo: null,
lineNumber: 154,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
'MD051',
'link-fragments',
],
},
{
errorContext: '[Invalid](#name-should-be-ignored)',
errorDetail: null,
errorRange: [
1,
34,
],
fixInfo: null,
lineNumber: 156,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
'MD051',
'link-fragments',
],
},
{
errorContext: '[Invalid](#not-an-id-should-be-ignored)',
errorDetail: null,
errorRange: [
1,
39,
],
fixInfo: null,
lineNumber: 158,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand All @@ -21027,7 +21075,7 @@ Generated by [AVA](https://avajs.dev).
errorDetail: null,
errorRange: null,
fixInfo: null,
lineNumber: 142,
lineNumber: 160,
ruleDescription: 'Link fragments should be valid',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md051',
ruleNames: [
Expand Down Expand Up @@ -21090,6 +21138,10 @@ Generated by [AVA](https://avajs.dev).
[Valid](#HREFandID)␊
[Valid](#id-for-other-element)␊
[Valid](#id-after-name)␊
[Valid][goodref]␊
### Valid H3 Heading␊
Expand Down Expand Up @@ -21163,6 +21215,14 @@ Generated by [AVA](https://avajs.dev).
<A href="https://example.com" id="HREFandID">Text</A>␊
<p id="id-for-other-element"></p>␊
<p name="name-for-other-element"></p>␊
<input name="name-should-be-ignored" id="id-after-name">␊
<a data-id="not-an-id-should-be-ignored">␊
[goodref]: #namedlink␊
## Invalid Fragments␊
Expand All @@ -21177,6 +21237,12 @@ Generated by [AVA](https://avajs.dev).
[Invalid](#hrefandid) {MD051}␊
[Invalid](#name-for-other-element) {MD051}␊
[Invalid](#name-should-be-ignored) {MD051}␊
[Invalid](#not-an-id-should-be-ignored) {MD051}␊
[Invalid][badref] {MD051}␊
[badref]: #missing␊
Expand Down
Binary file modified test/snapshots/markdownlint-test-scenarios.js.snap
Binary file not shown.

0 comments on commit 6c8ef48

Please sign in to comment.