您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button next to files on Github to quickly open it in your favorite IDE
当前为
// ==UserScript== // @name Github Open files in Editor // @namespace http://tampermonkey.net/GithubOpenFilesInEditor // @version 0.1 // @description Adds a button next to files on Github to quickly open it in your favorite IDE // @author Alexandre Blanc // @match https://github.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=undefined.localhost // @grant none // @license MIT // ==/UserScript== // For PhpStorm users, it requires plugin : IDE Remote Control // For VSCode users on Mac OS, please add in your terminal: // defaults write com.google.Chrome URLAllowlist -array "vscode://*" (function() { 'use strict'; let userSettings = {projectList: {}, editor: ''}; let currentUrl = ''; let project = ''; const loadSettings = function() { if (!window.localStorage.getItem('ghofieSettings')) { return {projectList: {}, editor: 'phpstorm'}; } userSettings = JSON.parse(window.localStorage.getItem('ghofieSettings')); } const saveSettings = function() { window.localStorage.setItem('ghofieSettings', JSON.stringify(userSettings)) removeLinks(); setLinks(); } const handleUrlChange = function() { if (window.location.href === currentUrl) { return; } window.setTimeout(initSettingsPanel, 500); removeLinks(); setLinks(); currentUrl = window.location.href; } const initUrlChangeDetection = function() { setInterval(function() { handleUrlChange(); },1000); } const icon = function (color) { return `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" x="0px" y="0px" viewBox="0 0 1000 1000" xml:space="preserve"> <g> <g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)" fill="red"> <path d="M267.3,4393.3c-47.8-23.9-100.4-76.5-124.3-124.3c-40.6-78.9-43-327.5-43-4159s2.4-4080.2,43-4159c23.9-47.8,76.5-100.4,124.3-124.3c78.9-40.6,353.8-43,4732.7-43c4378.9,0,4653.8,2.4,4732.7,43c47.8,23.9,100.4,76.5,124.3,124.3c40.6,78.9,43,327.5,43,4159s-2.4,4080.2-43,4159c-23.9,47.8-76.5,100.4-124.3,124.3c-78.9,40.6-353.8,43-4732.7,43C621.1,4436.3,346.2,4433.9,267.3,4393.3z M9314.4,2990.2v-860.5H5000H685.6l-7.2,836.6c-2.4,458.9,0,850.9,7.2,865.3c7.2,26.3,874.8,31.1,4319.2,26.3l4309.6-7.2V2990.2z M9321.6-1042.1l-7.2-2588.6H5000H685.6l-7.2,2588.6l-4.8,2586.2H5000h4326.3L9321.6-1042.1z"/> <path d="M8284.2,3140.8l-45.4-55l55,45.4c28.7,26.3,52.6,50.2,52.6,55C8346.3,3205.4,8327.2,3191,8284.2,3140.8z"/> <path d="M5425.5,927.5c-38.2-21.5-81.3-71.7-100.4-112.3c-16.7-38.2-294-855.7-611.9-1811.8c-621.5-1869.2-614.3-1845.3-499.6-1967.2c112.3-119.5,329.8-117.1,425.5,4.8c55,71.7,1221.4,3554.3,1221.4,3649.9C5860.5,905.9,5609.5,1044.6,5425.5,927.5z"/> <path d="M2248.8-227c-894-600-944.1-635.8-975.2-729c-31.1-88.4-28.7-105.2,11.9-191.2c40.6-81.3,162.5-172.1,965.7-707.5c800.7-537.8,932.2-616.7,1011.1-616.7c124.3,0,217.5,52.6,265.3,153c47.8,100.4,47.8,136.2,4.8,241.4c-28.7,66.9-148.2,157.8-741,552.1c-389.6,260.5-707.5,478-707.5,485.2c0,7.2,315.5,224.7,700.3,480.4c595.2,399.2,705.1,480.4,743.4,556.9c38.2,78.9,40.6,107.6,16.7,181.7c-35.9,124.3-121.9,196-248.6,210.3C3193,401.6,3181,394.4,2248.8-227z"/> <path d="M6601.5,365.8c-76.5-38.2-167.3-174.5-167.3-253.4c0-138.6,78.9-207.9,786.4-676.4c382.4-253.4,695.5-468.5,695.5-475.6c0-7.2-317.9-224.7-707.5-485.2c-592.8-394.4-712.3-485.2-741-552.1c-43-105.2-43-141,4.8-241.4c47.8-100.4,141-153,265.3-153c78.9,0,210.3,78.9,1011.1,616.7c1032.6,688.4,1039.8,695.6,975.2,896.3c-31.1,98-57.4,117.1-970.4,729C6766.4,427.9,6747.3,439.8,6601.5,365.8z"/> </g> </g> </svg>` }; document.phpStormLink = function (link) { const hrefLink = `http://localhost:63342/api/file?file=${link}`; const linkWindow = window.open(hrefLink,'autoOpenInEditor'); setTimeout(function() { linkWindow.close(); },1000); }; document.vsCodeLink = function (link) { const hrefLink = `vscode://file/${link}`; const linkWindow = window.open(hrefLink,'autoOpenInEditor'); setTimeout(function() { linkWindow.close(); },1000); }; const setLinks = function() { const tabnavs = document.querySelectorAll('.tabnav [data-pjax="#repo-content-pjax-container"] .tabnav-tab'); if (tabnavs.length === 0) { return; } project = document.querySelector('#repository-container-header [itemprop="name"] a').href.split('/').pop(); switch (Array.from(document.querySelectorAll('.tabnav [data-pjax="#repo-content-pjax-container"] .tabnav-tab')).findIndex(el => el.classList.contains("selected"))) { case 0: setLinksInConversationTab(); break; case 1: setLinksInCommitsTab(); break; case 3: setLinksInFilesChangedTab(); break; } } const handleClickOnOpenInEditorLink = function (link) { const projectPath = userSettings.projectList[project] || ''; switch (userSettings.editor) { case 'phpstorm': document.phpStormLink(projectPath + link); break; case 'vscode': document.vsCodeLink(projectPath + link); break; } } const setLinksInConversationTab = function() { let linkCounter = 0; document.querySelectorAll('turbo-frame[id^="review-thread-or-comment-id-"] summary a').forEach(function (a) { linkCounter++; const fileUrl = a.innerHTML; const ghofieLinkId = `js-open-in-phpstorm-${linkCounter}`; a.insertAdjacentHTML('afterend', ` <div id="${ghofieLinkId}" title="Open file in editor" data-link="${fileUrl}" class="ghofie-link" style="margin: 2px 5px 0px 0px" > ${icon()} </div> `); document.getElementById(ghofieLinkId).addEventListener('click',function(e){ e.preventDefault(); handleClickOnOpenInEditorLink(e.currentTarget.dataset.link); }); }); } const setLinksInCommitsTab = function() { let linkCounter = 0; document.querySelectorAll( 'diff-layout #files div.js-file div.file-header span.Truncate clipboard-copy' ).forEach(function (e) { linkCounter++; const fileUrl = e.value; const ghofieLinkId = `js-open-in-phpstorm-${linkCounter}`; e.insertAdjacentHTML('afterend', ` <div id="${ghofieLinkId}" title="Open file in editor" data-link="${fileUrl}" class="ghofie-link" style="margin: 2px 5px 0px 0px; cursor: pointer;" > ${icon()} </div> `); document.getElementById(ghofieLinkId).addEventListener('click',function(e){ e.preventDefault(); handleClickOnOpenInEditorLink(e.currentTarget.dataset.link); }); }); } const setLinksInFilesChangedTab = function() { let linkCounter = 0; document.querySelectorAll( 'div[data-target="diff-layout.mainContainer"] #files div.js-file div.file-header span.Truncate clipboard-copy' ).forEach(function (e) { linkCounter++; const fileUrl = e.value; const ghofieLinkId = `js-open-in-phpstorm-${linkCounter}`; e.insertAdjacentHTML('afterend', ` <div id="${ghofieLinkId}" title="Open file in editor" data-link="${fileUrl}" class="ghofie-link" style="margin: 2px 5px 0px 0px; cursor: pointer;" > ${icon()} </div> `); document.getElementById(ghofieLinkId).addEventListener('click',function(e){ e.preventDefault(); handleClickOnOpenInEditorLink(e.currentTarget.dataset.link); }); }); } const removeLinks = function() { document.querySelectorAll('.ghofie-link').forEach(function (v) { v.parentElement.removeChild(v); }); } const isConfigurationValid = function() { try { JSON.parse(document.getElementById("ghofie-project-list").value); return true; } catch (e) { return false; } }; const toggleSettingsDisplay = function() { const element = document.getElementById('ghofie-settings'); element.style.display = element.style.display == 'none' ? 'inline-block' : 'none' if (element.style.display == 'inline-block') { document.getElementById("ghofie-project-list").value = JSON.stringify(userSettings.projectList); document.getElementById('ghofie-editor-choice-' + userSettings.editor).checked = true; } }; const initSettingsPanel = function() { if (document.querySelector('#ghofie-settings') !== null) { document.querySelector('#ghofie-settings').remove(); document.querySelector('#js-btn-ghofie-settings').remove(); } document.querySelector('.Header').insertAdjacentHTML('afterend', ` <div class="row mt-4 px-3 px-md-4 px-lg-5" id="ghofie-settings" style="display:none;width:100%;"> <div class="form-group"> <h3>GitHub - Open file in editor</h3> <label class="label-bold" for="ghofie-project-list"> Project association <i>{"${project}":"/home/src/localpath/"}</i> </label> <textarea class="form-control" rows="3" maxlength="650" id="ghofie-project-list" name="ghofie-settings"></textarea> <label class="label-bold">Editor choice</label> <div class="form-check"> <input type="radio" class="form-check-input" id="ghofie-editor-choice-phpstorm" name="ghofie-editor-choice" value="phpstorm"> <label for="ghofie-editor-choice-phpstorm" class="form-check-label">PhpStorm</label> </div> <div class="form-check"> <input type="radio" class="form-check-input" id="ghofie-editor-choice-vscode" name="ghofie-editor-choice" value="vscode"> <label for="ghofie-editor-choice-vscode" class="form-check-label">VS Code</label> </div> <button id="ghofie-settings-save-button" class="btn btn-secondary" > Save Settings </button> </div> </div> `); let ghofieSettingsButton = document.createElement('a'); ghofieSettingsButton.addEventListener('click', function (e) { e.preventDefault(); toggleSettingsDisplay(); return false; }); ghofieSettingsButton.id = 'js-btn-ghofie-settings'; ghofieSettingsButton.href = '#'; ghofieSettingsButton.innerHTML = `${icon('#919191')}`; ghofieSettingsButton.style='margin:5px 0 0 10px' document.querySelector('.Header-item:last-child').insertAdjacentElement('afterend', ghofieSettingsButton); document.getElementById('ghofie-settings-save-button').addEventListener( 'click', function (e) { e.preventDefault(); if (isConfigurationValid()) { toggleSettingsDisplay(); userSettings.projectList = JSON.parse(document.getElementById("ghofie-project-list").value); userSettings.editor = document.querySelector('input[name="ghofie-editor-choice"]:checked').value; saveSettings(); } return false; } ); }; loadSettings(); initUrlChangeDetection(); })();