Composed-tree shadow DOM capture, sized invisible spacers, track re-anchoring, block fill-width slides, javascript: href sanitization

- Walker serializes the composed (flattened) tree: open shadow roots walk
  as host children with <slot> replaced by its assigned light nodes (or
  fallback), so custom-element content (product cards, web components) is
  captured instead of arriving childless
- In-flow visibility:hidden nodes with a nonzero border box survive the
  prune as sized invisible placeholders - ghost spacers carry load-bearing
  geometry
- When pruning drops leading in-flow children of a horizontally-translated
  track, the baked translateX is re-anchored by their aggregate margin-box
  width (settled carousel tracks return to origin instead of pushing real
  content off-screen); animation-owned transforms unaffected
- Circular-shrink slide guard counts block-level fill children as
  width-deriving regardless of wAuto (block auto-width IS fill), pinning
  library-sized slide widths uniformly
- javascript: hrefs emit as "#" and the link gate normalizes both sides

382 tests pass (18 new), typecheck clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samraaj Bath
2026-07-04 02:41:00 -07:00
co-authored by Claude Fable 5
parent 6e4921884c
commit 762855664c
10 changed files with 509 additions and 13 deletions
+32
View File
@@ -11,6 +11,7 @@ import {
PACKAGE_JSON_TW,
PACKAGE_JSON_VITE,
PACKAGE_JSON_VITE_TW,
propsList,
type ComponentRegistry,
} from "../src/generate/app.js";
import { DITTO_WIRE_TSX, ACCORDION_TSX } from "../src/generate/interactive.js";
@@ -165,3 +166,34 @@ describe("lottie-web is declared when its import is emitted (fix 7)", () => {
}
});
});
// ---- FIX 5: javascript: hrefs are sanitized to an inert '#' ----
// React refuses to render a `javascript:*` href verbatim — it rewrites it to a long
// `javascript:throw new Error('React has blocked a javascript: URL…')` string that no longer matches
// the source href in the link gate. Emit an inert `#` instead (the script behaviour isn't reproduced).
describe("javascript: hrefs are emitted as an inert '#' (FIX 5)", () => {
const hrefOf = (n: IRNode): string | undefined => {
const p = propsList(n, new Map(), "https://example.test/").find(([k]) => k === "href");
return p ? JSON.parse(p[1]) : undefined;
};
it("rewrites a javascript: href to #", () => {
const a = node("n1", "a", computed());
a.attrs = { href: "Javascript:{}" };
assert.equal(hrefOf(a), "#", "a javascript: href is sanitized to #");
});
it("rewrites javascript:void(0) too (case-insensitive, with args)", () => {
const a = node("n1", "a", computed());
a.attrs = { href: "javascript:void(0)" };
assert.equal(hrefOf(a), "#");
});
it("leaves a normal in-page anchor href untouched", () => {
const a = node("n1", "a", computed());
a.attrs = { href: "#section" };
assert.equal(hrefOf(a), "#section", "a real fragment link is preserved");
});
it("leaves an ordinary external href resolved (not collapsed to #)", () => {
const a = node("n1", "a", computed());
a.attrs = { href: "https://example.test/products" };
assert.equal(hrefOf(a), "https://example.test/products");
});
});