mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-11 19:09:20 +00:00
fix(core): a film that loads GSAP from its own folder can swap edited scenes in place
The preview's scan of root scripts read a vendored gsap.min.js as film code,
so the library's own strings ("*" among them) refused every scene. A root
script that is GSAP's own build (its banner, then one minified line) is now
read as the library, as the CDN copy already is; code after the build is
still scanned.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// @vitest-environment node
|
||||
import { mkdtempSync, writeFileSync, mkdirSync, symlinkSync, rmSync } from "node:fs";
|
||||
import { mkdtempSync, readFileSync, writeFileSync, mkdirSync, symlinkSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { parseHTML } from "linkedom";
|
||||
@@ -2465,6 +2465,27 @@ describe("bundleToSingleHtml sceneParts", () => {
|
||||
expect(await swapMarks(rootProject(root))).toEqual([null, null]);
|
||||
});
|
||||
|
||||
it("reads a vendored GSAP build as the library, and film code after it as film code", async () => {
|
||||
const gsap = readFileSync(
|
||||
join(
|
||||
__dirname,
|
||||
"../../../../skills/music-to-video/references/motion-primitives/assets/gsap.min.js",
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
const root = `<script src="assets/gsap.min.js"></script>`;
|
||||
expect(await swapMarks(rootProject(root, { "assets/gsap.min.js": gsap }))).toEqual([
|
||||
null,
|
||||
null,
|
||||
]);
|
||||
const bundle = `${gsap}\ndocument.querySelector(".go").onclick = () => {};`;
|
||||
// Read whole, so the library's own strings refuse as they did before.
|
||||
expect(await swapMarks(rootProject(root, { "assets/gsap.min.js": bundle }))).toEqual([
|
||||
selects("*"),
|
||||
selects("*"),
|
||||
]);
|
||||
});
|
||||
|
||||
it("runs a scene's local script file in source order with its inline scripts, as a render does", async () => {
|
||||
const dir = makeTempProject({
|
||||
"index.html": `<!doctype html><html><head></head><body>
|
||||
|
||||
@@ -61,6 +61,14 @@ const isNotASelector = (script: string, at: number, literal: string) =>
|
||||
CREATES_ELEMENT_RE.test(script.slice(Math.max(0, at - 60), at)) ||
|
||||
(literal.trim() === "*" && /,\s*$/.test(script.slice(Math.max(0, at - 20), at)));
|
||||
|
||||
// GSAP's own build as vendored beside a film: its banner, then one minified line. Film code has no such banner.
|
||||
const isGsapBuild = (script: string) =>
|
||||
/^\s*\/\*!\s*\*\s*GSAP \d+\.\d+\.\d+\s/.test(script) &&
|
||||
script
|
||||
.slice(script.indexOf("*/") + 2)
|
||||
.split("\n")
|
||||
.filter((line) => line.trim() && !line.startsWith("//# sourceMappingURL=")).length === 1;
|
||||
|
||||
/** Marks each scene whose nodes a script outside it names by selector, id or class: a swap would strand it. */
|
||||
export function refuseSwapsReachedByRootScripts(document: Document, rootScripts: string[]): void {
|
||||
const hosts = [...document.querySelectorAll(`[${SCENE_PART_ATTR}]`)];
|
||||
@@ -91,11 +99,13 @@ export function refuseSwapsReachedByRootScripts(document: Document, rootScripts:
|
||||
),
|
||||
);
|
||||
const literals = new Set(
|
||||
rootScripts.flatMap((s) =>
|
||||
[...s.matchAll(STRING_LITERAL_RE)]
|
||||
.filter((m) => !isNotASelector(s, m.index, m[2] ?? ""))
|
||||
.map((m) => m[2] ?? ""),
|
||||
),
|
||||
rootScripts
|
||||
.filter((s) => !isGsapBuild(s))
|
||||
.flatMap((s) =>
|
||||
[...s.matchAll(STRING_LITERAL_RE)]
|
||||
.filter((m) => !isNotASelector(s, m.index, m[2] ?? ""))
|
||||
.map((m) => m[2] ?? ""),
|
||||
),
|
||||
);
|
||||
for (const literal of literals) {
|
||||
const open = hosts.filter((host) => !host.hasAttribute(SCENE_NO_SWAP_ATTR));
|
||||
|
||||
Reference in New Issue
Block a user