Skip to content

Instantly share code, notes, and snippets.

@w4-hojin
Last active June 19, 2020 01:50
Show Gist options
  • Save w4-hojin/7b46d33472a65cfe3510059ab25bf1da to your computer and use it in GitHub Desktop.
Save w4-hojin/7b46d33472a65cfe3510059ab25bf1da to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Gerrit_Helper
// @namespace https://skelterlabs.com/
// @homepage https://gist.github.com/w4-hojin/7b46d33472a65cfe3510059ab25bf1da
// @version 0.22
// @description Gerrit Helper.
// @author hojin <hojin@wisefour.com>
// @require https://code.jquery.com/jquery-3.4.1.min.js
// @require https://cdn.jsdelivr.net/ally.js/1.4.1/ally.min.js
// @require https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js
// @downLoadUrl https://gist.githubusercontent.com/w4-hojin/7b46d33472a65cfe3510059ab25bf1da/raw/Gerrit_Helper.user.js
// @updateUrl https://gist.githubusercontent.com/w4-hojin/7b46d33472a65cfe3510059ab25bf1da/raw/Gerrit_Helper.user.js
// @match https://gerrit.wisefour.com/*
// @match https://youtrack.corp.skelterlabs.com/*
// @match https://skelterlabs.atlassian.net/*
// @match https://cs.corp.skelterlabs.com/*
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_openInTab
// @connect localhost
// ==/UserScript==
/*
릴리즈 노트
0.22
Open in CS 버튼 추가
**/
(function($) {
'use strict';
const debug = console.log;
function setupWatcher(parent, selector, handler, options = {}) {
if (!parent || parent.nodeName === '#comment' || parent.nodeName === '#text' || parent.nodeName === 'STYLE' || parent.nodeName==='SCRIPT') {
return
}
debug(`Watching.. (${selector})`, parent, options);
const handled = []
const handle = (index, element) => {
debug('Cheking need to handle...', selector, element)
if ($.inArray(element, handled) !== -1) {
return
}
if (options.contains) {
const text = $(element).text()
if (options.contains instanceof RegExp) {
if (!options.contains.test(text)) {
return
}
} else {
if (!text.includes(options.contains)) {
return
}
}
}
debug('Handle!', selector, element)
handled.push(element)
handler(index, element)
}
$(selector).each(handle)
// ally.observe.shadowMutations({
// context: parent,
// callback: function(mutations) {
// const addedNodes = _.flatMap(mutations, 'addedNodes')
// addedNodes.forEach(addedNode => {
// addedNode.forEach(node => {
// //console.log('shadowMutations', node)
// if (!node.parentNode || !node.shadowRoot) return
// //for (const child of node.shadowRoot.children) console.log(child)
// //for (const child of node.shadowRoot.children) setupWatcher(child, selector, handler, options)
// //console.log(node.parentNode)
// //console.log(node)
// setupWatcher(node.shadowRoot, selector, handler, options)
// })
// })
// //console.log(mutations)
// //console.log(_.map(nodes, 'localName'))
// //_.forEach(nodes, (node) => setupWatcher(node, selector, handler, options))
// },
// config: {
// childList: true,
// subtree: true,
// },
// })
const insertedNodes = []
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const tagets = $(mutation.target).find($(parent).find(selector))
tagets.each(handle)
//console.log(mutation)
mutation.addedNodes.forEach(node => {
if (node.shadowRoot) {
//console.log(_.map(node.shadowRoot.children, 'id'))
observer.observe(node.shadowRoot, { subtree: true, childList: true })
//setupWatcher(node.shadowRoot, selector, handler, options)
}
if (node.nodeName === '#comment' || node.nodeName === '#text' || node.nodeName === 'STYLE' || node.id ==='diffHost') {
return
}
observer.observe(node, { subtree: true, childList: true })
const nodes = $(node).find($(parent).find(selector))
nodes.each(handle)
})
})
})
observer.observe(parent, { subtree: true, childList: true })
_.forEach(parent.children, child => setupWatcher(child, selector, handler, options))
// const interval = setInterval(() => {
// if (parent.shadowRoot) {
// clearInterval(interval)
// // observer.observe(parent.shadowRoot, { subtree: true, childList: true })
// setupWatcher(parent.shadowRoot, selector, handler, options)
// //_.forEach(parent.shadowRoot.children, child => setupWatcher(child, selector, handler, options))
// }
// }, 3000)
}
function setupWatcher2(parent, selector, handler, options = {}) {
debug(parent, selector, handler, options)
const installed = []
const handled = []
const handle = (index, element) => {
if ($.inArray(element, handled) !== -1) {
return
}
debug('Cheking need to handle...', selector, element)
if (options.contains) {
const text = $(element).text()
if (options.contains instanceof RegExp) {
if (!options.contains.test(text)) {
return
}
} else {
if (!text.includes(options.contains)) {
return
}
}
}
debug('Handle!', selector, element)
handled.push(element)
handler(index, element)
}
const install = (parent) => {
if ($.inArray(parent, installed) !== -1) {
return
}
installed.push(parent)
const tryHandle = () => {
if ($(parent).is(selector)) {
handle(null, parent)
}
$(parent).find(selector).each(handle)
for (let el of [parent, ...parent.getElementsByTagName('*')]) {
if (el.shadowRoot) {
_.forEach(el.shadowRoot.children, element => {
install(element)
})
}
}
}
tryHandle()
setInterval(() => {
tryHandle()
}, 5000)
}
install (parent, selector, handler, options)
}
function requestOpenEditor(filePath) {
console.log(`Opening ${filePath}...`)
// GM_xmlhttpRequest({
// method: 'GET',
// url: 'http://localhost:63342/api/file/'+ filePath,
// onload: function(response) {
// console.debug(response)
// }
// })
GM_xmlhttpRequest({
method: 'GET',
url: 'http://localhost:8091?'+$.param({message: filePath}),
onload: function(response) {
console.debug(response)
}
})
GM_xmlhttpRequest({
method: 'GET',
url: 'http://localhost:8092?'+$.param({message: filePath}),
onload: function(response) {
console.debug(response)
}
})
}
const issuRegex = /\(#?(\w+-\d+)\)/g
const changeIdRegex = /Change-Id: (I\w+)/g
// To Issue Link
if (location.href.startsWith('https://gerrit.wisefour.com/')) {
setupWatcher2(document.body.firstElementChild, '.headerSubject', (index, element) => {
const commitMsg = $(element).text()
issuRegex.lastIndex=0
const test = issuRegex.exec(commitMsg)
const issueNum = test[1]
const youtrackLink = `https://youtrack.corp.skelterlabs.com/youtrack/issue/${issueNum}`
const jiraLink = `https://skelterlabs.atlassian.net/browse/${issueNum}`
// <span >Go to Youtrack <a href="${youtrackLink}" target="_blank">${issueNum}</a></span>
$(element).after($(`
<div style="margin-left: 12px;">
<span><a href="${jiraLink}" target="_blank">TO JIRA(${issueNum})</a></span>
</div>
`))
}, {contains: issuRegex})
}
// Topic clip copy
if (location.href.startsWith('https://gerrit.wisefour.com/')) {
setupWatcher2(document, 'gr-linked-chip', (index, element) => {
$(element).after(
$(`<button>Copy</button>`)
.click((event)=> {
GM_setClipboard(element.shadowRoot.querySelector('gr-limited-text').shadowRoot.textContent.trim())
}))
})
}
// File name copy button & Open button
if (location.href.startsWith('https://gerrit.wisefour.com/')) {
setupWatcher2(document.body.firstElementChild, '.jumpToFileContainer', (index, element) => {
const textElement = $(element)
$(element).after(
$(`<gr-button>Open in CS</gr-button>`)
.click((event)=> {
const filePath = $(element.firstElementChild.shadowRoot).find('#trigger').text().trim()
GM_openInTab(`https://cs.corp.skelterlabs.com/gerrit.wisefour.com/a/w4/-/blob/${filePath}`)
}))
$(element).after(
$(`<gr-button>Open</gr-button>`)
.click((event)=> {
const filePath = $(element.firstElementChild.shadowRoot).find('#trigger').text().trim() + location.hash
requestOpenEditor(filePath)
}))
$(element).after(
$(`<gr-button>Copy</gr-button>`)
.click((event)=> {
const filePath = $(element.firstElementChild.shadowRoot).find('#trigger').text().trim()
console.log(`Copying ${filePath}...`)
GM_setClipboard(filePath)
}))
})
}
// To Gerrit Link
// if (false && location.href.startsWith('https://youtrack.')) {
// setupWatcher(document, 'div.wiki.text.prewrapped', (index, element) => {
// const commitMsg = $(element).text()
// changeIdRegex.lastIndex=0
// const test = changeIdRegex.exec(commitMsg)
// const changeId = test[1]
// $(element).append($(`<br><a href="https://gerrit.wisefour.com/#/q/${changeId}" target=_blank>gerrit>></a>`))
// }, {contains: changeIdRegex})
// }
// Branch command
if (location.href.startsWith('https://skelterlabs.atlassian.net/')) {
setupWatcher2(document, "span[data-test-id='issue.issue-view.views.issue-base.foundation.quick-add.quick-add-item.link-page']", (index, element) => {
const param = window.location.search.replace(/^\?/,'').split('&').reduce((s,c) => {var t=c.split('=');s[t[0]]=t[1];return s;}, {})
let issue = param.selectedIssue
// https://skelterlabs.atlassian.net/browse/SS-174
if (!issue) {
issue = window.location.pathname.split('/').pop()
}
$(`<button>Copy</button>`)
.click((event)=> {
GM_setClipboard(`git fetch && gc -b ${issue} origin/master`)
}).insertAfter($(element).parent().parent())
})
}
// Storybook open link (not used)
if (location.href.startsWith('http://localhost:9009/')) {
setupWatcher2(document, "button[title='Open canvas in new tab']", (index, element) => {
$(element).parent().prepend($(`<button>Open</button>`)
.click((event)=> {
let path = window.location.href.split('/').pop()
path = path.split('--')
requestOpenEditor(path[0].replace(/-/g, '/') + '.story.jsx')
}))
})
}
// Sourcegraph open link
if (location.href.startsWith('https://cs.corp.skelterlabs.com/')) {
setupWatcher2(document, "li.nav-item>button.copy-link-action", (index, element) => {
const button = $(`<button class="btn btn-link btn-link-sm"><svg class="mdi-icon icon-inline" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></svg></button>`)
button.click((event)=> {
let path = window.location.href.split('-/blob/').pop().replace("#L", ":")
requestOpenEditor(path)
})
$(element).after(button)
})
}
})(jQuery.noConflict(true))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment