This commit is contained in:
Avad3 2024-07-14 05:16:54 -04:00
parent 555ae496a5
commit b448c5505b
20 changed files with 104 additions and 71 deletions

View file

@ -1,5 +1,5 @@
import typescript from "rollup-plugin-typescript2"; import typescript from "rollup-plugin-typescript2";
import { nodeResolve } from '@rollup/plugin-node-resolve'; import { nodeResolve } from "@rollup/plugin-node-resolve";
import { join } from "node:path"; import { join } from "node:path";
import fs from "node:fs" import fs from "node:fs"
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
@ -27,8 +27,8 @@ export default {
output: { output: {
entryFileNames: "scramjet.[name].js", entryFileNames: "scramjet.[name].js",
dir: "./dist", dir: "./dist",
format: "esm", // format: "amd",
sourcemap: true, sourcemap: true,
compact: production, compact: production
}, }
}; };

View file

@ -4,10 +4,8 @@ import { createServer } from "http";
import Fastify from "fastify"; import Fastify from "fastify";
import fastifyStatic from "@fastify/static"; import fastifyStatic from "@fastify/static";
import { join } from "node:path"; import { join } from "node:path";
import fs from "node:fs"
import { spawn } from "node:child_process" import { spawn } from "node:child_process"
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { loadConfigFile } from "rollup/loadConfigFile"
//transports //transports
import { baremuxPath } from "@mercuryworkshop/bare-mux/node" import { baremuxPath } from "@mercuryworkshop/bare-mux/node"
@ -71,7 +69,7 @@ fastify.listen({
port: process.env.PORT || 1337 port: process.env.PORT || 1337
}); });
const watch = spawn("rollup", ["-c", "-w"], { detached: true }); const watch = spawn("pnpm", ["rollup", "-c", "-w"], { detached: true, cwd: process.cwd() });
watch.stdout.on("data", (data) => { watch.stdout.on("data", (data) => {
console.log(`${data}`); console.log(`${data}`);

View file

@ -1,4 +1,4 @@
import { encodeUrl } from "../shared"; import { encodeUrl } from "./index";
navigator.sendBeacon = new Proxy(navigator.sendBeacon, { navigator.sendBeacon = new Proxy(navigator.sendBeacon, {
apply(target, thisArg, argArray) { apply(target, thisArg, argArray) {

View file

@ -1,4 +1,4 @@
import { rewriteCss } from "../shared"; import { rewriteCss } from "./index";
const cssProperties = ["background", "background-image", "mask", "mask-image", "list-style", "list-style-image", "border-image", "border-image-source", "cursor"]; const cssProperties = ["background", "background-image", "mask", "mask-image", "list-style", "list-style-image", "border-image", "border-image-source", "cursor"];
const jsProperties = ["background", "backgroundImage", "mask", "maskImage", "listStyle", "listStyleImage", "borderImage", "borderImageSource", "cursor"]; const jsProperties = ["background", "backgroundImage", "mask", "maskImage", "listStyle", "listStyleImage", "borderImage", "borderImageSource", "cursor"];

View file

@ -1,4 +1,4 @@
import { encodeUrl, rewriteCss, rewriteHtml, rewriteJs, rewriteSrcset } from "../shared"; import { encodeUrl, rewriteCss, rewriteHtml, rewriteJs, rewriteSrcset } from "./index";
const attrObject = { const attrObject = {
"nonce": [HTMLElement], "nonce": [HTMLElement],

View file

@ -1,5 +1,5 @@
import { encodeUrl } from "../shared"; import { encodeUrl } from "./index";
window.history.pushState = new Proxy(window.history.pushState, { window.history.pushState = new Proxy(window.history.pushState, {
apply(target, thisArg, argArray) { apply(target, thisArg, argArray) {

View file

@ -20,19 +20,15 @@ declare global {
} }
} }
const scripts = document.querySelectorAll("script:not([data-scramjet])"); export const {
encodeUrl,
for (const script of scripts) { decodeUrl,
const clone = document.createElement("script"); rewriteHeaders,
rewriteHtml,
for (const attr of Array.from(script.attributes)) { rewriteSrcset,
clone.setAttribute(attr.name, attr.value); rewriteJs,
} rewriteCss,
rewriteWorkers,
if (script.innerHTML !== "") { isScramjetFile,
clone.innerHTML = script.innerHTML; BareClient
} } = self.__scramjet$bundle;
script.insertAdjacentElement("afterend", clone);
script.remove();
}

View file

@ -1,18 +1,26 @@
// @ts-nocheck // @ts-nocheck
import { encodeUrl, decodeUrl } from "../shared"; import { encodeUrl, decodeUrl } from "./index";
function createLocation() {
const loc = new URL(decodeUrl(location.href)); const loc = new URL(decodeUrl(location.href));
loc.assign = (url: string) => location.assign(encodeUrl(url)); loc.assign = (url: string) => location.assign(encodeUrl(url));
loc.reload = () => location.reload(); loc.reload = () => location.reload();
loc.replace = (url: string) => location.replace(encodeUrl(url)); loc.replace = (url: string) => location.replace(encodeUrl(url));
loc.toString = () => loc.href; loc.toString = () => loc.href;
return loc;
}
export const locationProxy = new Proxy(window.location, { export const locationProxy = new Proxy(window.location, {
get(target, prop) { get(target, prop) {
const loc = createLocation();
return loc[prop]; return loc[prop];
}, },
set(obj, prop, value) { set(obj, prop, value) {
const loc = createLocation();
if (prop === "href") { if (prop === "href") {
location.href = encodeUrl(value); location.href = encodeUrl(value);
} else { } else {

View file

@ -1,4 +1,4 @@
import { rewriteJs } from "../../shared"; import { rewriteJs } from "../index";
const FunctionProxy = new Proxy(Function, { const FunctionProxy = new Proxy(Function, {
construct(target, argArray) { construct(target, argArray) {

View file

@ -1,6 +1,6 @@
// ts throws an error if you dont do window.fetch // ts throws an error if you dont do window.fetch
import { encodeUrl, rewriteHeaders } from "../../shared"; import { encodeUrl, rewriteHeaders } from "../index";
window.fetch = new Proxy(window.fetch, { window.fetch = new Proxy(window.fetch, {
apply(target, thisArg, argArray) { apply(target, thisArg, argArray) {

View file

@ -1,5 +1,6 @@
import { BareClient } from "@mercuryworkshop/bare-mux" import { BareClient } from "../index";
const client = new BareClient() const client = new BareClient();
WebSocket = new Proxy(WebSocket, { WebSocket = new Proxy(WebSocket, {
construct(target, args) { construct(target, args) {
return client.createWebSocket( return client.createWebSocket(
@ -12,4 +13,4 @@ WebSocket = new Proxy(WebSocket, {
ArrayBuffer.prototype ArrayBuffer.prototype
) )
} }
}); })

View file

@ -1,4 +1,4 @@
import { encodeUrl, rewriteHeaders } from "../../shared"; import { encodeUrl, rewriteHeaders } from "../index";
XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, { XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, {
apply(target, thisArg, argArray) { apply(target, thisArg, argArray) {

View file

@ -1,4 +1,4 @@
import { rewriteHtml, rewriteJs, encodeUrl } from "../shared"; import { rewriteHtml, rewriteJs, encodeUrl } from "./index";
// @ts-expect-error // @ts-expect-error
trustedTypes.createPolicy = new Proxy(trustedTypes.createPolicy, { trustedTypes.createPolicy = new Proxy(trustedTypes.createPolicy, {

View file

@ -1,4 +1,4 @@
import { encodeUrl } from "../shared"; import { encodeUrl } from "./index";
Worker = new Proxy(Worker, { Worker = new Proxy(Worker, {
construct(target, argArray) { construct(target, argArray) {

View file

@ -1,16 +1,38 @@
export { encodeUrl, decodeUrl } from "./rewriters/url"; import { encodeUrl, decodeUrl } from "./rewriters/url";
export { rewriteCss } from "./rewriters/css"; import { rewriteCss } from "./rewriters/css";
export { rewriteHtml, rewriteSrcset } from "./rewriters/html"; import { rewriteHtml, rewriteSrcset } from "./rewriters/html";
export { rewriteJs } from "./rewriters/js"; import { rewriteJs } from "./rewriters/js";
export { rewriteHeaders } from "./rewriters/headers"; import { rewriteHeaders } from "./rewriters/headers";
export { rewriteWorkers } from "./rewriters/worker" import { rewriteWorkers } from "./rewriters/worker";
export { BareClient } from "@mercuryworkshop/bare-mux" import { isScramjetFile } from "./rewriters/html";
import { BareClient } from "@mercuryworkshop/bare-mux";
export function isScramjetFile(src: string) { declare global {
let bool = false; interface Window {
["codecs", "client", "shared", "worker", "config"].forEach((file) => { __scramjet$bundle: {
if (src === self.__scramjet$config[file]) bool = true; encodeUrl: typeof encodeUrl;
}); decodeUrl: typeof decodeUrl;
rewriteCss: typeof rewriteCss;
return bool; rewriteHtml: typeof rewriteHtml;
rewriteSrcset: typeof rewriteSrcset;
rewriteJs: typeof rewriteJs;
rewriteHeaders: typeof rewriteHeaders;
rewriteWorkers: typeof rewriteWorkers;
BareClient: typeof BareClient;
isScramjetFile: typeof isScramjetFile
}
}
}
self.__scramjet$bundle = {
encodeUrl,
decodeUrl,
rewriteCss,
rewriteHtml,
rewriteSrcset,
rewriteJs,
rewriteHeaders,
rewriteWorkers,
isScramjetFile,
BareClient
} }

View file

@ -4,8 +4,16 @@ import { hasAttrib } from "domutils";
import render from "dom-serializer"; import render from "dom-serializer";
import { encodeUrl } from "./url"; import { encodeUrl } from "./url";
import { rewriteCss } from "./css"; import { rewriteCss } from "./css";
// import { rewriteJs } from "./js"; import { rewriteJs } from "./js";
import { isScramjetFile } from "..";
export function isScramjetFile(src: string) {
let bool = false;
["codecs", "client", "shared", "worker", "config"].forEach((file) => {
if (src === self.__scramjet$config[file]) bool = true;
});
return bool;
}
export function rewriteHtml(html: string, origin?: URL) { export function rewriteHtml(html: string, origin?: URL) {
const handler = new DomHandler((err, dom) => dom); const handler = new DomHandler((err, dom) => dom);
@ -50,7 +58,7 @@ function traverseParsedHtml(node, origin?: URL) {
if (hasAttrib(node, "style")) node.attribs.style = rewriteCss(node.attribs.style, origin); if (hasAttrib(node, "style")) node.attribs.style = rewriteCss(node.attribs.style, origin);
if (node.name === "style" && node.children[0] !== undefined) node.children[0].data = rewriteCss(node.children[0].data, origin); if (node.name === "style" && node.children[0] !== undefined) node.children[0].data = rewriteCss(node.children[0].data, origin);
// if (node.name === "script" && /(application|text)\/javascript|importmap|undefined/.test(node.attribs.type) && node.children[0] !== undefined) node.children[0].data = rewriteJs(node.children[0].data, origin); if (node.name === "script" && /(application|text)\/javascript|importmap|undefined/.test(node.attribs.type) && node.children[0] !== undefined) node.children[0].data = rewriteJs(node.children[0].data, origin);
if (node.name === "meta" && hasAttrib(node, "http-equiv")) { if (node.name === "meta" && hasAttrib(node, "http-equiv")) {
if (node.attribs["http-equiv"] === "content-security-policy") { if (node.attribs["http-equiv"] === "content-security-policy") {
node = {}; node = {};
@ -66,7 +74,6 @@ function traverseParsedHtml(node, origin?: URL) {
["codecs", "config", "shared", "client"].forEach((script) => { ["codecs", "config", "shared", "client"].forEach((script) => {
scramjetScripts.push(new Element("script", { scramjetScripts.push(new Element("script", {
src: self.__scramjet$config[script], src: self.__scramjet$config[script],
type: "module",
"data-scramjet": "" "data-scramjet": ""
})); }));
}); });

View file

@ -1,6 +1,4 @@
import { BareClient } from "@mercuryworkshop/bare-mux";
import { BareResponseFetch } from "@mercuryworkshop/bare-mux"; import { BareResponseFetch } from "@mercuryworkshop/bare-mux";
import { encodeUrl, decodeUrl, rewriteCss, rewriteHeaders, rewriteHtml, rewriteJs, rewriteWorkers } from "../shared";
declare global { declare global {
interface Window { interface Window {
@ -8,11 +6,11 @@ declare global {
} }
} }
export default class ScramjetServiceWorker { self.ScramjetServiceWorker = class ScramjetServiceWorker {
client: typeof BareClient.prototype; client: typeof self.__scramjet$bundle.BareClient.prototype;
config: typeof self.__scramjet$config; config: typeof self.__scramjet$config;
constructor(config = self.__scramjet$config) { constructor(config = self.__scramjet$config) {
this.client = new BareClient(); this.client = new self.__scramjet$bundle.BareClient();
if (!config.prefix) config.prefix = "/scramjet/"; if (!config.prefix) config.prefix = "/scramjet/";
this.config = config; this.config = config;
} }
@ -24,6 +22,7 @@ export default class ScramjetServiceWorker {
async fetch({ request }: FetchEvent) { async fetch({ request }: FetchEvent) {
const urlParam = new URLSearchParams(new URL(request.url).search); const urlParam = new URLSearchParams(new URL(request.url).search);
const { encodeUrl, decodeUrl, rewriteHeaders, rewriteHtml, rewriteJs, rewriteCss, rewriteWorkers } = self.__scramjet$bundle;
if (urlParam.has("url")) { if (urlParam.has("url")) {
return Response.redirect(encodeUrl(urlParam.get("url"), new URL(urlParam.get("url")))) return Response.redirect(encodeUrl(urlParam.get("url"), new URL(urlParam.get("url"))))

View file

@ -22,8 +22,8 @@
<body> <body>
<script src="https://unpkg.com/dreamland"></script> <script src="https://unpkg.com/dreamland"></script>
<script src="/baremux/index.js" defer></script> <script src="/baremux/index.js" defer></script>
<script src="/scram/scramjet.codecs.js" type="module"></script> <script src="/scram/scramjet.codecs.js"></script>
<script src="/scram/scramjet.config.js" type="module"></script> <script src="/scram/scramjet.config.js"></script>
<script src="ui.js" defer></script> <script src="ui.js" defer></script>
</body> </body>
</html> </html>

View file

@ -1,6 +1,9 @@
import ScramjetServiceWorker from "/scram/scramjet.worker.js"; importScripts(
import "/scram/scramjet.codecs.js"; "/scram/scramjet.codecs.js",
import "/scram/scramjet.config.js"; "/scram/scramjet.config.js",
"/scram/scramjet.shared.js",
"/scram/scramjet.worker.js"
);
const scramjet = new ScramjetServiceWorker(); const scramjet = new ScramjetServiceWorker();

View file

@ -1,6 +1,5 @@
navigator.serviceWorker.register("./sw.js", { navigator.serviceWorker.register("./sw.js", {
scope: __scramjet$config.prefix, scope: __scramjet$config.prefix
type: "module"
}) })
const connection = new BareMux.BareMuxConnection("/baremux/worker.js") const connection = new BareMux.BareMuxConnection("/baremux/worker.js")
const flex = css`display: flex;`; const flex = css`display: flex;`;