mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-11 19:09:20 +00:00
fix(lint): avoid unproven media and head leaks
This commit is contained in:
@@ -235,3 +235,36 @@ describe("template shell style sources", () => {
|
||||
expect(findings.some((finding) => finding.code === "texture_mask_asset_not_found")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("duplicate_audio_track", () => {
|
||||
async function duplicateAudioFindings(audioMarkup: string): Promise<HyperframeLintFinding[]> {
|
||||
const project = makeProject(`<html><body>
|
||||
<div data-composition-id="main" data-width="1920" data-height="1080" data-start="0" data-duration="20">
|
||||
${audioMarkup}
|
||||
</div>
|
||||
<script>window.__timelines = {};</script>
|
||||
</body></html>`);
|
||||
const { results } = await lintProject(project);
|
||||
return results
|
||||
.flatMap((entry) => entry.result.findings)
|
||||
.filter((finding) => finding.code === "duplicate_audio_track");
|
||||
}
|
||||
|
||||
it("does not infer overlap when same-track clips omit data-duration", async () => {
|
||||
const findings = await duplicateAudioFindings(`
|
||||
<audio id="first" src="voice.wav" data-track-index="0" data-start="0"></audio>
|
||||
<audio id="second" src="voice.wav" data-track-index="0" data-start="10"></audio>
|
||||
`);
|
||||
|
||||
expect(findings).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("still reports overlap when explicit clip durations overlap", async () => {
|
||||
const findings = await duplicateAudioFindings(`
|
||||
<audio id="first" src="voice.wav" data-track-index="0" data-start="0" data-duration="12"></audio>
|
||||
<audio id="second" src="voice.wav" data-track-index="0" data-start="10" data-duration="5"></audio>
|
||||
`);
|
||||
|
||||
expect(findings).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -503,11 +503,11 @@ function lintDuplicateAudioTracks(htmlSources: HtmlSource[]): HyperframeLintFind
|
||||
const startStr = extractAttr(tag, "data-start");
|
||||
const durStr = extractAttr(tag, "data-duration");
|
||||
const src = extractAttr(tag, "src") ?? "unknown";
|
||||
if (!trackStr || !startStr) continue;
|
||||
if (!trackStr || !startStr || !durStr) continue;
|
||||
|
||||
const trackIndex = parseInt(trackStr, 10);
|
||||
const start = parseFloat(startStr);
|
||||
const duration = durStr ? parseFloat(durStr) : Infinity;
|
||||
const duration = parseFloat(durStr);
|
||||
const key = `${src}:${start}:${duration}:${trackIndex}`;
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
|
||||
@@ -464,6 +464,17 @@ body {
|
||||
expect(finding).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not treat a head tag literal inside a template script comment as document head", async () => {
|
||||
const html = compositionWithBodyPrefix(
|
||||
"",
|
||||
`<template><script>// Explain the literal <head> marker.</script></template>`,
|
||||
);
|
||||
const result = await lintHyperframeHtml(html);
|
||||
const finding = result.findings.find((f) => f.code === "head_leaked_text");
|
||||
|
||||
expect(finding).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not report CSS-looking educational text inside the composition root", async () => {
|
||||
const html = compositionWithBodyPrefix(
|
||||
"",
|
||||
|
||||
@@ -107,12 +107,14 @@ function findLeakedTextInHeadContent(headContent: string): string | null {
|
||||
}
|
||||
|
||||
function findLeakedTextInHead(rawSource: string): string | null {
|
||||
const headMatches = [...rawSource.matchAll(HEAD_CONTENT_PATTERN)];
|
||||
for (const match of headMatches) {
|
||||
const leakedText = findLeakedTextInHeadContent(match[1] ?? "");
|
||||
if (leakedText) return leakedText;
|
||||
}
|
||||
return null;
|
||||
const headPattern = new RegExp(HEAD_CONTENT_PATTERN.source, "i");
|
||||
const match = headPattern.exec(rawSource);
|
||||
if (!match) return null;
|
||||
|
||||
const bodyIndex = rawSource.search(/<body\b/i);
|
||||
if (bodyIndex >= 0 && match.index > bodyIndex) return null;
|
||||
|
||||
return findLeakedTextInHeadContent(match[1] ?? "");
|
||||
}
|
||||
|
||||
function findLeakedTextBetweenHeadAndBody(rawSource: string): string | null {
|
||||
|
||||
Reference in New Issue
Block a user