hyperframes 0.8.68 → 0.8.69
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 -56
- package/dist/fontLocalizeCli.js +25 -10
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/renderSetupWorker.js +7 -7
- package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +5 -23
- package/dist/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/dist/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
- package/dist/skills/media-use/scripts/compatibility.test.mjs +68 -1
- package/dist/studio/assets/{hyperframes-player-RYzFlKye.js → hyperframes-player-B8bDHi2F.js} +1 -1
- package/dist/studio/assets/{index-CsnhFJIv.js → index-784N6Mag.js} +1 -1
- package/dist/studio/assets/{index-P0Rwat37.js → index-Bmd-35nQ.js} +4 -4
- package/dist/studio/assets/{index-C8-wAsq3.js → index-D-JPuFj7.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ var VERSION;
|
|
|
50
50
|
var init_version = __esm({
|
|
51
51
|
"src/version.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
VERSION = true ? "0.8.
|
|
53
|
+
VERSION = true ? "0.8.69" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -84131,17 +84131,17 @@ function mediaSrcTagRe(tagAlternation) {
|
|
|
84131
84131
|
return new RegExp(`<(${tagAlternation})\\b[^>]*\\ssrc\\s*=\\s*["']([^"']+)["'][^>]*>`, "gi");
|
|
84132
84132
|
}
|
|
84133
84133
|
function normalized(source) {
|
|
84134
|
-
|
|
84134
|
+
const chars2 = [];
|
|
84135
84135
|
const offsets = [];
|
|
84136
|
+
let lastWasSpace = false;
|
|
84136
84137
|
for (let i = 0; i < source.length; i++) {
|
|
84137
|
-
const
|
|
84138
|
-
if (
|
|
84139
|
-
|
|
84140
|
-
text2 += " ";
|
|
84141
|
-
} else text2 += char;
|
|
84138
|
+
const isSpace = /\s/.test(source[i]);
|
|
84139
|
+
if (isSpace && lastWasSpace) continue;
|
|
84140
|
+
chars2.push(isSpace ? " " : source[i]);
|
|
84142
84141
|
offsets.push(i);
|
|
84142
|
+
lastWasSpace = isSpace;
|
|
84143
84143
|
}
|
|
84144
|
-
return { text:
|
|
84144
|
+
return { text: chars2.join(""), offsets };
|
|
84145
84145
|
}
|
|
84146
84146
|
function createSourceLocator(source) {
|
|
84147
84147
|
const tags = parseHtmlStructure(source).tags;
|
|
@@ -92408,6 +92408,15 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
92408
92408
|
`FFmpeg exited successfully but produced no frames (start=${startTime}, duration=${duration})`
|
|
92409
92409
|
);
|
|
92410
92410
|
}
|
|
92411
|
+
if (framePaths.size > 0 && duration > 0 && !options.finalFrameOnly) {
|
|
92412
|
+
const expectedAtFps = extractionFrameCountForDuration(duration, normalizedFps, metadata.isVFR);
|
|
92413
|
+
if (expectedAtFps > 0 && framePaths.size <= expectedAtFps * 0.6) {
|
|
92414
|
+
const correctedDuration = startTime + framePaths.size / fps;
|
|
92415
|
+
if (correctedDuration < metadata.videoStreamDurationSeconds) {
|
|
92416
|
+
metadata.videoStreamDurationSeconds = correctedDuration;
|
|
92417
|
+
}
|
|
92418
|
+
}
|
|
92419
|
+
}
|
|
92411
92420
|
return {
|
|
92412
92421
|
videoId,
|
|
92413
92422
|
srcPath: videoPath,
|
|
@@ -109389,14 +109398,6 @@ function decode(raw) {
|
|
|
109389
109398
|
function encode2(json, quote) {
|
|
109390
109399
|
return quote === "'" ? json.replace(/'/g, "'") : json.replace(/"/g, """);
|
|
109391
109400
|
}
|
|
109392
|
-
function optionValues(decl) {
|
|
109393
|
-
return decl.type === "enum" ? decl.options.map((option) => option.value) : null;
|
|
109394
|
-
}
|
|
109395
|
-
function rejectEnum(decl, value) {
|
|
109396
|
-
const options = optionValues(decl);
|
|
109397
|
-
if (!options) return null;
|
|
109398
|
-
return options.includes(String(value)) ? null : `not one of ${options.join(", ")}`;
|
|
109399
|
-
}
|
|
109400
109401
|
function rejectNumber(decl, value) {
|
|
109401
109402
|
if (decl.type !== "number") return null;
|
|
109402
109403
|
const n3 = typeof value === "number" ? value : Number(value);
|
|
@@ -109406,7 +109407,12 @@ function rejectNumber(decl, value) {
|
|
|
109406
109407
|
return null;
|
|
109407
109408
|
}
|
|
109408
109409
|
function reject(decl, value) {
|
|
109409
|
-
|
|
109410
|
+
if (decl.type === "number") return rejectNumber(decl, value);
|
|
109411
|
+
const [issue] = validateVariables({ [decl.id]: value }, [decl]);
|
|
109412
|
+
if (!issue) return null;
|
|
109413
|
+
if (issue.kind === "enum-out-of-range") return `not one of ${issue.allowed.join(", ")}`;
|
|
109414
|
+
if (issue.kind === "type-mismatch") return `expected ${issue.expected}, got ${issue.actual}`;
|
|
109415
|
+
return null;
|
|
109410
109416
|
}
|
|
109411
109417
|
function applyVariableDefaults(source, values) {
|
|
109412
109418
|
const ids = Object.keys(values);
|
|
@@ -109436,7 +109442,7 @@ function applyVariableDefaults(source, values) {
|
|
|
109436
109442
|
invalid.push({ id, reason });
|
|
109437
109443
|
continue;
|
|
109438
109444
|
}
|
|
109439
|
-
updated.set(id, decl.type === "number" ? Number(value) :
|
|
109445
|
+
updated.set(id, decl.type === "number" ? Number(value) : value);
|
|
109440
109446
|
applied.push(id);
|
|
109441
109447
|
}
|
|
109442
109448
|
const unknown = ids.filter((id) => !byId2.has(id));
|
|
@@ -109452,11 +109458,19 @@ ${body}
|
|
|
109452
109458
|
const html = source.slice(0, found.start) + rewritten + source.slice(found.end);
|
|
109453
109459
|
return { html, applied, unknown, invalid };
|
|
109454
109460
|
}
|
|
109455
|
-
var ATTR;
|
|
109461
|
+
var InvalidVariableValuesError, ATTR;
|
|
109456
109462
|
var init_variableDefaults = __esm({
|
|
109457
109463
|
"src/registry/variableDefaults.ts"() {
|
|
109458
109464
|
"use strict";
|
|
109459
109465
|
init_variables();
|
|
109466
|
+
InvalidVariableValuesError = class extends Error {
|
|
109467
|
+
constructor(invalid) {
|
|
109468
|
+
super(`--vars refused: ${invalid.map(({ id, reason }) => `${id}: ${reason}`).join("; ")}`);
|
|
109469
|
+
this.invalid = invalid;
|
|
109470
|
+
this.name = "InvalidVariableValuesError";
|
|
109471
|
+
}
|
|
109472
|
+
invalid;
|
|
109473
|
+
};
|
|
109460
109474
|
ATTR = "data-composition-variables";
|
|
109461
109475
|
}
|
|
109462
109476
|
});
|
|
@@ -109465,7 +109479,9 @@ var init_variableDefaults = __esm({
|
|
|
109465
109479
|
var installer_exports = {};
|
|
109466
109480
|
__export(installer_exports, {
|
|
109467
109481
|
hasLocalEdits: () => hasLocalEdits,
|
|
109468
|
-
installItem: () => installItem
|
|
109482
|
+
installItem: () => installItem,
|
|
109483
|
+
prepareItem: () => prepareItem,
|
|
109484
|
+
publishItem: () => publishItem
|
|
109469
109485
|
});
|
|
109470
109486
|
import { createHash as createHash5 } from "crypto";
|
|
109471
109487
|
import { existsSync as existsSync23, readFileSync as readFileSync14 } from "fs";
|
|
@@ -109498,6 +109514,9 @@ function hasLocalEdits(record2, target, onDisk) {
|
|
|
109498
109514
|
if (!installed) return true;
|
|
109499
109515
|
return installed !== digest(onDisk);
|
|
109500
109516
|
}
|
|
109517
|
+
function keptByProject(record2, destPath, target, force) {
|
|
109518
|
+
return !force && existsSync23(destPath) && hasLocalEdits(record2, target, readFileSync14(destPath));
|
|
109519
|
+
}
|
|
109501
109520
|
function assertSafeTarget(destDir, target) {
|
|
109502
109521
|
if (isAbsolute6(target)) {
|
|
109503
109522
|
throw new Error(`Unsafe target "${target}": absolute paths are not allowed.`);
|
|
@@ -109527,30 +109546,40 @@ function addRegistryItemMarker(source, item) {
|
|
|
109527
109546
|
return `<!-- hyperframes-registry-item: ${item.name} -->
|
|
109528
109547
|
${source}`;
|
|
109529
109548
|
}
|
|
109530
|
-
|
|
109549
|
+
function bakeVariables(item, file, bytes, values) {
|
|
109550
|
+
const component = isInstalledComponentSnippet(item, file);
|
|
109551
|
+
if (!values || !(component || isInstalledRegistryBlockComposition(item, file))) {
|
|
109552
|
+
return { bytes, vars: null };
|
|
109553
|
+
}
|
|
109554
|
+
const vars = applyVariableDefaults(bytes.toString("utf8"), values);
|
|
109555
|
+
const rewrite = component && vars.applied.length > 0;
|
|
109556
|
+
return { bytes: rewrite ? Buffer.from(vars.html) : bytes, vars };
|
|
109557
|
+
}
|
|
109558
|
+
async function prepareOneFile(item, file, destDir, baseUrl, record2, options, budget) {
|
|
109531
109559
|
const destPath = registryTargetPath(destDir, file.target);
|
|
109532
|
-
if (
|
|
109533
|
-
return { destPath, target: file.target, preserved: true, hash: null, vars: null };
|
|
109560
|
+
if (keptByProject(record2, destPath, file.target, options.force)) {
|
|
109561
|
+
return { destPath, target: file.target, preserved: true, hash: null, vars: null, bytes: null };
|
|
109534
109562
|
}
|
|
109535
109563
|
let bytes = await fetchItemFile(item, file, baseUrl, budget);
|
|
109536
109564
|
if (isInstalledRegistryBlockComposition(item, file)) {
|
|
109537
109565
|
bytes = Buffer.from(addRegistryItemMarker(bytes.toString("utf8"), item));
|
|
109538
109566
|
}
|
|
109539
|
-
|
|
109540
|
-
|
|
109541
|
-
|
|
109542
|
-
if (vars.applied.length > 0) bytes = Buffer.from(vars.html);
|
|
109543
|
-
}
|
|
109544
|
-
publishRegistryFile(destDir, file.target, bytes);
|
|
109567
|
+
const baked = bakeVariables(item, file, bytes, options.variableValues);
|
|
109568
|
+
bytes = baked.bytes;
|
|
109569
|
+
const vars = baked.vars;
|
|
109545
109570
|
return {
|
|
109546
109571
|
destPath,
|
|
109547
109572
|
target: file.target,
|
|
109548
109573
|
preserved: false,
|
|
109549
109574
|
hash: digest(bytes),
|
|
109550
|
-
vars
|
|
109575
|
+
vars,
|
|
109576
|
+
bytes
|
|
109551
109577
|
};
|
|
109552
109578
|
}
|
|
109553
109579
|
async function installItem(item, options) {
|
|
109580
|
+
return publishItem(await prepareItem(item, options));
|
|
109581
|
+
}
|
|
109582
|
+
async function prepareItem(item, options) {
|
|
109554
109583
|
if (!validRegistryItem(item, item.name, item.type)) throw new Error("Invalid registry item");
|
|
109555
109584
|
const baseUrl = options.baseUrl ?? DEFAULT_REGISTRY_URL;
|
|
109556
109585
|
const destDir = resolve11(options.destDir);
|
|
@@ -109563,8 +109592,20 @@ async function installItem(item, options) {
|
|
|
109563
109592
|
const budget = { remainingBytes: 512 * 1024 * 1024 };
|
|
109564
109593
|
const outcomes = await installFileBatches(
|
|
109565
109594
|
item.files,
|
|
109566
|
-
(file) =>
|
|
109595
|
+
(file) => prepareOneFile(item, file, root, baseUrl, record2, options, budget)
|
|
109596
|
+
);
|
|
109597
|
+
const invalid = outcomes.flatMap((o) => o.vars?.invalid ?? []);
|
|
109598
|
+
if (invalid.length > 0) throw new InvalidVariableValuesError(invalid);
|
|
109599
|
+
return { root, outcomes, force: options.force ?? false };
|
|
109600
|
+
}
|
|
109601
|
+
function publishItem({ root, outcomes: prepared, force }) {
|
|
109602
|
+
const record2 = readInstallRecord(root);
|
|
109603
|
+
const outcomes = prepared.map(
|
|
109604
|
+
(o) => o.bytes && keptByProject(record2, o.destPath, o.target, force) ? { ...o, preserved: true, hash: null, vars: null, bytes: null } : o
|
|
109567
109605
|
);
|
|
109606
|
+
for (const outcome of outcomes) {
|
|
109607
|
+
if (outcome.bytes) publishRegistryFile(root, outcome.target, outcome.bytes);
|
|
109608
|
+
}
|
|
109568
109609
|
const written = outcomes.filter((o) => !o.preserved).map((o) => o.destPath);
|
|
109569
109610
|
const preserved = outcomes.filter((o) => o.preserved).map((o) => o.destPath);
|
|
109570
109611
|
if (written.length > 0) {
|
|
@@ -109583,8 +109624,7 @@ async function installItem(item, options) {
|
|
|
109583
109624
|
variablesUnknown: vars.length ? vars.reduce(
|
|
109584
109625
|
(acc, v2) => acc.filter((id) => v2.unknown.includes(id)),
|
|
109585
109626
|
vars[0].unknown
|
|
109586
|
-
) : []
|
|
109587
|
-
variablesInvalid: vars.flatMap((v2) => v2.invalid)
|
|
109627
|
+
) : []
|
|
109588
109628
|
};
|
|
109589
109629
|
}
|
|
109590
109630
|
function validatePhysicalTargets(root, files) {
|
|
@@ -109599,10 +109639,10 @@ function validatePhysicalTargets(root, files) {
|
|
|
109599
109639
|
targets.add(key2);
|
|
109600
109640
|
}
|
|
109601
109641
|
}
|
|
109602
|
-
async function installFileBatches(files,
|
|
109642
|
+
async function installFileBatches(files, prepare2) {
|
|
109603
109643
|
const outcomes = [];
|
|
109604
109644
|
for (let at4 = 0; at4 < files.length; at4 += 4) {
|
|
109605
|
-
const batch = await Promise.allSettled(files.slice(at4, at4 + 4).map(
|
|
109645
|
+
const batch = await Promise.allSettled(files.slice(at4, at4 + 4).map(prepare2));
|
|
109606
109646
|
for (const result of batch) {
|
|
109607
109647
|
if (result.status === "rejected") throw result.reason;
|
|
109608
109648
|
outcomes.push(result.value);
|
|
@@ -127640,6 +127680,7 @@ function createProjectWatcher(projectDir) {
|
|
|
127640
127680
|
const listeners = /* @__PURE__ */ new Set();
|
|
127641
127681
|
const pendingPaths = /* @__PURE__ */ new Set();
|
|
127642
127682
|
let debounceTimer = null;
|
|
127683
|
+
let lastFlushAt = Number.NEGATIVE_INFINITY;
|
|
127643
127684
|
let closeTree = null;
|
|
127644
127685
|
try {
|
|
127645
127686
|
closeTree = watchProjectTree(projectDir, (relativePath) => {
|
|
@@ -127648,16 +127689,18 @@ function createProjectWatcher(projectDir) {
|
|
|
127648
127689
|
}
|
|
127649
127690
|
pendingPaths.add(relativePath);
|
|
127650
127691
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
127692
|
+
const delay2 = Math.max(QUIET_MS, lastFlushAt + BURST_MS - Date.now());
|
|
127651
127693
|
debounceTimer = setTimeout(() => {
|
|
127652
127694
|
const changedPaths = [...pendingPaths];
|
|
127653
127695
|
pendingPaths.clear();
|
|
127654
127696
|
debounceTimer = null;
|
|
127697
|
+
lastFlushAt = Date.now();
|
|
127655
127698
|
for (const changedPath of changedPaths) {
|
|
127656
127699
|
for (const fn of listeners) {
|
|
127657
127700
|
fn(changedPath);
|
|
127658
127701
|
}
|
|
127659
127702
|
}
|
|
127660
|
-
},
|
|
127703
|
+
}, delay2);
|
|
127661
127704
|
});
|
|
127662
127705
|
} catch {
|
|
127663
127706
|
}
|
|
@@ -127676,7 +127719,7 @@ function createProjectWatcher(projectDir) {
|
|
|
127676
127719
|
}
|
|
127677
127720
|
};
|
|
127678
127721
|
}
|
|
127679
|
-
var WATCHER_EXCLUDED_DIRS,
|
|
127722
|
+
var WATCHER_EXCLUDED_DIRS, QUIET_MS, BURST_MS;
|
|
127680
127723
|
var init_fileWatcher = __esm({
|
|
127681
127724
|
"src/server/fileWatcher.ts"() {
|
|
127682
127725
|
"use strict";
|
|
@@ -127697,7 +127740,8 @@ var init_fileWatcher = __esm({
|
|
|
127697
127740
|
"outputs",
|
|
127698
127741
|
"renders"
|
|
127699
127742
|
]);
|
|
127700
|
-
|
|
127743
|
+
QUIET_MS = 30;
|
|
127744
|
+
BURST_MS = 300;
|
|
127701
127745
|
}
|
|
127702
127746
|
});
|
|
127703
127747
|
|
|
@@ -138837,6 +138881,12 @@ function resolveFontFetchRetryPolicy(configured) {
|
|
|
138837
138881
|
)
|
|
138838
138882
|
};
|
|
138839
138883
|
}
|
|
138884
|
+
function placeAfterEveryStylesheet(document2, head, styleEl) {
|
|
138885
|
+
const stylesheets = document2.querySelectorAll("style, link[rel~=stylesheet]");
|
|
138886
|
+
const lastStylesheet = stylesheets[stylesheets.length - 1];
|
|
138887
|
+
if (lastStylesheet) lastStylesheet.after(styleEl);
|
|
138888
|
+
else head.appendChild(styleEl);
|
|
138889
|
+
}
|
|
138840
138890
|
async function injectDeterministicFontFaces(html, options = {}) {
|
|
138841
138891
|
const failClosedFontFetch = options.failClosedFontFetch === true;
|
|
138842
138892
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
@@ -138887,7 +138937,7 @@ async function injectDeterministicFontFaces(html, options = {}) {
|
|
|
138887
138937
|
const styleEl = document2.createElement("style");
|
|
138888
138938
|
styleEl.setAttribute("data-hyperframes-deterministic-fonts", "true");
|
|
138889
138939
|
styleEl.textContent = css;
|
|
138890
|
-
|
|
138940
|
+
placeAfterEveryStylesheet(document2, head, styleEl);
|
|
138891
138941
|
defaultLogger.info(
|
|
138892
138942
|
`[Compiler] Injected deterministic @font-face rules for ${pendingFamilies.size - unresolved.length} requested font families`
|
|
138893
138943
|
);
|
|
@@ -155594,29 +155644,34 @@ async function installAll(installPlan, destDir, baseUrl, force, requestedName, v
|
|
|
155594
155644
|
const preserved = [];
|
|
155595
155645
|
let variablesApplied = [];
|
|
155596
155646
|
let variablesUnknown = [];
|
|
155597
|
-
let variablesInvalid = [];
|
|
155598
155647
|
try {
|
|
155648
|
+
const prepared = [];
|
|
155599
155649
|
for (const planItem of installPlan) {
|
|
155600
|
-
|
|
155601
|
-
|
|
155602
|
-
|
|
155603
|
-
|
|
155604
|
-
|
|
155605
|
-
|
|
155606
|
-
|
|
155607
|
-
|
|
155650
|
+
prepared.push(
|
|
155651
|
+
await prepareItem(planItem, {
|
|
155652
|
+
destDir,
|
|
155653
|
+
baseUrl,
|
|
155654
|
+
force,
|
|
155655
|
+
// Only the item the user named. A dependency dragged in behind it never
|
|
155656
|
+
// declared these variables and must not be rewritten by them.
|
|
155657
|
+
variableValues: planItem.name === requestedName ? variableValues : null
|
|
155658
|
+
})
|
|
155659
|
+
);
|
|
155660
|
+
}
|
|
155661
|
+
for (const [i, planItem] of installPlan.entries()) {
|
|
155662
|
+
const result = publishItem(prepared[i]);
|
|
155608
155663
|
written.push(...result.written);
|
|
155609
155664
|
preserved.push(...result.preserved);
|
|
155610
155665
|
if (planItem.name === requestedName) {
|
|
155611
155666
|
variablesApplied = result.variablesApplied;
|
|
155612
155667
|
variablesUnknown = result.variablesUnknown;
|
|
155613
|
-
variablesInvalid = result.variablesInvalid;
|
|
155614
155668
|
}
|
|
155615
155669
|
}
|
|
155616
155670
|
} catch (err) {
|
|
155671
|
+
if (err instanceof InvalidVariableValuesError) throw new AddError(err.message, "invalid-vars");
|
|
155617
155672
|
throw new AddError(describeInstallFailure(err, baseUrl), "install-failed");
|
|
155618
155673
|
}
|
|
155619
|
-
return { written, preserved, variablesApplied, variablesUnknown
|
|
155674
|
+
return { written, preserved, variablesApplied, variablesUnknown };
|
|
155620
155675
|
}
|
|
155621
155676
|
function describeInstallFailure(err, registry) {
|
|
155622
155677
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -155659,7 +155714,7 @@ async function runAdd(opts) {
|
|
|
155659
155714
|
}))
|
|
155660
155715
|
}));
|
|
155661
155716
|
const variableValues = parseVariableValues(opts.vars);
|
|
155662
|
-
const { written, preserved, variablesApplied, variablesUnknown
|
|
155717
|
+
const { written, preserved, variablesApplied, variablesUnknown } = await installAll(
|
|
155663
155718
|
installPlan,
|
|
155664
155719
|
projectDir,
|
|
155665
155720
|
config.registry,
|
|
@@ -155686,9 +155741,6 @@ async function runAdd(opts) {
|
|
|
155686
155741
|
const snippetTargetRel = primaryInstalledTarget(itemForInstall);
|
|
155687
155742
|
const snippet = buildSnippet(item, snippetTargetRel, variableValues);
|
|
155688
155743
|
const clipboardCopied = !opts.skipClipboard && snippet ? copyToClipboard(snippet) : false;
|
|
155689
|
-
for (const { id, reason } of variablesInvalid) {
|
|
155690
|
-
warnings.push(`--vars ${id} ignored: ${reason}`);
|
|
155691
|
-
}
|
|
155692
155744
|
if (variablesUnknown.length > 0) {
|
|
155693
155745
|
warnings.push(`--vars ignored (not declared by ${item.name}): ${variablesUnknown.join(", ")}`);
|
|
155694
155746
|
}
|
|
@@ -155716,6 +155768,7 @@ var init_add = __esm({
|
|
|
155716
155768
|
init_colors();
|
|
155717
155769
|
init_registry3();
|
|
155718
155770
|
init_resolver();
|
|
155771
|
+
init_variableDefaults();
|
|
155719
155772
|
init_compatibility();
|
|
155720
155773
|
init_projectConfig();
|
|
155721
155774
|
init_clipboard();
|
|
@@ -155870,8 +155923,9 @@ var init_add = __esm({
|
|
|
155870
155923
|
if (!json) console.log(` ${c.warn("Warning:")} ${warning}`);
|
|
155871
155924
|
}
|
|
155872
155925
|
if (!json) console.log(` ${c.success("\u2713")} ${result.name}`);
|
|
155873
|
-
} catch {
|
|
155874
|
-
|
|
155926
|
+
} catch (err) {
|
|
155927
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
155928
|
+
if (!json) console.log(` ${c.error("\u2717")} ${item.name} (skipped: ${reason})`);
|
|
155875
155929
|
}
|
|
155876
155930
|
}
|
|
155877
155931
|
if (json) {
|
package/dist/fontLocalizeCli.js
CHANGED
|
@@ -72911,17 +72911,17 @@ function truncateSnippet(value, maxLength = 220) {
|
|
|
72911
72911
|
return `${normalized2.slice(0, maxLength - 3)}...`;
|
|
72912
72912
|
}
|
|
72913
72913
|
function normalized(source) {
|
|
72914
|
-
|
|
72914
|
+
const chars = [];
|
|
72915
72915
|
const offsets = [];
|
|
72916
|
+
let lastWasSpace = false;
|
|
72916
72917
|
for (let i = 0; i < source.length; i++) {
|
|
72917
|
-
const
|
|
72918
|
-
if (
|
|
72919
|
-
|
|
72920
|
-
text += " ";
|
|
72921
|
-
} else text += char;
|
|
72918
|
+
const isSpace = /\s/.test(source[i]);
|
|
72919
|
+
if (isSpace && lastWasSpace) continue;
|
|
72920
|
+
chars.push(isSpace ? " " : source[i]);
|
|
72922
72921
|
offsets.push(i);
|
|
72922
|
+
lastWasSpace = isSpace;
|
|
72923
72923
|
}
|
|
72924
|
-
return { text, offsets };
|
|
72924
|
+
return { text: chars.join(""), offsets };
|
|
72925
72925
|
}
|
|
72926
72926
|
function createSourceLocator(source) {
|
|
72927
72927
|
const tags = parseHtmlStructure(source).tags;
|
|
@@ -79430,6 +79430,15 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
79430
79430
|
`FFmpeg exited successfully but produced no frames (start=${startTime}, duration=${duration})`
|
|
79431
79431
|
);
|
|
79432
79432
|
}
|
|
79433
|
+
if (framePaths.size > 0 && duration > 0 && !options.finalFrameOnly) {
|
|
79434
|
+
const expectedAtFps = extractionFrameCountForDuration(duration, normalizedFps, metadata.isVFR);
|
|
79435
|
+
if (expectedAtFps > 0 && framePaths.size <= expectedAtFps * 0.6) {
|
|
79436
|
+
const correctedDuration = startTime + framePaths.size / fps;
|
|
79437
|
+
if (correctedDuration < metadata.videoStreamDurationSeconds) {
|
|
79438
|
+
metadata.videoStreamDurationSeconds = correctedDuration;
|
|
79439
|
+
}
|
|
79440
|
+
}
|
|
79441
|
+
}
|
|
79433
79442
|
return {
|
|
79434
79443
|
videoId,
|
|
79435
79444
|
srcPath: videoPath,
|
|
@@ -94205,6 +94214,12 @@ function resolveFontFetchRetryPolicy(configured) {
|
|
|
94205
94214
|
)
|
|
94206
94215
|
};
|
|
94207
94216
|
}
|
|
94217
|
+
function placeAfterEveryStylesheet(document2, head, styleEl) {
|
|
94218
|
+
const stylesheets = document2.querySelectorAll("style, link[rel~=stylesheet]");
|
|
94219
|
+
const lastStylesheet = stylesheets[stylesheets.length - 1];
|
|
94220
|
+
if (lastStylesheet) lastStylesheet.after(styleEl);
|
|
94221
|
+
else head.appendChild(styleEl);
|
|
94222
|
+
}
|
|
94208
94223
|
async function injectDeterministicFontFaces(html, options = {}) {
|
|
94209
94224
|
const failClosedFontFetch = options.failClosedFontFetch === true;
|
|
94210
94225
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
@@ -94255,7 +94270,7 @@ async function injectDeterministicFontFaces(html, options = {}) {
|
|
|
94255
94270
|
const styleEl = document2.createElement("style");
|
|
94256
94271
|
styleEl.setAttribute("data-hyperframes-deterministic-fonts", "true");
|
|
94257
94272
|
styleEl.textContent = css;
|
|
94258
|
-
|
|
94273
|
+
placeAfterEveryStylesheet(document2, head, styleEl);
|
|
94259
94274
|
defaultLogger.info(
|
|
94260
94275
|
`[Compiler] Injected deterministic @font-face rules for ${pendingFamilies.size - unresolved.length} requested font families`
|
|
94261
94276
|
);
|
|
@@ -103722,8 +103737,8 @@ async function runFontLocalize(io, localize) {
|
|
|
103722
103737
|
}
|
|
103723
103738
|
|
|
103724
103739
|
// src/version.ts
|
|
103725
|
-
var VERSION = true ? "0.8.
|
|
103726
|
-
var PRODUCER_VERSION = true ? "0.8.
|
|
103740
|
+
var VERSION = true ? "0.8.69" : "0.0.0-dev";
|
|
103741
|
+
var PRODUCER_VERSION = true ? "0.8.69" : "0.0.0-dev";
|
|
103727
103742
|
|
|
103728
103743
|
// src/fontLocalizeCli.ts
|
|
103729
103744
|
async function readStdin() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var HyperframesPlayer=(()=>{var Se=Object.defineProperty;var fn=Object.getOwnPropertyDescriptor;var hn=Object.getOwnPropertyNames;var bn=Object.prototype.hasOwnProperty;var gn=(n,e)=>{for(var t in e)Se(n,t,{get:e[t],enumerable:!0})},_n=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of hn(e))!bn.call(n,r)&&r!==t&&Se(n,r,{get:()=>e[r],enumerable:!(i=fn(e,r))||i.enumerable});return n};var yn=n=>_n(Se({},"__esModule",{value:!0}),n);var Xi={};gn(Xi,{HyperframesPlayer:()=>Ee,SPEED_PRESETS:()=>we,formatSpeed:()=>G,formatTime:()=>ie});function ct(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function H(n){return typeof n=="object"&&n!==null}function mt(n){return H(n)&&typeof n.getDuration=="function"}function pt(n){return H(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}var L="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.
|
|
1
|
+
"use strict";var HyperframesPlayer=(()=>{var Se=Object.defineProperty;var fn=Object.getOwnPropertyDescriptor;var hn=Object.getOwnPropertyNames;var bn=Object.prototype.hasOwnProperty;var gn=(n,e)=>{for(var t in e)Se(n,t,{get:e[t],enumerable:!0})},_n=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of hn(e))!bn.call(n,r)&&r!==t&&Se(n,r,{get:()=>e[r],enumerable:!(i=fn(e,r))||i.enumerable});return n};var yn=n=>_n(Se({},"__esModule",{value:!0}),n);var Xi={};gn(Xi,{HyperframesPlayer:()=>Ee,SPEED_PRESETS:()=>we,formatSpeed:()=>G,formatTime:()=>ie});function ct(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function H(n){return typeof n=="object"&&n!==null}function mt(n){return H(n)&&typeof n.getDuration=="function"}function pt(n){return H(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}var L="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.69/dist/hyperframe.runtime.iife.js";function V(n){if(n===null)return null;let e=Number.parseInt(n,10);return Number.isFinite(e)&&e>0?e:null}function vn(n){let e=n?.querySelector("[data-composition-id][data-width][data-height]")??n?.querySelector("[data-width][data-height]");if(!e)return null;let t=V(e.getAttribute("data-width")),i=V(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var ne=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),r=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(ct({hasRuntime:i,hasTimelines:r,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let a=this._resolvePlaybackDurationAdapter(t);if(a&&a.getDuration()>0){this.stop();let s=vn(this._iframe.contentDocument);this._callbacks.onReady({duration:a.getDuration(),adapter:a,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||H(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=L,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!H(t))return null;let i=Object.keys(t);if(i.length===0)return null;let r=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=r&&r in t?r:i[i.length-1],a=t[o];return pt(a)?a:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(mt(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var ft=`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
position: relative;
|
|
@@ -25768,17 +25768,17 @@ function mediaSrcTagRe(tagAlternation) {
|
|
|
25768
25768
|
return new RegExp(`<(${tagAlternation})\\b[^>]*\\ssrc\\s*=\\s*["']([^"']+)["'][^>]*>`, "gi");
|
|
25769
25769
|
}
|
|
25770
25770
|
function normalized(source) {
|
|
25771
|
-
|
|
25771
|
+
const chars = [];
|
|
25772
25772
|
const offsets = [];
|
|
25773
|
+
let lastWasSpace = false;
|
|
25773
25774
|
for (let i = 0; i < source.length; i++) {
|
|
25774
|
-
const
|
|
25775
|
-
if (
|
|
25776
|
-
|
|
25777
|
-
text += " ";
|
|
25778
|
-
} else text += char;
|
|
25775
|
+
const isSpace = /\s/.test(source[i]);
|
|
25776
|
+
if (isSpace && lastWasSpace) continue;
|
|
25777
|
+
chars.push(isSpace ? " " : source[i]);
|
|
25779
25778
|
offsets.push(i);
|
|
25779
|
+
lastWasSpace = isSpace;
|
|
25780
25780
|
}
|
|
25781
|
-
return { text, offsets };
|
|
25781
|
+
return { text: chars.join(""), offsets };
|
|
25782
25782
|
}
|
|
25783
25783
|
function createSourceLocator(source) {
|
|
25784
25784
|
const tags = parseHtmlStructure(source).tags;
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// its own paths (animation skill, role delta, design-truth resolution, extra packet
|
|
5
|
-
// sections) and delegates everything else here, exactly as the markdown half already
|
|
6
|
-
// does with `references/frame-worker-core.md` + each workflow's delta. One owner for
|
|
7
|
-
// the packet-building logic; the wrappers own only what genuinely differs per workflow.
|
|
8
|
-
//
|
|
9
|
-
// Packet (<frame_id>.md) = project inputs + the frame's exact `## Frame N` block
|
|
10
|
-
// + the blueprint body + every cited rule recipe, inlined — so a worker never opens
|
|
11
|
-
// the shared STORYBOARD.md or any skill document. Cited motions are found
|
|
12
|
-
// mechanically: the explicit `- rules:` field when present, plus every valid rule id
|
|
13
|
-
// (a filename under the animation skill's rules/) mentioned in the block.
|
|
14
|
-
//
|
|
15
|
-
// _role.md = frame-worker-core.md + the workflow's sub-agents/frame-worker.md,
|
|
16
|
-
// concatenated verbatim — the complete worker role, assembled from the two source
|
|
17
|
-
// documents so nothing is hand-maintained twice.
|
|
1
|
+
// Frame packets inline the storyboard frame, blueprint and cited recipes.
|
|
2
|
+
// Workflow wrappers supply resource paths and workflow-specific sections.
|
|
3
|
+
// The role combines the shared worker contract with the workflow delta.
|
|
18
4
|
|
|
19
5
|
import {
|
|
20
6
|
existsSync,
|
|
@@ -100,12 +86,8 @@ export function resourceSections(block, { animationDir, ruleIds, frameId }) {
|
|
|
100
86
|
if (blueprint) {
|
|
101
87
|
const blueprintsDir = join(animationDir, "blueprints");
|
|
102
88
|
const path = join(blueprintsDir, `${blueprint}.md`);
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
// the run still reported success. Name it instead — but only when the library
|
|
106
|
-
// is actually there to be named against. The animation skill installs on
|
|
107
|
-
// demand, so an absent blueprints/ is a missing install, not a bad id, and it
|
|
108
|
-
// degrades with a warning exactly like an absent rules/ (see knownRuleIds).
|
|
89
|
+
// An installed library must contain the named blueprint.
|
|
90
|
+
// An absent on-demand library warns, like missing motion rules.
|
|
109
91
|
if (!existsSync(blueprintsDir)) {
|
|
110
92
|
console.warn(
|
|
111
93
|
`frame-packets: no blueprints dir at ${blueprintsDir} — packets will inline no blueprint`,
|
|
@@ -20,12 +20,8 @@ import { pythonInvocation } from "./python.mjs";
|
|
|
20
20
|
const r3 = (x) => Number(x.toFixed(3));
|
|
21
21
|
const lyriaKey = () => process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY || "";
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// beneath, so BGM sits forward at 0.9. Callers may override per composition.
|
|
26
|
-
export const BGM_BED_VOLUME = 0.12;
|
|
27
|
-
export const BGM_SILENT_VOLUME = 0.9;
|
|
28
|
-
export const bgmDefaultVolume = (hasVoice) => (hasVoice ? BGM_BED_VOLUME : BGM_SILENT_VOLUME);
|
|
23
|
+
import { bgmDefaultVolume } from "./bgm-volume.mjs";
|
|
24
|
+
export { BGM_BED_VOLUME, BGM_SILENT_VOLUME, bgmDefaultVolume } from "./bgm-volume.mjs";
|
|
29
25
|
|
|
30
26
|
const BGM_PY_DEPS = ["transformers", "torch", "soundfile", "numpy"];
|
|
31
27
|
const BGM_PY_PROBE =
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { tmpdir } from "node:os";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { execFileSync } from "node:child_process";
|
|
5
6
|
import test from "node:test";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
6
8
|
|
|
7
9
|
function run(scriptsDir, script, args) {
|
|
8
10
|
return execFileSync(process.execPath, [join(scriptsDir, script), ...args], {
|
|
@@ -25,3 +27,68 @@ test("published memory scripts run without reaching outside the skill", () => {
|
|
|
25
27
|
rmSync(scratchDir, { recursive: true, force: true });
|
|
26
28
|
}
|
|
27
29
|
});
|
|
30
|
+
|
|
31
|
+
test("published audio helpers import without the CLI package tree", () => {
|
|
32
|
+
const root = mkdtempSync(join(tmpdir(), "media-use-audio-"));
|
|
33
|
+
const skill = join(root, "media-use");
|
|
34
|
+
try {
|
|
35
|
+
cpSync(new URL("..", import.meta.url), skill, { recursive: true });
|
|
36
|
+
for (const helper of ["heygen.mjs", "tts.mjs"])
|
|
37
|
+
run(join(skill, "audio/scripts/lib"), helper, []);
|
|
38
|
+
} finally {
|
|
39
|
+
rmSync(root, { recursive: true, force: true });
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
for (const name of ["faceless-explainer", "pr-to-video", "product-launch-video"]) {
|
|
44
|
+
test(name + " assembles from its installed directory alone", () => {
|
|
45
|
+
const root = mkdtempSync(join(tmpdir(), "installed-workflow-"));
|
|
46
|
+
try {
|
|
47
|
+
const skill = join(root, name);
|
|
48
|
+
cpSync(new URL("../../" + name, import.meta.url), skill, { recursive: true });
|
|
49
|
+
const project = join(root, "project");
|
|
50
|
+
mkdirSync(join(project, "compositions/frames"), { recursive: true });
|
|
51
|
+
writeFileSync(
|
|
52
|
+
join(project, "STORYBOARD.md"),
|
|
53
|
+
"---\nformat: 1920x1080\nmessage: Test\n---\n\n## Frame 1\n- duration: 3s\n- src: compositions/frames/01-a.html\n",
|
|
54
|
+
);
|
|
55
|
+
writeFileSync(
|
|
56
|
+
join(project, "compositions/frames/01-a.html"),
|
|
57
|
+
'<template><div data-composition-id="01-a" data-duration="3" data-width="1920" data-height="1080"><section class="clip" data-start="0" data-duration="3"></section></div></template>',
|
|
58
|
+
);
|
|
59
|
+
run(join(skill, "scripts"), "assemble-index.mjs", [
|
|
60
|
+
"--hyperframes",
|
|
61
|
+
project,
|
|
62
|
+
"--storyboard",
|
|
63
|
+
join(project, "STORYBOARD.md"),
|
|
64
|
+
]);
|
|
65
|
+
assert.match(readFileSync(join(project, "index.html"), "utf8"), /01-a/);
|
|
66
|
+
importPacketBuilder(join(skill, "scripts/frame-packets.mjs"));
|
|
67
|
+
} finally {
|
|
68
|
+
rmSync(root, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("general-video packet builder starts from its installed directory alone", () => {
|
|
74
|
+
const root = mkdtempSync(join(tmpdir(), "installed-packets-"));
|
|
75
|
+
try {
|
|
76
|
+
cpSync(new URL("../../general-video", import.meta.url), root, { recursive: true });
|
|
77
|
+
importPacketBuilder(join(root, "scripts/frame-packets.mjs"));
|
|
78
|
+
} finally {
|
|
79
|
+
rmSync(root, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
function importPacketBuilder(path) {
|
|
84
|
+
execFileSync(
|
|
85
|
+
process.execPath,
|
|
86
|
+
[
|
|
87
|
+
"--input-type=module",
|
|
88
|
+
"-e",
|
|
89
|
+
'const m = await import(process.argv[1]); if (typeof m.buildFramePackets !== "function") throw new Error("missing builder");',
|
|
90
|
+
pathToFileURL(path).href,
|
|
91
|
+
],
|
|
92
|
+
{ stdio: "pipe" },
|
|
93
|
+
);
|
|
94
|
+
}
|