Merge pull request #918 from heygen-com/refactor/unify-subcomp-inlining

fix: hold external sub-compositions in render mode + regenerate baseline
This commit is contained in:
Miguel Ángel
2026-05-17 20:22:21 +02:00
committed by GitHub
24 changed files with 10815 additions and 4588 deletions
+25 -136
View File
@@ -7,15 +7,12 @@ import {
parseHTMLContent, parseHTMLContent,
stripEmbeddedRuntimeScripts, stripEmbeddedRuntimeScripts,
} from "./htmlDocument"; } from "./htmlDocument";
import { // rewriteSubCompPaths functions are used by inlineSubCompositions (shared module)
rewriteAssetPaths,
rewriteCssAssetUrls,
rewriteInlineStyleAssetUrls,
} from "./rewriteSubCompPaths";
import { scopeCssToComposition, wrapScopedCompositionScript } from "./compositionScoping"; import { scopeCssToComposition, wrapScopedCompositionScript } from "./compositionScoping";
import { validateHyperframeHtmlContract } from "./staticGuard"; import { validateHyperframeHtmlContract } from "./staticGuard";
import { getHyperframeRuntimeScript } from "../generated/runtime-inline"; import { getHyperframeRuntimeScript } from "../generated/runtime-inline";
import { readDeclaredDefaults } from "../runtime/getVariables"; import { readDeclaredDefaults } from "../runtime/getVariables";
import { inlineSubCompositions } from "./inlineSubCompositions";
/** Resolve a relative path within projectDir, rejecting traversal outside it. */ /** Resolve a relative path within projectDir, rejecting traversal outside it. */
function safePath(projectDir: string, relativePath: string): string | null { function safePath(projectDir: string, relativePath: string): string | null {
@@ -581,144 +578,36 @@ export async function bundleToSingleHtml(
} }
} }
// Inline sub-compositions // Inline sub-compositions (via shared function)
const compStyleChunks: string[] = [];
const compScriptChunks: string[] = [];
const compExternalScriptSrcs: string[] = [];
const compVariablesByComp: Record<string, Record<string, unknown>> = {};
const trackedCompositionHosts = getBundledTrackedCompositionHosts(document); const trackedCompositionHosts = getBundledTrackedCompositionHosts(document);
const hostIdentityByElement = assignBundledRuntimeCompositionIds(trackedCompositionHosts); const hostIdentityByElement = assignBundledRuntimeCompositionIds(trackedCompositionHosts);
const subCompositionHosts = trackedCompositionHosts.filter((host) => const subCompositionHosts = trackedCompositionHosts.filter((host) =>
host.hasAttribute("data-composition-src"), host.hasAttribute("data-composition-src"),
); );
for (const hostEl of subCompositionHosts) { const subCompResult = inlineSubCompositions(document, subCompositionHosts, {
const src = hostEl.getAttribute("data-composition-src"); resolveHtml: (srcPath: string) => {
if (!src || !isRelativeUrl(src)) continue; if (!isRelativeUrl(srcPath)) return null;
const compPath = safePath(projectDir, src); const compPath = safePath(projectDir, srcPath);
const compHtml = compPath ? safeReadFile(compPath) : null; return compPath ? safeReadFile(compPath) : null;
if (compHtml == null) {
console.warn(`[Bundler] Composition file not found: ${src}`);
continue;
}
const compDoc = parseHTMLContent(compHtml);
const hostIdentity = hostIdentityByElement.get(hostEl);
const compId = hostIdentity?.authoredCompositionId || null;
const runtimeCompId = hostIdentity?.runtimeCompositionId || compId || "";
const contentRoot = compDoc.querySelector("template");
const contentHtml = contentRoot ? contentRoot.innerHTML || "" : compDoc.body.innerHTML || "";
const contentDoc = parseHTMLContent(contentHtml);
const innerRoot = compId
? contentDoc.querySelector(`[data-composition-id="${compId}"]`)
: contentDoc.querySelector("[data-composition-id]");
const inferredCompId = innerRoot?.getAttribute("data-composition-id")?.trim() || "";
const authoredRootId = innerRoot?.getAttribute("id")?.trim() || null;
const scopeCompId = compId || inferredCompId;
const runtimeScope = runtimeCompId
? cssAttributeSelector("data-composition-id", runtimeCompId)
: "";
const mergedVariables = runtimeCompId
? {
...readDeclaredDefaults(compDoc.documentElement),
...parseHostVariableValues(hostEl),
}
: {};
if (runtimeCompId && Object.keys(mergedVariables).length > 0) {
compVariablesByComp[runtimeCompId] = mergedVariables;
}
// When a sub-composition is a full HTML document (no <template>), styles
// and scripts in <head> are not part of contentDoc (which only has body
// content). Extract them so backgrounds, positioning, fonts, and library
// scripts (e.g. GSAP CDN) are not silently dropped.
if (!contentRoot && compDoc.head) {
for (const s of [...compDoc.head.querySelectorAll("style")]) {
const css = rewriteCssAssetUrls(s.textContent || "", src);
compStyleChunks.push(
scopeCompId ? scopeCssToComposition(css, scopeCompId, runtimeScope, authoredRootId) : css,
);
}
for (const s of [...compDoc.head.querySelectorAll("script")]) {
const externalSrc = (s.getAttribute("src") || "").trim();
if (externalSrc && !compExternalScriptSrcs.includes(externalSrc)) {
compExternalScriptSrcs.push(externalSrc);
}
}
}
for (const s of [...contentDoc.querySelectorAll("style")]) {
const css = rewriteCssAssetUrls(s.textContent || "", src);
compStyleChunks.push(
scopeCompId ? scopeCssToComposition(css, scopeCompId, runtimeScope, authoredRootId) : css,
);
s.remove();
}
for (const s of [...contentDoc.querySelectorAll("script")]) {
const externalSrc = (s.getAttribute("src") || "").trim();
if (externalSrc) {
// External CDN/remote script — collect for deduped injection into the document.
// Do NOT try to inline the content (external scripts have no innerHTML).
if (!compExternalScriptSrcs.includes(externalSrc)) {
compExternalScriptSrcs.push(externalSrc);
}
} else {
compScriptChunks.push(
scopeCompId
? wrapScopedCompositionScript(
s.textContent || "",
scopeCompId,
"[HyperFrames] composition script error:",
runtimeScope,
runtimeCompId || scopeCompId,
authoredRootId,
)
: `(function(){ try { ${s.textContent || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`,
);
}
s.remove();
}
// Rewrite relative asset paths before inlining so ../foo.svg from
// compositions/ resolves correctly when the content moves to root.
const assetEls = innerRoot
? innerRoot.querySelectorAll("[src], [href]")
: contentDoc.querySelectorAll("[src], [href]");
rewriteAssetPaths(
assetEls,
src,
(el: Element, attr: string) => el.getAttribute(attr),
(el: Element, attr: string, val: string) => {
el.setAttribute(attr, val);
}, },
); parseHtml: parseHTMLContent,
const styledEls = innerRoot hostIdentityMap: hostIdentityByElement,
? innerRoot.querySelectorAll("[style]") rewriteInlineStyles: true,
: contentDoc.querySelectorAll("[style]"); flattenInnerRoot: prepareFlattenedInnerRoot,
rewriteInlineStyleAssetUrls( readVariableDefaults: readDeclaredDefaults,
styledEls, parseHostVariables: parseHostVariableValues,
src, buildScopeSelector: (compId: string) => cssAttributeSelector("data-composition-id", compId),
(el: Element) => el.getAttribute("style"), scriptErrorLabel: "[HyperFrames] composition script error:",
(el: Element, val: string) => { onMissingComposition: (srcPath: string) => {
el.setAttribute("style", val); console.warn(`[Bundler] Composition file not found: ${srcPath}`);
}, },
); });
const compStyleChunks: string[] = [...subCompResult.styles];
if (innerRoot) { const compScriptChunks: string[] = [...subCompResult.scripts];
const innerW = innerRoot.getAttribute("data-width"); const compExternalScriptSrcs: string[] = [...subCompResult.externalScriptSrcs];
const innerH = innerRoot.getAttribute("data-height"); const compVariablesByComp: Record<string, Record<string, unknown>> = {
if (innerW && !hostEl.getAttribute("data-width")) hostEl.setAttribute("data-width", innerW); ...subCompResult.variablesByComp,
if (innerH && !hostEl.getAttribute("data-height")) hostEl.setAttribute("data-height", innerH); };
innerRoot.setAttribute("data-composition-file", src);
for (const child of [...innerRoot.querySelectorAll("style, script")]) child.remove();
const preparedInnerRoot = prepareFlattenedInnerRoot(innerRoot);
hostEl.innerHTML = preparedInnerRoot.outerHTML || "";
} else {
for (const child of [...contentDoc.querySelectorAll("style, script")]) child.remove();
hostEl.innerHTML = contentDoc.body.innerHTML || "";
}
hostEl.setAttribute("data-composition-file", src);
hostEl.removeAttribute("data-composition-src");
}
// Inline template compositions: inject <template id="X-template"> content into // Inline template compositions: inject <template id="X-template"> content into
// matching empty host elements with data-composition-id="X" (no data-composition-src) // matching empty host elements with data-composition-id="X" (no data-composition-src)
+7
View File
@@ -34,3 +34,10 @@ export {
// Composition isolation helpers // Composition isolation helpers
export { scopeCssToComposition, wrapScopedCompositionScript } from "./compositionScoping"; export { scopeCssToComposition, wrapScopedCompositionScript } from "./compositionScoping";
// Sub-composition inlining (shared between bundler and producer)
export {
inlineSubCompositions,
type InlineSubCompositionsOptions,
type InlineSubCompositionsResult,
} from "./inlineSubCompositions";
@@ -0,0 +1,323 @@
/**
* Shared sub-composition inlining logic.
*
* Both the core bundler (preview) and the producer compiler (render) need to
* inline sub-composition HTML referenced via `data-composition-src`. This
* module is the single source of truth for that transformation, eliminating
* divergence that previously caused bugs (e.g. producer not setting
* `data-composition-file`).
*/
import {
rewriteAssetPaths,
rewriteCssAssetUrls,
rewriteInlineStyleAssetUrls,
} from "./rewriteSubCompPaths";
import { scopeCssToComposition, wrapScopedCompositionScript } from "./compositionScoping";
// ---------------------------------------------------------------------------
// Public interface
// ---------------------------------------------------------------------------
export interface InlineSubCompositionsOptions {
/**
* Resolve the HTML content for a sub-composition given its `data-composition-src` value.
* Return `null` when the file cannot be found.
*/
resolveHtml: (srcPath: string) => string | null;
/**
* Parse an HTML string into a Document. The returned object must expose
* standard DOM APIs (querySelector, querySelectorAll, body, head, etc.).
* Both linkedom's `parseHTML(...).document` and the core bundler's
* `parseHTMLContent(...)` satisfy this contract.
*/
parseHtml: (html: string) => Document;
/**
* Identity map produced by `assignBundledRuntimeCompositionIds`.
* When provided, authoredCompositionId and runtimeCompositionId are read
* from this map instead of from the host element's attributes directly.
* The bundler uses this; the producer can omit it.
*/
hostIdentityMap?: Map<
Element,
{ authoredCompositionId: string | null; runtimeCompositionId: string | null }
>;
/**
* When true, rewrite `url(...)` references in inline `style` attributes
* on sub-composition elements. The bundler enables this; the producer
* can skip it.
*/
rewriteInlineStyles?: boolean;
/**
* Prepare the inner root element before injecting it into the host.
* The bundler's `prepareFlattenedInnerRoot` clones the element, strips
* timing attributes, and adds `data-hf-inner-root`. When omitted, the
* inner root's outerHTML is injected as-is.
*/
flattenInnerRoot?: (innerRoot: Element) => Element;
/**
* Read declared variable defaults from a sub-composition's `<html>` element.
* The bundler passes `readDeclaredDefaults`; the producer can omit this.
*/
readVariableDefaults?: (docElement: Element) => Record<string, unknown>;
/**
* Parse host-level variable overrides from `data-variable-values`.
* The bundler passes `parseHostVariableValues`; the producer can omit this.
*/
parseHostVariables?: (host: Element) => Record<string, unknown>;
/**
* Build a CSS attribute selector for scoping, e.g.
* `[data-composition-id="my-comp"]`. Defaults to a simple implementation
* when not provided. The bundler passes `cssAttributeSelector` which
* handles escaping.
*/
buildScopeSelector?: (compId: string) => string;
/**
* Error label prefix used in wrapped composition scripts.
* Defaults to `"[HyperFrames] composition script error:"`.
*/
scriptErrorLabel?: string;
/**
* Log a warning when a composition file cannot be resolved.
* Defaults to `console.warn`.
*/
onMissingComposition?: (srcPath: string) => void;
}
export interface InlineSubCompositionsResult {
styles: string[];
scripts: string[];
externalScriptSrcs: string[];
variablesByComp: Record<string, Record<string, unknown>>;
}
// ---------------------------------------------------------------------------
// Default helpers
// ---------------------------------------------------------------------------
function defaultBuildScopeSelector(compId: string): string {
const escaped = compId.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
return `[data-composition-id="${escaped}"]`;
}
// ---------------------------------------------------------------------------
// Core implementation
// ---------------------------------------------------------------------------
/**
* Inline sub-compositions into a document. For each host element in `hosts`:
*
* 1. Resolve the sub-composition HTML via `options.resolveHtml`
* 2. Parse it, find `<template>` or `<body>` content
* 3. Find the inner `[data-composition-id]` root
* 4. Extract `<style>` elements, scope CSS, collect them
* 5. Extract `<script>` elements, wrap inline scripts, collect them
* 6. Collect external script `src` URLs for deduplication
* 7. Rewrite asset paths (and optionally inline-style asset URLs)
* 8. Copy dimension attrs from inner root to host if missing
* 9. Set `data-composition-file` on host
* 10. Remove `data-composition-src` from host
* 11. Inject the content into the host element
*/
export function inlineSubCompositions(
document: Document,
hosts: Element[],
options: InlineSubCompositionsOptions,
): InlineSubCompositionsResult {
const {
resolveHtml,
parseHtml,
hostIdentityMap,
rewriteInlineStyles = false,
flattenInnerRoot,
readVariableDefaults,
parseHostVariables,
buildScopeSelector = defaultBuildScopeSelector,
scriptErrorLabel = "[HyperFrames] composition script error:",
onMissingComposition,
} = options;
const styles: string[] = [];
const scripts: string[] = [];
const externalScriptSrcs: string[] = [];
const variablesByComp: Record<string, Record<string, unknown>> = {};
for (const hostEl of hosts) {
const src = hostEl.getAttribute("data-composition-src");
if (!src) continue;
const compHtml = resolveHtml(src);
if (compHtml == null) {
if (onMissingComposition) {
onMissingComposition(src);
}
continue;
}
const compDoc = parseHtml(compHtml);
// Determine composition IDs
let compId: string | null;
let runtimeCompId: string;
if (hostIdentityMap) {
const identity = hostIdentityMap.get(hostEl);
compId = identity?.authoredCompositionId || null;
runtimeCompId = identity?.runtimeCompositionId || compId || "";
} else {
compId = hostEl.getAttribute("data-composition-id") || null;
runtimeCompId = compId || "";
}
// Find content: prefer <template>, fall back to <body>
const contentRoot = compDoc.querySelector("template");
const contentHtml = contentRoot ? contentRoot.innerHTML || "" : compDoc.body?.innerHTML || "";
const contentDoc = parseHtml(contentHtml);
// Find the inner composition root
const innerRoot = compId
? contentDoc.querySelector(`[data-composition-id="${compId}"]`)
: contentDoc.querySelector("[data-composition-id]");
const inferredCompId = innerRoot?.getAttribute("data-composition-id")?.trim() || "";
const authoredRootId = innerRoot?.getAttribute("id")?.trim() || null;
const scopeCompId = compId || inferredCompId;
const runtimeScope = runtimeCompId ? buildScopeSelector(runtimeCompId) : "";
// Variable merging (bundler feature)
if (readVariableDefaults && parseHostVariables && runtimeCompId) {
const mergedVariables = {
...readVariableDefaults(compDoc.documentElement),
...parseHostVariables(hostEl),
};
if (Object.keys(mergedVariables).length > 0) {
variablesByComp[runtimeCompId] = mergedVariables;
}
}
// When a sub-composition is a full HTML document (no <template>), styles
// and scripts in <head> are not part of contentDoc (which only has body
// content). Extract them so backgrounds, positioning, fonts, and library
// scripts (e.g. GSAP CDN) are not silently dropped.
if (!contentRoot && compDoc.head) {
for (const s of [...compDoc.head.querySelectorAll("style")]) {
const css = rewriteCssAssetUrls(s.textContent || "", src);
styles.push(
scopeCompId
? scopeCssToComposition(css, scopeCompId, runtimeScope || undefined, authoredRootId)
: css,
);
}
for (const s of [...compDoc.head.querySelectorAll("script")]) {
const externalSrc = (s.getAttribute("src") || "").trim();
if (externalSrc && !externalScriptSrcs.includes(externalSrc)) {
externalScriptSrcs.push(externalSrc);
}
}
}
// Extract styles from content
for (const s of [...contentDoc.querySelectorAll("style")]) {
const css = rewriteCssAssetUrls(s.textContent || "", src);
styles.push(
scopeCompId
? scopeCssToComposition(css, scopeCompId, runtimeScope || undefined, authoredRootId)
: css,
);
s.remove();
}
// Extract scripts from content
for (const s of [...contentDoc.querySelectorAll("script")]) {
const externalSrc = (s.getAttribute("src") || "").trim();
if (externalSrc) {
if (!externalScriptSrcs.includes(externalSrc)) {
externalScriptSrcs.push(externalSrc);
}
} else {
scripts.push(
scopeCompId
? wrapScopedCompositionScript(
s.textContent || "",
scopeCompId,
scriptErrorLabel,
runtimeScope || undefined,
runtimeCompId || scopeCompId,
authoredRootId,
)
: `(function(){ try { ${s.textContent || ""} } catch (_err) { console.error(${JSON.stringify(scriptErrorLabel)}, _err); } })();`,
);
}
s.remove();
}
// Rewrite relative asset paths before inlining so ../foo.svg from
// compositions/ resolves correctly when the content moves to root.
const assetEls = innerRoot
? innerRoot.querySelectorAll("[src], [href]")
: contentDoc.querySelectorAll("[src], [href]");
rewriteAssetPaths(
assetEls,
src,
(el: Element, attr: string) => el.getAttribute(attr),
(el: Element, attr: string, val: string) => {
el.setAttribute(attr, val);
},
);
if (rewriteInlineStyles) {
const styledEls = innerRoot
? innerRoot.querySelectorAll("[style]")
: contentDoc.querySelectorAll("[style]");
rewriteInlineStyleAssetUrls(
styledEls,
src,
(el: Element) => el.getAttribute("style"),
(el: Element, val: string) => {
el.setAttribute("style", val);
},
);
}
// Copy dimension attributes from inner root to host if missing
if (innerRoot) {
const innerW = innerRoot.getAttribute("data-width");
const innerH = innerRoot.getAttribute("data-height");
if (innerW && !hostEl.getAttribute("data-width")) hostEl.setAttribute("data-width", innerW);
if (innerH && !hostEl.getAttribute("data-height")) {
hostEl.setAttribute("data-height", innerH);
}
}
// Inject content into the host element
if (innerRoot) {
innerRoot.setAttribute("data-composition-file", src);
for (const child of [...innerRoot.querySelectorAll("style, script")]) child.remove();
if (flattenInnerRoot) {
const prepared = flattenInnerRoot(innerRoot);
hostEl.innerHTML = prepared.outerHTML || "";
} else {
hostEl.innerHTML = compId ? innerRoot.innerHTML || "" : innerRoot.outerHTML || "";
}
} else {
for (const child of [...contentDoc.querySelectorAll("style, script")]) child.remove();
// linkedom fragment parsing: when content is `<div data-composition-id="X">...</div>`,
// the div becomes documentElement and body is empty. Fall back to documentElement.outerHTML
// to preserve the composition wrapper.
const bodyHtml = contentDoc.body?.innerHTML || "";
hostEl.innerHTML = bodyHtml || contentDoc.documentElement?.outerHTML || "";
}
hostEl.setAttribute("data-composition-file", src);
hostEl.removeAttribute("data-composition-src");
}
return { styles, scripts, externalScriptSrcs, variablesByComp };
}
+30 -141
View File
@@ -20,10 +20,8 @@ import {
shouldClampMediaDuration, shouldClampMediaDuration,
type ResolvedDuration, type ResolvedDuration,
type UnresolvedElement, type UnresolvedElement,
rewriteAssetPaths,
rewriteCssAssetUrls,
} from "@hyperframes/core"; } from "@hyperframes/core";
import { scopeCssToComposition, wrapScopedCompositionScript } from "@hyperframes/core/compiler"; import { inlineSubCompositions as inlineSubCompositionsShared } from "@hyperframes/core/compiler";
import { extractMediaMetadata, extractAudioMetadata } from "../utils/ffprobe.js"; import { extractMediaMetadata, extractAudioMetadata } from "../utils/ffprobe.js";
import { isPathInside, toExternalAssetKey } from "../utils/paths.js"; import { isPathInside, toExternalAssetKey } from "../utils/paths.js";
import { import {
@@ -543,13 +541,11 @@ function coalesceHeadStylesAndBodyScripts(html: string): string {
} }
/** /**
* Inline sub-composition HTML into the main document, mirroring what the * Inline sub-composition HTML into the main document using the shared
* bundler's step 6 does. For each host element with `data-composition-src`: * inlining logic from @hyperframes/core. This wrapper handles the
* - Resolve the composition HTML from the pre-compiled map or disk * producer-specific concerns: parsing HTML via linkedom, resolving
* - Extract <template> (or <body>) content * compositions from the pre-compiled map or disk, and setting explicit
* - Move composition <style> to <head>, <script> to end of <body> * pixel dimensions on host elements for headless rendering.
* - Replace host innerHTML with composition children
* - Remove data-composition-src so the runtime skips async fetching
*/ */
function inlineSubCompositions( function inlineSubCompositions(
html: string, html: string,
@@ -559,18 +555,15 @@ function inlineSubCompositions(
const { document } = parseHTML(html); const { document } = parseHTML(html);
const head = document.querySelector("head"); const head = document.querySelector("head");
const body = document.querySelector("body"); const body = document.querySelector("body");
const hosts = document.querySelectorAll("[data-composition-src]"); const hosts = Array.from(document.querySelectorAll("[data-composition-src]"));
if (!hosts.length) return html; if (!hosts.length) return html;
const collectedStyles: string[] = []; const result = inlineSubCompositionsShared(
const collectedScripts: string[] = []; document as unknown as Document,
const collectedExternalScriptSrcs: string[] = []; hosts as unknown as Element[],
{
for (const host of hosts) { resolveHtml: (srcPath: string) => {
const srcPath = host.getAttribute("data-composition-src");
if (!srcPath) continue;
let compHtml = subCompositions.get(srcPath) || null; let compHtml = subCompositions.get(srcPath) || null;
if (!compHtml) { if (!compHtml) {
const filePath = resolve(projectDir, srcPath); const filePath = resolve(projectDir, srcPath);
@@ -578,123 +571,17 @@ function inlineSubCompositions(
compHtml = readFileSync(filePath, "utf-8"); compHtml = readFileSync(filePath, "utf-8");
} }
} }
if (!compHtml) { return compHtml;
continue; },
} parseHtml: (htmlStr: string) => parseHTML(htmlStr).document as unknown as Document,
scriptErrorLabel: "[Compiler] Composition script failed",
const compDoc = parseHTML(compHtml).document; },
const compId = host.getAttribute("data-composition-id");
const templateEl = compDoc.querySelector("template");
const bodyEl = compDoc.querySelector("body");
const contentHtml = templateEl
? templateEl.innerHTML || ""
: bodyEl
? bodyEl.innerHTML || ""
: compDoc.toString();
const contentDoc = parseHTML(contentHtml).document;
const innerRoot = compId
? contentDoc.querySelector(`[data-composition-id="${compId}"]`)
: contentDoc.querySelector("[data-composition-id]");
const inferredCompId = innerRoot?.getAttribute("data-composition-id")?.trim() || null;
// When a sub-composition is a full HTML document (no <template>), styles
// and scripts in <head> are not part of contentDoc (which only has body
// content). Extract them separately so backgrounds, positioning, fonts,
// and library scripts (e.g. GSAP CDN) are not silently dropped.
if (!templateEl) {
const compHead = compDoc.querySelector("head");
if (compHead) {
for (const styleEl of compHead.querySelectorAll("style")) {
const css = rewriteCssAssetUrls(styleEl.textContent || "", srcPath);
const scopeId = compId || inferredCompId;
if (scopeId && css.trim()) {
collectedStyles.push(scopeCssToComposition(css, scopeId));
} else {
collectedStyles.push(css);
}
}
for (const scriptEl of compHead.querySelectorAll("script")) {
const src = (scriptEl.getAttribute("src") || "").trim();
if (src && !collectedExternalScriptSrcs.includes(src)) {
collectedExternalScriptSrcs.push(src);
}
}
}
}
for (const styleEl of contentDoc.querySelectorAll("style")) {
const css = rewriteCssAssetUrls(styleEl.textContent || "", srcPath);
const scopeId = compId || inferredCompId;
if (scopeId && css.trim()) {
// Scope sub-composition styles to their composition ID to prevent
// CSS class collisions when multiple compositions use the same
// class names (e.g. ".content"). This matches preview behavior
// where each composition's styles are naturally scoped.
collectedStyles.push(scopeCssToComposition(css, scopeId));
} else {
collectedStyles.push(css);
}
styleEl.remove();
}
for (const scriptEl of contentDoc.querySelectorAll("script")) {
const src = (scriptEl.getAttribute("src") || "").trim();
if (src) {
// External CDN/remote script — collect for deduped injection into the
// parent document, mirroring the bundler's hoisting behavior.
if (!collectedExternalScriptSrcs.includes(src)) {
collectedExternalScriptSrcs.push(src);
}
scriptEl.remove();
continue;
}
const content = (scriptEl.textContent || "").trim();
if (content) {
const scriptMountCompId = compId || inferredCompId || "";
collectedScripts.push(
scriptMountCompId
? wrapScopedCompositionScript(
content,
scriptMountCompId,
"[Compiler] Composition script failed",
)
: `(function(){ try { ${content} } catch (_err) { console.error("[Compiler] Composition script failed", _err); } })()`,
);
}
scriptEl.remove();
}
// Rewrite relative asset paths before inlining so ../foo.svg from
// compositions/ resolves correctly when the content moves to root.
const rewriteTarget = innerRoot || contentDoc;
rewriteAssetPaths(
rewriteTarget.querySelectorAll("[src], [href]"),
srcPath,
(el, attr) => (el.getAttribute(attr) || "").trim(),
(el, attr, val) => el.setAttribute(attr, val),
); );
if (innerRoot) { // Producer-specific: set explicit pixel dimensions on host elements so
const innerW = innerRoot.getAttribute("data-width"); // children using width/height: 100% resolve correctly. The runtime does
const innerH = innerRoot.getAttribute("data-height"); // this automatically but compiled HTML needs it inline.
if (innerW && !host.getAttribute("data-width")) host.setAttribute("data-width", innerW); for (const host of hosts) {
if (innerH && !host.getAttribute("data-height")) host.setAttribute("data-height", innerH);
innerRoot.querySelectorAll("style, script").forEach((el) => el.remove());
host.innerHTML = compId ? innerRoot.innerHTML || "" : innerRoot.outerHTML || "";
} else {
contentDoc.querySelectorAll("style, script").forEach((el) => el.remove());
host.innerHTML = contentDoc.toString();
}
host.setAttribute("data-composition-file", srcPath);
host.removeAttribute("data-composition-src");
// Set explicit pixel dimensions on the host element so children using
// width/height: 100% resolve correctly. The runtime does this
// automatically but compiled HTML needs it inline.
const hostW = host.getAttribute("data-width"); const hostW = host.getAttribute("data-width");
const hostH = host.getAttribute("data-height"); const hostH = host.getAttribute("data-height");
if (hostW && hostH) { if (hostW && hostH) {
@@ -713,22 +600,23 @@ function inlineSubCompositions(
} }
} }
if (collectedStyles.length && head) { // Append collected styles to <head>
if (result.styles.length && head) {
const styleEl = document.createElement("style"); const styleEl = document.createElement("style");
styleEl.textContent = collectedStyles.join("\n\n"); styleEl.textContent = result.styles.join("\n\n");
head.appendChild(styleEl); head.appendChild(styleEl);
} }
// Inject external CDN scripts before inline scripts so plugins (e.g. // Inject external CDN scripts before inline scripts so plugins (e.g.
// TextPlugin, ScrollTrigger) are registered before composition code runs. // TextPlugin, ScrollTrigger) are registered before composition code runs.
// Deduplicate against scripts already present in the document. // Deduplicate against scripts already present in the document.
if (collectedExternalScriptSrcs.length && body) { if (result.externalScriptSrcs.length && body) {
const existingScriptSrcs = new Set( const existingScriptSrcs = new Set(
Array.from(document.querySelectorAll("script[src]")).map((el) => Array.from(document.querySelectorAll("script[src]")).map((el: Element) =>
(el.getAttribute("src") || "").trim(), (el.getAttribute("src") || "").trim(),
), ),
); );
for (const src of collectedExternalScriptSrcs) { for (const src of result.externalScriptSrcs) {
if (!existingScriptSrcs.has(src)) { if (!existingScriptSrcs.has(src)) {
const scriptEl = document.createElement("script"); const scriptEl = document.createElement("script");
scriptEl.setAttribute("src", src); scriptEl.setAttribute("src", src);
@@ -738,9 +626,10 @@ function inlineSubCompositions(
} }
} }
if (collectedScripts.length && body) { // Append collected inline scripts to <body>
if (result.scripts.length && body) {
const scriptEl = document.createElement("script"); const scriptEl = document.createElement("script");
scriptEl.textContent = collectedScripts.join("\n;\n"); scriptEl.textContent = result.scripts.join("\n;\n");
body.appendChild(scriptEl); body.appendChild(scriptEl);
} }
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:324369f32516e8408fd11bf3e1644d3fc25a024cea3f2483a932621c4e264293 oid sha256:6b1a1f0e54d8196829e1dd6d4a0ef128747f98a76c50755bbb8150b792ee5b64
size 450917 size 689794
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:936aff6bdaf542f3fa6311288e056def65bfdba420ed9577243e203da954fb7e oid sha256:d7a67603547c49da6f75e967afbdc5f849aed3323658ae0ad4d45fc5dfad2eeb
size 18979575 size 22330971
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f5e7d82a72a22b19ecda914727c0bb45453e213865f7d44ba88bd328053eded7 oid sha256:fa7e5d324d183f9edbab0a428954428fa204dc53dd08615237d7994cdb265998
size 7614486 size 12322028
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:701ec3b1ece40ca89d8b1836b10f8a02f2ed5c442f99c059c62dd86fa66003b5 oid sha256:abe913663b03ac7ea0d47427e38fc26b0afde872a91444636a7299c1168fc2ee
size 10757091 size 17106658
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:d260f106a6ad907a2b4d07b78e8e8d4b286eea3f8650be9d8a6b4674c194e64c oid sha256:5bc77b1c42ebaf496bcff565bd334bd67ae1e2fc44f685d1d41c840a57f810df
size 6114459 size 15232127
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:798f6756d8c07f5b0a44f7c861fcf051c6a043f03ec13e71249bd5ae8175d98a oid sha256:20f1d8f5824520f55369794c6674717c230f5ceacc05222f06080bd555ccc1f7
size 3900890 size 7198724
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ed6c28c61ca54c7b45229eb7fe6222ab5aef34cd2132a285d7a4e164319127b9 oid sha256:f1c6af0c1460f17cfe8c28b1813d2d28807c3c848ea313c49b2f54f498ffb3bd
size 6704037 size 11365418
@@ -358,7 +358,7 @@
</div> </div>
<!-- Compositions --> <!-- Compositions -->
<div style="width:1920px;height:1080px" id="intro-comp" data-composition-id="intro" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="100"> <div style="width:1920px;height:1080px" data-composition-file="compositions/intro.html" id="intro-comp" data-composition-id="intro" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="100">
<div class="intro-container"> <div class="intro-container">
<h1 class="title">EDITOR AGENT</h1> <h1 class="title">EDITOR AGENT</h1>
</div> </div>
@@ -367,14 +367,14 @@
</div> </div>
<div style="width:1920px;height:1080px" id="captions-comp" data-composition-id="captions" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="200"> <div style="width:1920px;height:1080px" data-composition-file="compositions/captions.html" id="captions-comp" data-composition-id="captions" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="200">
<div id="captions-container"></div> <div id="captions-container"></div>
</div> </div>
<div style="width:1920px;height:1080px" id="stats-comp" data-composition-id="stats" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="150"> <div style="width:1920px;height:1080px" data-composition-file="compositions/stats.html" id="stats-comp" data-composition-id="stats" data-start="0" data-duration="16.04" data-width="1920" data-height="1080" data-track-index="150">
<div id="stats-container"> <div id="stats-container">
<!-- Moment 1: 47% NEED MOTION GRAPHICS --> <!-- Moment 1: 47% NEED MOTION GRAPHICS -->
<div id="moment-1" class="moment" style="opacity: 0; transform: scale(0) rotate(8deg)"> <div id="moment-1" class="moment" style="opacity: 0; transform: scale(0) rotate(8deg)">
@@ -476,20 +476,87 @@ window.__timelines = window.__timelines || {};
var __hfCompId = "intro"; var __hfCompId = "intro";
var __hfTimelineCompId = "intro"; var __hfTimelineCompId = "intro";
var __hfErrorLabel = "[Compiler] Composition script failed"; var __hfErrorLabel = "[Compiler] Composition script failed";
var __hfAuthoredRootId = "intro-comp";
var __hfAuthoredRootAttr = "data-hf-authored-id";
var __hfEscapeAttr = function(value) { var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\""); return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
}; };
var __hfRootSelector = null || (__hfCompId var __hfRootSelector = "[data-composition-id=\"intro\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]' ? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: ""); : "");
var __hfRoot = null; var __hfRoot = null;
var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"intro\"|'intro')\\s*\\]"; var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"intro\"|'intro')\\s*\\]";
var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]"; var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]";
var __hfAuthoredRootIdForms = ["intro-comp"];
var __hfAuthoredRootSelector = __hfAuthoredRootId
? "[" + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(__hfAuthoredRootId) + '"]'
: "";
var __hfIsSelectorNameChar = function(char) {
return !!char && /[\w-]/.test(char);
};
var __hfReplaceAuthoredRootIdSelectors = function(selector) {
if (!__hfAuthoredRootSelector || !__hfAuthoredRootIdForms.length || typeof selector !== "string") {
return selector;
}
var result = "";
var bracketDepth = 0;
var quote = null;
for (var index = 0; index < selector.length; index += 1) {
var char = selector[index];
var previousChar = index > 0 ? selector[index - 1] : "";
if (quote) {
result += char;
if (char === quote && previousChar !== "\\") {
quote = null;
}
continue;
}
if (char === '"' || char === "'") {
quote = char;
result += char;
continue;
}
if (char === "[") {
bracketDepth += 1;
result += char;
continue;
}
if (char === "]") {
bracketDepth = Math.max(0, bracketDepth - 1);
result += char;
continue;
}
if (char === "#" && bracketDepth === 0) {
var matchedForm = null;
for (var formIndex = 0; formIndex < __hfAuthoredRootIdForms.length; formIndex += 1) {
var form = __hfAuthoredRootIdForms[formIndex];
if (selector.slice(index + 1, index + 1 + form.length) === form) {
matchedForm = form;
break;
}
}
if (matchedForm) {
var nextChar = selector[index + 1 + matchedForm.length];
if (!__hfIsSelectorNameChar(nextChar)) {
result += __hfAuthoredRootSelector;
index += matchedForm.length;
continue;
}
}
}
result += char;
}
return result;
};
var __hfNormalizeSelector = function(selector) { var __hfNormalizeSelector = function(selector) {
if (!__hfCompId || typeof selector !== "string") return selector; if (!__hfCompId || typeof selector !== "string") return selector;
return selector var normalized = selector
.replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector) .replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector)
.replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector); .replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector);
if (__hfAuthoredRootSelector) {
normalized = __hfReplaceAuthoredRootIdSelectors(normalized);
}
return normalized;
}; };
var __hfFindRoot = function() { var __hfFindRoot = function() {
if (!__hfRoot && __hfRootSelector) { if (!__hfRoot && __hfRootSelector) {
@@ -520,8 +587,15 @@ window.__timelines = window.__timelines || {};
var root = __hfFindRoot(); var root = __hfFindRoot();
if (!root) return found || null; if (!root) return found || null;
var idValue = id + ""; var idValue = id + "";
if (__hfAuthoredRootId && __hfAuthoredRootId === idValue && root.getAttribute && root.getAttribute(__hfAuthoredRootAttr) === idValue) {
return root;
}
if (root.id === idValue) return root; if (root.id === idValue) return root;
if (typeof root.querySelector !== "function") return null; if (typeof root.querySelector !== "function") return null;
try {
var authoredRootMatch = root.querySelector('[' + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(idValue) + '"]');
if (authoredRootMatch) return authoredRootMatch;
} catch {}
if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") { if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") {
try { try {
return root.querySelector("#" + CSS.escape(idValue)) || null; return root.querySelector("#" + CSS.escape(idValue)) || null;
@@ -638,7 +712,12 @@ window.__timelines = window.__timelines || {};
var root = baseEl || __hfFindRoot(); var root = baseEl || __hfFindRoot();
return function(selector) { return function(selector) {
if (!root || typeof selector !== "string") return []; if (!root || typeof selector !== "string") return [];
return Array.prototype.slice.call(root.querySelectorAll(selector)); return Array.prototype.filter.call(
window.document.querySelectorAll(__hfNormalizeSelector(selector)),
function(node) {
return node === root || (typeof root.contains === "function" && root.contains(node));
},
);
}; };
}; };
} }
@@ -657,13 +736,14 @@ window.__timelines = window.__timelines || {};
: Object.assign({}, __hfBaseHyperframes, { : Object.assign({}, __hfBaseHyperframes, {
getVariables: function() { getVariables: function() {
var byComp = window.__hfVariablesByComp; var byComp = window.__hfVariablesByComp;
var scoped = byComp && __hfCompId ? byComp[__hfCompId] : null; var scoped = byComp && __hfTimelineCompId ? byComp[__hfTimelineCompId] : null;
return scoped ? Object.assign({}, scoped) : {}; return scoped ? Object.assign({}, scoped) : {};
}, },
}); });
var __hfRun = function() { var __hfRun = function() {
try { try {
(function(document, gsap, window, __hyperframes) { (function(document, gsap, window, __hyperframes) {
(function () { (function () {
const tl = gsap.timeline({ paused: true }); const tl = gsap.timeline({ paused: true });
@@ -725,6 +805,7 @@ window.__timelines = window.__timelines || {};
window.__timelines["intro"] = tl; window.__timelines["intro"] = tl;
})(); })();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes); }).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) { } catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err); console.error(__hfErrorLabel, __hfCompId, _err);
@@ -738,20 +819,87 @@ window.__timelines = window.__timelines || {};
var __hfCompId = "captions"; var __hfCompId = "captions";
var __hfTimelineCompId = "captions"; var __hfTimelineCompId = "captions";
var __hfErrorLabel = "[Compiler] Composition script failed"; var __hfErrorLabel = "[Compiler] Composition script failed";
var __hfAuthoredRootId = null;
var __hfAuthoredRootAttr = "data-hf-authored-id";
var __hfEscapeAttr = function(value) { var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\""); return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
}; };
var __hfRootSelector = null || (__hfCompId var __hfRootSelector = "[data-composition-id=\"captions\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]' ? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: ""); : "");
var __hfRoot = null; var __hfRoot = null;
var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"captions\"|'captions')\\s*\\]"; var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"captions\"|'captions')\\s*\\]";
var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]"; var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]";
var __hfAuthoredRootIdForms = [];
var __hfAuthoredRootSelector = __hfAuthoredRootId
? "[" + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(__hfAuthoredRootId) + '"]'
: "";
var __hfIsSelectorNameChar = function(char) {
return !!char && /[\w-]/.test(char);
};
var __hfReplaceAuthoredRootIdSelectors = function(selector) {
if (!__hfAuthoredRootSelector || !__hfAuthoredRootIdForms.length || typeof selector !== "string") {
return selector;
}
var result = "";
var bracketDepth = 0;
var quote = null;
for (var index = 0; index < selector.length; index += 1) {
var char = selector[index];
var previousChar = index > 0 ? selector[index - 1] : "";
if (quote) {
result += char;
if (char === quote && previousChar !== "\\") {
quote = null;
}
continue;
}
if (char === '"' || char === "'") {
quote = char;
result += char;
continue;
}
if (char === "[") {
bracketDepth += 1;
result += char;
continue;
}
if (char === "]") {
bracketDepth = Math.max(0, bracketDepth - 1);
result += char;
continue;
}
if (char === "#" && bracketDepth === 0) {
var matchedForm = null;
for (var formIndex = 0; formIndex < __hfAuthoredRootIdForms.length; formIndex += 1) {
var form = __hfAuthoredRootIdForms[formIndex];
if (selector.slice(index + 1, index + 1 + form.length) === form) {
matchedForm = form;
break;
}
}
if (matchedForm) {
var nextChar = selector[index + 1 + matchedForm.length];
if (!__hfIsSelectorNameChar(nextChar)) {
result += __hfAuthoredRootSelector;
index += matchedForm.length;
continue;
}
}
}
result += char;
}
return result;
};
var __hfNormalizeSelector = function(selector) { var __hfNormalizeSelector = function(selector) {
if (!__hfCompId || typeof selector !== "string") return selector; if (!__hfCompId || typeof selector !== "string") return selector;
return selector var normalized = selector
.replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector) .replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector)
.replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector); .replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector);
if (__hfAuthoredRootSelector) {
normalized = __hfReplaceAuthoredRootIdSelectors(normalized);
}
return normalized;
}; };
var __hfFindRoot = function() { var __hfFindRoot = function() {
if (!__hfRoot && __hfRootSelector) { if (!__hfRoot && __hfRootSelector) {
@@ -782,8 +930,15 @@ window.__timelines = window.__timelines || {};
var root = __hfFindRoot(); var root = __hfFindRoot();
if (!root) return found || null; if (!root) return found || null;
var idValue = id + ""; var idValue = id + "";
if (__hfAuthoredRootId && __hfAuthoredRootId === idValue && root.getAttribute && root.getAttribute(__hfAuthoredRootAttr) === idValue) {
return root;
}
if (root.id === idValue) return root; if (root.id === idValue) return root;
if (typeof root.querySelector !== "function") return null; if (typeof root.querySelector !== "function") return null;
try {
var authoredRootMatch = root.querySelector('[' + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(idValue) + '"]');
if (authoredRootMatch) return authoredRootMatch;
} catch {}
if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") { if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") {
try { try {
return root.querySelector("#" + CSS.escape(idValue)) || null; return root.querySelector("#" + CSS.escape(idValue)) || null;
@@ -900,7 +1055,12 @@ window.__timelines = window.__timelines || {};
var root = baseEl || __hfFindRoot(); var root = baseEl || __hfFindRoot();
return function(selector) { return function(selector) {
if (!root || typeof selector !== "string") return []; if (!root || typeof selector !== "string") return [];
return Array.prototype.slice.call(root.querySelectorAll(selector)); return Array.prototype.filter.call(
window.document.querySelectorAll(__hfNormalizeSelector(selector)),
function(node) {
return node === root || (typeof root.contains === "function" && root.contains(node));
},
);
}; };
}; };
} }
@@ -919,13 +1079,14 @@ window.__timelines = window.__timelines || {};
: Object.assign({}, __hfBaseHyperframes, { : Object.assign({}, __hfBaseHyperframes, {
getVariables: function() { getVariables: function() {
var byComp = window.__hfVariablesByComp; var byComp = window.__hfVariablesByComp;
var scoped = byComp && __hfCompId ? byComp[__hfCompId] : null; var scoped = byComp && __hfTimelineCompId ? byComp[__hfTimelineCompId] : null;
return scoped ? Object.assign({}, scoped) : {}; return scoped ? Object.assign({}, scoped) : {};
}, },
}); });
var __hfRun = function() { var __hfRun = function() {
try { try {
(function(document, gsap, window, __hyperframes) { (function(document, gsap, window, __hyperframes) {
(function () { (function () {
const TRANSCRIPT = [ const TRANSCRIPT = [
{ text: "We", start: 0.119, end: 0.259 }, { text: "We", start: 0.119, end: 0.259 },
@@ -1038,6 +1199,7 @@ window.__timelines = window.__timelines || {};
window.__timelines["captions"] = tl; window.__timelines["captions"] = tl;
})(); })();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes); }).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) { } catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err); console.error(__hfErrorLabel, __hfCompId, _err);
@@ -1051,20 +1213,87 @@ window.__timelines = window.__timelines || {};
var __hfCompId = "stats"; var __hfCompId = "stats";
var __hfTimelineCompId = "stats"; var __hfTimelineCompId = "stats";
var __hfErrorLabel = "[Compiler] Composition script failed"; var __hfErrorLabel = "[Compiler] Composition script failed";
var __hfAuthoredRootId = null;
var __hfAuthoredRootAttr = "data-hf-authored-id";
var __hfEscapeAttr = function(value) { var __hfEscapeAttr = function(value) {
return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\""); return (value + "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
}; };
var __hfRootSelector = null || (__hfCompId var __hfRootSelector = "[data-composition-id=\"stats\"]" || (__hfCompId
? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]' ? '[data-composition-id="' + __hfEscapeAttr(__hfCompId) + '"]'
: ""); : "");
var __hfRoot = null; var __hfRoot = null;
var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"stats\"|'stats')\\s*\\]"; var __hfRootSelectorPattern = "\\[\\s*data-composition-id\\s*=\\s*(?:\"stats\"|'stats')\\s*\\]";
var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]"; var __hfTimingSelectorPattern = "\\s*\\[\\s*data-(?:start|duration)\\s*=\\s*(?:\"[^\"]*\"|'[^']*')\\s*\\]";
var __hfAuthoredRootIdForms = [];
var __hfAuthoredRootSelector = __hfAuthoredRootId
? "[" + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(__hfAuthoredRootId) + '"]'
: "";
var __hfIsSelectorNameChar = function(char) {
return !!char && /[\w-]/.test(char);
};
var __hfReplaceAuthoredRootIdSelectors = function(selector) {
if (!__hfAuthoredRootSelector || !__hfAuthoredRootIdForms.length || typeof selector !== "string") {
return selector;
}
var result = "";
var bracketDepth = 0;
var quote = null;
for (var index = 0; index < selector.length; index += 1) {
var char = selector[index];
var previousChar = index > 0 ? selector[index - 1] : "";
if (quote) {
result += char;
if (char === quote && previousChar !== "\\") {
quote = null;
}
continue;
}
if (char === '"' || char === "'") {
quote = char;
result += char;
continue;
}
if (char === "[") {
bracketDepth += 1;
result += char;
continue;
}
if (char === "]") {
bracketDepth = Math.max(0, bracketDepth - 1);
result += char;
continue;
}
if (char === "#" && bracketDepth === 0) {
var matchedForm = null;
for (var formIndex = 0; formIndex < __hfAuthoredRootIdForms.length; formIndex += 1) {
var form = __hfAuthoredRootIdForms[formIndex];
if (selector.slice(index + 1, index + 1 + form.length) === form) {
matchedForm = form;
break;
}
}
if (matchedForm) {
var nextChar = selector[index + 1 + matchedForm.length];
if (!__hfIsSelectorNameChar(nextChar)) {
result += __hfAuthoredRootSelector;
index += matchedForm.length;
continue;
}
}
}
result += char;
}
return result;
};
var __hfNormalizeSelector = function(selector) { var __hfNormalizeSelector = function(selector) {
if (!__hfCompId || typeof selector !== "string") return selector; if (!__hfCompId || typeof selector !== "string") return selector;
return selector var normalized = selector
.replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector) .replace(new RegExp(__hfRootSelectorPattern + '(?:' + __hfTimingSelectorPattern + ')+', 'g'), __hfRootSelector)
.replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector); .replace(new RegExp('(?:' + __hfTimingSelectorPattern + ')+' + __hfRootSelectorPattern, 'g'), __hfRootSelector);
if (__hfAuthoredRootSelector) {
normalized = __hfReplaceAuthoredRootIdSelectors(normalized);
}
return normalized;
}; };
var __hfFindRoot = function() { var __hfFindRoot = function() {
if (!__hfRoot && __hfRootSelector) { if (!__hfRoot && __hfRootSelector) {
@@ -1095,8 +1324,15 @@ window.__timelines = window.__timelines || {};
var root = __hfFindRoot(); var root = __hfFindRoot();
if (!root) return found || null; if (!root) return found || null;
var idValue = id + ""; var idValue = id + "";
if (__hfAuthoredRootId && __hfAuthoredRootId === idValue && root.getAttribute && root.getAttribute(__hfAuthoredRootAttr) === idValue) {
return root;
}
if (root.id === idValue) return root; if (root.id === idValue) return root;
if (typeof root.querySelector !== "function") return null; if (typeof root.querySelector !== "function") return null;
try {
var authoredRootMatch = root.querySelector('[' + __hfAuthoredRootAttr + '="' + __hfEscapeAttr(idValue) + '"]');
if (authoredRootMatch) return authoredRootMatch;
} catch {}
if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") { if (typeof CSS !== "undefined" && CSS && typeof CSS.escape === "function") {
try { try {
return root.querySelector("#" + CSS.escape(idValue)) || null; return root.querySelector("#" + CSS.escape(idValue)) || null;
@@ -1213,7 +1449,12 @@ window.__timelines = window.__timelines || {};
var root = baseEl || __hfFindRoot(); var root = baseEl || __hfFindRoot();
return function(selector) { return function(selector) {
if (!root || typeof selector !== "string") return []; if (!root || typeof selector !== "string") return [];
return Array.prototype.slice.call(root.querySelectorAll(selector)); return Array.prototype.filter.call(
window.document.querySelectorAll(__hfNormalizeSelector(selector)),
function(node) {
return node === root || (typeof root.contains === "function" && root.contains(node));
},
);
}; };
}; };
} }
@@ -1232,13 +1473,14 @@ window.__timelines = window.__timelines || {};
: Object.assign({}, __hfBaseHyperframes, { : Object.assign({}, __hfBaseHyperframes, {
getVariables: function() { getVariables: function() {
var byComp = window.__hfVariablesByComp; var byComp = window.__hfVariablesByComp;
var scoped = byComp && __hfCompId ? byComp[__hfCompId] : null; var scoped = byComp && __hfTimelineCompId ? byComp[__hfTimelineCompId] : null;
return scoped ? Object.assign({}, scoped) : {}; return scoped ? Object.assign({}, scoped) : {};
}, },
}); });
var __hfRun = function() { var __hfRun = function() {
try { try {
(function(document, gsap, window, __hyperframes) { (function(document, gsap, window, __hyperframes) {
(function () { (function () {
const TRANSCRIPT = [ const TRANSCRIPT = [
{ text: "We", start: 0.119, end: 0.259 }, { text: "We", start: 0.119, end: 0.259 },
@@ -1404,6 +1646,7 @@ window.__timelines = window.__timelines || {};
window.__timelines["stats"] = tl; window.__timelines["stats"] = tl;
})(); })();
}).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes); }).call(window, __hfScopedDocument, __hfScopedGsap, __hfScopedWindow, __hfScopedHyperframes);
} catch (_err) { } catch (_err) {
console.error(__hfErrorLabel, __hfCompId, _err); console.error(__hfErrorLabel, __hfCompId, _err);
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:a256872dd11c18a5cbb776d105af04f13432264c5c0689fa79c6ca697c86cf6b oid sha256:1c5c34878cfe63ce79e60fe792c018e7b0b481ca59bd9c0dec558ed5e7cbb341
size 13478856 size 13503597
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4a1ac6cb0517b8224364833754981228f1138848e4f70715065f64f939ab4253 oid sha256:d2ca0d92ccf9740ad67c4ea46f50f65c3e3cefac88a07a171bd0fdcaf865efe0
size 7277596 size 13513666