Created
February 24, 2019 13:07
-
-
Save jmerle/cfe83b11607f524bcb63fb14a6e37201 to your computer and use it in GitHub Desktop.
Export the GitKraken tree to a png image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Save the visible part of the GitKraken tree to a png file. | |
* | |
* Instructions: | |
* 1. Start GitKraken with the `--remote-debugging-port=9222` argument and wait for the tree to show | |
* 2. Open Chrome and go to `http://localhost:9222/` | |
* 3. Click on the GitKraken link and go to the Console tab | |
* 4. Copy-paste the script down below and wait until it logs the image file path | |
* 5. Reload GitKraken (Ctrl+R) because the script messes up the view in order to create a neat screenshot | |
* | |
* Known issues: | |
* - The max height of the resulting image is 32767px (which shows around 1100 commits). This is because | |
* we stitch images together using a canvas which (on Chrome) can be max 32767px high. | |
*/ | |
(async () => { | |
const { remote, webFrame } = require('electron'); | |
const fs = require('fs'); | |
const os = require('os'); | |
const path = require('path'); | |
const maxHeight = 32767; | |
const container = '.graph-container'; | |
const list = document.querySelector(`${container} .graph-panel:nth-child(3)`); | |
const { scrollHeight } = list; | |
const visibleHeight = parseInt(list.style.height.split('px')[0]); | |
function loadScript(src) { | |
return new Promise((resolve, reject) => { | |
const el = document.createElement('script'); | |
el.src = src; | |
el.onload = resolve; | |
el.onerror = reject; | |
const scheme = src.split('://')[0]; | |
webFrame.registerURLSchemeAsBypassingCSP(scheme); | |
document.head.appendChild(el); | |
}); | |
} | |
function formatNumber(x) { | |
return x < 9 ? '0' + x : x; | |
} | |
function getImagePath() { | |
const now = new Date(); | |
const year = now.getFullYear(); | |
const month = formatNumber(now.getMonth() + 1); | |
const day = formatNumber(now.getDate()); | |
const hour = formatNumber(now.getHours()); | |
const minute = formatNumber(now.getMinutes()); | |
const second = formatNumber(now.getSeconds()); | |
const dateSuffix = `${year}${month}${day}-${hour}${minute}${second}`; | |
return path.resolve(os.homedir(), `gitkraken-tree-${dateSuffix}.png`); | |
} | |
function removeClass(cls) { | |
const nodes = [...document.querySelectorAll(`${container} .${cls}`)]; | |
nodes.forEach(node => node.classList.remove(cls)); | |
} | |
function beautifyTree() { | |
[ | |
'is-selected', | |
'horizontal_scrollbar', | |
'vertical_scrollbar', | |
].forEach(removeClass); | |
[ | |
...document.querySelectorAll('.commit-zone .absolute.top-0.bottom-0.z3'), | |
].forEach(node => node.remove()); | |
document.querySelector('.toolbar .upper').style.boxShadow = 'none'; | |
} | |
function takeScreenshot() { | |
return new Promise(async resolve => { | |
beautifyTree(); | |
await new Promise(resolve => setTimeout(resolve, 50)); | |
const bounds = document.querySelector(container).getBoundingClientRect(); | |
const options = { | |
x: Math.round(bounds.left), | |
y: Math.round(bounds.top), | |
width: Math.round(bounds.width), | |
height: Math.round(bounds.height), | |
}; | |
remote.webContents.getAllWebContents()[0].capturePage(options, image => { | |
resolve(image); | |
}); | |
}); | |
} | |
async function getImageAtY(y) { | |
list.scrollTop = y; | |
await new Promise(resolve => setTimeout(resolve, 50)); | |
const image = await takeScreenshot(); | |
return { | |
src: image.toDataURL(), | |
x: 0, | |
y: list.scrollTop, | |
}; | |
} | |
await loadScript('https://unpkg.com/[email protected]/dist/index.umd.js'); | |
const images = []; | |
for (let y = 0; y < maxHeight - visibleHeight && y < scrollHeight; y += visibleHeight) { | |
images.push(await getImageAtY(y)); | |
} | |
images.push(await getImageAtY(scrollHeight - visibleHeight)); | |
const base64 = await mergeImages(images, { | |
height: Math.min(scrollHeight, maxHeight), | |
}); | |
const imageData = base64.replace(/^data:image\/png;base64,/, ''); | |
const imagePath = getImagePath(); | |
fs.writeFile(imagePath, imageData, { encoding: 'base64' }, err => { | |
if (err) { | |
console.error('Something went wrong while saving the tree'); | |
console.error(err); | |
} else { | |
console.log(`Saved the tree to ${imagePath}`); | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment