Skip to content

Commit

Permalink
Add support for hash ranges
Browse files Browse the repository at this point in the history
Closes GH-27.

Co-authored-by: Philipp Brumm <[email protected]>
  • Loading branch information
wooorm and brumm committed Aug 21, 2021
1 parent 7ad41e3 commit 042f5c0
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 14 deletions.
80 changes: 66 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const repoGroup = '(' + userGroup + ')\\/(' + projectGroup + ')'
const linkRegex = new RegExp(
'^https?:\\/\\/github\\.com\\/' +
repoGroup +
'\\/(commit|issues|pull)\\/([a-f\\d]+\\/?(?=[#?]|$))',
'\\/(commit|compare|issues|pull)\\/([a-f\\d]+(?:\\.{3}[a-f\\d]+)?\\/?(?=[#?]|$))',
'i'
)

Expand Down Expand Up @@ -134,10 +134,12 @@ export default function remarkGithub(options = {}) {
[referenceRegex, replaceReference],
[mentionRegex, replaceMention],
[/(?:#|\bgh-)([1-9]\d*)/gi, replaceIssue],
[/\b([a-f\d]{7,40})\.{3}([a-f\d]{7,40})\b/gi, replaceHashRange],
[/\b[a-f\d]{7,40}\b/gi, replaceHash]
],
{ignore: ['link', 'linkReference']}
)

visit(tree, 'link', (node) => {
const link = parse(node)

Expand All @@ -149,7 +151,11 @@ export default function remarkGithub(options = {}) {
/** @type {string} */
let base

if (link.project !== repositoryInfo.project) {
if (
link.project !== repositoryInfo.project ||
// Compare page uses full `user/project` for forks.
(link.page === 'compare' && link.user !== repositoryInfo.user)
) {
base = link.user + '/' + link.project
} else if (link.user === repositoryInfo.user) {
base = ''
Expand All @@ -160,22 +166,22 @@ export default function remarkGithub(options = {}) {
/** @type {StaticPhrasingContent[]} */
const children = []

if (link.page === 'commit') {
if (link.page === 'issues' || link.page === 'pull') {
base += '#'
children.push({
type: 'text',
value: base + link.reference + comment
})
} else {
if (base) {
children.push({type: 'text', value: base + '@'})
}

children.push({type: 'inlineCode', value: abbr(link.reference)})
children.push({type: 'inlineCode', value: link.reference})

if (link.comment) {
children.push({type: 'text', value: comment})
}
} else {
base += '#'
children.push({
type: 'text',
value: base + abbr(link.reference) + comment
})
}

node.children = children
Expand Down Expand Up @@ -243,9 +249,11 @@ export default function remarkGithub(options = {}) {
/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} a
* @param {string} b
* @param {Match} match
*/
function replaceHash(value, match) {
function replaceHashRange(value, a, b, match) {
if (
/[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
Expand All @@ -254,6 +262,37 @@ export default function remarkGithub(options = {}) {
return false
}

return {
type: 'link',
title: null,
url:
'https://github.com/' +
repositoryInfo.user +
'/' +
repositoryInfo.project +
'/compare/' +
value,
children: [{type: 'inlineCode', value: abbr(a) + '...' + abbr(b)}]
}
}

/**
* @type {ReplaceFunction}
* @param {string} value
* @param {Match} match
*/
function replaceHash(value, match) {
if (
/[^\t\n\r (@[{.]/.test(match.input.charAt(match.index - 1)) ||
// For some weird reason GH does link two dots, but not one 🤷‍♂️
(match.input.charAt(match.index - 1) === '.' &&
match.input.charAt(match.index - 2) !== '.') ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
denyHash.has(value)
) {
return false
}

return {
type: 'link',
title: null,
Expand Down Expand Up @@ -352,21 +391,34 @@ function parse(node) {
node.children.length !== 1 ||
node.children[0].type !== 'text' ||
toString(node) !== url ||
// Issues / PRs are decimal only.
(match[3] !== 'commit' && /[a-f]/i.test(match[4])) ||
// SHAs can be min 4, max 40 characters.
(match[3] === 'commit' && (match[4].length < 4 || match[4].length > 40)) ||
// SHAs can be min 4, max 40 characters.
(match[3] === 'compare' &&
!/^[a-f\d]{4,40}\.{3}[a-f\d]{4,40}$/.test(match[4])) ||
// Issues / PRs are decimal only.
((match[3] === 'issues' || match[3] === 'pull') &&
/[a-f]/i.test(match[4])) ||
// Projects can be at most 99 characters.
match[2].length >= 100
) {
return
}

let reference = match[4]

if (match[3] === 'compare') {
const [base, compare] = reference.split('...')
reference = abbr(base) + '...' + abbr(compare)
} else {
reference = abbr(reference)
}

return {
user: match[1],
project: match[2],
page: match[3],
reference: match[4],
reference,
comment:
url.charAt(match[0].length) === '#' && match[0].length + 1 < url.length
}
Expand Down
59 changes: 59 additions & 0 deletions test/fixtures/sha-range/input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
range comparison: e2acebc...2aa9311

actual unicode ellipsis: e2acebc…2aa9311

punctuation before: -e2acebc...2aa9311

e2acebc...2aa9311.punctuation after

two: e2acebc..2aa9311

one: e2acebc.2aa9311

fork? [email protected]

repo: name/[email protected]

5/5: e2ace...2aa93

7/5: e2acebc...2aa93

5/7: e2ace...2aa9311

lonely a e2acebc...

lonely b ...2aa9311

Full links:

Other project: https://github.com/wooorm/remark-toc/compare/e2ac...2aa9

Fork: https://github.com/other/remark/compare/e2ac...2aa9

4/4: https://github.com/wooorm/remark/compare/e2ac...2aa9

4/40: https://github.com/wooorm/remark/compare/e2ac...2aa931154d6e0f6317aff644924163999cb61894

40/4: https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa9

40/40: https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa931154d6e0f6317aff644924163999cb61894

Dots 5:

2aa93

.2aa93

..2aa93

...2aa93

Dots 7:

e2acebc

.e2acebc

..e2acebc

...e2acebc
59 changes: 59 additions & 0 deletions test/fixtures/sha-range/output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
range comparison: [`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebc...2aa9311)

actual unicode ellipsis: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)…2aa9311

punctuation before: -e2acebc...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

[`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebc...2aa9311).punctuation after

two: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)..[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

one: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc).2aa9311

fork? [other@`e2acebc`](https://github.com/other/remark/commit/e2acebc)...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

repo: [name/project@`e2acebc`](https://github.com/name/project/commit/e2acebc)...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

5/5: e2ace...2aa93

7/5: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)...2aa93

5/7: e2ace...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

lonely a [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)...

lonely b ...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311)

Full links:

Other project: [wooorm/remark-toc@`e2ac...2aa9`](https://github.com/wooorm/remark-toc/compare/e2ac...2aa9)

Fork: [other/remark@`e2ac...2aa9`](https://github.com/other/remark/compare/e2ac...2aa9)

4/4: [`e2ac...2aa9`](https://github.com/wooorm/remark/compare/e2ac...2aa9)

4/40: [`e2ac...2aa9311`](https://github.com/wooorm/remark/compare/e2ac...2aa931154d6e0f6317aff644924163999cb61894)

40/4: [`e2acebc...2aa9`](https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa9)

40/40: [`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa931154d6e0f6317aff644924163999cb61894)

Dots 5:

2aa93

.2aa93

..2aa93

...2aa93

Dots 7:

[`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)

.e2acebc

..[`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)

...[`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)

0 comments on commit 042f5c0

Please sign in to comment.