mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(registry): glass-shard-title renders when mounted, and 4 skipped blocks install again (#4423)
* fix(registry): glass-shard-title renders when mounted, and 4 skipped blocks install again * fix(registry): glass-shard-title loads in Studio and ?play, and its docs payload fails loudly * test(scripts): pin the glass payload's hdr guard for any quote style
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { validRegistryName, validRegistryManifest, validRegistryItem } from "./validation.js";
|
||||
|
||||
@@ -39,4 +41,21 @@ describe("registry manifest boundary", () => {
|
||||
validRegistryManifest({ ...manifest, items: Array(10_001).fill(manifest.items[0]) }),
|
||||
).toBe(false);
|
||||
});
|
||||
it("accepts every registry-item.json the repo publishes", () => {
|
||||
const registry = join(import.meta.dirname, "../../../../registry");
|
||||
const rejected = readdirSync(registry, { withFileTypes: true })
|
||||
.filter((dir) => dir.isDirectory())
|
||||
.flatMap((dir) =>
|
||||
readdirSync(join(registry, dir.name)).map((name) => ({ dir: dir.name, name })),
|
||||
)
|
||||
.filter(({ dir, name }) => existsSync(join(registry, dir, name, "registry-item.json")))
|
||||
.filter(({ dir, name }) => {
|
||||
const item = JSON.parse(
|
||||
readFileSync(join(registry, dir, name, "registry-item.json"), "utf8"),
|
||||
);
|
||||
return !validRegistryItem(item, name, item.type);
|
||||
})
|
||||
.map(({ dir, name }) => `${dir}/${name}`);
|
||||
expect(rejected).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -67,7 +67,7 @@ point.position.set(0, -3, 1);
|
||||
scene.add(point);
|
||||
|
||||
/* ---- Environment + matcap (glass look) ---- */
|
||||
const hdrTex = await new HDRLoader().loadAsync("assets/ferndale_studio_01_1k.hdr");
|
||||
const hdrTex = await new HDRLoader().loadAsync(document.getElementById("gst-hdr").href);
|
||||
const pmrem = new THREE.PMREMGenerator(renderer);
|
||||
const envRT = pmrem.fromEquirectangular(hdrTex);
|
||||
scene.environment = envRT.texture;
|
||||
@@ -75,7 +75,9 @@ scene.environmentRotation = new THREE.Euler(0, 0.6, 0);
|
||||
hdrTex.dispose();
|
||||
pmrem.dispose();
|
||||
|
||||
const matcapTex = await new THREE.TextureLoader().loadAsync("assets/matcap-1.png");
|
||||
const matcapTex = await new THREE.TextureLoader().loadAsync(
|
||||
document.getElementById("gst-matcap").href,
|
||||
);
|
||||
matcapTex.colorSpace = THREE.SRGBColorSpace;
|
||||
matcapTex.wrapS = matcapTex.wrapT = THREE.RepeatWrapping;
|
||||
const mk = 1 / 0.2;
|
||||
|
||||
+15
-7
@@ -4,13 +4,6 @@
|
||||
data-composition-variables='[{"id":"headline","type":"string","label":"Headline","default":"Designed in glass","maxLength":40},{"id":"tileCount","type":"number","label":"Tiles","default":8,"min":1,"max":400,"step":1},{"id":"roundness","type":"number","label":"Roundness (0-1)","default":0.4,"min":0,"max":1,"step":0.01},{"id":"bevel","type":"number","label":"Bevel (0-1)","default":0.35,"min":0,"max":1,"step":0.01},{"id":"meshSmooth","type":"number","label":"Surface smoothness (0-1)","default":0.6,"min":0,"max":1,"step":0.01},{"id":"flyInTime","type":"number","label":"Fly-in time (s)","default":2.3,"min":0.2,"max":6,"step":0.05},{"id":"flyOutTime","type":"number","label":"Fly-out time (s)","default":2.4,"min":0.2,"max":6,"step":0.05},{"id":"stagger","type":"number","label":"Stagger (0-1)","default":0.27,"min":0,"max":1,"step":0.01},{"id":"flyInRotation","type":"number","label":"Fly-in rotation (0-60)","description":"Amount of inbound tumbling over the entire flight. 0 disables flight rotation; final orientation lands with each shard position.","default":5,"min":0,"max":60,"step":0.1},{"id":"flyOutRotation","type":"number","label":"Fly-out rotation (0-6)","default":6,"min":0,"max":6,"step":0.1},{"id":"chaos","type":"number","label":"Outline chaos (0-1)","default":0.25,"min":0,"max":1,"step":0.01},{"id":"padding","type":"number","label":"Edge padding (0-1)","default":1,"min":0,"max":1,"step":0.01},{"id":"sizeVariance","type":"number","label":"Size variance (0-1)","default":0.35,"min":0,"max":1,"step":0.01},{"id":"gap","type":"number","label":"Tile gap","default":0.03,"min":0,"max":0.3,"step":0.002},{"id":"easePow","type":"number","label":"Fly-in position ease (1-10)","description":"Shapes lateral and depth travel. Rotation uses the same staggered flight window with a gentle settle through arrival.","default":10,"min":1,"max":10,"step":0.1},{"id":"sideDist","type":"number","label":"Side fly distance","default":3,"min":0,"max":60,"step":0.5},{"id":"zDist","type":"number","label":"Z fly-from (negative)","default":-42,"min":-400,"max":0,"step":2},{"id":"zOut","type":"number","label":"Z fly-out to (+ = past camera)","default":14,"min":-400,"max":60,"step":2},{"id":"fog","type":"number","label":"Fog distance (0 = off)","default":36,"min":0,"max":400,"step":2}]'
|
||||
>
|
||||
<head>
|
||||
<script>
|
||||
/* ?play standalone mode only: this file lives in compositions/ but its
|
||||
asset paths are project-root-relative (they resolve there when the
|
||||
runtime inlines it into the host). Never runs for Studio/render. */
|
||||
if (new URLSearchParams(location.search).has("play")) document.write('<base href="../">');
|
||||
</script>
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=1920, height=1080" />
|
||||
<title>Glass Shard Title</title>
|
||||
@@ -103,6 +96,21 @@
|
||||
<span data-hf-id="hf-kqtg" style="font-weight: 400">Aa</span
|
||||
><span data-hf-id="hf-7bxm" style="font-weight: 600">Aa</span>
|
||||
</div>
|
||||
<!-- glass-main.js reads these hrefs: a mounted block's src/href are rebased, strings in its script are not. -->
|
||||
<link
|
||||
id="gst-hdr"
|
||||
rel="preload"
|
||||
as="fetch"
|
||||
crossorigin="anonymous"
|
||||
href="assets/ferndale_studio_01_1k.hdr"
|
||||
/>
|
||||
<link
|
||||
id="gst-matcap"
|
||||
rel="preload"
|
||||
as="image"
|
||||
crossorigin="anonymous"
|
||||
href="assets/matcap-1.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
{
|
||||
"path": "assets/hyperframes-logo-dark.svg",
|
||||
"target": "compositions/assets/hyperframes-logo-dark.svg",
|
||||
"type": "registry:asset"
|
||||
"type": "hyperframes:asset"
|
||||
},
|
||||
{
|
||||
"path": "lib/liquid-glass.iife.js",
|
||||
"target": "compositions/lib/liquid-glass.iife.js",
|
||||
"type": "registry:asset"
|
||||
"type": "hyperframes:asset"
|
||||
}
|
||||
],
|
||||
"preview": {
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
{
|
||||
"path": "assets/hyperframes-logo-dark.svg",
|
||||
"target": "compositions/assets/hyperframes-logo-dark.svg",
|
||||
"type": "registry:asset"
|
||||
"type": "hyperframes:asset"
|
||||
},
|
||||
{
|
||||
"path": "lib/liquid-glass.iife.js",
|
||||
"target": "compositions/lib/liquid-glass.iife.js",
|
||||
"type": "registry:asset"
|
||||
"type": "hyperframes:asset"
|
||||
}
|
||||
],
|
||||
"preview": {
|
||||
|
||||
@@ -100,7 +100,8 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "lt-neon-border.html",
|
||||
"type": "hyperframes:block"
|
||||
"target": "compositions/lt-neon-border.html",
|
||||
"type": "hyperframes:composition"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
|
||||
@@ -20,22 +20,22 @@
|
||||
{
|
||||
"path": "models/iphone.glb",
|
||||
"target": "models/iphone.glb",
|
||||
"type": "asset"
|
||||
"type": "hyperframes:asset"
|
||||
},
|
||||
{
|
||||
"path": "models/macbook.glb",
|
||||
"target": "models/macbook.glb",
|
||||
"type": "asset"
|
||||
"type": "hyperframes:asset"
|
||||
},
|
||||
{
|
||||
"path": "models/hyperframes-mobile.png",
|
||||
"target": "models/hyperframes-mobile.png",
|
||||
"type": "asset"
|
||||
"type": "hyperframes:asset"
|
||||
},
|
||||
{
|
||||
"path": "models/hyperframes-desktop.png",
|
||||
"target": "models/hyperframes-desktop.png",
|
||||
"type": "asset"
|
||||
"type": "hyperframes:asset"
|
||||
}
|
||||
],
|
||||
"preview": {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { withHostedRefs } from "./catalog-script-inlining.ts";
|
||||
import { inlineCatalogScripts, withHostedRefs } from "./catalog-script-inlining.ts";
|
||||
|
||||
const CDN = "https://static.example.com/registry-assets";
|
||||
|
||||
@@ -52,3 +52,40 @@ describe("withHostedRefs", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("glass-shard-title payload", () => {
|
||||
const scriptTag = `<script src="assets/glass-main.js"></script>`;
|
||||
const withGlassMain = (fn: (dir: string) => void) => {
|
||||
const dir = mkdtempSync(join(tmpdir(), "hf-inlining-"));
|
||||
try {
|
||||
mkdirSync(join(dir, "assets"));
|
||||
writeFileSync(join(dir, "assets/glass-main.js"), "window.GLASS = 1;");
|
||||
fn(dir);
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
};
|
||||
|
||||
it("inlines glass-main.js once the hdr link is a data URL", () => {
|
||||
withGlassMain((dir) => {
|
||||
const html = `<link id="gst-hdr" href="data:image/vnd.radiance;base64,AA">${scriptTag}`;
|
||||
const out = inlineCatalogScripts("glass-shard-title", html, dir, {});
|
||||
assert.ok(out.includes("window.GLASS = 1;"));
|
||||
assert.ok(!out.includes(scriptTag));
|
||||
});
|
||||
});
|
||||
|
||||
it("refuses a payload whose hdr link still points at the local file", () => {
|
||||
withGlassMain((dir) => {
|
||||
for (const link of [
|
||||
`<link id="gst-hdr" href="assets/ferndale_studio_01_1k.hdr">`,
|
||||
`<link id='gst-hdr' href='assets/ferndale_studio_01_1k.hdr'>`,
|
||||
]) {
|
||||
assert.throws(
|
||||
() => inlineCatalogScripts("glass-shard-title", link + scriptTag, dir, {}),
|
||||
/hdr <link> was not inlined/,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -227,21 +227,10 @@ ${gsapLoaderJs(vendorUrls)}
|
||||
}
|
||||
|
||||
function inlineGlassScripts(html: string, projectDir: string): string {
|
||||
const hdrRelPath = "assets/ferndale_studio_01_1k.hdr";
|
||||
let glassText = withHostedRefs(
|
||||
readFileSync(join(projectDir, "assets/glass-main.js"), "utf-8"),
|
||||
projectDir,
|
||||
);
|
||||
if (!glassText.includes(hdrRelPath)) {
|
||||
throw new Error(
|
||||
`catalog-script-inlining: glass-main.js no longer references "${hdrRelPath}"; ` +
|
||||
`the hdr substitution needs updating.`,
|
||||
);
|
||||
if (html.includes("assets/ferndale_studio_01_1k.hdr")) {
|
||||
throw new Error("catalog-script-inlining: glass-shard-title's hdr <link> was not inlined.");
|
||||
}
|
||||
const hdrBytes = readFileSync(join(projectDir, hdrRelPath));
|
||||
const hdrDataUrl = `data:application/octet-stream;base64,${hdrBytes.toString("base64")}`;
|
||||
glassText = glassText.split(hdrRelPath).join(hdrDataUrl);
|
||||
|
||||
const glassText = readFileSync(join(projectDir, "assets/glass-main.js"), "utf-8");
|
||||
const bootstrap = `<script>(0,eval)(${jsStringLiteral(glassText)});</script>`;
|
||||
return replaceOnce(
|
||||
html,
|
||||
|
||||
Reference in New Issue
Block a user