mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-12 23:29:50 +00:00
feat(check): add data-layout-allow-caption-zone waiver (#2853)
* feat(check): add data-layout-allow-caption-zone waiver Opt intentional lower-third copy out of caption_zone_collision. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(check): address caption-zone waiver review nits Co-authored-by: Cursor <cursoragent@cursor.com> * docs(skills): document caption-zone waiver on CLI agent path Co-authored-by: Cursor <cursoragent@cursor.com> * docs(cli): document caption-zone waiver under check, not inspect Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -175,11 +175,13 @@ interface GeometryFixture {
|
||||
elementRect?: LayoutRect;
|
||||
time: number;
|
||||
overflow?: LayoutOverflow;
|
||||
dataAttributes?: Record<string, string>;
|
||||
}
|
||||
|
||||
function geometryCandidate(fixture: GeometryFixture) {
|
||||
return {
|
||||
...anchor(fixture.selector, fixture.time),
|
||||
...(fixture.dataAttributes ? { dataAttributes: fixture.dataAttributes } : {}),
|
||||
kind: fixture.kind,
|
||||
tag: fixture.tag,
|
||||
text: fixture.text,
|
||||
@@ -446,6 +448,26 @@ it("flags only text whose center is inside the caption band at the default end s
|
||||
expect(report.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("skips caption_zone_collision when data-layout-allow-caption-zone is set", async () => {
|
||||
const collectGeometryCandidates = vi.fn(async (time: number) => [
|
||||
geometryCandidate({
|
||||
kind: "text",
|
||||
tag: "div",
|
||||
text: "Intentional lower third",
|
||||
selector: "#lower-third",
|
||||
rect: fixtureRect(860, 870, 200, 60),
|
||||
time,
|
||||
dataAttributes: { "data-layout-allow-caption-zone": "" },
|
||||
}),
|
||||
]);
|
||||
const { report } = await runScenario(
|
||||
fakeDriver({ getDuration: vi.fn(async () => 10), collectGeometryCandidates }),
|
||||
{ samples: 1, contrast: false, captionZone: { x0: 0, y0: 0.8, x1: 1, y1: 0.9 } },
|
||||
);
|
||||
|
||||
expect(report.layout.findings).toEqual([]);
|
||||
});
|
||||
|
||||
it("filters caption candidates by the element box while centering the text rect", async () => {
|
||||
const collectGeometryCandidates = vi.fn(async (time: number) => [
|
||||
geometryCandidate({
|
||||
|
||||
@@ -105,6 +105,10 @@
|
||||
return !!element.closest("[data-layout-allow-overflow]");
|
||||
}
|
||||
|
||||
function hasAllowCaptionZoneFlag(element) {
|
||||
return !!element.closest("[data-layout-allow-caption-zone]");
|
||||
}
|
||||
|
||||
function hasTextClipOptOut(element) {
|
||||
return hasAllowOverflowFlag(element) || element.hasAttribute("data-layout-bleed");
|
||||
}
|
||||
@@ -1396,7 +1400,7 @@
|
||||
}
|
||||
if (!isVisibleElement(element, 0.05, false)) continue;
|
||||
const elementRect = toRect(element.getBoundingClientRect());
|
||||
if (includeText && hasOwnTextCandidate(element, true)) {
|
||||
if (includeText && hasOwnTextCandidate(element, true) && !hasAllowCaptionZoneFlag(element)) {
|
||||
const rect = textRectFor(element, true);
|
||||
if (rect) {
|
||||
candidates.push(
|
||||
|
||||
@@ -381,6 +381,27 @@ it("returns own-text rects and media overflow while excluding caption layers", (
|
||||
expect(candidates.some((candidate) => candidate.selector === "#caption")).toBe(false);
|
||||
});
|
||||
|
||||
it("excludes text marked data-layout-allow-caption-zone from geometry candidates", () => {
|
||||
document.body.innerHTML = `
|
||||
<div id="root" data-composition-id="main" data-width="640" data-height="360">
|
||||
<p id="copy">Main copy</p>
|
||||
<p id="lower" data-layout-allow-caption-zone>Lower third</p>
|
||||
<div data-layout-allow-caption-zone><span id="nested">Nested lower</span></div>
|
||||
</div>
|
||||
`;
|
||||
installGeometry({
|
||||
root: rect({ left: 0, top: 0, width: 640, height: 360 }),
|
||||
copy: rect({ left: 100, top: 100, width: 200, height: 40 }),
|
||||
lower: rect({ left: 100, top: 280, width: 200, height: 40 }),
|
||||
nested: rect({ left: 100, top: 300, width: 200, height: 40 }),
|
||||
text: rect({ left: 100, top: 100, width: 200, height: 40 }),
|
||||
});
|
||||
installAuditScript();
|
||||
|
||||
const candidates = runGeometryCandidates({ text: true, media: false, tolerance: 2 });
|
||||
expect(candidates.map((candidate) => candidate.selector)).toEqual(["#copy"]);
|
||||
});
|
||||
|
||||
it("scans body-level composition siblings and includes a media boundary root", () => {
|
||||
document.body.innerHTML = `
|
||||
<canvas id="boundary" data-composition-id="background" data-width="640" data-height="360"></canvas>
|
||||
|
||||
Reference in New Issue
Block a user