From fbb6e03eee9528d183f8217f4f4d5cf4bf569f95 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 6 Jun 2017 18:23:10 +0800 Subject: [PATCH 01/21] Shorten URLs to files --- src/content.js | 20 ++++++++++++++++++++ src/libs/util.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/libs/util.js diff --git a/src/content.js b/src/content.js index f086f82370aa..37a643ee1c9e 100644 --- a/src/content.js +++ b/src/content.js @@ -16,6 +16,7 @@ import showRealNames from './libs/show-names'; import filePathCopyBtnListner from './libs/copy-file-path'; import addFileCopyButton from './libs/copy-file'; import linkifyCode, {editTextNodes} from './libs/linkify-urls-in-code'; +import {shortenUrl} from './libs/util'; import * as icons from './libs/icons'; import * as pageDetect from './libs/page-detect'; @@ -465,6 +466,24 @@ function addTitleToEmojis() { } } +function shortenVisibleUrls() { + $('a[href]').get().forEach(a => { + // Don't change if it was already customized + if (a.href !== a.textContent) { + return; + } + + const shortened = shortenUrl(a.href); + + // Don't touch the dom if there's nothing to change + if (shortened === a.href) { + return; + } + + a.innerHTML = shortened; + }); +} + // Support indent with tab key in comments $(document).on('keydown', '.js-comment-field', event => { if (event.which === 9 && !event.shiftKey) { @@ -552,6 +571,7 @@ function init() { addCompareTab(); removeProjectsTab(); addTitleToEmojis(); + shortenVisibleUrls(); diffFileHeader.destroy(); enableCopyOnY.destroy(); diff --git a/src/libs/util.js b/src/libs/util.js new file mode 100644 index 000000000000..0b99d4be733f --- /dev/null +++ b/src/libs/util.js @@ -0,0 +1,36 @@ +import {getRepoURL} from './page-detect'; + +export const shortenUrl = url => url + // Drop HTTPS, but not HTTP + .replace(/^https:\/\//, '') + + // Drop host if pathname makes sense on its own + .replace(`${location.host}/`, (host, i, url) => { + if (i === 0 && url.split('/').length > 3) { + return ''; + } + return host; + }) + + // Shorten and highlight commit hashes + .replace(/([^/]+\/[^/]+)\/blob\/([\da-f]{7,})/i, (m, repo, hash) => { + return `${repo}/${hash.substr(0, 7)}`; + }) + + // Shorten and highlight branches + .replace(/([^/]+\/[^/]+)\/(blob|blame)\/([^/]+)/, (m, repo, type, revision) => { + return `${repo}/${type === 'blob' ? '' : `${type}/`}${revision}`; + }) + + // Shorten and highlight branches + .replace(`${getRepoURL()}/`, ''); + +export const issueRegex = /([a-zA-Z0-9-_.]+\/[a-zA-Z0-9-_.]+)?#[0-9]+/; +export const linkifyIssueRef = (repoPath, issue, attrs) => { + if (/\//.test(issue)) { + const issueParts = issue.split('#'); + return `${issue}`; + } + return `${issue}`; +}; + From 2bb924108aaa6de55de4def6ed8d939815ff7ac4 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Wed, 7 Jun 2017 14:05:17 +0800 Subject: [PATCH 02/21] Switch to for of loop --- src/content.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content.js b/src/content.js index 37a643ee1c9e..a8339f657236 100644 --- a/src/content.js +++ b/src/content.js @@ -467,21 +467,21 @@ function addTitleToEmojis() { } function shortenVisibleUrls() { - $('a[href]').get().forEach(a => { + for (const a of select.all('a[href]')) { // Don't change if it was already customized if (a.href !== a.textContent) { - return; + continue; } const shortened = shortenUrl(a.href); // Don't touch the dom if there's nothing to change if (shortened === a.href) { - return; + continue; } a.innerHTML = shortened; - }); + } } // Support indent with tab key in comments From 536beaf6c254d97f20b0aee7319b96520716588d Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Wed, 7 Jun 2017 14:06:16 +0800 Subject: [PATCH 03/21] Move from string+regex parsing to explicit piece-by-piece handling --- src/libs/util.js | 96 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/src/libs/util.js b/src/libs/util.js index 0b99d4be733f..995ae213cebd 100644 --- a/src/libs/util.js +++ b/src/libs/util.js @@ -1,29 +1,85 @@ import {getRepoURL} from './page-detect'; -export const shortenUrl = url => url - // Drop HTTPS, but not HTTP - .replace(/^https:\/\//, '') - - // Drop host if pathname makes sense on its own - .replace(`${location.host}/`, (host, i, url) => { - if (i === 0 && url.split('/').length > 3) { - return ''; +export const shortenUrl = plainUrl => { + let { + origin, + pathname, + search, + hash + } = new URL(plainUrl); + + let [ + , // Always empty + user, + repo, + type, + revision, + ...filePath + ] = pathname.split('/'); + + const isLocalUrl = origin === location.origin; + const isCurrentRepo = isLocalUrl && getRepoURL() === `${user}/${repo}`; + + const isRaw = [ + 'https://raw.githubusercontent.com', + 'https://cdn.rawgit.com', + 'https://rawgit.com' + ].includes(origin); + + const isFile = [ + 'blob', + 'blame' + ].includes(type); + + // Drop origin if pathname makes sense on its own + if ((isRaw || isLocalUrl) && pathname.split('/').length > 3) { + origin = ''; + } else { + // Otherwise just drop HTTPS + origin = origin.replace('https://', ''); + } + + // Shorten GitHub file URLs + if (isFile || isRaw) { + let newPath = ''; + + // Drop 'user/repo' where possible + if (!isCurrentRepo) { + newPath += `/${user}/${repo}`; } - return host; - }) - // Shorten and highlight commit hashes - .replace(/([^/]+\/[^/]+)\/blob\/([\da-f]{7,})/i, (m, repo, hash) => { - return `${repo}/${hash.substr(0, 7)}`; - }) + // Shift variables on "raw" urls because they don't have a type + if (isRaw) { + filePath.unshift(revision); + revision = type; + } else if (type !== 'blob') { + // Highlight 'type'; drop it if it's 'blob' + newPath += `/${type}`; + } + + if (revision) { + // Shorten hashes + if (/^[0-9a-f]{40}$/.test(revision)) { + revision = revision.substr(0, 7); + } + // Highlight hashes and branches + newPath += `/${revision}`; + } - // Shorten and highlight branches - .replace(/([^/]+\/[^/]+)\/(blob|blame)\/([^/]+)/, (m, repo, type, revision) => { - return `${repo}/${type === 'blob' ? '' : `${type}/`}${revision}`; - }) + if (filePath.length > 0) { + filePath = filePath.join('/'); + if (isRaw) { + filePath = `${filePath}`; + } + newPath += `:${filePath}`; + } - // Shorten and highlight branches - .replace(`${getRepoURL()}/`, ''); + pathname = newPath; + } + + // Join all; drop possible starting backslash + return `${origin}${pathname}${search}${hash}`.replace(/^[/]/, ''); +}; export const issueRegex = /([a-zA-Z0-9-_.]+\/[a-zA-Z0-9-_.]+)?#[0-9]+/; export const linkifyIssueRef = (repoPath, issue, attrs) => { From a0242ae8a8d7da4544660a16a50909bb5dbe7f4f Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Wed, 14 Jun 2017 11:11:03 +0800 Subject: [PATCH 04/21] Parse first, shorten in one shot if it matches a pattern --- src/content.js | 4 +- src/libs/util.js | 139 ++++++++++++++++++++++++++++------------------- 2 files changed, 86 insertions(+), 57 deletions(-) diff --git a/src/content.js b/src/content.js index a8339f657236..9402bdfc072a 100644 --- a/src/content.js +++ b/src/content.js @@ -469,7 +469,9 @@ function addTitleToEmojis() { function shortenVisibleUrls() { for (const a of select.all('a[href]')) { // Don't change if it was already customized - if (a.href !== a.textContent) { + // .href automatically adds a / to naked origins + // so that needs to be tested too + if (a.href !== a.textContent && a.href !== `${a.textContent}/`) { continue; } diff --git a/src/libs/util.js b/src/libs/util.js index 995ae213cebd..8fa582fb1b39 100644 --- a/src/libs/util.js +++ b/src/libs/util.js @@ -1,84 +1,111 @@ import {getRepoURL} from './page-detect'; -export const shortenUrl = plainUrl => { - let { +// Filter out null values +const joinValues = (array, delimiter = '/') => { + return array.filter(s => s).join(delimiter); +}; + +export const shortenUrl = href => { + /** + * Parse URL + */ + const { origin, pathname, search, hash - } = new URL(plainUrl); + } = new URL(href); + + const isRaw = [ + 'https://raw.githubusercontent.com', + 'https://cdn.rawgit.com', + 'https://rawgit.com' + ].includes(origin); let [ - , // Always empty user, repo, type, revision, ...filePath - ] = pathname.split('/'); + ] = pathname.substr(1).split('/'); - const isLocalUrl = origin === location.origin; - const isCurrentRepo = isLocalUrl && getRepoURL() === `${user}/${repo}`; + if (isRaw) { + [ + user, + repo, + // Raw URLs don't have `blob` here + revision, + ...filePath + ] = pathname.substr(1).split('/'); + type = 'raw'; + } - const isRaw = [ - 'https://raw.githubusercontent.com', - 'https://cdn.rawgit.com', - 'https://rawgit.com' - ].includes(origin); + if (/^[0-9a-f]{40}$/.test(revision)) { + revision = revision.substr(0, 7); + } - const isFile = [ - 'blob', - 'blame' - ].includes(type); + const isLocal = origin === location.origin; + const isThisRepo = (isLocal || isRaw) && getRepoURL() === `${user}/${repo}`; - // Drop origin if pathname makes sense on its own - if ((isRaw || isLocalUrl) && pathname.split('/').length > 3) { - origin = ''; - } else { - // Otherwise just drop HTTPS - origin = origin.replace('https://', ''); - } + const isReserved = [ + 'join', + 'site', + 'blog', + 'about', + 'login', + 'pulls', + 'search', + 'issues', + 'explore', + 'contact', + 'pricing', + 'trending', + 'settings', + 'features', + 'business', + 'personal', + 'security', + 'dashboard', + 'showcases', + 'open-source', + 'marketplace' + ].includes(user); - // Shorten GitHub file URLs - if (isFile || isRaw) { - let newPath = ''; + const isFileOrDir = revision && [ + 'raw', + 'tree', + 'blob', + 'blame', + 'commits' + ].includes(type); - // Drop 'user/repo' where possible - if (!isCurrentRepo) { - newPath += `/${user}/${repo}`; - } + /** + * Shorten URL + */ - // Shift variables on "raw" urls because they don't have a type - if (isRaw) { - filePath.unshift(revision); - revision = type; - } else if (type !== 'blob') { - // Highlight 'type'; drop it if it's 'blob' - newPath += `/${type}`; - } + if (isReserved || !repo || (!isLocal && !isRaw)) { + return href + .replace(/^https:[/][/]/, '') + .replace(/^www[.]/, '') + .replace(/[/]$/, ''); + } - if (revision) { - // Shorten hashes - if (/^[0-9a-f]{40}$/.test(revision)) { - revision = revision.substr(0, 7); - } - // Highlight hashes and branches - newPath += `/${revision}`; - } + const repoUrl = isThisRepo ? '' : `${user}/${repo}`; - if (filePath.length > 0) { - filePath = filePath.join('/'); - if (isRaw) { - filePath = `${filePath}`; - } - newPath += `:${filePath}`; + if (isFileOrDir) { + const file = joinValues([repoUrl, ...filePath]); + const revisioned = joinValues([ + file, + `${revision}${search}${hash}` + ], '@'); + if (type !== 'blob' && type !== 'tree') { + return `${revisioned} (${type})`; } - - pathname = newPath; + return revisioned; } - // Join all; drop possible starting backslash - return `${origin}${pathname}${search}${hash}`.replace(/^[/]/, ''); + return `${pathname.substr(1).replace(/[/]$/, '')}${search}${hash}`; }; export const issueRegex = /([a-zA-Z0-9-_.]+\/[a-zA-Z0-9-_.]+)?#[0-9]+/; From a3c9003e01a25bb0389c9e66c5cbfb2adb99e1c8 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Thu, 15 Jun 2017 11:07:15 +0800 Subject: [PATCH 05/21] Extract into its own file --- src/content.js | 24 ++------------------- src/libs/{util.js => shorten-links.js} | 29 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 31 deletions(-) rename src/libs/{util.js => shorten-links.js} (78%) diff --git a/src/content.js b/src/content.js index 9402bdfc072a..909fefdd1cbf 100644 --- a/src/content.js +++ b/src/content.js @@ -16,7 +16,7 @@ import showRealNames from './libs/show-names'; import filePathCopyBtnListner from './libs/copy-file-path'; import addFileCopyButton from './libs/copy-file'; import linkifyCode, {editTextNodes} from './libs/linkify-urls-in-code'; -import {shortenUrl} from './libs/util'; +import shortenLinks from './libs/shorten-links'; import * as icons from './libs/icons'; import * as pageDetect from './libs/page-detect'; @@ -466,26 +466,6 @@ function addTitleToEmojis() { } } -function shortenVisibleUrls() { - for (const a of select.all('a[href]')) { - // Don't change if it was already customized - // .href automatically adds a / to naked origins - // so that needs to be tested too - if (a.href !== a.textContent && a.href !== `${a.textContent}/`) { - continue; - } - - const shortened = shortenUrl(a.href); - - // Don't touch the dom if there's nothing to change - if (shortened === a.href) { - continue; - } - - a.innerHTML = shortened; - } -} - // Support indent with tab key in comments $(document).on('keydown', '.js-comment-field', event => { if (event.which === 9 && !event.shiftKey) { @@ -573,7 +553,7 @@ function init() { addCompareTab(); removeProjectsTab(); addTitleToEmojis(); - shortenVisibleUrls(); + shortenLinks(); diffFileHeader.destroy(); enableCopyOnY.destroy(); diff --git a/src/libs/util.js b/src/libs/shorten-links.js similarity index 78% rename from src/libs/util.js rename to src/libs/shorten-links.js index 8fa582fb1b39..97982714e489 100644 --- a/src/libs/util.js +++ b/src/libs/shorten-links.js @@ -1,3 +1,4 @@ +import select from 'select-dom'; import {getRepoURL} from './page-detect'; // Filter out null values @@ -5,7 +6,7 @@ const joinValues = (array, delimiter = '/') => { return array.filter(s => s).join(delimiter); }; -export const shortenUrl = href => { +function shortenUrl(href) { /** * Parse URL */ @@ -106,14 +107,24 @@ export const shortenUrl = href => { } return `${pathname.substr(1).replace(/[/]$/, '')}${search}${hash}`; -}; +} + +export default () => { + for (const a of select.all('a[href]')) { + // Don't change if it was already customized + // .href automatically adds a / to naked origins + // so that needs to be tested too + if (a.href !== a.textContent && a.href !== `${a.textContent}/`) { + continue; + } + + const shortened = shortenUrl(a.href); -export const issueRegex = /([a-zA-Z0-9-_.]+\/[a-zA-Z0-9-_.]+)?#[0-9]+/; -export const linkifyIssueRef = (repoPath, issue, attrs) => { - if (/\//.test(issue)) { - const issueParts = issue.split('#'); - return `${issue}`; + // Don't touch the dom if there's nothing to change + if (shortened === a.href) { + continue; + } + + a.innerHTML = shortened; } - return `${issue}`; }; - From 5d1863bc42617169e1c30c1305968750927fa6df Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Thu, 15 Jun 2017 11:07:36 +0800 Subject: [PATCH 06/21] Cleanup --- src/libs/shorten-links.js | 63 ++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 97982714e489..a6488b653f8c 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -1,6 +1,34 @@ import select from 'select-dom'; import {getRepoURL} from './page-detect'; +const reservedPaths = [ + 'join', + 'site', + 'blog', + 'about', + 'login', + 'pulls', + 'search', + 'issues', + 'explore', + 'contact', + 'pricing', + 'trending', + 'settings', + 'features', + 'business', + 'personal', + 'security', + 'dashboard', + 'showcases', + 'open-source', + 'marketplace' +]; + +const shortenRevision = revision => { + return /^[0-9a-f]{40}$/.test(revision) ? revision.substr(0, 7) : revision; +}; + // Filter out null values const joinValues = (array, delimiter = '/') => { return array.filter(s => s).join(delimiter); @@ -42,37 +70,12 @@ function shortenUrl(href) { type = 'raw'; } - if (/^[0-9a-f]{40}$/.test(revision)) { - revision = revision.substr(0, 7); - } + revision = shortenRevision(revision); + filePath = filePath.join('/'); const isLocal = origin === location.origin; const isThisRepo = (isLocal || isRaw) && getRepoURL() === `${user}/${repo}`; - - const isReserved = [ - 'join', - 'site', - 'blog', - 'about', - 'login', - 'pulls', - 'search', - 'issues', - 'explore', - 'contact', - 'pricing', - 'trending', - 'settings', - 'features', - 'business', - 'personal', - 'security', - 'dashboard', - 'showcases', - 'open-source', - 'marketplace' - ].includes(user); - + const isReserved = reservedPaths.includes(user); const isFileOrDir = revision && [ 'raw', 'tree', @@ -81,6 +84,8 @@ function shortenUrl(href) { 'commits' ].includes(type); + const repoUrl = isThisRepo ? '' : `${user}/${repo}`; + /** * Shorten URL */ @@ -92,8 +97,6 @@ function shortenUrl(href) { .replace(/[/]$/, ''); } - const repoUrl = isThisRepo ? '' : `${user}/${repo}`; - if (isFileOrDir) { const file = joinValues([repoUrl, ...filePath]); const revisioned = joinValues([ From 060b5a45bd50b7957f8ab98380b1a9a0029917c4 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Thu, 15 Jun 2017 18:47:52 +0800 Subject: [PATCH 07/21] Leave / at the beginning of file repo-less paths --- src/libs/shorten-links.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index a6488b653f8c..0fbd88a609f6 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -98,9 +98,9 @@ function shortenUrl(href) { } if (isFileOrDir) { - const file = joinValues([repoUrl, ...filePath]); + const file = [repoUrl, filePath].join('/') const revisioned = joinValues([ - file, + file === '/' ? '' : file, // We don't want "/@v1.2" `${revision}${search}${hash}` ], '@'); if (type !== 'blob' && type !== 'tree') { From 9d1ef3f820dae47acc0383cf1c8d738a20c5199c Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 15:49:20 +0800 Subject: [PATCH 08/21] Correct isShortened test target --- src/libs/shorten-links.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 0fbd88a609f6..3d142c0164e8 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -124,7 +124,7 @@ export default () => { const shortened = shortenUrl(a.href); // Don't touch the dom if there's nothing to change - if (shortened === a.href) { + if (shortened === a.textContent) { continue; } From 591b84e8817fc1c21736950ad59d9419dcc8bfc4 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 15:48:50 +0800 Subject: [PATCH 09/21] Shorten commit.diff and commit.patch --- src/libs/shorten-links.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 3d142c0164e8..9d76c351cec0 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -1,6 +1,8 @@ import select from 'select-dom'; import {getRepoURL} from './page-detect'; +const patchDiffRegex = /[.](patch|diff)$/; + const reservedPaths = [ 'join', 'site', @@ -26,7 +28,14 @@ const reservedPaths = [ ]; const shortenRevision = revision => { - return /^[0-9a-f]{40}$/.test(revision) ? revision.substr(0, 7) : revision; + if (!revision) { + return; + } + revision = revision.replace(patchDiffRegex, ''); + if (/^[0-9a-f]{40}$/.test(revision)) { + revision = revision.substr(0, 7); + } + return revision; }; // Filter out null values @@ -76,6 +85,7 @@ function shortenUrl(href) { const isLocal = origin === location.origin; const isThisRepo = (isLocal || isRaw) && getRepoURL() === `${user}/${repo}`; const isReserved = reservedPaths.includes(user); + const [, diffOrPatch] = pathname.match(patchDiffRegex) || []; const isFileOrDir = revision && [ 'raw', 'tree', @@ -109,6 +119,14 @@ function shortenUrl(href) { return revisioned; } + if (diffOrPatch) { + const url = joinValues([ + repoUrl, + `${revision}${search}${hash}` + ], '@'); + return `${url}.${diffOrPatch}`; + } + return `${pathname.substr(1).replace(/[/]$/, '')}${search}${hash}`; } From 12040ac2e63ccfa9448b3b3911315710e7cedeee Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:08:41 +0800 Subject: [PATCH 10/21] Wrap revision in once --- src/libs/shorten-links.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 9d76c351cec0..642f885ce1ff 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -27,7 +27,7 @@ const reservedPaths = [ 'marketplace' ]; -const shortenRevision = revision => { +const styleRevision = revision => { if (!revision) { return; } @@ -35,7 +35,7 @@ const shortenRevision = revision => { if (/^[0-9a-f]{40}$/.test(revision)) { revision = revision.substr(0, 7); } - return revision; + return `${revision}`; }; // Filter out null values @@ -79,7 +79,7 @@ function shortenUrl(href) { type = 'raw'; } - revision = shortenRevision(revision); + revision = styleRevision(revision); filePath = filePath.join('/'); const isLocal = origin === location.origin; @@ -111,7 +111,7 @@ function shortenUrl(href) { const file = [repoUrl, filePath].join('/') const revisioned = joinValues([ file === '/' ? '' : file, // We don't want "/@v1.2" - `${revision}${search}${hash}` + `${revision}${search}${hash}` ], '@'); if (type !== 'blob' && type !== 'tree') { return `${revisioned} (${type})`; @@ -122,7 +122,7 @@ function shortenUrl(href) { if (diffOrPatch) { const url = joinValues([ repoUrl, - `${revision}${search}${hash}` + `${revision}${search}${hash}` ], '@'); return `${url}.${diffOrPatch}`; } From f987e524597e86364475e0e5be2a009eb6e0e374 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:14:10 +0800 Subject: [PATCH 11/21] Cleanup --- src/libs/shorten-links.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 642f885ce1ff..2c13ab375133 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -108,23 +108,20 @@ function shortenUrl(href) { } if (isFileOrDir) { - const file = [repoUrl, filePath].join('/') + const file = [repoUrl, filePath].join('/'); const revisioned = joinValues([ file === '/' ? '' : file, // We don't want "/@v1.2" - `${revision}${search}${hash}` + revision ], '@'); if (type !== 'blob' && type !== 'tree') { - return `${revisioned} (${type})`; + return `${revisioned}${search}${hash} (${type})`; } return revisioned; } if (diffOrPatch) { - const url = joinValues([ - repoUrl, - `${revision}${search}${hash}` - ], '@'); - return `${url}.${diffOrPatch}`; + const partial = joinValues([repoUrl, revision], '@'); + return `${partial}.${diffOrPatch}${search}${hash}`; } return `${pathname.substr(1).replace(/[/]$/, '')}${search}${hash}`; From 71ea9a752a05030beaa0c7b5d47df80a26e3356b Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:56:55 +0800 Subject: [PATCH 12/21] Fix file links inconsistencies --- src/libs/shorten-links.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 2c13ab375133..c4a6cc28abb6 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -108,15 +108,13 @@ function shortenUrl(href) { } if (isFileOrDir) { - const file = [repoUrl, filePath].join('/'); - const revisioned = joinValues([ - file === '/' ? '' : file, // We don't want "/@v1.2" - revision - ], '@'); + const file = `${repoUrl}${filePath ? '/' + filePath : ''}`; + const revisioned = joinValues([file, revision], '@'); + const partial = `${revisioned}${search}${hash}`; if (type !== 'blob' && type !== 'tree') { - return `${revisioned}${search}${hash} (${type})`; + return `${partial} (${type})`; } - return revisioned; + return partial; } if (diffOrPatch) { From afeac8d7dccb7ab9b806b2c2bb8d7d2e5d3a0b68 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:14:41 +0800 Subject: [PATCH 13/21] More explicitly drop leading+trailing slash --- src/libs/shorten-links.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index c4a6cc28abb6..3449f2ba32d3 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -122,7 +122,8 @@ function shortenUrl(href) { return `${partial}.${diffOrPatch}${search}${hash}`; } - return `${pathname.substr(1).replace(/[/]$/, '')}${search}${hash}`; + // Drop leading and trailing slash of relative path + return `${pathname.replace(/^[/]|[/]$/g, '')}${search}${hash}`; } export default () => { From cc2426e691980e9c854ddeec952df1c2659ad89d Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:22:08 +0800 Subject: [PATCH 14/21] Shorten releases --- src/libs/shorten-links.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 3449f2ba32d3..633edabb9f02 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -2,6 +2,7 @@ import select from 'select-dom'; import {getRepoURL} from './page-detect'; const patchDiffRegex = /[.](patch|diff)$/; +const releaseRegex = /releases[/]tag[/]([^/]+)/; const reservedPaths = [ 'join', @@ -86,6 +87,7 @@ function shortenUrl(href) { const isThisRepo = (isLocal || isRaw) && getRepoURL() === `${user}/${repo}`; const isReserved = reservedPaths.includes(user); const [, diffOrPatch] = pathname.match(patchDiffRegex) || []; + const [, release] = pathname.match(releaseRegex) || []; const isFileOrDir = revision && [ 'raw', 'tree', @@ -122,6 +124,11 @@ function shortenUrl(href) { return `${partial}.${diffOrPatch}${search}${hash}`; } + if (release) { + const partial = joinValues([repoUrl, `${release}`], '@'); + return `${partial}${search}${hash} (release)`; + } + // Drop leading and trailing slash of relative path return `${pathname.replace(/^[/]|[/]$/g, '')}${search}${hash}`; } From cfec9879ee51a27a22e6094f4cb8c1166601f9d9 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:22:20 +0800 Subject: [PATCH 15/21] Shorten labels --- src/libs/shorten-links.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 633edabb9f02..b7e2a13f0222 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -3,6 +3,7 @@ import {getRepoURL} from './page-detect'; const patchDiffRegex = /[.](patch|diff)$/; const releaseRegex = /releases[/]tag[/]([^/]+)/; +const labelRegex = /labels[/]([^/]+)/; const reservedPaths = [ 'join', @@ -88,6 +89,7 @@ function shortenUrl(href) { const isReserved = reservedPaths.includes(user); const [, diffOrPatch] = pathname.match(patchDiffRegex) || []; const [, release] = pathname.match(releaseRegex) || []; + const [, label] = pathname.match(labelRegex) || []; const isFileOrDir = revision && [ 'raw', 'tree', @@ -129,6 +131,10 @@ function shortenUrl(href) { return `${partial}${search}${hash} (release)`; } + if (label) { + return joinValues([repoUrl, label]) + `${search}${hash} (label)`; + } + // Drop leading and trailing slash of relative path return `${pathname.replace(/^[/]|[/]$/g, '')}${search}${hash}`; } From 1154c7dacabd6f4e9353d1e6fd7408d305a4aa52 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:34:26 +0800 Subject: [PATCH 16/21] Shorten release archive links --- src/libs/shorten-links.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index b7e2a13f0222..3d0817f55acb 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -4,6 +4,7 @@ import {getRepoURL} from './page-detect'; const patchDiffRegex = /[.](patch|diff)$/; const releaseRegex = /releases[/]tag[/]([^/]+)/; const labelRegex = /labels[/]([^/]+)/; +const releaseArchiveRegex = /archive[/](.+)([.]zip|[.]tar[.]gz)/; const reservedPaths = [ 'join', @@ -89,6 +90,7 @@ function shortenUrl(href) { const isReserved = reservedPaths.includes(user); const [, diffOrPatch] = pathname.match(patchDiffRegex) || []; const [, release] = pathname.match(releaseRegex) || []; + const [, releaseTag, releaseTagExt] = pathname.match(releaseArchiveRegex) || []; const [, label] = pathname.match(labelRegex) || []; const isFileOrDir = revision && [ 'raw', @@ -131,6 +133,11 @@ function shortenUrl(href) { return `${partial}${search}${hash} (release)`; } + if (releaseTagExt) { + const partial = joinValues([repoUrl, `${releaseTag}`], '@'); + return `${partial}${releaseTagExt}${search}${hash}`; + } + if (label) { return joinValues([repoUrl, label]) + `${search}${hash} (label)`; } From 0a9139a6772dcae9781c6f87077c08529e605e05 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 16:58:34 +0800 Subject: [PATCH 17/21] Shorten release downloads --- src/libs/shorten-links.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 3d0817f55acb..8470a717bd53 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -5,6 +5,7 @@ const patchDiffRegex = /[.](patch|diff)$/; const releaseRegex = /releases[/]tag[/]([^/]+)/; const labelRegex = /labels[/]([^/]+)/; const releaseArchiveRegex = /archive[/](.+)([.]zip|[.]tar[.]gz)/; +const releaseDownloadRegex = /releases[/]download[/]([^/]+)[/](.+)/; const reservedPaths = [ 'join', @@ -91,6 +92,7 @@ function shortenUrl(href) { const [, diffOrPatch] = pathname.match(patchDiffRegex) || []; const [, release] = pathname.match(releaseRegex) || []; const [, releaseTag, releaseTagExt] = pathname.match(releaseArchiveRegex) || []; + const [, downloadTag, downloadFilename] = pathname.match(releaseDownloadRegex) || []; const [, label] = pathname.match(labelRegex) || []; const isFileOrDir = revision && [ 'raw', @@ -138,6 +140,11 @@ function shortenUrl(href) { return `${partial}${releaseTagExt}${search}${hash}`; } + if (downloadFilename) { + const partial = joinValues([repoUrl, `${downloadTag}`], '@'); + return `${partial} ${downloadFilename}${search}${hash} (download)`; + } + if (label) { return joinValues([repoUrl, label]) + `${search}${hash} (label)`; } From 24cf74ad80afce4c6ba586f7e1870a5d59ef6f71 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 17:00:33 +0800 Subject: [PATCH 18/21] Shorten users --- src/libs/shorten-links.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index 8470a717bd53..e6b679fdb414 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -108,13 +108,17 @@ function shortenUrl(href) { * Shorten URL */ - if (isReserved || !repo || (!isLocal && !isRaw)) { + if (isReserved || (!isLocal && !isRaw)) { return href .replace(/^https:[/][/]/, '') .replace(/^www[.]/, '') .replace(/[/]$/, ''); } + if (user && !repo) { + return `@${user}${search}${hash}`; + } + if (isFileOrDir) { const file = `${repoUrl}${filePath ? '/' + filePath : ''}`; const revisioned = joinValues([file, revision], '@'); From 55245003f08722a9bfecf7aeccec3b35f9395476 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 20:40:14 +0800 Subject: [PATCH 19/21] Add tests Generated with copy($$('#issue-233840042 .comment-body a:not([class])').map(a => `['${a.href}', '${a.innerHTML}']`).join(',\n')) On page https://github.com/sindresorhus/refined-github/pull/473 --- src/libs/shorten-links.js | 2 +- test/fixtures/window.js | 19 ++----- test/shorten-links.js | 102 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 test/shorten-links.js diff --git a/src/libs/shorten-links.js b/src/libs/shorten-links.js index e6b679fdb414..2cb278664b27 100644 --- a/src/libs/shorten-links.js +++ b/src/libs/shorten-links.js @@ -47,7 +47,7 @@ const joinValues = (array, delimiter = '/') => { return array.filter(s => s).join(delimiter); }; -function shortenUrl(href) { +export function shortenUrl(href) { /** * Parse URL */ diff --git a/test/fixtures/window.js b/test/fixtures/window.js index c7e0cfb2b16a..5d9c9de1f0cd 100644 --- a/test/fixtures/window.js +++ b/test/fixtures/window.js @@ -1,20 +1,7 @@ -const url = require('url'); +const URL = require('url').URL; -function WindowMock(initialURI) { - this._currentURI = initialURI; +function WindowMock(initialURI = 'https://github.com') { + this.location = new URL(initialURI); } -WindowMock.prototype.location = { - set href(uri) { - const uriParts = url.parse(uri); - this.hostname = uriParts.hostname; - this.pathname = uriParts.pathname; - this._currentURI = uri; - }, - - get href() { - return this._currentURI; - } -}; - module.exports = WindowMock; diff --git a/test/shorten-links.js b/test/shorten-links.js new file mode 100644 index 000000000000..54195b8efa87 --- /dev/null +++ b/test/shorten-links.js @@ -0,0 +1,102 @@ +import {URL} from 'url'; +import test from 'ava'; +import {shortenUrl} from '../src/libs/shorten-links'; +import Window from './fixtures/window'; + +global.URL = URL; +global.window = new Window('https://github.com/sindresorhus/refined-github/pull/473'); +global.location = window.location; + +function urlMatcherMacro(t, shouldMatch = []) { + for (const [originalUrl, expectedShortenedUrl] of shouldMatch) { + t.is(shortenUrl(originalUrl), expectedShortenedUrl); + } +} + +test('shortenUrl', urlMatcherMacro, new Map([ + ['https://github.com/sindresorhus/refined-github/', 'sindresorhus/refined-github'], + ['https://github.com/sindresorhus/refined-github/tree/v0.12', 'v0.12'], + ['https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a', 'd71718d'], + ['https://github.com/nodejs/node/', 'nodejs/node'], + ['https://github.com/nodejs/node/tree/v0.12', 'nodejs/node@v0.12'], + ['https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a', 'nodejs/node@d71718d'], + ['https://github.com/sindresorhus/refined-github/tree/master/doc', '/doc@master'], + ['https://github.com/sindresorhus/refined-github/tree/v0.12/doc', '/doc@v0.12'], + ['https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', '/doc@d71718d'], + ['https://github.com/nodejs/node/tree/master/doc', 'nodejs/node/doc@master'], + ['https://github.com/nodejs/node/tree/v0.12/doc', 'nodejs/node/doc@v0.12'], + ['https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', 'nodejs/node/doc@d71718d'], + ['https://github.com/sindresorhus/refined-github/blob/master/.gitignore', '/.gitignore@master'], + ['https://github.com/sindresorhus/refined-github/blob/v0.12/.gitignore', '/.gitignore@v0.12'], + ['https://github.com/sindresorhus/refined-github/blob/cc8fc46/.gitignore', '/.gitignore@cc8fc46'], + ['https://github.com/nodejs/node/blob/master/.gitignore', 'nodejs/node/.gitignore@master'], + ['https://github.com/nodejs/node/blob/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12'], + ['https://github.com/nodejs/node/blob/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46'], + ['https://github.com/sindresorhus/refined-github/blame/master/.gitignore', '/.gitignore@master (blame)'], + ['https://github.com/sindresorhus/refined-github/blame/v0.12/.gitignore', '/.gitignore@v0.12 (blame)'], + ['https://github.com/sindresorhus/refined-github/blame/cc8fc46/.gitignore', '/.gitignore@cc8fc46 (blame)'], + ['https://github.com/nodejs/node/blame/master/.gitignore', 'nodejs/node/.gitignore@master (blame)'], + ['https://github.com/nodejs/node/blame/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (blame)'], + ['https://github.com/nodejs/node/blame/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46 (blame)'], + ['https://github.com/sindresorhus/refined-github/commits/master/.gitignore', '/.gitignore@master (commits)'], + ['https://github.com/sindresorhus/refined-github/commits/v0.12/.gitignore', '/.gitignore@v0.12 (commits)'], + ['https://github.com/sindresorhus/refined-github/commits/cc8fc46/.gitignore', '/.gitignore@cc8fc46 (commits)'], + ['https://github.com/nodejs/node/commits/master/.gitignore', 'nodejs/node/.gitignore@master (commits)'], + ['https://github.com/nodejs/node/commits/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (commits)'], + ['https://github.com/nodejs/node/commits/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46 (commits)'], + ['https://github.com/sindresorhus/refined-github/commit/cc8fc46.diff', 'cc8fc46.diff'], + ['https://github.com/sindresorhus/refined-github/commit/cc8fc46.patch', 'cc8fc46.patch'], + ['https://github.com/nodejs/node/commit/cc8fc46.diff', 'nodejs/node@cc8fc46.diff'], + ['https://github.com/nodejs/node/commit/cc8fc46.patch', 'nodejs/node@cc8fc46.patch'], + ['https://github.com/sindresorhus/refined-github/releases/tag/v0.12.0', 'v0.12.0 (release)'], + ['https://github.com/nodejs/node/releases/tag/v0.12.0', 'nodejs/node@v0.12.0 (release)'], + ['https://github.com/sindresorhus/refined-github/milestone/25', 'sindresorhus/refined-github/milestone/25'], + ['https://github.com/nodejs/node/milestone/25', 'nodejs/node/milestone/25'], + ['https://github.com/sindresorhus/refined-github/labels/npm', 'npm (label)'], + ['https://github.com/nodejs/node/labels/npm', 'nodejs/node/npm (label)'], + ['https://github.com/sindresorhus/refined-github/archive/6.4.1.zip', '6.4.1.zip'], + ['https://github.com/sindresorhus/refined-github/releases/download/6.4.1/now-macos', '6.4.1 now-macos (download)'], + ['https://github.com/zeit/now-cli/archive/6.4.1.zip', 'zeit/now-cli@6.4.1.zip'], + ['https://github.com/zeit/now-cli/releases/download/6.4.1/now-macos', 'zeit/now-cli@6.4.1 now-macos (download)'], + ['https://github.com/sindresorhus/refined-github/wiki', 'sindresorhus/refined-github/wiki'], + ['https://github.com/sindresorhus/refined-github/pulse', 'sindresorhus/refined-github/pulse'], + ['https://github.com/sindresorhus/refined-github/labels', 'sindresorhus/refined-github/labels'], + ['https://github.com/sindresorhus/refined-github/network', 'sindresorhus/refined-github/network'], + ['https://github.com/sindresorhus/refined-github/projects', 'sindresorhus/refined-github/projects'], + ['https://github.com/sindresorhus/refined-github/releases', 'sindresorhus/refined-github/releases'], + ['https://github.com/sindresorhus/refined-github/milestones', 'sindresorhus/refined-github/milestones'], + ['https://github.com/sindresorhus/refined-github/contributors', 'sindresorhus/refined-github/contributors'], + ['https://github.com/nodejs/node/wiki', 'nodejs/node/wiki'], + ['https://github.com/nodejs/node/pulse', 'nodejs/node/pulse'], + ['https://github.com/nodejs/node/labels', 'nodejs/node/labels'], + ['https://github.com/nodejs/node/network', 'nodejs/node/network'], + ['https://github.com/nodejs/node/projects', 'nodejs/node/projects'], + ['https://github.com/nodejs/node/releases', 'nodejs/node/releases'], + ['https://github.com/nodejs/node/milestones', 'nodejs/node/milestones'], + ['https://github.com/nodejs/node/contributors', 'nodejs/node/contributors'], + ['https://github.com/nodejs/node/graphs/commit-activity', 'nodejs/node/graphs/commit-activity'], + ['https://rawgit.com/sindresorhus/refined-github/master/.gitignore', '/.gitignore@master (raw)'], + ['https://cdn.rawgit.com/sindresorhus/refined-github/v0.12/.gitignore', '/.gitignore@v0.12 (raw)'], + ['https://cdn.rawgit.com/sindresorhus/refined-github/d71718db/.gitignore', '/.gitignore@d71718db (raw)'], + ['https://raw.githubusercontent.com/sindresorhus/refined-github/master/.gitignore', '/.gitignore@master (raw)'], + ['https://raw.githubusercontent.com/sindresorhus/refined-github/v0.12/.gitignore', '/.gitignore@v0.12 (raw)'], + ['https://raw.githubusercontent.com/sindresorhus/refined-github/d71718db/.gitignore', '/.gitignore@d71718db (raw)'], + ['https://rawgit.com/nodejs/node/master/.gitignore', 'nodejs/node/.gitignore@master (raw)'], + ['https://cdn.rawgit.com/nodejs/node/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (raw)'], + ['https://cdn.rawgit.com/nodejs/node/d71718db/.gitignore', 'nodejs/node/.gitignore@d71718db (raw)'], + ['https://raw.githubusercontent.com/nodejs/node/master/.gitignore', 'nodejs/node/.gitignore@master (raw)'], + ['https://raw.githubusercontent.com/nodejs/node/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (raw)'], + ['https://raw.githubusercontent.com/nodejs/node/d71718db/.gitignore', 'nodejs/node/.gitignore@d71718db (raw)'], + ['https://github.com/sindresorhus', '@sindresorhus'], + ['https://github.com/nodejs', '@nodejs'], + ['https://github.com/pulls', 'github.com/pulls'], + ['https://github.com/issues', 'github.com/issues'], + ['https://github.com/trending', 'github.com/trending'], + ['https://github.com/features', 'github.com/features'], + ['https://github.com/marketplace', 'github.com/marketplace'], + ['https://github.com/trending/developers', 'github.com/trending/developers'], + ['https://github.com/settings/profile', 'github.com/settings/profile'], + ['https://www.npmjs.com/', 'npmjs.com'], + ['https://www.npmjs.com/package/node', 'npmjs.com/package/node'], + ['https://example.com/nodejs/node/blob/cc8fc46/.gitignore', 'example.com/nodejs/node/blob/cc8fc46/.gitignore'] +])); From d1a99c99f12743f8fe2e7681a842efc764fbbf02 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Fri, 16 Jun 2017 20:44:05 +0800 Subject: [PATCH 20/21] Wrap test's URL list --- test/shorten-links.js | 425 +++++++++++++++++++++++++++++++++--------- 1 file changed, 340 insertions(+), 85 deletions(-) diff --git a/test/shorten-links.js b/test/shorten-links.js index 54195b8efa87..13617c48264c 100644 --- a/test/shorten-links.js +++ b/test/shorten-links.js @@ -14,89 +14,344 @@ function urlMatcherMacro(t, shouldMatch = []) { } test('shortenUrl', urlMatcherMacro, new Map([ - ['https://github.com/sindresorhus/refined-github/', 'sindresorhus/refined-github'], - ['https://github.com/sindresorhus/refined-github/tree/v0.12', 'v0.12'], - ['https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a', 'd71718d'], - ['https://github.com/nodejs/node/', 'nodejs/node'], - ['https://github.com/nodejs/node/tree/v0.12', 'nodejs/node@v0.12'], - ['https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a', 'nodejs/node@d71718d'], - ['https://github.com/sindresorhus/refined-github/tree/master/doc', '/doc@master'], - ['https://github.com/sindresorhus/refined-github/tree/v0.12/doc', '/doc@v0.12'], - ['https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', '/doc@d71718d'], - ['https://github.com/nodejs/node/tree/master/doc', 'nodejs/node/doc@master'], - ['https://github.com/nodejs/node/tree/v0.12/doc', 'nodejs/node/doc@v0.12'], - ['https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', 'nodejs/node/doc@d71718d'], - ['https://github.com/sindresorhus/refined-github/blob/master/.gitignore', '/.gitignore@master'], - ['https://github.com/sindresorhus/refined-github/blob/v0.12/.gitignore', '/.gitignore@v0.12'], - ['https://github.com/sindresorhus/refined-github/blob/cc8fc46/.gitignore', '/.gitignore@cc8fc46'], - ['https://github.com/nodejs/node/blob/master/.gitignore', 'nodejs/node/.gitignore@master'], - ['https://github.com/nodejs/node/blob/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12'], - ['https://github.com/nodejs/node/blob/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46'], - ['https://github.com/sindresorhus/refined-github/blame/master/.gitignore', '/.gitignore@master (blame)'], - ['https://github.com/sindresorhus/refined-github/blame/v0.12/.gitignore', '/.gitignore@v0.12 (blame)'], - ['https://github.com/sindresorhus/refined-github/blame/cc8fc46/.gitignore', '/.gitignore@cc8fc46 (blame)'], - ['https://github.com/nodejs/node/blame/master/.gitignore', 'nodejs/node/.gitignore@master (blame)'], - ['https://github.com/nodejs/node/blame/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (blame)'], - ['https://github.com/nodejs/node/blame/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46 (blame)'], - ['https://github.com/sindresorhus/refined-github/commits/master/.gitignore', '/.gitignore@master (commits)'], - ['https://github.com/sindresorhus/refined-github/commits/v0.12/.gitignore', '/.gitignore@v0.12 (commits)'], - ['https://github.com/sindresorhus/refined-github/commits/cc8fc46/.gitignore', '/.gitignore@cc8fc46 (commits)'], - ['https://github.com/nodejs/node/commits/master/.gitignore', 'nodejs/node/.gitignore@master (commits)'], - ['https://github.com/nodejs/node/commits/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (commits)'], - ['https://github.com/nodejs/node/commits/cc8fc46/.gitignore', 'nodejs/node/.gitignore@cc8fc46 (commits)'], - ['https://github.com/sindresorhus/refined-github/commit/cc8fc46.diff', 'cc8fc46.diff'], - ['https://github.com/sindresorhus/refined-github/commit/cc8fc46.patch', 'cc8fc46.patch'], - ['https://github.com/nodejs/node/commit/cc8fc46.diff', 'nodejs/node@cc8fc46.diff'], - ['https://github.com/nodejs/node/commit/cc8fc46.patch', 'nodejs/node@cc8fc46.patch'], - ['https://github.com/sindresorhus/refined-github/releases/tag/v0.12.0', 'v0.12.0 (release)'], - ['https://github.com/nodejs/node/releases/tag/v0.12.0', 'nodejs/node@v0.12.0 (release)'], - ['https://github.com/sindresorhus/refined-github/milestone/25', 'sindresorhus/refined-github/milestone/25'], - ['https://github.com/nodejs/node/milestone/25', 'nodejs/node/milestone/25'], - ['https://github.com/sindresorhus/refined-github/labels/npm', 'npm (label)'], - ['https://github.com/nodejs/node/labels/npm', 'nodejs/node/npm (label)'], - ['https://github.com/sindresorhus/refined-github/archive/6.4.1.zip', '6.4.1.zip'], - ['https://github.com/sindresorhus/refined-github/releases/download/6.4.1/now-macos', '6.4.1 now-macos (download)'], - ['https://github.com/zeit/now-cli/archive/6.4.1.zip', 'zeit/now-cli@6.4.1.zip'], - ['https://github.com/zeit/now-cli/releases/download/6.4.1/now-macos', 'zeit/now-cli@6.4.1 now-macos (download)'], - ['https://github.com/sindresorhus/refined-github/wiki', 'sindresorhus/refined-github/wiki'], - ['https://github.com/sindresorhus/refined-github/pulse', 'sindresorhus/refined-github/pulse'], - ['https://github.com/sindresorhus/refined-github/labels', 'sindresorhus/refined-github/labels'], - ['https://github.com/sindresorhus/refined-github/network', 'sindresorhus/refined-github/network'], - ['https://github.com/sindresorhus/refined-github/projects', 'sindresorhus/refined-github/projects'], - ['https://github.com/sindresorhus/refined-github/releases', 'sindresorhus/refined-github/releases'], - ['https://github.com/sindresorhus/refined-github/milestones', 'sindresorhus/refined-github/milestones'], - ['https://github.com/sindresorhus/refined-github/contributors', 'sindresorhus/refined-github/contributors'], - ['https://github.com/nodejs/node/wiki', 'nodejs/node/wiki'], - ['https://github.com/nodejs/node/pulse', 'nodejs/node/pulse'], - ['https://github.com/nodejs/node/labels', 'nodejs/node/labels'], - ['https://github.com/nodejs/node/network', 'nodejs/node/network'], - ['https://github.com/nodejs/node/projects', 'nodejs/node/projects'], - ['https://github.com/nodejs/node/releases', 'nodejs/node/releases'], - ['https://github.com/nodejs/node/milestones', 'nodejs/node/milestones'], - ['https://github.com/nodejs/node/contributors', 'nodejs/node/contributors'], - ['https://github.com/nodejs/node/graphs/commit-activity', 'nodejs/node/graphs/commit-activity'], - ['https://rawgit.com/sindresorhus/refined-github/master/.gitignore', '/.gitignore@master (raw)'], - ['https://cdn.rawgit.com/sindresorhus/refined-github/v0.12/.gitignore', '/.gitignore@v0.12 (raw)'], - ['https://cdn.rawgit.com/sindresorhus/refined-github/d71718db/.gitignore', '/.gitignore@d71718db (raw)'], - ['https://raw.githubusercontent.com/sindresorhus/refined-github/master/.gitignore', '/.gitignore@master (raw)'], - ['https://raw.githubusercontent.com/sindresorhus/refined-github/v0.12/.gitignore', '/.gitignore@v0.12 (raw)'], - ['https://raw.githubusercontent.com/sindresorhus/refined-github/d71718db/.gitignore', '/.gitignore@d71718db (raw)'], - ['https://rawgit.com/nodejs/node/master/.gitignore', 'nodejs/node/.gitignore@master (raw)'], - ['https://cdn.rawgit.com/nodejs/node/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (raw)'], - ['https://cdn.rawgit.com/nodejs/node/d71718db/.gitignore', 'nodejs/node/.gitignore@d71718db (raw)'], - ['https://raw.githubusercontent.com/nodejs/node/master/.gitignore', 'nodejs/node/.gitignore@master (raw)'], - ['https://raw.githubusercontent.com/nodejs/node/v0.12/.gitignore', 'nodejs/node/.gitignore@v0.12 (raw)'], - ['https://raw.githubusercontent.com/nodejs/node/d71718db/.gitignore', 'nodejs/node/.gitignore@d71718db (raw)'], - ['https://github.com/sindresorhus', '@sindresorhus'], - ['https://github.com/nodejs', '@nodejs'], - ['https://github.com/pulls', 'github.com/pulls'], - ['https://github.com/issues', 'github.com/issues'], - ['https://github.com/trending', 'github.com/trending'], - ['https://github.com/features', 'github.com/features'], - ['https://github.com/marketplace', 'github.com/marketplace'], - ['https://github.com/trending/developers', 'github.com/trending/developers'], - ['https://github.com/settings/profile', 'github.com/settings/profile'], - ['https://www.npmjs.com/', 'npmjs.com'], - ['https://www.npmjs.com/package/node', 'npmjs.com/package/node'], - ['https://example.com/nodejs/node/blob/cc8fc46/.gitignore', 'example.com/nodejs/node/blob/cc8fc46/.gitignore'] + [ + 'https://github.com/sindresorhus/refined-github/', + 'sindresorhus/refined-github' + ], + [ + 'https://github.com/sindresorhus/refined-github/tree/v0.12', + 'v0.12' + ], + [ + 'https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a', + 'd71718d' + ], + [ + 'https://github.com/nodejs/node/', + 'nodejs/node' + ], + [ + 'https://github.com/nodejs/node/tree/v0.12', + 'nodejs/node@v0.12' + ], + [ + 'https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a', + 'nodejs/node@d71718d' + ], + [ + 'https://github.com/sindresorhus/refined-github/tree/master/doc', + '/doc@master' + ], + [ + 'https://github.com/sindresorhus/refined-github/tree/v0.12/doc', + '/doc@v0.12' + ], + [ + 'https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', + '/doc@d71718d' + ], + [ + 'https://github.com/nodejs/node/tree/master/doc', + 'nodejs/node/doc@master' + ], + [ + 'https://github.com/nodejs/node/tree/v0.12/doc', + 'nodejs/node/doc@v0.12' + ], + [ + 'https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc', + 'nodejs/node/doc@d71718d' + ], + [ + 'https://github.com/sindresorhus/refined-github/blob/master/.gitignore', + '/.gitignore@master' + ], + [ + 'https://github.com/sindresorhus/refined-github/blob/v0.12/.gitignore', + '/.gitignore@v0.12' + ], + [ + 'https://github.com/sindresorhus/refined-github/blob/cc8fc46/.gitignore', + '/.gitignore@cc8fc46' + ], + [ + 'https://github.com/nodejs/node/blob/master/.gitignore', + 'nodejs/node/.gitignore@master' + ], + [ + 'https://github.com/nodejs/node/blob/v0.12/.gitignore', + 'nodejs/node/.gitignore@v0.12' + ], + [ + 'https://github.com/nodejs/node/blob/cc8fc46/.gitignore', + 'nodejs/node/.gitignore@cc8fc46' + ], + [ + 'https://github.com/sindresorhus/refined-github/blame/master/.gitignore', + '/.gitignore@master (blame)' + ], + [ + 'https://github.com/sindresorhus/refined-github/blame/v0.12/.gitignore', + '/.gitignore@v0.12 (blame)' + ], + [ + 'https://github.com/sindresorhus/refined-github/blame/cc8fc46/.gitignore', + '/.gitignore@cc8fc46 (blame)' + ], + [ + 'https://github.com/nodejs/node/blame/master/.gitignore', + 'nodejs/node/.gitignore@master (blame)' + ], + [ + 'https://github.com/nodejs/node/blame/v0.12/.gitignore', + 'nodejs/node/.gitignore@v0.12 (blame)' + ], + [ + 'https://github.com/nodejs/node/blame/cc8fc46/.gitignore', + 'nodejs/node/.gitignore@cc8fc46 (blame)' + ], + [ + 'https://github.com/sindresorhus/refined-github/commits/master/.gitignore', + '/.gitignore@master (commits)' + ], + [ + 'https://github.com/sindresorhus/refined-github/commits/v0.12/.gitignore', + '/.gitignore@v0.12 (commits)' + ], + [ + 'https://github.com/sindresorhus/refined-github/commits/cc8fc46/.gitignore', + '/.gitignore@cc8fc46 (commits)' + ], + [ + 'https://github.com/nodejs/node/commits/master/.gitignore', + 'nodejs/node/.gitignore@master (commits)' + ], + [ + 'https://github.com/nodejs/node/commits/v0.12/.gitignore', + 'nodejs/node/.gitignore@v0.12 (commits)' + ], + [ + 'https://github.com/nodejs/node/commits/cc8fc46/.gitignore', + 'nodejs/node/.gitignore@cc8fc46 (commits)' + ], + [ + 'https://github.com/sindresorhus/refined-github/commit/cc8fc46.diff', + 'cc8fc46.diff' + ], + [ + 'https://github.com/sindresorhus/refined-github/commit/cc8fc46.patch', + 'cc8fc46.patch' + ], + [ + 'https://github.com/nodejs/node/commit/cc8fc46.diff', + 'nodejs/node@cc8fc46.diff' + ], + [ + 'https://github.com/nodejs/node/commit/cc8fc46.patch', + 'nodejs/node@cc8fc46.patch' + ], + [ + 'https://github.com/sindresorhus/refined-github/releases/tag/v0.12.0', + 'v0.12.0 (release)' + ], + [ + 'https://github.com/nodejs/node/releases/tag/v0.12.0', + 'nodejs/node@v0.12.0 (release)' + ], + [ + 'https://github.com/sindresorhus/refined-github/milestone/25', + 'sindresorhus/refined-github/milestone/25' + ], + [ + 'https://github.com/nodejs/node/milestone/25', + 'nodejs/node/milestone/25' + ], + [ + 'https://github.com/sindresorhus/refined-github/labels/npm', + 'npm (label)' + ], + [ + 'https://github.com/nodejs/node/labels/npm', + 'nodejs/node/npm (label)' + ], + [ + 'https://github.com/sindresorhus/refined-github/archive/6.4.1.zip', + '6.4.1.zip' + ], + [ + 'https://github.com/sindresorhus/refined-github/releases/download/6.4.1/now-macos', + '6.4.1 now-macos (download)' + ], + [ + 'https://github.com/zeit/now-cli/archive/6.4.1.zip', + 'zeit/now-cli@6.4.1.zip' + ], + [ + 'https://github.com/zeit/now-cli/releases/download/6.4.1/now-macos', + 'zeit/now-cli@6.4.1 now-macos (download)' + ], + [ + 'https://github.com/sindresorhus/refined-github/wiki', + 'sindresorhus/refined-github/wiki' + ], + [ + 'https://github.com/sindresorhus/refined-github/pulse', + 'sindresorhus/refined-github/pulse' + ], + [ + 'https://github.com/sindresorhus/refined-github/labels', + 'sindresorhus/refined-github/labels' + ], + [ + 'https://github.com/sindresorhus/refined-github/network', + 'sindresorhus/refined-github/network' + ], + [ + 'https://github.com/sindresorhus/refined-github/projects', + 'sindresorhus/refined-github/projects' + ], + [ + 'https://github.com/sindresorhus/refined-github/releases', + 'sindresorhus/refined-github/releases' + ], + [ + 'https://github.com/sindresorhus/refined-github/milestones', + 'sindresorhus/refined-github/milestones' + ], + [ + 'https://github.com/sindresorhus/refined-github/contributors', + 'sindresorhus/refined-github/contributors' + ], + [ + 'https://github.com/nodejs/node/wiki', + 'nodejs/node/wiki' + ], + [ + 'https://github.com/nodejs/node/pulse', + 'nodejs/node/pulse' + ], + [ + 'https://github.com/nodejs/node/labels', + 'nodejs/node/labels' + ], + [ + 'https://github.com/nodejs/node/network', + 'nodejs/node/network' + ], + [ + 'https://github.com/nodejs/node/projects', + 'nodejs/node/projects' + ], + [ + 'https://github.com/nodejs/node/releases', + 'nodejs/node/releases' + ], + [ + 'https://github.com/nodejs/node/milestones', + 'nodejs/node/milestones' + ], + [ + 'https://github.com/nodejs/node/contributors', + 'nodejs/node/contributors' + ], + [ + 'https://github.com/nodejs/node/graphs/commit-activity', + 'nodejs/node/graphs/commit-activity' + ], + [ + 'https://rawgit.com/sindresorhus/refined-github/master/.gitignore', + '/.gitignore@master (raw)' + ], + [ + 'https://cdn.rawgit.com/sindresorhus/refined-github/v0.12/.gitignore', + '/.gitignore@v0.12 (raw)' + ], + [ + 'https://cdn.rawgit.com/sindresorhus/refined-github/d71718db/.gitignore', + '/.gitignore@d71718db (raw)' + ], + [ + 'https://raw.githubusercontent.com/sindresorhus/refined-github/master/.gitignore', + '/.gitignore@master (raw)' + ], + [ + 'https://raw.githubusercontent.com/sindresorhus/refined-github/v0.12/.gitignore', + '/.gitignore@v0.12 (raw)' + ], + [ + 'https://raw.githubusercontent.com/sindresorhus/refined-github/d71718db/.gitignore', + '/.gitignore@d71718db (raw)' + ], + [ + 'https://rawgit.com/nodejs/node/master/.gitignore', + 'nodejs/node/.gitignore@master (raw)' + ], + [ + 'https://cdn.rawgit.com/nodejs/node/v0.12/.gitignore', + 'nodejs/node/.gitignore@v0.12 (raw)' + ], + [ + 'https://cdn.rawgit.com/nodejs/node/d71718db/.gitignore', + 'nodejs/node/.gitignore@d71718db (raw)' + ], + [ + 'https://raw.githubusercontent.com/nodejs/node/master/.gitignore', + 'nodejs/node/.gitignore@master (raw)' + ], + [ + 'https://raw.githubusercontent.com/nodejs/node/v0.12/.gitignore', + 'nodejs/node/.gitignore@v0.12 (raw)' + ], + [ + 'https://raw.githubusercontent.com/nodejs/node/d71718db/.gitignore', + 'nodejs/node/.gitignore@d71718db (raw)' + ], + [ + 'https://github.com/sindresorhus', + '@sindresorhus' + ], + [ + 'https://github.com/nodejs', + '@nodejs' + ], + [ + 'https://github.com/pulls', + 'github.com/pulls' + ], + [ + 'https://github.com/issues', + 'github.com/issues' + ], + [ + 'https://github.com/trending', + 'github.com/trending' + ], + [ + 'https://github.com/features', + 'github.com/features' + ], + [ + 'https://github.com/marketplace', + 'github.com/marketplace' + ], + [ + 'https://github.com/trending/developers', + 'github.com/trending/developers' + ], + [ + 'https://github.com/settings/profile', + 'github.com/settings/profile' + ], + [ + 'https://www.npmjs.com/', + 'npmjs.com' + ], + [ + 'https://www.npmjs.com/package/node', + 'npmjs.com/package/node' + ], + [ + 'https://example.com/nodejs/node/blob/cc8fc46/.gitignore', + 'example.com/nodejs/node/blob/cc8fc46/.gitignore' + ] ])); From effca1f83334ee8923c8ee1c8be68cc7859d1a96 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sat, 17 Jun 2017 18:36:14 +0800 Subject: [PATCH 21/21] Mention feature in the readme --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index d89e67e98b15..806ab8d8fdda 100644 --- a/readme.md +++ b/readme.md @@ -44,6 +44,7 @@ GitHub Enterprise is also supported by [authorizing your own domain in the optio - [Adds search filter for 'Everything commented by you'](https://cloud.githubusercontent.com/assets/940070/25518367/cb917d3e-2c36-11e7-8475-c4e6dbe0ed6c.png) - [Moves destructive buttons ("Close issue", "Cancel") in commenting forms away from primary button](#comment-box) - [Adds `Yours` button to Issues/Pull Requests page](https://cloud.githubusercontent.com/assets/1282980/14636384/0d8770e4-0623-11e6-8520-2054bece2771.png) +- [Condenses long URLs into references like _user/repo/.file@`d71718d`_](https://user-images.githubusercontent.com/1402241/27252232-8fdf8ed0-538b-11e7-8f19-12d317c9cd32.png) - Easier copy-pasting from diffs by making +/- signs unselectable - Shows the reactions popover on hover instead of click - Supports indenting with the tab key in textareas like the comment box (ShiftTab for original behavior)