GitHub リポジトリのページと GitHub Pages を行き来するブックマークレット

のような URL の GitHub Pages を閲覧中、このページに対応する GitHub リポジトリのページに飛びたいな、と思うことがある。URL としては

のように変換すれば良いので、頑張れば相互変換できそうだ。

…というワケでブックマークレットを作ってみた。

ブックマークレット

以下のブックマークレットを登録し、GitHub Pages や GitHub リポジトリページで使えば、良い感じに移動できる。

javascript:((u,t)=>{(u=location.href.replace(/^https?:\/\//u,"").replace(/^www\./u,"")).match(/^github\.com/u)?t=`${u}/`.replace(/^github\.com\/(.*?)\//u,"$1.github.io/").replace(/^(.*?)\.github\.io\/(.*?)\/.*/u,"$1.github.io/$2").replace(/\/(.*?)\.github\.io$/u,""):u.match(/^(.*?)\.github\.io/u)&&(t=u.replace(/^(.*)\.github\.io/u,"github.com/$1").replace(/^github\.com\/(.*?)\/(.*?)\/.*/u,"github.com/$1/$2").replace(/^github\.com\/(.*?)\/(.*?)\.(html|css|js)$/u,"github.com/$1")),t?open(`https://${t.replace(/\/$/u,"")}`):alert("Invalid URL")})();

↑コチラは window.open() を使っていて、Chrome だと上手く遷移できないことがあったりするので、location.href で移動するパターンも作ってみた。↓

javascript:((u,t)=>{(u=location.href.replace(/^https?:\/\//u,"").replace(/^www\./u,"")).match(/^github\.com/u)?t=`${u}/`.replace(/^github\.com\/(.*?)\//u,"$1.github.io/").replace(/^(.*?)\.github\.io\/(.*?)\/.*/u,"$1.github.io/$2").replace(/\/(.*?)\.github\.io$/u,""):u.match(/^(.*?)\.github\.io/u)&&(t=u.replace(/^(.*)\.github\.io/u,"github.com/$1").replace(/^github\.com\/(.*?)\/(.*?)\/.*/u,"github.com/$1/$2").replace(/^github\.com\/(.*?)\/(.*?)\.(html|css|js)$/u,"github.com/$1")),t?location.href=`https://${t.replace(/\/$/u,"")}`:alert("Invalid URL")})();

元のコード

圧縮前のコードは以下。

javascript:((inputUrl, resultUrl) => {
  // Remove 'http://', 'https://', 'www.'
  inputUrl = location.href.replace((/^https?:\/\//u), '').replace((/^www\./u), '');
  
  if(inputUrl.match(/^github\.com/u)) {
    // Repository : GitHub Pages
    resultUrl = `${inputUrl}/`.replace((/^github\.com\/(.*?)\//u), '$1.github.io/')
                              .replace((/^(.*?)\.github\.io\/(.*?)\/.*/u), '$1.github.io/$2')
                              .replace((/\/(.*?)\.github\.io$/u), '');
  }
  else if(inputUrl.match(/^(.*?)\.github\.io/u)) {
    // GitHub Pages : Repository
    resultUrl = inputUrl.replace((/^(.*)\.github\.io/u), 'github.com/$1')
                        .replace((/^github\.com\/(.*?)\/(.*?)\/.*/u), 'github.com/$1/$2')
                        .replace((/^github\.com\/(.*?)\/(.*?)\.(html|css|js)$/u), 'github.com/$1')
  }
  
  if(resultUrl) {
    // or location.href
    open(`https://${resultUrl.replace((/\/$/u), '')}`);
  } else {
    alert('Invalid URL');
  }
})();

汎用関数にする

URL を引数で渡し、変換後の URL を取得できるような汎用関数にしてみる。

/**
 * GitHub リポジトリの URL は GitHub Pages の URL に、
 * GitHub Pages の URL は GitHub リポジトリの URL に変換する
 * 
 * @param {string} rawInputUrl URL
 * @return {string} 変換後の URL
 * @throws {string} 変換できない URL が渡された場合にスローする
 */
function convertBetweenGitHubAndGitHubPages(rawInputUrl) {
  // Remove 'http://', 'https://', 'www.'
  const inputUrl = rawInputUrl.replace((/^https?:\/\//u), '').replace((/^www\./u), '');
  
  let resultUrl = '';
  if(inputUrl.match(/^github\.com/u)) {
    // Repository : GitHub Pages
    resultUrl = `${inputUrl}/`.replace((/^github\.com\/(.*?)\//u), '$1.github.io/')
                              .replace((/^(.*?)\.github\.io\/(.*?)\/.*/u), '$1.github.io/$2')
                              .replace((/\/(.*?)\.github\.io$/u), '');
  }
  else if(inputUrl.match(/^(.*?)\.github\.io/u)) {
    // GitHub Pages : Repository
    resultUrl = inputUrl.replace((/^(.*)\.github\.io/u), 'github.com/$1')
                        .replace((/^github\.com\/(.*?)\/(.*?)\/.*/u), 'github.com/$1/$2')
                        .replace((/^github\.com\/(.*?)\/(.*?)\.(html|css|js)$/u), 'github.com/$1')
  }
  
  if(resultUrl) {
    return `https://${resultUrl.replace((/\/$/u), '')}`;
  } else {
    throw new Error('Invalid URL');
  }
}

以下のようにテストコードを書いてみた。

[
  // GitHub (User Name Only) → GitHub Pages
  'http://github.com/Neos21',
  'http://www.github.com/Neos21',
  'https://www.github.com/Neos21',
  'https://github.com/Neos21',
  'https://github.com/Neos21/',
  // GitHub (User Site Repository) → GitHub Pages (User Site)
  'https://github.com/Neos21/Neos21.github.io',
  'https://github.com/Neos21/Neos21.github.io/',
  'https://github.com/Neos21/Neos21.github.io/issues',
  'https://github.com/Neos21/Neos21.github.io/issues/',
  'https://github.com/Neos21/Neos21.github.io/blob/master/index.html',
  // GitHub (Project Repository) → GitHub Pages (Project Site)
  'https://github.com/Neos21/about',
  'https://github.com/Neos21/about/',
  'https://github.com/Neos21/about/issues',
  'https://github.com/Neos21/about/issues/',
  'https://github.com/Neos21/about/blob/master/index.html',
  // GitHub Pages → GitHub
  'http://Neos21.github.io',
  'http://www.Neos21.github.io',
  'https://www.Neos21.github.io',
  'https://Neos21.github.io',
  'https://Neos21.github.io/',
  'https://Neos21.github.io/index.html',
  'https://Neos21.github.io/about',
  'https://Neos21.github.io/about/',
  'https://Neos21.github.io/about/index.html',
  'https://Neos21.github.io/about/test',
  'https://Neos21.github.io/about/test/',
  'https://Neos21.github.io/about/test/index.html',
  // Invalid URL
  'http://example.com/'
].forEach((inputUrl) => {
  try {
    const resultUrl = convertBetweenGitHubAndGitHubPages(inputUrl);
    console.log(inputUrl, '→', resultUrl);
  }
  catch(error) {
    console.log(inputUrl, ':', error.toString());
  }
});

結果は次のようになる。

// GitHub (User Name Only) → GitHub Pages
http://github.com/Neos21      → https://Neos21.github.io
http://www.github.com/Neos21  → https://Neos21.github.io
https://www.github.com/Neos21 → https://Neos21.github.io
https://github.com/Neos21     → https://Neos21.github.io
https://github.com/Neos21/    → https://Neos21.github.io

// GitHub (User Site Repository) → GitHub Pages (User Site)
https://github.com/Neos21/Neos21.github.io                        → https://Neos21.github.io
https://github.com/Neos21/Neos21.github.io/                       → https://Neos21.github.io
https://github.com/Neos21/Neos21.github.io/issues                 → https://Neos21.github.io
https://github.com/Neos21/Neos21.github.io/issues/                → https://Neos21.github.io
https://github.com/Neos21/Neos21.github.io/blob/master/index.html → https://Neos21.github.io

// GitHub (Project Repository) → GitHub Pages (Project Site)
https://github.com/Neos21/about                        → https://Neos21.github.io/about
https://github.com/Neos21/about/                       → https://Neos21.github.io/about
https://github.com/Neos21/about/issues                 → https://Neos21.github.io/about
https://github.com/Neos21/about/issues/                → https://Neos21.github.io/about
https://github.com/Neos21/about/blob/master/index.html → https://Neos21.github.io/about

// GitHub Pages → GitHub
http://Neos21.github.io             → https://github.com/Neos21
http://www.Neos21.github.io         → https://github.com/Neos21
https://www.Neos21.github.io        → https://github.com/Neos21
https://Neos21.github.io            → https://github.com/Neos21
https://Neos21.github.io/           → https://github.com/Neos21
https://Neos21.github.io/index.html → https://github.com/Neos21
https://Neos21.github.io/about                 → https://github.com/Neos21/about
https://Neos21.github.io/about/                → https://github.com/Neos21/about
https://Neos21.github.io/about/index.html      → https://github.com/Neos21/about
https://Neos21.github.io/about/test            → https://github.com/Neos21/about
https://Neos21.github.io/about/test/           → https://github.com/Neos21/about
https://Neos21.github.io/about/test/index.html → https://github.com/Neos21/about

// Invalid URL
http://example.com/ : Error: Invalid URL

とりあえず良い感じの遷移先 URL になるよう調整している。


以上。