Last active
November 4, 2017 05:26
-
-
Save o0101/3ef33431114be0fb28e7e37790d2e325 to your computer and use it in GitHub Desktop.
This file contains 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
(async function (){ | |
try { | |
const {width,height} = getDOMRect(); | |
const doc = document.implementation.createHTMLDocument(''); | |
doc.write(document.head.outerHTML); | |
const dom = getSelectedDOMOrBody(); | |
doc.write(dom.outerHTML); | |
doc.documentElement.setAttribute('xmlns', doc.documentElement.namespaceURI); | |
const page = `<article id=fantasticprogress style="z-index:1000000000;width:100vw;height:100vh;position: fixed;top:0;left:0;background:rgba(50,50,50,0.5);display:flex;justify-content:center;align-items:center;"> | |
<span style="background:#af1;">Loading...</span><progress id=updatingprogressbar max=${document.styleSheets.length} value=0></progress></article>`; | |
document.body.insertAdjacentHTML('beforeEnd', page); | |
const styles = []; | |
for( let i = 0; i < document.styleSheets.length; i++ ) { | |
const ss = document.styleSheets[i]; | |
if ( ss.cssRules ) { | |
for( let j = 0; j < ss.cssRules.length; j++ ) { | |
styles.push( ss.cssRules[j].cssText ); | |
} | |
} else { | |
try { | |
const res = await fetch(ss.href); | |
const cssText = await res.text(); | |
styles.push(cssText); | |
} catch(e) { | |
try { | |
const res = await fetch(`https://dompeg-proxy-90jseygqo65r.runkit.sh/?url=${btoa(ss.href)}`); | |
const cssText = await res.text(); | |
styles.push(cssText); | |
} catch(e) { | |
console.warn(`Exception adding styles from ${ss.href}`, e, e.stack); | |
} | |
} | |
} | |
updatingprogressbar.value += 1; | |
} | |
Array.from( doc.querySelectorAll('noscript, link, script')).forEach( el => el.remove() ); | |
stripComments(doc); | |
Array.from( doc.querySelectorAll('*[style]')).forEach( el => { | |
const styleText = el.getAttribute('style'); | |
const uniq = (Math.random()+''+performance.now()).replace(/\./g,'x'); | |
const className = `class${uniq}`; | |
const cssText = `.${className} {${ styleText }}`; | |
styles.push( cssText ); | |
el.classList.add( className ); | |
}); | |
const styleElement = doc.createElement('style'); | |
styleElement.innerText = styles.join('\n'); | |
doc.documentElement.appendChild(styleElement); | |
const canvas = document.createElement('canvas'); | |
Object.assign( canvas, {width,height}); | |
const ctx = canvas.getContext('2d'); | |
const data = ` | |
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"> | |
<foreignObject width="100%" height="100%"> | |
${(new XMLSerializer).serializeToString(doc).slice(15)} | |
</foreignObject> | |
</svg>`; | |
const DOMURL = window.URL || window.webkitURL || window; | |
const img = new Image(); | |
const svg = new Blob([data], {type: 'image/svg+xml'}); | |
Object.assign( img, {width,height}); | |
img.crossOrigin = "Anonymous"; | |
img.onload = function() { | |
ctx.fillStyle = 'white'; | |
ctx.fillRect( 0, 0, canvas.width, canvas.height ); | |
ctx.drawImage(img, 0, 0); | |
const datauri = canvas.toDataURL('image/jpeg'); | |
const anchor = document.createElement('a'); | |
anchor.download = 'screen.jpg'; | |
anchor.href = datauri; | |
anchor.target = "_new"; | |
anchor.innerText = 'download screen.jpg'; | |
anchor.addEventListener('click', e => {e.stopPropagation();anchor.remove();}, { capture: true }); | |
document.body.appendChild(anchor); | |
Object.assign( anchor.style, { | |
position: 'fixed', | |
background:'white', | |
fontSize: '18px', | |
fontFamily: 'monospace', | |
color: 'blue', | |
top: 0, | |
left: 0, | |
zIndex: Number.MAX_SAFE_INTEGER | |
}); | |
} | |
img.src = buildSvgImageUrl(data); | |
img.style.position = "absolute"; | |
img.style.zIndex = "10000000"; | |
img.style.backgroundColor = "white"; | |
window.open(URL.createObjectURL(svg)); | |
fantasticprogress.remove(); | |
} catch(e) { | |
alert("Capture did not work. Please re-select or reload the page and try again. See the console for a copy of the error."); | |
console.warn("Capture did not work", e ); | |
} | |
function buildSvgImageUrl(svg) { | |
const b64 = btoa(unescape(encodeURIComponent(svg))); | |
return "data:image/svg+xml;base64," + b64; | |
} | |
function stripComments(docNode){ | |
const commentWalker = docNode.evaluate('//comment()', docNode, null, XPathResult.ANY_TYPE, null); | |
let comment = commentWalker.iterateNext(); | |
const cuts = []; | |
while (comment) { | |
cuts.push(comment); | |
comment = commentWalker.iterateNext(); | |
} | |
cuts.forEach( node => node.remove()); | |
} | |
function getSelectedDOMOrBody() { | |
const sel = getSelection(); | |
if ( ! sel || ! sel.rangeCount ) { | |
return document.body.cloneNode(true); | |
} | |
const df = sel.getRangeAt(0).cloneContents(); | |
if ( df.childNodes.length > 1 ) { | |
const body = document.createElement('body'); | |
body.appendChild(df); | |
return body; | |
} else if ( df.childNodes.length == 1 ) { | |
return df.childNodes[0]; | |
} | |
} | |
function getDOMRect() { | |
const sel = getSelection(); | |
if ( ! sel || ! sel.rangeCount ) { | |
const windowEl = document.scrollingElement || document.documentElement; | |
const {scrollWidth:width,scrollHeight: height} = windowEl; | |
return {width,height}; | |
} | |
const {width,height} = sel.getRangeAt(0).cloneRange().getBoundingClientRect(); | |
return {width: width+32, height: height+32}; | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment