diff --git a/packages/core/src/compiler/inlineSubCompositions.test.ts b/packages/core/src/compiler/inlineSubCompositions.test.ts
index c86583199..0b1b87898 100644
--- a/packages/core/src/compiler/inlineSubCompositions.test.ts
+++ b/packages/core/src/compiler/inlineSubCompositions.test.ts
@@ -37,6 +37,16 @@ function makeHostDocument(compId: string) {
return document;
}
+function makeAnonymousHostDocument() {
+ const { document } = parseHTML(`
+
+
+`);
+ return document;
+}
+
describe("inlineSubCompositions – #ID selector scoping divergence", () => {
it.each([
{ label: "empty", html: "" },
@@ -154,6 +164,31 @@ describe("inlineSubCompositions – #ID selector scoping divergence", () => {
expect(scopedCss).toContain('[data-hf-authored-id="intro"]');
});
+ it("preserves the inferred composition boundary for anonymous hosts", () => {
+ const document = makeAnonymousHostDocument();
+ const host = document.querySelector('[data-composition-src="intro.html"]')!;
+
+ function flattenInnerRoot(innerRoot: Element): Element {
+ const clone = innerRoot.cloneNode(true) as Element;
+ clone.removeAttribute("id");
+ clone.removeAttribute("data-composition-id");
+ clone.setAttribute("data-hf-inner-root", "true");
+ return clone;
+ }
+
+ inlineSubCompositions(document, [host], {
+ resolveHtml: () => SUB_COMP_HTML,
+ parseHtml: (html) => parseHTML(html).document,
+ flattenInnerRoot,
+ });
+
+ expect(host.getAttribute("data-composition-id")).toBeNull();
+ const inferredRoot = host.querySelector('[data-composition-id="intro"]');
+ expect(inferredRoot?.getAttribute("data-hf-inner-root")).toBe("true");
+ expect(inferredRoot?.getAttribute("id")).toBeNull();
+ expect(inferredRoot?.querySelector(".title")?.textContent).toBe("HELLO WORLD");
+ });
+
it("extracts elements from sub-composition with original rel and crossorigin", () => {
const subCompWithLinks = `
diff --git a/packages/core/src/compiler/inlineSubCompositions.ts b/packages/core/src/compiler/inlineSubCompositions.ts
index 14e8341dd..24193a0a6 100644
--- a/packages/core/src/compiler/inlineSubCompositions.ts
+++ b/packages/core/src/compiler/inlineSubCompositions.ts
@@ -357,6 +357,11 @@ export function inlineSubCompositions(
for (const child of [...innerRoot.querySelectorAll("style, script")]) child.remove();
if (flattenInnerRoot) {
const prepared = flattenInnerRoot(innerRoot);
+ if (!compId && inferredCompId) {
+ // Anonymous hosts have no outer composition id, so keep the inferred
+ // boundary on the preserved inner root after flattenInnerRoot strips it.
+ prepared.setAttribute("data-composition-id", inferredCompId);
+ }
hostEl.innerHTML = prepared.outerHTML || "";
} else {
hostEl.innerHTML = compId ? innerRoot.innerHTML || "" : innerRoot.outerHTML || "";
diff --git a/packages/producer/src/services/htmlCompiler.test.ts b/packages/producer/src/services/htmlCompiler.test.ts
index 7f5ed8c31..cf3fdf38b 100644
--- a/packages/producer/src/services/htmlCompiler.test.ts
+++ b/packages/producer/src/services/htmlCompiler.test.ts
@@ -593,13 +593,15 @@ describe("template-wrapped sub-composition media offsets", () => {
join(compositionsDir, "scene.html"),
`
-
+
Scene