Last active
February 15, 2024 11:32
-
-
Save christophemarois/fa4e023419dda613fde03cbb610df83f to your computer and use it in GitHub Desktop.
Demonstrate how to replace images with their base64 equivalent regardless of same-origin policy using GM_xmlhttpRequest. Still requires permission from Tampermonkey.
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
// ==UserScript== | |
// @name Base64 inline images | |
// @author @christophemarois | |
// @match * | |
// @grant GM_xmlhttpRequest | |
// @connect * | |
// ==/UserScript== | |
// NOTE: NOT MEANT TO BE INSTALLED | |
// AS IT WILL REPLACE EVERY IMAGE ON EVERY PAGE | |
// INFORMATIVE PURPOSES ONLY | |
(function() { | |
const inlineBase64Images = nodes => { | |
let imgs = Array.from(nodes).filter(node => node.matches('img')) | |
return Promise.all(imgs.map(img => new Promise(res => { | |
GM_xmlhttpRequest({ | |
method: 'GET', | |
url: img.src, | |
responseType: 'blob', | |
onload: function(xhr) { | |
if (xhr.status !== 200) return res(null) | |
let headers = {} | |
for (let header of xhr.responseHeaders.trim().split(/\n/)) { | |
let parts = header.split(':') | |
if (parts.length === 1) continue | |
headers[parts[0].trim()] = parts[1].trim() | |
} | |
let type = headers['Content-Type'] | |
if (!/^image\//.test(type)) { | |
if (/\.jpe?g$/i.test(img.src)) type = 'image/jpeg' | |
if (/\.png$/i.test(img.src)) type = 'image/png' | |
if (/\.gif$/i.test(img.src)) type = 'image/png' | |
} | |
if (!/^image\//.test(type)) { | |
console.error(`Can't process "${img.src}" because its type is "${type}"`) | |
return res(null) | |
} | |
let imgEl = new Image() | |
imgEl.onload = function () { | |
let canvas = document.createElement('canvas'); | |
canvas.width = imgEl.naturalWidth; | |
canvas.height = imgEl.naturalHeight; | |
try { | |
canvas.getContext('2d').drawImage(imgEl, 0, 0) | |
img.src = canvas.toDataURL(type, 0.7) | |
res(img) | |
} catch (e) { | |
console.error(`Can't draw "${img.src}" on a canvas`, e) | |
res(null) | |
} | |
} | |
imgEl.onerror = () => res(null) | |
imgEl.src = window.URL.createObjectURL(xhr.response) | |
} | |
}) | |
}))) | |
// At this point, imgs is an array of all the <img> tags of the page | |
// who had their content base64'd. Some elements might be null if | |
// XHR or canvas conversion failed on them. Filter them out. | |
.then(imgs => Promise.resolve(imgs.filter(img => !!img))) | |
} | |
let startTime = +new Date | |
inlineBase64Images(document.querySelectorAll('img')).then(imgs => { | |
console.log(imgs.length + ' images converted in ' + ((+new Date) - startTime) / 1000 + 's') | |
}) | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment