Browse Source

Use bfred-it/shorten-repo-url (#532)

master
Federico Brigante 7 years ago
committed by Sindre Sorhus
parent
commit
2287112068
  1. 1
      package.json
  2. 3
      rollup.config.js
  3. 7
      src/content.js
  4. 182
      src/libs/shorten-links.js
  5. 357
      test/shorten-links.js

1
package.json

@ -21,6 +21,7 @@
"linkify-issues": "^1.1.0",
"linkify-urls": "^1.0.2",
"select-dom": "^4.1.0",
"shorten-repo-url": "^1.1.0",
"to-markdown": "^3.0.4",
"to-semver": "^1.1.0",
"webext-dynamic-content-scripts": "^2.0.1",

3
rollup.config.js

@ -11,7 +11,8 @@ export default [
dest: entry.replace('src', 'extension'),
plugins: [
nodeResolve({
browser: true
browser: true,
preferBuiltins: false
}),
commonJS(),
json({

7
src/content.js

@ -2,6 +2,7 @@ import 'webext-dynamic-content-scripts';
import OptionsSync from 'webext-options-sync';
import elementReady from 'element-ready';
import gitHubInjection from 'github-injection';
import {applyToLink as shortenLink} from 'shorten-repo-url';
import toSemver from 'to-semver';
import linkifyIssues from 'linkify-issues';
import select from 'select-dom';
@ -19,7 +20,6 @@ import filePathCopyBtnListner from './libs/copy-file-path';
import addFileCopyButton from './libs/copy-file';
import copyMarkdown from './libs/copy-markdown';
import linkifyCode, {editTextNodes} from './libs/linkify-urls-in-code';
import shortenLinks from './libs/shorten-links';
import autoLoadMoreNews from './libs/auto-load-more-news';
import * as icons from './libs/icons';
import * as pageDetect from './libs/page-detect';
@ -528,9 +528,12 @@ function init(options) {
addCompareLink();
renameInsightsDropdown();
addTitleToEmojis();
shortenLinks();
addReadmeButtons();
for (const a of select.all('a[href]')) {
shortenLink(a, location.href);
}
diffFileHeader.destroy();
enableCopyOnY.destroy();
markUnread.destroy();

182
src/libs/shorten-links.js

@ -1,182 +0,0 @@
import select from 'select-dom';
import {getRepoURL} from './page-detect';
const patchDiffRegex = /[.](patch|diff)$/;
const releaseRegex = /releases[/]tag[/]([^/]+)/;
const labelRegex = /labels[/]([^/]+)/;
const releaseArchiveRegex = /archive[/](.+)([.]zip|[.]tar[.]gz)/;
const releaseDownloadRegex = /releases[/]download[/]([^/]+)[/](.+)/;
const reservedPaths = [
'new',
'join',
'site',
'blog',
'gist',
'about',
'login',
'pulls',
'search',
'issues',
'explore',
'contact',
'pricing',
'trending',
'settings',
'features',
'business',
'personal',
'security',
'dashboard',
'showcases',
'open-source',
'marketplace',
'organizations',
'notifications'
];
const styleRevision = revision => {
if (!revision) {
return;
}
revision = revision.replace(patchDiffRegex, '');
if (/^[0-9a-f]{40}$/.test(revision)) {
revision = revision.substr(0, 7);
}
return `<code>${revision}</code>`;
};
// Filter out null values
const joinValues = (array, delimiter = '/') => {
return array.filter(s => s).join(delimiter);
};
export function shortenUrl(href) {
/**
* Parse URL
*/
const {
origin,
pathname,
search,
hash
} = new URL(href);
const isRaw = [
'https://raw.githubusercontent.com',
'https://cdn.rawgit.com',
'https://rawgit.com'
].includes(origin);
let [
user,
repo,
type,
revision,
...filePath
] = pathname.substr(1).split('/');
if (isRaw) {
[
user,
repo,
// Raw URLs don't have `blob` here
revision,
...filePath
] = pathname.substr(1).split('/');
type = 'raw';
}
revision = styleRevision(revision);
filePath = filePath.join('/');
const isLocal = origin === location.origin;
const isThisRepo = (isLocal || isRaw) && getRepoURL() === `${user}/${repo}`;
const isReserved = reservedPaths.includes(user);
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',
'tree',
'blob',
'blame',
'commits'
].includes(type);
const repoUrl = isThisRepo ? '' : `${user}/${repo}`;
/**
* Shorten URL
*/
if (isReserved || (!isLocal && !isRaw)) {
return href
.replace(/^https:[/][/]/, '')
.replace(/^www[.]/, '')
.replace(/[/]$/, '');
}
if (user && !repo) {
return `@${user}${search}${hash}`;
}
if (isFileOrDir) {
const file = `${repoUrl}${filePath ? (repoUrl ? ':' : '/') : ''}${filePath}`;
const revisioned = joinValues([file, revision], '@');
const partial = `${revisioned}${search}${hash}`;
if (type !== 'blob' && type !== 'tree') {
return `${partial} (${type})`;
}
return partial;
}
if (diffOrPatch) {
const partial = joinValues([repoUrl, revision], '@');
return `${partial}.${diffOrPatch}${search}${hash}`;
}
if (release) {
const partial = joinValues([repoUrl, `<code>${release}</code>`], '@');
return `${partial}${search}${hash} (release)`;
}
if (releaseTagExt) {
const partial = joinValues([repoUrl, `<code>${releaseTag}</code>`], '@');
return `${partial}${releaseTagExt}${search}${hash}`;
}
if (downloadFilename) {
const partial = joinValues([repoUrl, `<code>${downloadTag}</code>`], '@');
return `${partial} ${downloadFilename}${search}${hash} (download)`;
}
if (label) {
return joinValues([repoUrl, label]) + `${search}${hash} (label)`;
}
// Drop leading and trailing slash of relative path
return `${pathname.replace(/^[/]|[/]$/g, '')}${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);
// Don't touch the dom if there's nothing to change
if (shortened === a.textContent) {
continue;
}
a.innerHTML = shortened;
}
};

357
test/shorten-links.js

@ -1,357 +0,0 @@
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',
'<code>v0.12</code>'
],
[
'https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a',
'<code>d71718d</code>'
],
[
'https://github.com/nodejs/node/',
'nodejs/node'
],
[
'https://github.com/nodejs/node/tree/v0.12',
'nodejs/node@<code>v0.12</code>'
],
[
'https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a',
'nodejs/node@<code>d71718d</code>'
],
[
'https://github.com/sindresorhus/refined-github/tree/master/doc',
'/doc@<code>master</code>'
],
[
'https://github.com/sindresorhus/refined-github/tree/v0.12/doc',
'/doc@<code>v0.12</code>'
],
[
'https://github.com/sindresorhus/refined-github/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc',
'/doc@<code>d71718d</code>'
],
[
'https://github.com/nodejs/node/tree/master/doc',
'nodejs/node:doc@<code>master</code>'
],
[
'https://github.com/nodejs/node/tree/v0.12/doc',
'nodejs/node:doc@<code>v0.12</code>'
],
[
'https://github.com/nodejs/node/tree/d71718db6aa4feb8dc10edbad1134472468e971a/doc',
'nodejs/node:doc@<code>d71718d</code>'
],
[
'https://github.com/sindresorhus/refined-github/blob/master/.gitignore',
'/.gitignore@<code>master</code>'
],
[
'https://github.com/sindresorhus/refined-github/blob/v0.12/.gitignore',
'/.gitignore@<code>v0.12</code>'
],
[
'https://github.com/sindresorhus/refined-github/blob/cc8fc46/.gitignore',
'/.gitignore@<code>cc8fc46</code>'
],
[
'https://github.com/nodejs/node/blob/master/.gitignore',
'nodejs/node:.gitignore@<code>master</code>'
],
[
'https://github.com/nodejs/node/blob/v0.12/.gitignore',
'nodejs/node:.gitignore@<code>v0.12</code>'
],
[
'https://github.com/nodejs/node/blob/cc8fc46/.gitignore',
'nodejs/node:.gitignore@<code>cc8fc46</code>'
],
[
'https://github.com/sindresorhus/refined-github/blame/master/.gitignore',
'/.gitignore@<code>master</code> (blame)'
],
[
'https://github.com/sindresorhus/refined-github/blame/v0.12/.gitignore',
'/.gitignore@<code>v0.12</code> (blame)'
],
[
'https://github.com/sindresorhus/refined-github/blame/cc8fc46/.gitignore',
'/.gitignore@<code>cc8fc46</code> (blame)'
],
[
'https://github.com/nodejs/node/blame/master/.gitignore',
'nodejs/node:.gitignore@<code>master</code> (blame)'
],
[
'https://github.com/nodejs/node/blame/v0.12/.gitignore',
'nodejs/node:.gitignore@<code>v0.12</code> (blame)'
],
[
'https://github.com/nodejs/node/blame/cc8fc46/.gitignore',
'nodejs/node:.gitignore@<code>cc8fc46</code> (blame)'
],
[
'https://github.com/sindresorhus/refined-github/commits/master/.gitignore',
'/.gitignore@<code>master</code> (commits)'
],
[
'https://github.com/sindresorhus/refined-github/commits/v0.12/.gitignore',
'/.gitignore@<code>v0.12</code> (commits)'
],
[
'https://github.com/sindresorhus/refined-github/commits/cc8fc46/.gitignore',
'/.gitignore@<code>cc8fc46</code> (commits)'
],
[
'https://github.com/nodejs/node/commits/master/.gitignore',
'nodejs/node:.gitignore@<code>master</code> (commits)'
],
[
'https://github.com/nodejs/node/commits/v0.12/.gitignore',
'nodejs/node:.gitignore@<code>v0.12</code> (commits)'
],
[
'https://github.com/nodejs/node/commits/cc8fc46/.gitignore',
'nodejs/node:.gitignore@<code>cc8fc46</code> (commits)'
],
[
'https://github.com/sindresorhus/refined-github/commit/cc8fc46.diff',
'<code>cc8fc46</code>.diff'
],
[
'https://github.com/sindresorhus/refined-github/commit/cc8fc46.patch',
'<code>cc8fc46</code>.patch'
],
[
'https://github.com/nodejs/node/commit/cc8fc46.diff',
'nodejs/node@<code>cc8fc46</code>.diff'
],
[
'https://github.com/nodejs/node/commit/cc8fc46.patch',
'nodejs/node@<code>cc8fc46</code>.patch'
],
[
'https://github.com/sindresorhus/refined-github/releases/tag/v0.12.0',
'<code>v0.12.0</code> (release)'
],
[
'https://github.com/nodejs/node/releases/tag/v0.12.0',
'nodejs/node@<code>v0.12.0</code> (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',
'<code>6.4.1</code>.zip'
],
[
'https://github.com/sindresorhus/refined-github/releases/download/6.4.1/now-macos',
'<code>6.4.1</code> now-macos (download)'
],
[
'https://github.com/zeit/now-cli/archive/6.4.1.zip',
'zeit/now-cli@<code>6.4.1</code>.zip'
],
[
'https://github.com/zeit/now-cli/releases/download/6.4.1/now-macos',
'zeit/now-cli@<code>6.4.1</code> 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@<code>master</code> (raw)'
],
[
'https://cdn.rawgit.com/sindresorhus/refined-github/v0.12/.gitignore',
'/.gitignore@<code>v0.12</code> (raw)'
],
[
'https://cdn.rawgit.com/sindresorhus/refined-github/d71718db/.gitignore',
'/.gitignore@<code>d71718db</code> (raw)'
],
[
'https://raw.githubusercontent.com/sindresorhus/refined-github/master/.gitignore',
'/.gitignore@<code>master</code> (raw)'
],
[
'https://raw.githubusercontent.com/sindresorhus/refined-github/v0.12/.gitignore',
'/.gitignore@<code>v0.12</code> (raw)'
],
[
'https://raw.githubusercontent.com/sindresorhus/refined-github/d71718db/.gitignore',
'/.gitignore@<code>d71718db</code> (raw)'
],
[
'https://rawgit.com/nodejs/node/master/.gitignore',
'nodejs/node:.gitignore@<code>master</code> (raw)'
],
[
'https://cdn.rawgit.com/nodejs/node/v0.12/.gitignore',
'nodejs/node:.gitignore@<code>v0.12</code> (raw)'
],
[
'https://cdn.rawgit.com/nodejs/node/d71718db/.gitignore',
'nodejs/node:.gitignore@<code>d71718db</code> (raw)'
],
[
'https://raw.githubusercontent.com/nodejs/node/master/.gitignore',
'nodejs/node:.gitignore@<code>master</code> (raw)'
],
[
'https://raw.githubusercontent.com/nodejs/node/v0.12/.gitignore',
'nodejs/node:.gitignore@<code>v0.12</code> (raw)'
],
[
'https://raw.githubusercontent.com/nodejs/node/d71718db/.gitignore',
'nodejs/node:.gitignore@<code>d71718db</code> (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'
]
]));
Loading…
Cancel
Save