feat(registry): bring back the video-primitive moves (#3169)

Restores the 208 catalog items reverted after their previews 404'd in
production, this time on the payload mechanism rather than the .html files
that caused the outage.

The generator no longer writes a preview document to docs/public. That writer,
and the machinery under it, existed only to produce files the docs host
discards, so it is gone rather than bypassed. Items now embed the composition
itself via a payload, which is what the previous change already does for the
items that were already in the catalog.

The variables explorer is parked, not restored: it drove its preview through
the same unpublished .html path, so it would have shown an empty frame. Items
that declare variables get the live player plus the static variables table, and
reconnecting the explorer to payloads is a follow-up.
This commit is contained in:
Miguel Ángel
2026-08-10 18:46:03 -04:00
committed by GitHub
parent 0f76305191
commit 9734578e60
1383 changed files with 255573 additions and 5760 deletions
+123 -1
View File
@@ -3,8 +3,9 @@ import { mkdtempSync, writeFileSync, mkdirSync, symlinkSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { parseHTML } from "linkedom";
import { describe, it, expect, vi } from "vitest";
import { afterEach, beforeEach, describe, it, expect, vi } from "vitest";
import { bundleToSingleHtml } from "./htmlBundler";
import { resetUnknownEnumWarnings } from "../runtime/getVariables";
import { getHyperframeRuntimeScript } from "../generated/runtime-inline";
function makeTempProject(files: Record<string, string>): string {
@@ -1388,3 +1389,124 @@ describe("bundleToSingleHtml", () => {
}
});
});
/**
* A sub-composition given a value outside a declared enum's `options` falls
* back silently. The runtime guard in getVariables.ts cannot see it: the
* bundler bakes the per-instance values into `window.__hfVariablesByComp` at
* compile time and the sub-comp's scoped `getVariables` shim only reads that
* table. Compile time is therefore the only place the defect is observable on
* this path, so the same warning is emitted here.
*/
describe("bundleToSingleHtml unknown enum values", () => {
let warnings: string[];
beforeEach(() => {
resetUnknownEnumWarnings();
warnings = [];
vi.spyOn(console, "warn").mockImplementation((...args: unknown[]) => {
warnings.push(args.map(String).join(" "));
});
});
afterEach(() => {
vi.restoreAllMocks();
resetUnknownEnumWarnings();
});
const enumWarnings = () => warnings.filter((w) => w.includes("runtime_unknown_enum_value"));
const ACCENT_ENUM =
'[{"id":"accent","type":"enum","label":"Accent","default":"green","options":["green","blue","violet"]}]';
function makeSubCompProject(variableValues: string, declaration = ACCENT_ENUM): string {
return makeTempProject({
"index.html": `<!doctype html>
<html><head></head><body>
<div id="root" data-composition-id="main" data-width="1920" data-height="1080">
<div
data-composition-id="card"
data-composition-src="compositions/card.html"
data-variable-values='${variableValues}'></div>
</div>
<script>window.__timelines={};</script>
</body></html>`,
"compositions/card.html": `<!doctype html>
<html data-composition-variables='${declaration}'>
<body>
<div data-composition-id="card" data-width="1920" data-height="1080"></div>
</body>
</html>`,
});
}
it("warns when a sub-composition instance value is not a declared option", async () => {
await bundleToSingleHtml(makeSubCompProject('{"accent":"orange"}'));
expect(enumWarnings()).toEqual([
'[hyperframes] runtime_unknown_enum_value: card variable "accent" got "orange", ' +
"which is not a declared option (green, blue, violet). " +
'Rendering "green" instead.',
]);
});
it("is silent when the instance value is a declared option", async () => {
await bundleToSingleHtml(makeSubCompProject('{"accent":"violet"}'));
expect(enumWarnings()).toEqual([]);
});
it("never inspects a variable declared without options", async () => {
const declaration = '[{"id":"accent","type":"string","label":"Accent","default":"green"}]';
await bundleToSingleHtml(makeSubCompProject('{"accent":"orange"}', declaration));
expect(enumWarnings()).toEqual([]);
});
it("is silent for a declared enum absent from the instance values", async () => {
await bundleToSingleHtml(makeSubCompProject('{"unrelated":"whatever"}'));
expect(enumWarnings()).toEqual([]);
});
it("passes the unknown value through to the bundle unrewritten", async () => {
const bundled = await bundleToSingleHtml(makeSubCompProject('{"accent":"orange"}'));
expect(bundled).toContain("window.__hfVariablesByComp = Object.assign({}, ");
expect(bundled).toContain('{ "card": { "accent": "orange" } }');
expect(bundled).toMatch(/\[data-composition-id="card"\]\s*\{[^}]*--accent:\s*orange/);
expect(bundled).not.toContain("--accent: green");
});
it("warns once for the same composition, variable and value across bundles", async () => {
const dir = makeSubCompProject('{"accent":"orange"}');
await bundleToSingleHtml(dir);
await bundleToSingleHtml(dir);
expect(enumWarnings()).toHaveLength(1);
});
it("warns for a <template>-mounted composition too", async () => {
const dir = makeTempProject({
"index.html": `<!doctype html>
<html><head></head><body>
<div id="root" data-composition-id="main" data-width="1920" data-height="1080">
<div data-composition-id="card" data-variable-values='{"accent":"orange"}'></div>
</div>
<template id="card-template">
<div data-composition-id="card" data-width="1920" data-height="1080"
data-composition-variables='${ACCENT_ENUM}'></div>
</template>
<script>window.__timelines={};</script>
</body></html>`,
});
await bundleToSingleHtml(dir);
expect(enumWarnings()).toEqual([
'[hyperframes] runtime_unknown_enum_value: card variable "accent" got "orange", ' +
"which is not a declared option (green, blue, violet). " +
'Rendering "green" instead.',
]);
});
});
+8 -1
View File
@@ -1,6 +1,6 @@
import { markFlattenedInnerRoot } from "../runtime/flattenedRoot";
export { FLATTENED_INNER_ROOT_STRIP_ATTRS } from "../runtime/flattenedRoot";
import { parseHostVariableValues } from "../runtime/getVariables";
import { parseHostVariableValues, warnUnknownEnumValues } from "../runtime/getVariables";
import { cssVariableName } from "../tokenSlug";
import { readFileSync, existsSync } from "fs";
import { resolve, relative, dirname, isAbsolute, sep } from "path";
@@ -980,6 +980,13 @@ export async function bundleToSingleHtml(
if (runtimeCompId && Object.keys(mergedVariables).length > 0) {
compVariablesByComp[runtimeCompId] = mergedVariables;
}
// Same defect on the <template> mount as on the data-composition-src
// mount (see inlineSubCompositions): the merged instance values are
// baked in here, so only compile time can see a value that falls back.
if (runtimeCompId) {
warnUnknownEnumValues(innerDoc.documentElement, mergedVariables, runtimeCompId);
warnUnknownEnumValues(innerRoot, mergedVariables, runtimeCompId);
}
pushSubCompVariableStyles(
innerDoc,
innerRoot,
@@ -15,6 +15,7 @@ import {
rewriteInlineStyleAssetUrls,
type AssetExists,
} from "./rewriteSubCompPaths";
import { warnUnknownEnumValues } from "../runtime/getVariables";
import {
scopeCssToComposition,
wrapInlineScriptWithErrorBoundary,
@@ -272,6 +273,14 @@ export function inlineSubCompositions(
if (Object.keys(mergedVariables).length > 0) {
variablesByComp[runtimeCompId] = mergedVariables;
}
// Compile time is the only place this defect is visible on the sub-comp
// path: the instance value is baked into `__hfVariablesByComp` right
// here, and the scoped `getVariables` shim only reads that table, so the
// runtime's identical guard never runs. Same helper, so the message and
// the per-process dedupe set are shared with the runtime path and the
// author sees one warning either way.
warnUnknownEnumValues(compDoc.documentElement, mergedVariables, runtimeCompId);
warnUnknownEnumValues(innerRoot, mergedVariables, runtimeCompId);
}
// `<head>` <link>/<script src> are hoisted into the ROOT document, so they