mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 23:03:09 +00:00
fix: escape href in compiler link dedup + add font-link extraction tests
Escape href values in querySelector calls for link dedup in both htmlBundler.ts and htmlCompiler.ts to match the runtime path (which uses CSS.escape). Prevents SyntaxError on hrefs containing quotes. Add two tests for inlineSubCompositions font-link extraction: - Verifies <link> elements are extracted with original rel + crossorigin - Verifies dedup across multiple sub-compositions sharing the same font
This commit is contained in:
@@ -813,7 +813,8 @@ export async function bundleToSingleHtml(
|
||||
}
|
||||
|
||||
for (const link of compExternalLinks) {
|
||||
if (!document.querySelector(`link[href="${link.href}"]`)) {
|
||||
const escapedHref = link.href.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
||||
if (!document.querySelector(`link[href="${escapedHref}"]`)) {
|
||||
const linkEl = document.createElement("link");
|
||||
linkEl.setAttribute("rel", link.rel);
|
||||
linkEl.setAttribute("href", link.href);
|
||||
|
||||
@@ -131,6 +131,72 @@ describe("inlineSubCompositions – #ID selector scoping divergence", () => {
|
||||
expect(scopedCss).toContain('[data-hf-authored-id="intro"]');
|
||||
});
|
||||
|
||||
it("extracts <link> elements from sub-composition <head> with original rel and crossorigin", () => {
|
||||
const subCompWithLinks = `<!doctype html>
|
||||
<html><head>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap">
|
||||
</head><body>
|
||||
<div data-composition-id="captions" data-width="1920" data-height="1080">
|
||||
<span>Hello</span>
|
||||
</div>
|
||||
</body></html>`;
|
||||
|
||||
const document = makeHostDocument("captions");
|
||||
const host = document.querySelector('[data-composition-src="intro.html"]')!;
|
||||
|
||||
const result = inlineSubCompositions(document, [host], {
|
||||
resolveHtml: () => subCompWithLinks,
|
||||
parseHtml: (html) => parseHTML(html).document,
|
||||
});
|
||||
|
||||
expect(result.externalLinks).toHaveLength(3);
|
||||
expect(result.externalLinks[0]).toEqual({
|
||||
href: "https://fonts.googleapis.com",
|
||||
rel: "preconnect",
|
||||
crossorigin: undefined,
|
||||
});
|
||||
expect(result.externalLinks[1]).toEqual({
|
||||
href: "https://fonts.gstatic.com",
|
||||
rel: "preconnect",
|
||||
crossorigin: "",
|
||||
});
|
||||
expect(result.externalLinks[2]).toEqual({
|
||||
href: "https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap",
|
||||
rel: "stylesheet",
|
||||
crossorigin: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("deduplicates link hrefs across multiple sub-compositions", () => {
|
||||
const subComp = `<!doctype html>
|
||||
<html><head>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@800">
|
||||
</head><body>
|
||||
<div data-composition-id="cap1" data-width="1920" data-height="1080"><span>A</span></div>
|
||||
</body></html>`;
|
||||
|
||||
const { document } = parseHTML(`<!DOCTYPE html>
|
||||
<html><body>
|
||||
<div data-composition-id="main">
|
||||
<div data-composition-id="cap1" data-composition-src="cap1.html" data-start="0" data-duration="4" data-track-index="0"></div>
|
||||
<div data-composition-id="cap2" data-composition-src="cap2.html" data-start="4" data-duration="4" data-track-index="1"></div>
|
||||
</div>
|
||||
</body></html>`);
|
||||
const hosts = Array.from(document.querySelectorAll("[data-composition-src]"));
|
||||
|
||||
const result = inlineSubCompositions(document, hosts, {
|
||||
resolveHtml: () => subComp,
|
||||
parseHtml: (html) => parseHTML(html).document,
|
||||
});
|
||||
|
||||
expect(result.externalLinks).toHaveLength(1);
|
||||
expect(result.externalLinks[0]!.href).toBe(
|
||||
"https://fonts.googleapis.com/css2?family=Montserrat:wght@800",
|
||||
);
|
||||
});
|
||||
|
||||
it("producer path propagates data-hf-authored-id to host when inner root has id", () => {
|
||||
const document = makeHostDocument("intro");
|
||||
const host = document.querySelector('[data-composition-src="intro.html"]')!;
|
||||
|
||||
Reference in New Issue
Block a user