NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name phab.mercurial-scm.org customization // @namespace http://tampermonkey.net/ // @version 0.2 // @description Make reviewing a bit easier // @author Jun Wu // @match https://phab.mercurial-scm.org/D* // @grant none // ==/UserScript== (function() { 'use strict'; //// Utilities // Select an outer element by text of an inner element let selectByInner = (outer, inner, text) => { let results = []; document.querySelectorAll(outer).forEach((outer) => { if (inner) { outer.querySelectorAll(inner).forEach((inner) => { if (inner.textContent === text) { results.push(outer); } }); } else { if (outer.textContent.includes(text)) { results.push(outer); } } }); return results; }; let hide = (e) => { e.style.display = 'none'; }; let toArray = (l) => Array.prototype.slice.call(l); // Find Differential Revision number in an element let drevRegex = /\/D([1-9][0-9]*)$/; let findDRevNum = (e) => { let result = null; if (e) { e.querySelectorAll('a').forEach((a) => { let match = drevRegex.exec(a.href); if (match) result = match[1]; }); } return result; }; //// Actual interface tweaks // Hide "Authored by ..." - duplicated with "... created this revision" // document.querySelectorAll('.phui-two-column-subheader .phui-head-thing-view').forEach(hide); // Hide "Details" label selectByInner('.phui-header-shell', '.phui-header-header', 'Details').forEach(hide); // Hide "Reviewers" selectByInner('.phui-property-list-container', null, 'Reviewers').forEach(hide); // Hide "SUMMARY" label selectByInner('.phui-property-list-section-header', null, 'Summary').forEach(hide); // Hide "Diff Detail" selectByInner('.phui-box.phui-object-box.phui-box-border', '.phui-header-header', 'Diff Detail').forEach(hide); // Simplify side column let toRemove = /(Update Diff|Edit Revision|Download Raw Diff|Edit Related Objects|Automatically Subscribed|Flag For Later)/; document.querySelectorAll('.phabricator-action-view').forEach((e) => { if (toRemove.exec(e.textContent)) hide(e); }); // Hide "Tags" or "Subscribers" if it's "None" ['Subscribers', 'Tags'].forEach((name) => { selectByInner('.phui-curtain-panel', '.phui-curtain-panel-header', name).forEach((e) => { if (e.textContent.includes('None')) hide(e); }); }); // Hide actions document.querySelectorAll('.phui-timeline-shell').forEach((e) => { let needHide = false; // Hide Herald if (!needHide && toArray(e.querySelectorAll('a')).some((a) => a.textContent === 'Herald')) needHide = true; // Hide "added a dependent revision" actions if (!needHide && /(added a dependent revision|created this revision)/.exec(e.textContent)) needHide = true; // Hide non-human text like "This revision now requires changes to proceed" if (!needHide && e.querySelectorAll('.phui-timeline-title .phui-link-person').length === 0) needHide = true; if (needHide) { hide(e); // Hide the spacer too let next = e.nextElementSibling; if (next && next.classList.contains('phui-timeline-spacer')) hide(next); } }); // Hide "Revision Contents" label selectByInner('.phui-header-shell', '.phui-header-header', 'Revision Contents').forEach(hide); // Hide "Lint was skipped ..." warning box selectByInner('.phui-info-view.phui-info-severity-warning', null, 'Lint was skipped').forEach(hide); // Get some information about the stack let prevDRev, nextDRev, stackSize = 0, stackIndex; document.querySelectorAll('.object-graph-table').forEach((e) => { e.querySelectorAll('tr.highlighted, tr.alt-highlighted').forEach((currRow) => { if (!stackIndex) { let rows = toArray(e.querySelector('tbody').children).slice(1); // remove table header stackSize = rows.length; stackIndex = stackSize - rows.indexOf(currRow); } if (!nextDRev) nextDRev = findDRevNum(currRow.previousElementSibling); if (!prevDRev) prevDRev = findDRevNum(currRow.nextElementSibling); }); }); // Show "x of y" in subtitle if (stackSize > 0) { document.querySelectorAll('.phui-header-row .phui-header-subheader').forEach((e) => { let span = document.createElement('span'); span.innerHTML = '<span class="phui-tag-core">' + stackIndex + ' of ' + stackSize + '</span>'; span.className = 'phui-tag-view phui-tag-type-shade phui-tag-shade'; e.appendChild(span); }); } // Use a smaller title with "Patch X of Y" information let title = null; document.querySelectorAll('.phui-two-column-header .phui-header-header').forEach((e) => { title = e.textContent; }); if (title && stackSize > 0) { title = '[' + stackIndex + ' of ' + stackSize + '] ' + title; } if (title) { let header = document.querySelector('.phui-two-column-subheader > .phui-head-thing-view.head-thing-small'); if (!header) return; // Change the small title and hide the large title let e = document.createElement('a'); e.appendChild(document.createTextNode(title)); e.style.fontWeight = 'bold'; // Insert the title after the profile picture header.insertBefore(e, header.childNodes[1]); // Change "Authored by" to " authored by " header.childNodes[2].textContent = ' authored by '; // Hide main header document.querySelectorAll('.phui-two-column-header').forEach(hide); } // Register more keyboard shortcuts if (JX.KeyboardShortcut) { // Register "[", "]" to navigate to previous/next patch if (prevDRev) { let k = new JX.KeyboardShortcut('[', 'Navigate to previous patch in the stack'); k.setHandler(() => { window.location.href = '/D' + prevDRev; }).register(); } if (nextDRev) { let k = new JX.KeyboardShortcut(']', 'Navigate to next patch in the stack'); k.setHandler(() => { window.location.href = '/D' + nextDRev; }).register(); } // Register "a" for triggering a custom protocol: action://... // To register an non-web custom protocol handler, see: // Firefox: http://kb.mozillazine.org/Register_protocol // Windows: https://customurl.codeplex.com/ // Linux: https://stackoverflow.com/questions/32064229 // Also see https://secure.phabricator.com/book/phabricator/article/external_editor let k = new JX.KeyboardShortcut('A', 'Trigger an "action" protocol for this URL'); k.setHandler(() => { let url = 'action://open?url=' + encodeURIComponent(window.location.href); console.log('Trigger! ' + url); window.location.href = url; }).register(); } })();