mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix: address review feedback — observability, dedup, query-strip, catalog
Review items addressed: 1. Mirror video-failure warning in beginFrame path (was screenshot-only) 2. Fix resolveProjectRelativeSrc escape-fallback to use query-stripped cleanSrc instead of raw src for the normalize/strip arm 3. Export prepareFlattenedInnerRoot from @hyperframes/core/compiler and consume in the producer instead of duplicating the implementation 4. Use typed Window cast instead of (window as any) for __hfForceTimelineRebind 5. Regenerate docs/public/catalog-index.json with all 6 map blocks 6. Restore Maps nav group in docs.json (catalog generator had merged them into Data)
This commit is contained in:
@@ -368,7 +368,7 @@ function parseHostVariableValues(host: Element): Record<string, unknown> {
|
||||
return parsed as Record<string, unknown>;
|
||||
}
|
||||
|
||||
const FLATTENED_INNER_ROOT_STRIP_ATTRS = [
|
||||
export const FLATTENED_INNER_ROOT_STRIP_ATTRS = [
|
||||
"data-composition-id",
|
||||
"data-composition-file",
|
||||
"data-start",
|
||||
@@ -381,7 +381,7 @@ const FLATTENED_INNER_ROOT_STRIP_ATTRS = [
|
||||
"data-hf-authored-end",
|
||||
];
|
||||
|
||||
function prepareFlattenedInnerRoot(innerRoot: Element): Element {
|
||||
export function prepareFlattenedInnerRoot(innerRoot: Element): Element {
|
||||
const prepared = innerRoot.cloneNode(true) as Element;
|
||||
const authoredRootId = prepared.getAttribute("id")?.trim();
|
||||
for (const attrName of FLATTENED_INNER_ROOT_STRIP_ATTRS) {
|
||||
|
||||
@@ -15,7 +15,12 @@ export {
|
||||
export { compileHtml, type MediaDurationProber } from "./htmlCompiler";
|
||||
|
||||
// HTML bundler (Node.js — requires fs, linkedom, esbuild)
|
||||
export { bundleToSingleHtml, type BundleOptions } from "./htmlBundler";
|
||||
export {
|
||||
bundleToSingleHtml,
|
||||
type BundleOptions,
|
||||
prepareFlattenedInnerRoot,
|
||||
FLATTENED_INNER_ROOT_STRIP_ATTRS,
|
||||
} from "./htmlBundler";
|
||||
|
||||
export {
|
||||
RUNTIME_BOOTSTRAP_ATTR,
|
||||
|
||||
@@ -964,7 +964,7 @@ export function initSandboxRuntimeModular(): void {
|
||||
return true;
|
||||
};
|
||||
|
||||
(window as any).__hfForceTimelineRebind = () => {
|
||||
(window as Window & { __hfForceTimelineRebind?: () => void }).__hfForceTimelineRebind = () => {
|
||||
childrenBound = false;
|
||||
bindRootTimelineIfAvailable();
|
||||
};
|
||||
|
||||
@@ -682,11 +682,25 @@ export async function initializeSession(session: CaptureSession): Promise<void>
|
||||
await applyVideoMetadataHints(page, session.options.videoMetadataHints);
|
||||
|
||||
// Same readyState contract as the screenshot path above (>= 2 / HAVE_CURRENT_DATA).
|
||||
await pollVideosReady(
|
||||
const bfVideosReady = await pollVideosReady(
|
||||
page,
|
||||
session.options.skipReadinessVideoIds ?? [],
|
||||
session.config?.playerReadyTimeout ?? DEFAULT_CONFIG.playerReadyTimeout,
|
||||
);
|
||||
if (!bfVideosReady) {
|
||||
const failedVideos = await page.evaluate((skipIdList: readonly string[]) => {
|
||||
const skip = new Set(skipIdList);
|
||||
return Array.from(document.querySelectorAll("video"))
|
||||
.filter((v) => !skip.has(v.id))
|
||||
.filter((v) => (v as HTMLVideoElement).readyState < 2 && !(v as HTMLVideoElement).error)
|
||||
.map((v) => (v as HTMLVideoElement).src || v.getAttribute("src") || "(no src)")
|
||||
.join(", ");
|
||||
}, session.options.skipReadinessVideoIds ?? []);
|
||||
console.warn(
|
||||
`[FrameCapture] Some video elements did not decode within ${pageReadyTimeout}ms: ${failedVideos}. ` +
|
||||
`Continuing render — affected videos will appear as blank/black frames.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Font check (no rAF dependency — uses fonts.ready API directly)
|
||||
await page.evaluate(`document.fonts?.ready`);
|
||||
|
||||
@@ -530,7 +530,7 @@ export function resolveProjectRelativeSrc(
|
||||
// then strip any remaining leading `..` segments. Stripping `..` from the
|
||||
// raw input would leave dangling siblings (`assets/../../assets/foo`
|
||||
// would become `assets/assets/foo` instead of `assets/foo`).
|
||||
const normalized = posix.normalize(src.replace(/\\/g, "/"));
|
||||
const normalized = posix.normalize(cleanSrc.replace(/\\/g, "/"));
|
||||
const stripped = normalized.replace(/^(\.\.\/)+/, "");
|
||||
if (stripped && stripped !== src && !stripped.startsWith("..")) {
|
||||
if (compiledDir) candidates.push(join(compiledDir, stripped));
|
||||
|
||||
@@ -21,7 +21,10 @@ import {
|
||||
type ResolvedDuration,
|
||||
type UnresolvedElement,
|
||||
} from "@hyperframes/core";
|
||||
import { inlineSubCompositions as inlineSubCompositionsShared } from "@hyperframes/core/compiler";
|
||||
import {
|
||||
inlineSubCompositions as inlineSubCompositionsShared,
|
||||
prepareFlattenedInnerRoot,
|
||||
} from "@hyperframes/core/compiler";
|
||||
import { extractMediaMetadata, extractAudioMetadata } from "../utils/ffprobe.js";
|
||||
import { isPathInside, toExternalAssetKey } from "../utils/paths.js";
|
||||
import {
|
||||
@@ -559,19 +562,6 @@ function inlineSubCompositions(
|
||||
|
||||
if (!hosts.length) return html;
|
||||
|
||||
const FLATTENED_INNER_ROOT_STRIP_ATTRS = [
|
||||
"data-composition-id",
|
||||
"data-composition-file",
|
||||
"data-start",
|
||||
"data-duration",
|
||||
"data-end",
|
||||
"data-track-index",
|
||||
"data-track",
|
||||
"data-composition-src",
|
||||
"data-hf-authored-duration",
|
||||
"data-hf-authored-end",
|
||||
];
|
||||
|
||||
const result = inlineSubCompositionsShared(
|
||||
document as unknown as Document,
|
||||
hosts as unknown as Element[],
|
||||
@@ -587,19 +577,7 @@ function inlineSubCompositions(
|
||||
return compHtml;
|
||||
},
|
||||
parseHtml: (htmlStr: string) => parseHTML(htmlStr).document as unknown as Document,
|
||||
flattenInnerRoot: (innerRoot: Element): Element => {
|
||||
const prepared = innerRoot.cloneNode(true) as Element;
|
||||
const authoredRootId = prepared.getAttribute("id")?.trim();
|
||||
for (const attrName of FLATTENED_INNER_ROOT_STRIP_ATTRS) {
|
||||
prepared.removeAttribute(attrName);
|
||||
}
|
||||
if (authoredRootId) {
|
||||
prepared.removeAttribute("id");
|
||||
prepared.setAttribute("data-hf-authored-id", authoredRootId);
|
||||
}
|
||||
prepared.setAttribute("data-hf-inner-root", "true");
|
||||
return prepared;
|
||||
},
|
||||
flattenInnerRoot: prepareFlattenedInnerRoot as (innerRoot: Element) => Element,
|
||||
scriptErrorLabel: "[Compiler] Composition script failed",
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user