outerHtml and a get impl

This commit is contained in:
velzie 2024-08-25 19:12:02 -04:00
parent 8e191b45ab
commit e8b9e04d46
No known key found for this signature in database
GPG key ID: 048413F95F0DDE1F
5 changed files with 65 additions and 36 deletions

View file

@ -1,5 +1,5 @@
import { ScramjetClient } from "../client";
import { config, decodeUrl, htmlRules } from "../shared";
import { config, decodeUrl, htmlRules, unrewriteHtml } from "../shared";
import {
encodeUrl,
rewriteCss,
@ -8,11 +8,6 @@ import {
rewriteSrcset,
} from "../shared";
declare global {
interface Element {
$origattrs: Record<string, string>;
}
}
export default function (client: ScramjetClient, self: typeof window) {
const attrObject = {
nonce: [self.HTMLElement],
@ -100,22 +95,27 @@ export default function (client: ScramjetClient, self: typeof window) {
},
});
const innerHTML = Object.getOwnPropertyDescriptor(
self.Element.prototype,
"innerHTML"
);
Object.defineProperty(self.Element.prototype, "innerHTML", {
set(value) {
if (this instanceof self.HTMLScriptElement) {
value = rewriteJs(value);
} else if (this instanceof self.HTMLStyleElement) {
value = rewriteCss(value);
client.Trap("Element.prototype.innerHTML", {
set(ctx, value: string) {
if (ctx.this instanceof self.HTMLScriptElement) {
return rewriteJs(value, client.url);
} else if (ctx.this instanceof self.HTMLStyleElement) {
return rewriteCss(value, client.url);
} else {
value = rewriteHtml(value, client.cookieStore);
return rewriteHtml(value, client.cookieStore, client.url);
}
},
get(ctx) {
return unrewriteHtml(ctx.get());
},
});
return innerHTML.set.call(this, value);
client.Trap("Element.prototype.outerHTML", {
set(ctx, value: string) {
return rewriteHtml(value, client.cookieStore, client.url);
},
get(ctx) {
return unrewriteHtml(ctx.get());
},
});

View file

@ -4,6 +4,7 @@ export const {
rewrite: {
rewriteCss,
rewriteHtml,
unrewriteHtml,
rewriteSrcset,
rewriteJs,
rewriteHeaders,

View file

@ -8,7 +8,7 @@ import { BareClient } from "@mercuryworkshop/bare-mux";
import { parseDomain } from "parse-domain";
import { ScramjetHeaders } from "./headers";
import { CookieStore } from "./cookie";
import { htmlRules } from "./rewriters/html";
import { htmlRules, unrewriteHtml } from "./rewriters/html";
self.$scramjet.shared = {
util: {
@ -23,6 +23,7 @@ self.$scramjet.shared = {
rewrite: {
rewriteCss,
rewriteHtml,
unrewriteHtml,
rewriteSrcset,
rewriteJs,
rewriteHeaders,

View file

@ -48,28 +48,49 @@ export function rewriteHtml(
}
`;
const script = (src) => new Element("script", { src });
head.children.unshift(
new Element("script", {
src: self.$scramjet.config["wasm"],
}),
new Element("script", {
src: self.$scramjet.config["codecs"],
}),
new Element("script", {
src: "data:application/javascript;base64," + btoa(injected),
}),
new Element("script", {
src: self.$scramjet.config["shared"],
}),
new Element("script", {
src: self.$scramjet.config["client"],
})
script(self.$scramjet.config["wasm"]),
script(self.$scramjet.config["codecs"]),
script("data:application/javascript;base64," + btoa(injected)),
script(self.$scramjet.config["shared"]),
script(self.$scramjet.config["client"])
);
}
return render(handler.root);
}
export function unrewriteHtml(html: string) {
const handler = new DomHandler((err, dom) => dom);
const parser = new Parser(handler);
parser.write(html);
parser.end();
function traverse(node: ChildNode) {
if ("attribs" in node) {
for (const key in node.attribs) {
if (key.startsWith("data-scramjet-")) {
node.attribs[key.slice(13)] = node.attribs[key];
delete node.attribs[key];
}
}
}
if ("childNodes" in node) {
for (const child of node.childNodes) {
traverse(child);
}
}
}
traverse(handler.root);
return render(handler.root);
}
export const htmlRules: {
[key: string]: "*" | string[] | Function;
fn: (

8
src/types.d.ts vendored
View file

@ -1,7 +1,12 @@
import { ScramjetController } from "./bootsrapper/index";
import { encodeUrl, decodeUrl } from "./shared/rewriters/url";
import { rewriteCss } from "./shared/rewriters/css";
import { htmlRules, rewriteHtml, rewriteSrcset } from "./shared/rewriters/html";
import {
htmlRules,
rewriteHtml,
rewriteSrcset,
unrewriteHtml,
} from "./shared/rewriters/html";
import { rewriteJs } from "./shared/rewriters/js";
import { rewriteHeaders } from "./shared/rewriters/headers";
import { rewriteWorkers } from "./shared/rewriters/worker";
@ -43,6 +48,7 @@ declare global {
rewrite: {
rewriteCss: typeof rewriteCss;
rewriteHtml: typeof rewriteHtml;
unrewriteHtml: typeof unrewriteHtml;
rewriteSrcset: typeof rewriteSrcset;
rewriteJs: typeof rewriteJs;
rewriteHeaders: typeof rewriteHeaders;