diff --git a/src/rewriter.test.ts b/src/rewriter.test.ts
index f379c4e..30f1f90 100644
--- a/src/rewriter.test.ts
+++ b/src/rewriter.test.ts
@@ -108,6 +108,19 @@ describe("HTMLRewriter integration", () => {
expect(resp.headers.get("access-control-allow-origin")).toBe("*");
});
+ it("does not double-inject CSS when both head and body exist", async () => {
+ const resp = await worker.fetch("/browse/https://httpbin.org/html");
+ if (resp.status !== 200) return;
+ const html = await resp.text();
+ const cssCount = (html.match(/text-transform: uppercase/g) || []).length;
+ expect(cssCount).toBe(1);
+ const scriptCount = (html.match(/walkAndUppercase/g) || []).length;
+ // walkAndUppercase appears multiple times within the single script (definition + calls)
+ // but should NOT appear in a second duplicate script block
+ expect(scriptCount).toBeGreaterThan(0);
+ expect(scriptCount).toBeLessThan(10);
+ });
+
it("injects resolveForProxy for relative URL handling", async () => {
const resp = await worker.fetch("/browse/https://httpbin.org/html");
if (resp.status !== 200) return;
diff --git a/src/rewriter.ts b/src/rewriter.ts
index e654b2c..d14858a 100644
--- a/src/rewriter.ts
+++ b/src/rewriter.ts
@@ -81,17 +81,18 @@ class SrcsetRewriter implements HTMLRewriterElementContentHandlers {
}
}
-class HeadInjector implements HTMLRewriterElementContentHandlers {
- constructor(private targetUrl: string) {}
+const INJECTED_CSS = ``;
+
+class ScriptAndStyleInjector implements HTMLRewriterElementContentHandlers {
+ injected = false;
element(el: Element) {
- // no