mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-03 12:17:03 +00:00
* fix(inspector): report nested hosts' authored window, one location per source line The runtime strips data-duration/data-end from nested composition hosts after boot and keeps them as data-hf-authored-*. Timeline inspection built its resolver without authored attrs, so a host with data-duration="4" reported its GSAP timeline length (3.72s) instead. Timeline text and events[].sources listed the same file:line once per mapped snippet (creation, caller, dependency), so a one-line script printed one location up to nine times. * refactor(inspector): carry the dedupe reason in the helper's name * fix(inspector): end continuation on a page that fits no snippet; fill budget with candidates * fix(inspector): timeline groups by component, names attr values, eases, film end * fix(studio-server): stamp hf ids into a file without reformatting it * fix(inspector): find an element's tag before its served hf id reaches the source * fix(inspector): live element map shows authored classes and text, not the playhead's * fix(inspector): collapse script-built text so the element map ignores the playhead Class names stay in source order, a runtime-stripped id is shown as id="…" rather than a selector, and a grouped row names which children it covers. * fix(inspector): keep paging, stamping, and the live map still on the reported edges A snippet larger than the page ended the walk, so later snippets could not be reached. Raw text ended at a longer tag name, which could stamp an id inside a script. An empty or mixed source element showed live text, and an unknown duration read as a film that ends at 0s. * fix(inspector): mint ids for an empty hf id and keep an unquoted class An empty data-hf-id was treated as already assigned, so stamping left it blank while the older stamper minted one. An unquoted class was read as no class, so the live map dropped it. * fix(inspector): narrow markup before reading a child tag skipMarkup returns a boolean, so the build still sees Markup where a tag is required. Narrow on the kind first so the inspector typechecks. * fix: quiet check false positives and name the ancestor of an id-less target Endpoint contact, disjoint fromTo pairs, and a negative z-index under a stacking-context parent were warnings with bad advice. Layout and contrast blamed a dot grid, a circular avatar's panel, and a visibility override. A faint texture veil is no longer the click target. * fix(lint): drop a history sentence and six gsap comments The comments check treats "load-bearing" as history, and gsap.ts added six comment lines. The names already carry what those lines said. * fix(parsers): ignore an empty id written inside another attribute The empty-id scan matched the first data-hf-id="" in the tag, including one inside a quoted title. It now skips quoted text, so the real attribute is minted. * fix(lint): keep real covers and a negative z-index under a card A gradient scale-down treated every fill like a radial dot, so a panel that starts transparent stopped counting as a cover. A stacking context on any ancestor cleared a negative z-index, and a faint wrapper made images inside it unpickable. * fix: keep an emoji from shifting a stamped id The quote mask replaced one emoji with one space, so the id landed before the closing quote. A radial cover that turns opaque after a clear stop stays fully painted. * fix(lint): score a letter-only dot as a dot, not a color name namesAColor saw #fff and rgba as words, so those dot grids counted as a full cover. Hex and rgb colors are stripped before that word check.
92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import type { TimelineRequest } from "../../core/src/runtime/timelineInspection";
|
|
import { withAuthoredState } from "./authoredState";
|
|
import { collectElementDom, formatElementMap, type ElementMap } from "./elementMap.js";
|
|
import { mapInspection } from "./mapInspection";
|
|
import { queryPage, timelinePage, type PageRunner } from "./pageQueries";
|
|
import type { AuthoredHtml, Sources } from "./sources";
|
|
import { formatTimeline, type TimelineReport } from "./timelineReport";
|
|
import type { InspectRequest, Snippet } from "./types";
|
|
|
|
export interface SourceContext {
|
|
sources: Sources;
|
|
map: ReturnType<Sources["mapper"]>;
|
|
}
|
|
|
|
export interface InspectionView {
|
|
readonly generation: string;
|
|
readonly sourceVersion: string;
|
|
readonly pageGeneration?: string;
|
|
sourceContext(): SourceContext;
|
|
authoredHtml?(): AuthoredHtml;
|
|
assertCurrent(): Promise<void>;
|
|
}
|
|
|
|
export type ComponentReport = ReturnType<typeof mapInspection>;
|
|
export type ElementMapReport = ElementMap & { sourceVersion: string; generation: string };
|
|
|
|
function assertPageGeneration(view: InspectionView, actual: string | null) {
|
|
if (view.pageGeneration !== undefined && actual !== view.pageGeneration)
|
|
throw new Error("stale_preview: the preview reloaded; query again");
|
|
}
|
|
|
|
export async function inspectComponents(
|
|
runner: PageRunner,
|
|
view: InspectionView,
|
|
request: InspectRequest,
|
|
context: {
|
|
catalog: Map<string, Snippet>;
|
|
reused: boolean;
|
|
start: number;
|
|
visualState?: { time: number | undefined; duration: number | undefined };
|
|
},
|
|
): Promise<ComponentReport> {
|
|
const { sources, map } = view.sourceContext();
|
|
const raw = await runner.run(queryPage, {
|
|
targets: request.targets,
|
|
descendants: request.descendants ?? true,
|
|
cssRules: sources.cssRules.map(({ id, selector }) => ({ id, selector })),
|
|
});
|
|
assertPageGeneration(view, raw.generation);
|
|
await view.assertCurrent();
|
|
return mapInspection(raw, request, {
|
|
...context,
|
|
sources,
|
|
map,
|
|
generation: view.generation,
|
|
sourceVersion: view.sourceVersion,
|
|
});
|
|
}
|
|
|
|
export async function inspectTimeline(
|
|
runner: PageRunner,
|
|
view: InspectionView,
|
|
request: TimelineRequest,
|
|
reused: boolean,
|
|
): Promise<TimelineReport> {
|
|
const raw = await runner.run(timelinePage, request);
|
|
assertPageGeneration(view, raw.generation);
|
|
await view.assertCurrent();
|
|
return formatTimeline(raw, request, {
|
|
generation: view.generation,
|
|
map: view.sourceContext().map,
|
|
reused,
|
|
});
|
|
}
|
|
|
|
export async function inspectElementMap(
|
|
runner: PageRunner,
|
|
view: InspectionView,
|
|
file = "index.html",
|
|
): Promise<ElementMapReport> {
|
|
const snapshot = await runner.run(collectElementDom, undefined);
|
|
assertPageGeneration(view, snapshot.generation);
|
|
const authored = view.authoredHtml?.();
|
|
const map = formatElementMap(authored ? withAuthoredState(snapshot, authored) : snapshot, {
|
|
file,
|
|
});
|
|
await view.assertCurrent();
|
|
return { ...map, sourceVersion: view.sourceVersion, generation: view.generation };
|
|
}
|
|
|
|
export type { PageRunner, TimelineReport };
|