forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create Linter Rule to Remove Quotes Around Internal Links (#53510)
Co-authored-by: Rachael Sewell <rachmari@github.com>
- Loading branch information
1 parent
ecc1417
commit 3a792f8
Showing
12 changed files
with
133 additions
and
10 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...ub/managing-email-preferences/adding-an-email-address-to-your-github-account.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ng-your-membership-in-organizations/viewing-peoples-roles-in-an-organization.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...iewing-activity-and-data-for-your-repository/viewing-traffic-to-a-repository.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { addError, filterTokens } from 'markdownlint-rule-helpers' | ||
import { getRange, quotePrecedesLinkOpen } from '../helpers/utils.js' | ||
import { escapeRegExp } from 'lodash-es' | ||
|
||
export const linkQuotation = { | ||
names: ['GHD043', 'link-quotation'], | ||
description: 'Internal link titles must not be surrounded by quotations', | ||
tags: ['links', 'url'], | ||
parser: 'markdownit', | ||
function: (params, onError) => { | ||
filterTokens(params, 'inline', (token) => { | ||
const { children } = token | ||
let previous_child = children[0] | ||
let inLinkWithPrecedingQuotes = false | ||
let linkUrl = '' | ||
let content = [] | ||
let line = '' | ||
for (let i = 1; i < children.length; i++) { | ||
const child = children[i] | ||
if (child.type === 'link_open' && quotePrecedesLinkOpen(previous_child.content)) { | ||
inLinkWithPrecedingQuotes = true | ||
linkUrl = escapeRegExp(child.attrs[0][1]) | ||
line = child.line | ||
} else if (inLinkWithPrecedingQuotes && child.type === 'text') { | ||
content.push(escapeRegExp(child.content.trim())) | ||
} else if (inLinkWithPrecedingQuotes && child.type === 'code_inline') { | ||
content.push('`' + escapeRegExp(child.content.trim()) + '`') | ||
} else if (child.type === 'link_close') { | ||
const title = content.join(' ') | ||
const regex = new RegExp(`"\\[${title}\\]\\(${linkUrl}\\)({%.*%})?(!|\\.|\\?|,)?"`) | ||
if (regex.test(child.line)) { | ||
const match = child.line.match(regex)[0] | ||
const range = getRange(child.line, match) | ||
let newLine = match | ||
if (newLine.startsWith('"')) { | ||
newLine = newLine.slice(1) | ||
} | ||
if (newLine.endsWith('"')) { | ||
newLine = newLine.slice(0, -1) | ||
} | ||
if (newLine.endsWith('".')) { | ||
newLine = newLine.slice(0, -2) + '.' | ||
} | ||
const lineNumber = child.lineNumber | ||
addError( | ||
onError, | ||
lineNumber, | ||
'Remove quotes surrounding the link title.', | ||
match, | ||
range, | ||
{ | ||
lineNumber, | ||
editColumn: range[0], | ||
deleteCount: range[1], | ||
insertText: newLine, | ||
}, | ||
) | ||
} | ||
inLinkWithPrecedingQuotes = false | ||
content = [] | ||
line = '' | ||
linkUrl = '' | ||
} | ||
previous_child = child | ||
} | ||
}) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { describe, expect, test } from 'vitest' | ||
|
||
import { runRule } from '../../lib/init-test.js' | ||
import { linkQuotation } from '../../lib/linting-rules/link-quotation.js' | ||
|
||
describe(linkQuotation.names.join(' - '), () => { | ||
test('links that are formatted correctly should not generate an error', async () => { | ||
const markdown = [ | ||
'Random stuff [A title](./image.png)', | ||
'"This is a direct quote" [A title](./image.png)', | ||
].join('\n') | ||
const result = await runRule(linkQuotation, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(0) | ||
}) | ||
|
||
test('links with quotes around them should error out', async () => { | ||
const markdown = [ | ||
'Random stuff "[A title](./image.png)."', | ||
'Random stuff "[A title](./image.png)?"', | ||
'Random stuff "[A title](./image.png)!"', | ||
'Random stuff "[A title](./image.png)".', | ||
'Random stuff "[A title](./image.png)"?', | ||
'Random stuff "[A title](./image.png)"!', | ||
'See "[AUTOTITLE](/foo/bar){% ifversion fpt %}."{% elsif ghes or ghec %}" and "[AUTOTITLE](/foo/bar)."{% endif %}', | ||
'See "[AUTOTITLE](/foo/bar)," "[AUTOTITLE](/foo/bar2)," "[AUTOTITLE](/foo/bar3)," and "[AUTOTITLE](/foo/bar4)."', | ||
'See "[Anchor link](#anchor-link)."', | ||
].join('\n') | ||
const result = await runRule(linkQuotation, { strings: { markdown } }) | ||
const errors = result.markdown | ||
expect(errors.length).toBe(13) | ||
expect(errors[0].errorRange).toEqual([14, 25]) | ||
expect(errors[0].fixInfo.insertText).toBe('[A title](./image.png).') | ||
expect(errors[1].fixInfo.insertText).toBe('[A title](./image.png)?') | ||
}) | ||
}) |