Skip to content

Instantly share code, notes, and snippets.

@thatrandomperson5
Created November 27, 2024 20:58
Show Gist options
  • Save thatrandomperson5/e98e36bc119c962d8d26ed159d349fe4 to your computer and use it in GitHub Desktop.
Save thatrandomperson5/e98e36bc119c962d8d26ed159d349fe4 to your computer and use it in GitHub Desktop.
Attempt at js html inliner
function download(file, name) {
let a = document.createElement("a")
a.style.display = "none"
a.href = URL.createObjectURL(file)
a.setAttribute("download", name)
document.body.append(a)
a.click()
URL.revokeObjectURL(a.href)
}
inline().then((html) => {
let eruda = document.createElement("script")
eruda.src = "//cdn.jsdelivr.net/npm/eruda"
html.body.prepend(eruda)
let erudaInit = document.createElement("script")
erudaInit.innerHTML = "eruda.init();"
eruda.after(erudaInit)
console.log(html.documentElement)
let filename = document.title.replace(" ", "-")
let rhtml = "<!doctype html>\n" + html.documentElement.outerHTML
let file = new File([rhtml], filename, {
type: "text/html",
})
download(file, filename)
})
function absoluteUrl(url, base=window.location.href) {
let newUrl = new URL(url, base)
return newUrl.toString()
}
function getDataUrl(blob) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onloadend = () => {
resolve(reader.result)
}
reader.readAsDataURL(blob)
})
}
async function currentPage() {
try {
let code = await fetch(window.location.href).then((r) => r.text())
let parser = new DOMParser()
return parser.parseFromString(code, "text/html")
} catch (error) {
console.error(error)
}
}
window.inline = async function (current = false) {
var html = current ? document : await currentPage()
var handled = []
for (var el of html.querySelectorAll(
"script[src], img[src], link[href][rel='stylesheet']",
)) {
try {
var url
switch (el.tagName) {
case "LINK":
url = absoluteUrl(el.href)
let css = await fetch(url).then((r) => r.text())
el.outerHTML = `<style data-href="${url}">${css}</style>`
break
case "SCRIPT":
url = absoluteUrl(el.src)
let js = await fetch(url).then((r) => r.text())
el.removeAttribute("src")
el.setAttribute("data-src", url)
el.textContent = js
break
case "IMG":
url = absoluteUrl(el.src)
let img = await fetch(url).then((r) => r.blob())
el.setAttribute("data-src", url)
el.src = await getDataUrl(img)
}
handled.push(url)
} catch (error) {
console.trace(error)
}
}
if (!current) {
var cache = {}
for (var el of document.querySelectorAll(
"script[src], img[src], link[href][rel='stylesheet']",
)) {
try {
var url = absoluteUrl(el.tagName === "LINK" ? el.href : el.src)
if (!handled.includes(url)) {
let r = await fetch(url)
cache[url] = await (el.tagName === "IMG"
? getDataUrl(await r.blob())
: r.text())
}
} catch (error) {
console.trace(error)
}
}
let tag = document.createElement("script")
tag.type = "text/json"
tag.textContent = JSON.stringify(cache)
tag.id = "__inline_cache_custom"
html.head.prepend(tag)
let script = document.createElement("script")
script.id = "__inline_script_handle"
script.innerHTML = `
(() => {
${absoluteUrl.toString()}
const cache = JSON.parse(
document.getElementById("__inline_cache_custom").innerHTML,
);
const observer = new MutationObserver((mutationList, observer) => {
for (const mutation of mutationList) {
for (const child of mutation.addedNodes) {
if (child.nodeType !== 1) {
continue
}
const urlAttr = child.tagName === "LINK" ? "href" : "src";
var url = child.getAttribute(urlAttr);
if (!url) {
continue
}
url = absoluteUrl(url, "${window.location.href}");
if (cache.hasOwnProperty(url)) {
console.log(url);
child.setAttribute("data-" + urlAttr, url);
if (child.tagName === "IMG") {
child.src = cache[url];
} else if (child.tagName === "SCRIPT") {
child.removeAttribute("src");
child.textContent = cache[url];
} else {
child.outerHTML =
"<style data-href=" + url + ">" + cache[url] + "</style>";
}
}
}
}
});
observer.observe(document.documentElement, {
subtree: true,
childList: true,
});
})();
`
tag.after(script)
}
return html
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment