diff --git a/__snapshots__/index.test.js.snap b/__snapshots__/index.test.js.snap index a18cc02..1833926 100644 --- a/__snapshots__/index.test.js.snap +++ b/__snapshots__/index.test.js.snap @@ -40,6 +40,8 @@ exports[`https://github.com/fregante/shorten-repo-url/blame/v0.12/.gitignore 1`] exports[`https://github.com/fregante/shorten-repo-url/blob/cc8fc46/.gitignore 1`] = `cc8fc46/.gitignore`; +exports[`https://github.com/fregante/shorten-repo-url/blob/main/한글.txt 1`] = `main/한글.txt`; + exports[`https://github.com/fregante/shorten-repo-url/blob/master/.gitignore 1`] = `master/.gitignore`; exports[`https://github.com/fregante/shorten-repo-url/blob/v0.12/.gitignore 1`] = `v0.12/.gitignore`; @@ -202,6 +204,10 @@ exports[`https://github.com/refined-github/refined-github/wiki/%22Can-you-add-th exports[`https://github.com/refined-github/refined-github/wiki/%22Can-you-add-this-feature%3F%22#3-it-doesnt-require-options 1`] = `Wiki: "Can you add this feature?" (3 it doesnt require options) (refined-github/refined-github)`; +exports[`https://github.com/scarf005/hangul-test/wiki/한글-위키-페이지 1`] = `Wiki: 한글 위키 페이지 (scarf005/hangul-test)`; + +exports[`https://github.com/scarf005/hangul-test/wiki/한글-위키-페이지#한글-헤딩 1`] = `Wiki: 한글 위키 페이지 (한글 헤딩) (scarf005/hangul-test)`; + exports[`https://github.com/settings/profile 1`] = `github.com/settings/profile`; exports[`https://github.com/sindresorhus 1`] = `@sindresorhus`; @@ -261,3 +267,5 @@ exports[`https://www.npmjs.com/ 1`] = `npmjs.com`; exports[`https://www.npmjs.com/packaasdge/node 1`] = `npmjs.com/packaasdge/node`; exports[`https://wwww.google.com/ 1`] = `wwww.google.com`; + +exports[`https://한글로-된-경로.com/하위경로#한글-해시 1`] = `한글로-된-경로.com/하위경로#한글-해시`; diff --git a/index.js b/index.js index 399efdb..1a1abfe 100644 --- a/index.js +++ b/index.js @@ -81,16 +81,15 @@ function shortenRepoUrl(href, currentUrl = 'https://github.com') { const currentRepo = currentUrl.pathname.slice(1).split('/', 2).join('/'); /** - * Parse URL + * Parse URL manually to avoid URL encoding and punycode */ + const origin = href.split('/', 3).join('/'); + const pathname = href.slice(origin.length).replace(/[?#].*/, ''); + const hash = /#.+$/.exec(href)?.[0] ?? ''; + + // Use URL exclusively for search parameters because they're too hard to parse const url = new URL(href); - const { - origin, - pathname, - search, - searchParams, - hash, - } = url; + const {search, searchParams} = url; const pathnameParts = pathname.slice(1).split('/'); // ['user', 'repo', 'pull', '342'] const repoPath = pathnameParts.slice(2).join('/'); // 'pull/342' @@ -158,31 +157,24 @@ function shortenRepoUrl(href, currentUrl = 'https://github.com') { * Shorten URL */ if (isReserved || pathname === '/' || (!isLocal && !isRaw && !isRedirection)) { - const parsedUrl = new URL(href); const cleanHref = [ - parsedUrl.origin + origin .replace(/^https:[/][/]/, '') .replace(/^www[.]/, ''), - parsedUrl.pathname + pathname .replace(/[/]$/, ''), ]; if (['issues', 'pulls'].includes(user) && !repo) { - const query = pullQueryOut(parsedUrl.searchParams, parsedUrl.pathname); - cleanHref.push(parsedUrl.search, query); + const query = pullQueryOut(url.searchParams, url.pathname); + cleanHref.push(url.search, query); } else { - cleanHref.push(parsedUrl.search); + cleanHref.push(url.search); } - cleanHref.push(parsedUrl.hash); + cleanHref.push(decodeURI(url.hash)); - // The user prefers seeing the URL as it was typed, so we need to decode it - try { - return decodeURI(cleanHref.join('')); - } catch { - // Decoding fails if the URL includes '%%' - return href; - } + return cleanHref.join(''); } if (user && !repo) { @@ -290,16 +282,18 @@ function shortenRepoUrl(href, currentUrl = 'https://github.com') { */ function safeDecode(url) { try { - return decodeURIComponent(url); + return new URL(url).href; } catch { return url; } } +/** @param a {HTMLAnchorElement} */ function getLinkHref(a) { return a.dataset.originalHref ?? a.href; } +/** @param a {HTMLAnchorElement} */ function isCustomLink(a) { const url = safeDecode(getLinkHref(a)); const label = safeDecode(a.textContent); @@ -321,7 +315,7 @@ export function applyToLink(a, currentUrl) { // And if there are no additional images in the link && !a.firstElementChild ) { - const url = getLinkHref(a); + const url = a.textContent; const shortened = shortenRepoUrl(url, currentUrl); a.replaceChildren( ...shortened.split( diff --git a/index.test.js b/index.test.js index fd8dac0..f7ec7e7 100644 --- a/index.test.js +++ b/index.test.js @@ -32,6 +32,7 @@ const urls = [ 'https://github.com/fregante/shorten-repo-url/blob/master/.gitignore', 'https://github.com/fregante/shorten-repo-url/blob/v0.12/.gitignore', 'https://github.com/fregante/shorten-repo-url/blob/cc8fc46/.gitignore', + 'https://github.com/fregante/shorten-repo-url/blob/main/한글.txt', 'https://github.com/nodejs/node/blob/master/.gitignore', 'https://github.com/nodejs/node/blob/v0.12/.gitignore', 'https://github.com/nodejs/node/blob/cc8fc46/.gitignore', @@ -138,6 +139,8 @@ const urls = [ 'https://github.com/refined-github/refined-github/wiki/%22Can-you-add-this-feature%3F%22#', 'https://github.com/refined-github/refined-github/wiki/%22Can-you-add-this-feature%3F%22', 'https://github.com/fregante/shorten-repo-url/wiki/%22Can-you-add-this-feature%3F%22', + 'https://github.com/scarf005/hangul-test/wiki/한글-위키-페이지', + 'https://github.com/scarf005/hangul-test/wiki/한글-위키-페이지#한글-헤딩', 'https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement#parameters', 'https://www.google.com/', 'https://wwww.google.com/', @@ -146,6 +149,7 @@ const urls = [ 'https://www.npmjs.com/packaasdge/node', 'https://example.com/nodejs/node/blob/cc8fc46/.gitignore', 'https://example.site/한글로-된-URL', + 'https://한글로-된-경로.com/하위경로#한글-해시', ]; test.each(urls)('%s', url => {