Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save forivall/49bb31234168481e68843cb5800fab0c to your computer and use it in GitHub Desktop.
Save forivall/49bb31234168481e68843cb5800fab0c to your computer and use it in GitHub Desktop.
github-review-keyboard-shortcuts
// https://github.com/forivall/dotfiles/blob/osx/userscripts/github-review-keyboard-shortcuts.js
/* global document */
;(() => {
/**
* @param {{[key: string]: (ev: KeyboardEvent) => any}} handlers
* @returns {(event: KeyboardEvent) => any}
*/
const reviewKeyboardHandler = (handlers) => (event) => {
if (!document.location.pathname.endsWith('/files')) return
const ae = document.activeElement
if (ae && ae.nodeName !== 'BODY') return
const handler = handlers[event.key]
return handler?.(event)
}
/** @type {string=} */
let prev
const getCurrentLink = () => {
const { hash } = document.location;
if (hash) {
const m = /^#diff-[0-9a-f]+/.exec(hash);
if (m) return m[0]
}
return prev;
}
/** @param a {HTMLAnchorElement | null} */
const focusFile = (a) => {
if (!a) return
prev = a.href
const h = new URL(prev).hash;
// github a11y bug! it says expanded on initial page load even if it is hidden. So use the classes instead
const wasExpanded = !document.querySelector(
h + ' [aria-label="Toggle diff contents"] .octicon-chevron-right.Details-content--shown,' +
h + ' [aria-label="Toggle diff contents"][aria-expanded="false"]'
);
a.click()
if (wasExpanded) return;
setTimeout(() => {
/** @type {HTMLInputElement | null} */
const t = document.querySelector(h + ' .js-reviewed-checkbox')
if (t?.checked) {
/** @type {HTMLButtonElement | null} */
const expander = document.querySelector(h + ' [aria-label="Toggle diff contents"][aria-expanded="true"]');
expander?.click();
}}, 10)
}
const navHandler =
/** @param {1 | -1} offset */
(offset) => /** @param {KeyboardEvent} ev */ (ev) => {
const h = getCurrentLink()
if (!h) {
/** @type {HTMLAnchorElement | null} */
const a = document.querySelector('.file-info a[href^="#"]')
return focusFile(a)
}
/** @type {NodeListOf<HTMLAnchorElement>} */
const files = document.querySelectorAll('.file-info a[href^="#"]')
const i = [...files].findIndex((a) => a.href.endsWith(h))
return focusFile(files[i + offset])
}
document.onkeyup = reviewKeyboardHandler({
j: navHandler(1),
k: navHandler(-1),
v: () => {
const h = getCurrentLink()
if (!h) return
/** @type {HTMLElement | null} */
const t = document.querySelector(h + ' .js-reviewed-toggle')
t?.click()
},
// D: () => { debugger }
})
})()
javascript:(()=>{let e;const t=()=>{const{hash:t}=document.location;if(t){const e=/^#diff-[0-9a-f]+/.exec(t);if(e)return e[0]}return e},n=t=>{if(!t)return;e=t.href;const n=new URL(e).hash,o=!document.querySelector(n+' [aria-label="Toggle diff contents"] .octicon-chevron-right.Details-content--shown,'+n+' [aria-label="Toggle diff contents"][aria-expanded="false"]');t.click(),o||setTimeout((()=>{if(document.querySelector(n+" .js-reviewed-checkbox")?.checked){document.querySelector(n+' [aria-label="Toggle diff contents"][aria-expanded="true"]')?.click()}}),10)},o=e=>o=>{const c=t();if(!c){const e=document.querySelector('.file-info a[href^="#"]');return n(e)}const r=document.querySelectorAll('.file-info a[href^="#"]'),i=[...r].findIndex((e=>e.href.endsWith(c)));return n(r[i+e])};var c;document.onkeyup=(c={j:o(1),k:o(-1),v:()=>{const e=t();e&&document.querySelector(e+" .js-reviewed-toggle")?.click()}},e=>{if(!document.location.pathname.endsWith("/files"))return;const t=document.activeElement;return t&&"BODY"!==t.nodeName?void 0:(0,c[e.key])?.(e)})})()
@forivall
Copy link
Author

forivall commented Apr 27, 2022

Usage:

Add as a bookmarklet, with the "min" source as the url. I use "𝒋𝒔 review keyboard shortcuts" as the name. After clicking the bookmarklet, the following keyboard shortcuts will be available:

j: next
k: previous
v: toggle viewed

You could also use a userscript manager like greasemonkey or tampermonkey, but i prefer the manual control.

original version

See also:

Refined Github browser extension includes j/k. I've opened an issue to add a "toggle viewed" but as m (for "mark") since v is already taken for leaving a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment