hyperframes 0.4.13-alpha.4 → 0.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +110 -6
- package/dist/docs/compositions.md +8 -2
- package/dist/hyperframe-runtime.js +5 -5
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +5 -5
- package/dist/studio/assets/hyperframes-player-vibA20NC.js +198 -0
- package/dist/studio/assets/{index-CXGVO3lH.js → index-Dcn0cnE7.js} +25 -26
- package/dist/studio/assets/index-DhO5JhHF.css +1 -0
- package/dist/studio/index.html +2 -2
- package/package.json +1 -1
- package/dist/studio/assets/hyperframes-player-BOs_kypk.js +0 -198
- package/dist/studio/assets/index-DgkDtcMf.css +0 -1
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ var VERSION;
|
|
|
54
54
|
var init_version = __esm({
|
|
55
55
|
"src/version.ts"() {
|
|
56
56
|
"use strict";
|
|
57
|
-
VERSION = true ? "0.4.
|
|
57
|
+
VERSION = true ? "0.4.14" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -4422,6 +4422,110 @@ var init_core = __esm({
|
|
|
4422
4422
|
});
|
|
4423
4423
|
|
|
4424
4424
|
// ../core/src/lint/rules/media.ts
|
|
4425
|
+
function escapeRegExp(value) {
|
|
4426
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4427
|
+
}
|
|
4428
|
+
function selectorTargetsManagedMedia(selector, mediaIds) {
|
|
4429
|
+
const normalized = selector.trim();
|
|
4430
|
+
if (!normalized) return false;
|
|
4431
|
+
if (/\b(video|audio)\b/i.test(normalized)) return true;
|
|
4432
|
+
for (const mediaId of mediaIds) {
|
|
4433
|
+
if (normalized.includes(`#${mediaId}`) || normalized.includes(`[id="${mediaId}"]`) || normalized.includes(`[id='${mediaId}']`)) {
|
|
4434
|
+
return true;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
return false;
|
|
4438
|
+
}
|
|
4439
|
+
function findImperativeMediaControlFindings(ctx) {
|
|
4440
|
+
const findings = [];
|
|
4441
|
+
const managedMediaIds = new Set(
|
|
4442
|
+
ctx.tags.filter((tag) => tag.name === "video" || tag.name === "audio").map((tag) => readAttr(tag.raw, "id")).filter((id) => Boolean(id))
|
|
4443
|
+
);
|
|
4444
|
+
if (managedMediaIds.size === 0 || ctx.scripts.length === 0) return findings;
|
|
4445
|
+
for (const script of ctx.scripts) {
|
|
4446
|
+
const mediaVars = /* @__PURE__ */ new Map();
|
|
4447
|
+
const assignmentPatterns = [
|
|
4448
|
+
/\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)/g,
|
|
4449
|
+
/\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)/g
|
|
4450
|
+
];
|
|
4451
|
+
for (const pattern of assignmentPatterns) {
|
|
4452
|
+
let match;
|
|
4453
|
+
while ((match = pattern.exec(script.content)) !== null) {
|
|
4454
|
+
const variableName = match[1];
|
|
4455
|
+
const target = match[2];
|
|
4456
|
+
if (!variableName || !target) continue;
|
|
4457
|
+
if (managedMediaIds.has(target) || selectorTargetsManagedMedia(target, managedMediaIds)) {
|
|
4458
|
+
mediaVars.set(variableName, managedMediaIds.has(target) ? target : void 0);
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
}
|
|
4462
|
+
const directIdPatterns = [
|
|
4463
|
+
{
|
|
4464
|
+
pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.play\s*\(/g,
|
|
4465
|
+
kind: "play()"
|
|
4466
|
+
},
|
|
4467
|
+
{
|
|
4468
|
+
pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.pause\s*\(/g,
|
|
4469
|
+
kind: "pause()"
|
|
4470
|
+
},
|
|
4471
|
+
{
|
|
4472
|
+
pattern: /\b(?:document|window\.document)\.getElementById\(\s*["']([^"']+)["']\s*\)\.currentTime\s*=/g,
|
|
4473
|
+
kind: "currentTime"
|
|
4474
|
+
},
|
|
4475
|
+
{
|
|
4476
|
+
pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.play\s*\(/g,
|
|
4477
|
+
kind: "play()"
|
|
4478
|
+
},
|
|
4479
|
+
{
|
|
4480
|
+
pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.pause\s*\(/g,
|
|
4481
|
+
kind: "pause()"
|
|
4482
|
+
},
|
|
4483
|
+
{
|
|
4484
|
+
pattern: /\b(?:document|window\.document)\.querySelector\(\s*["']([^"']+)["']\s*\)\.currentTime\s*=/g,
|
|
4485
|
+
kind: "currentTime"
|
|
4486
|
+
}
|
|
4487
|
+
];
|
|
4488
|
+
for (const { pattern, kind } of directIdPatterns) {
|
|
4489
|
+
let match;
|
|
4490
|
+
while ((match = pattern.exec(script.content)) !== null) {
|
|
4491
|
+
const target = match[1];
|
|
4492
|
+
if (!target) continue;
|
|
4493
|
+
const elementId = managedMediaIds.has(target) ? target : selectorTargetsManagedMedia(target, managedMediaIds) ? void 0 : null;
|
|
4494
|
+
if (elementId === null) continue;
|
|
4495
|
+
findings.push({
|
|
4496
|
+
code: "imperative_media_control",
|
|
4497
|
+
severity: "error",
|
|
4498
|
+
message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,
|
|
4499
|
+
elementId: elementId || void 0,
|
|
4500
|
+
fixHint: "Remove imperative media play/pause/currentTime control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.",
|
|
4501
|
+
snippet: truncateSnippet(match[0])
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
for (const [variableName, elementId] of mediaVars) {
|
|
4506
|
+
const escapedVar = escapeRegExp(variableName);
|
|
4507
|
+
const variablePatterns = [
|
|
4508
|
+
{ pattern: new RegExp(`\\b${escapedVar}\\.play\\s*\\(`, "g"), kind: "play()" },
|
|
4509
|
+
{ pattern: new RegExp(`\\b${escapedVar}\\.pause\\s*\\(`, "g"), kind: "pause()" },
|
|
4510
|
+
{ pattern: new RegExp(`\\b${escapedVar}\\.currentTime\\s*=`, "g"), kind: "currentTime" }
|
|
4511
|
+
];
|
|
4512
|
+
for (const { pattern, kind } of variablePatterns) {
|
|
4513
|
+
let match;
|
|
4514
|
+
while ((match = pattern.exec(script.content)) !== null) {
|
|
4515
|
+
findings.push({
|
|
4516
|
+
code: "imperative_media_control",
|
|
4517
|
+
severity: "error",
|
|
4518
|
+
message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,
|
|
4519
|
+
elementId,
|
|
4520
|
+
fixHint: "Remove imperative media play/pause/currentTime control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.",
|
|
4521
|
+
snippet: truncateSnippet(match[0])
|
|
4522
|
+
});
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
return findings;
|
|
4528
|
+
}
|
|
4425
4529
|
var mediaRules;
|
|
4426
4530
|
var init_media = __esm({
|
|
4427
4531
|
"../core/src/lint/rules/media.ts"() {
|
|
@@ -4649,7 +4753,9 @@ var init_media = __esm({
|
|
|
4649
4753
|
}
|
|
4650
4754
|
}
|
|
4651
4755
|
return findings;
|
|
4652
|
-
}
|
|
4756
|
+
},
|
|
4757
|
+
// imperative_media_control
|
|
4758
|
+
findImperativeMediaControlFindings
|
|
4653
4759
|
];
|
|
4654
4760
|
}
|
|
4655
4761
|
});
|
|
@@ -29622,7 +29728,6 @@ __export(src_exports2, {
|
|
|
29622
29728
|
getEncoderPreset: () => getEncoderPreset,
|
|
29623
29729
|
getFrameAtTime: () => getFrameAtTime,
|
|
29624
29730
|
getHdrEncoderColorParams: () => getHdrEncoderColorParams,
|
|
29625
|
-
getSrgbToHdrLut: () => getSrgbToHdrLut,
|
|
29626
29731
|
getSystemResources: () => getSystemResources,
|
|
29627
29732
|
groupIntoLayers: () => groupIntoLayers,
|
|
29628
29733
|
hdrToLinear: () => hdrToLinear,
|
|
@@ -33095,8 +33200,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
33095
33200
|
)
|
|
33096
33201
|
});
|
|
33097
33202
|
}
|
|
33098
|
-
for (
|
|
33099
|
-
const layer = layers[layerIdx];
|
|
33203
|
+
for (const [layerIdx, layer] of layers.entries()) {
|
|
33100
33204
|
if (layer.type === "hdr") {
|
|
33101
33205
|
const before2 = shouldLog ? countNonZeroRgb482(canvas) : 0;
|
|
33102
33206
|
const isHdrImage = nativeHdrImageIds.has(layer.element.id);
|
|
@@ -34675,7 +34779,7 @@ function createStudioServer(options) {
|
|
|
34675
34779
|
});
|
|
34676
34780
|
app.get("/api/runtime.js", (c2) => {
|
|
34677
34781
|
const serve4 = async () => {
|
|
34678
|
-
const runtimeSource = existsSync31(runtimePath) ? readFileSync23(runtimePath, "utf-8") :
|
|
34782
|
+
const runtimeSource = await loadRuntimeSourceFallback() ?? (existsSync31(runtimePath) ? readFileSync23(runtimePath, "utf-8") : null);
|
|
34679
34783
|
if (!runtimeSource) return c2.text("runtime not available", 404);
|
|
34680
34784
|
return c2.body(runtimeSource, 200, {
|
|
34681
34785
|
"Content-Type": "text/javascript",
|
|
@@ -26,8 +26,14 @@ Use `npx hyperframes compositions` to see all compositions in a project.
|
|
|
26
26
|
|
|
27
27
|
## Variables
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
HyperFrames does not automatically bind `data-var-*` attributes into your composition DOM.
|
|
30
30
|
|
|
31
31
|
```html
|
|
32
|
-
<div
|
|
32
|
+
<div
|
|
33
|
+
data-composition-id="card"
|
|
34
|
+
data-composition-src="compositions/card.html"
|
|
35
|
+
data-variable-values='{"title":"Hello","color":"#ff4d4f"}'
|
|
36
|
+
></div>
|
|
33
37
|
```
|
|
38
|
+
|
|
39
|
+
Read `data-variable-values` inside the nested composition and apply the values in your own script. Variable metadata for tooling is declared separately via `data-composition-variables` and read with `extractCompositionMetadata()`.
|