mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-08-31 02:41:44 +00:00
* docs(skills): fix anime.js v3 syntax in v4 adapter guidance
The animejs adapter docs teach v3 syntax against a v4 build, so the examples
cannot run as written: every v4 bundle assigns a *namespace object* to the
global `anime`, making v3's `anime({ targets })` call form a TypeError. `easing:`
is now `ease:`, ease names lost their `ease` prefix, and `timeline.add()` takes
`(targets, parameters, position)`.
- Rewrite `skills/hyperframes-animation/adapters/animejs.md` for v4:
`anime.animate()` / `anime.createTimeline()`, `ease:` names, targets-first
`add()`, position shorthands, and a note that the producer fixtures pin
4.0.2 (`lib/`) while 4.1+ moved bundles to `dist/bundles/`.
- Fix the same v3 `anime.timeline({ targets })` snippet in
`skills/hyperframes-keyframes/references/keyframe-patterns.md`.
- Stop advertising `anime.running` auto-discovery as a safety net. No v4 build
exports `running` (checked 4.0.2 and 4.5.0), so `discover()` returns
immediately and any instance a composition forgets to push onto
`window.__hfAnime` is silently never seeked. Marked v3-only/inert in the
skill page and the adapter docstring; explicit registration is now stated
as mandatory.
- Add render-safety notes the page lacked: `createSeededRandom()` as the
deterministic replacement for `Math.random()`, and why
`autoplay: onScroll(...)`, `createDraggable`, and pointer-driven
`createAnimatable` cannot work under headless seek rendering.
- Regenerate skills-manifest.json.
Runtime behaviour is unchanged: the `packages/core` edit is comment-only, and
the seek path already works on v4 (registered instances expose
seek/pause/play). The now-dead `anime.running` branch in `discover()` is left
in place — it is guarded and try/caught, and removing it is a behaviour change
that belongs in its own PR.
* fix(core): align Anime.js globals with v4
---------
Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
64 lines
2.3 KiB
JavaScript
64 lines
2.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import test from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
|
const guidance = [
|
|
{
|
|
path: "packages/core/src/runtime/adapters/animejs.ts",
|
|
required: ["anime.animate", "anime.createTimeline"],
|
|
},
|
|
{
|
|
path: "skills/hyperframes-animation/adapters/animejs.md",
|
|
required: ["anime.animate", "anime.createTimeline"],
|
|
},
|
|
{
|
|
path: "skills/hyperframes-keyframes/references/keyframe-patterns.md",
|
|
required: ["anime.createTimeline"],
|
|
},
|
|
];
|
|
|
|
function read(path) {
|
|
return readFileSync(join(repoRoot, path), "utf8");
|
|
}
|
|
|
|
function fencedCode(source) {
|
|
const normalized = source.replace(/^\s*\* ?/gm, "");
|
|
return [...normalized.matchAll(/```[^\n]*\n([\s\S]*?)```/g)].map((match) => match[1]).join("\n");
|
|
}
|
|
|
|
for (const { path, required } of guidance) {
|
|
test(`${path} uses Anime.js v4 call sites in executable examples`, () => {
|
|
const snippets = fencedCode(read(path));
|
|
for (const call of required) {
|
|
assert.match(snippets, new RegExp(`\\b${call.replace(".", "\\.")}\\s*\\(`));
|
|
}
|
|
assert.doesNotMatch(snippets, /\banime\s*\(\s*\{/);
|
|
assert.doesNotMatch(snippets, /\banime\.timeline\s*\(/);
|
|
});
|
|
}
|
|
|
|
test("the window anime global advertises the v4 namespace API", () => {
|
|
const source = read("packages/core/src/runtime/window.d.ts");
|
|
const global = source.match(/\n\s*anime\?: \{([\s\S]*?)\n\s*\};/);
|
|
assert.ok(global, "found Window.anime declaration");
|
|
assert.match(global[1], /\banimate\??:\s*\(/);
|
|
assert.match(global[1], /\bcreateTimeline\??:\s*\(/);
|
|
assert.doesNotMatch(global[1], /^\s*\(params:/m);
|
|
assert.doesNotMatch(global[1], /\btimeline\??:/);
|
|
});
|
|
|
|
test("the adapter's local anime global shape matches v4 while retaining legacy discovery", () => {
|
|
const source = read("packages/core/src/runtime/adapters/animejs.ts");
|
|
const global = source.match(/interface AnimeGlobal \{([\s\S]*?)\n\}/);
|
|
assert.ok(global, "found AnimeGlobal declaration");
|
|
assert.match(global[1], /\banimate\??:\s*\(/);
|
|
assert.match(global[1], /\bcreateTimeline\??:\s*\(/);
|
|
assert.match(global[1], /\brunning\??:/);
|
|
assert.doesNotMatch(global[1], /^\s*\(params:/m);
|
|
assert.doesNotMatch(global[1], /\btimeline\??:/);
|
|
});
|