@hyperframes/core 0.8.188 → 0.8.190

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/index.d.ts CHANGED
@@ -32,7 +32,7 @@ export { clearGifFramesBeforeNext, gifClearsAfterLeavingFrameInPlace, parseAnima
32
32
  export { HF_COLOR_GRADING_ATTR, HF_COLOR_GRADING_ADJUST_KEYS, HF_COLOR_GRADING_ACTIVE_EFFECT_KEYS, HF_COLOR_GRADING_ANIMATABLE_PROPERTIES, HF_COLOR_GRADING_CANVAS_ID_PREFIX, HF_COLOR_GRADING_COLOR_SPACE, HF_COLOR_GRADING_CURVE_KEYS, HF_COLOR_GRADING_DETAIL_KEYS, HF_COLOR_GRADING_EFFECT_APPLY_DEFAULTS, HF_COLOR_GRADING_EFFECT_KEYS, HF_COLOR_GRADING_EFFECT_PRESETS, HF_COLOR_GRADING_GRADE_PRESETS, HF_COLOR_GRADING_HUE_CURVE_KEYS, HF_COLOR_GRADING_LUT_KEYS, HF_COLOR_GRADING_PALETTES, HF_COLOR_GRADING_PRESETS, HF_COLOR_GRADING_TOP_LEVEL_KEYS, HF_COLOR_GRADING_WHEEL_KEYS, getHfColorGradingCapabilities, hasHfColorGradingAuthoredValues, isHfColorGradingActive, normalizeHfColorGrading, normalizeHfColorGradingWithVariables, resolveHfColorGradingVariables, serializeHfColorGrading, type HfColorGrading, type HfColorGradingAdjust, type HfColorGradingAdjustKey, type HfColorGradingAnimatablePath, type HfColorGradingActiveEffectKey, type HfColorGradingDetailKey, type HfColorGradingDetails, type HfColorGradingEffectKey, type HfColorGradingEffects, type HfColorGradingLutRef, type HfColorGradingPreset, type HfColorGradingPresetId, type HfColorGradingTarget, type HfColorGradingVariableMap, type HfColorGradingCapabilities, type HfColorGradingCurveKey, type HfColorGradingCurves, type HfColorGradingHueCurveKey, type HfColorGradingHueCurves, type HfColorGradingHueRange, type HfColorGradingSecondary, type HfColorGradingSecondaryCorrection, type HfColorGradingSoftRange, type HfColorGradingTonalWheel, type HfColorGradingWheelKey, type HfColorGradingWheels, type HfColorCurvePoint, type HfHueCurvePoint, type NormalizedHfColorGrading, type NormalizedHfColorGradingCurves, type NormalizedHfColorGradingHueCurves, type NormalizedHfColorGradingSecondary, type NormalizedHfColorGradingWheels, type ResolvedHfColorGrading, } from "./colorGrading.js";
33
33
  export { parseCubeLut, CubeLutParseError, type ParseCubeLutOptions } from "./colorLuts.js";
34
34
  export { firstFrameColourArgs, hdrToSdrToneMapFilter, parseFirstFrameColour, type ToneMapSourceColour, } from "./hdrToneMap.js";
35
- export { PREVIEW_PROXY_BOX_PARAM, formatPreviewProxyBox, parsePreviewProxyBox, type PreviewProxyBox, } from "./previewProxyBox.js";
35
+ export { PREVIEW_PROXY_BOX_PARAM, formatPreviewProxyBox, parsePreviewProxyBox, quantizePreviewProxyBox, type PreviewProxyBox, } from "./previewProxyBox.js";
36
36
  export { HYPERFRAME_RUNTIME_ARTIFACTS, HYPERFRAME_RUNTIME_CONTRACT, loadHyperframeRuntimeSource, type HyperframeRuntimeContract, } from "./inline-scripts/hyperframe.js";
37
37
  export { HYPERFRAME_RUNTIME_GLOBALS, HYPERFRAME_BRIDGE_SOURCES, HYPERFRAME_CONTROL_ACTIONS, type HyperframeControlAction, } from "./inline-scripts/runtimeContract.js";
38
38
  export { getHyperframeRuntimeScript } from "./generated/runtime-inline.js";
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ export { clearGifFramesBeforeNext, gifClearsAfterLeavingFrameInPlace, parseAnima
28
28
  export { HF_COLOR_GRADING_ATTR, HF_COLOR_GRADING_ADJUST_KEYS, HF_COLOR_GRADING_ACTIVE_EFFECT_KEYS, HF_COLOR_GRADING_ANIMATABLE_PROPERTIES, HF_COLOR_GRADING_CANVAS_ID_PREFIX, HF_COLOR_GRADING_COLOR_SPACE, HF_COLOR_GRADING_CURVE_KEYS, HF_COLOR_GRADING_DETAIL_KEYS, HF_COLOR_GRADING_EFFECT_APPLY_DEFAULTS, HF_COLOR_GRADING_EFFECT_KEYS, HF_COLOR_GRADING_EFFECT_PRESETS, HF_COLOR_GRADING_GRADE_PRESETS, HF_COLOR_GRADING_HUE_CURVE_KEYS, HF_COLOR_GRADING_LUT_KEYS, HF_COLOR_GRADING_PALETTES, HF_COLOR_GRADING_PRESETS, HF_COLOR_GRADING_TOP_LEVEL_KEYS, HF_COLOR_GRADING_WHEEL_KEYS, getHfColorGradingCapabilities, hasHfColorGradingAuthoredValues, isHfColorGradingActive, normalizeHfColorGrading, normalizeHfColorGradingWithVariables, resolveHfColorGradingVariables, serializeHfColorGrading, } from "./colorGrading.js";
29
29
  export { parseCubeLut, CubeLutParseError } from "./colorLuts.js";
30
30
  export { firstFrameColourArgs, hdrToSdrToneMapFilter, parseFirstFrameColour, } from "./hdrToneMap.js";
31
- export { PREVIEW_PROXY_BOX_PARAM, formatPreviewProxyBox, parsePreviewProxyBox, } from "./previewProxyBox.js";
31
+ export { PREVIEW_PROXY_BOX_PARAM, formatPreviewProxyBox, parsePreviewProxyBox, quantizePreviewProxyBox, } from "./previewProxyBox.js";
32
32
  // Inline scripts
33
33
  export { HYPERFRAME_RUNTIME_ARTIFACTS, HYPERFRAME_RUNTIME_CONTRACT, loadHyperframeRuntimeSource, } from "./inline-scripts/hyperframe.js";
34
34
  export { HYPERFRAME_RUNTIME_GLOBALS, HYPERFRAME_BRIDGE_SOURCES, HYPERFRAME_CONTROL_ACTIONS, } from "./inline-scripts/runtimeContract.js";
@@ -9,6 +9,7 @@ import { rateAt, sourceTimeAt, timeAtSourceTime } from "../speedRamp.js";
9
9
  import { clampAudioGain, clipGain, gainTimesLane } from "../audioGain.js";
10
10
  import { isMemberGroupHidden } from "../audioGroups.js";
11
11
  import { findInjectedRenderFrame } from "./renderFrameSibling.js";
12
+ import { isRenderFrameVideo } from "./preloadMedia.js";
12
13
  import { registerSeekCompletion } from "./adapters/seek-dispatch.js";
13
14
  import { cutToHostSlots } from "../mediaTiming.js";
14
15
  export { readElementPlaybackRate, readElementRateSpec, resolveNaturalMediaTimelineDuration, } from "./playbackRate.js";
@@ -401,7 +402,7 @@ export function syncRuntimeMedia(params) {
401
402
  // past the buffered range. Setting this on every tick is cheap
402
403
  // (no-op when already "auto") and catches elements whose preload
403
404
  // was overridden after init.ts set it.
404
- if (el.preload !== "auto")
405
+ if (el.preload !== "auto" && !isRenderFrameVideo(el))
405
406
  el.preload = "auto";
406
407
  // Per-element rate × global transport rate
407
408
  const baseRate = rateAt(clipRate, params.timeSeconds - origin) * params.playbackRate;
@@ -0,0 +1,11 @@
1
+ type PreloadableMedia = Pick<HTMLMediaElement, "id" | "tagName" | "getAttribute" | "preload" | "readyState" | "networkState" | "load">;
2
+ export declare function isRenderFrameVideo(media: Pick<Element, "getAttribute" | "id" | "tagName">): boolean;
3
+ export declare function preloadMedia(media: PreloadableMedia): void;
4
+ /** Ends a fetch in flight for good, which preload none alone does not. */
5
+ export declare function stopMediaDownload(media: HTMLMediaElement): void;
6
+ export declare function releaseMedia(media: HTMLMediaElement): void;
7
+ export declare function lengthIsAuthored(media: Element): boolean;
8
+ /** Preview only: later clips parse at preload none, as Chromium ignores a none set mid-fetch.
9
+ * One watcher per page: a runtime evaluated again replaces the last one's. */
10
+ export declare function deferMediaUntilDue(): void;
11
+ export {};
@@ -0,0 +1,65 @@
1
+ import { parseStrictFiniteTimingNumber } from "./playbackRate.js";
2
+ import { createRuntimeStartTimeResolver } from "./startResolver.js";
3
+ import { readMediaRenderId } from "./renderFrameSibling.js";
4
+ import { defersMedia } from "./timedClipHide.js";
5
+ export function isRenderFrameVideo(media) {
6
+ const ids = window
7
+ .__HF_RENDER_FRAME_VIDEO_IDS;
8
+ return media.tagName === "VIDEO" && ids?.includes(readMediaRenderId(media) ?? "") === true;
9
+ }
10
+ export function preloadMedia(media) {
11
+ if (isRenderFrameVideo(media))
12
+ return;
13
+ if (media.preload !== "auto")
14
+ media.preload = "auto";
15
+ // load() resets an in-flight video fetch, discarding its selected resource and buffered data.
16
+ const videoAlreadyLoading = media.tagName === "VIDEO" && media.networkState === 2;
17
+ if (media.readyState < 3 && !videoAlreadyLoading)
18
+ media.load();
19
+ }
20
+ /** Ends a fetch in flight for good, which preload none alone does not. */
21
+ export function stopMediaDownload(media) {
22
+ for (const source of media.querySelectorAll("source"))
23
+ source.remove();
24
+ media.removeAttribute("src");
25
+ media.load();
26
+ }
27
+ export function releaseMedia(media) {
28
+ if (media.querySelector("source"))
29
+ return;
30
+ const src = media.getAttribute("src");
31
+ stopMediaDownload(media);
32
+ if (src !== null)
33
+ media.setAttribute("src", src);
34
+ }
35
+ export function lengthIsAuthored(media) {
36
+ return parseStrictFiniteTimingNumber(media.getAttribute("data-duration")) != null;
37
+ }
38
+ /** Preview only: later clips parse at preload none, as Chromium ignores a none set mid-fetch.
39
+ * One watcher per page: a runtime evaluated again replaces the last one's. */
40
+ export function deferMediaUntilDue() {
41
+ const win = window;
42
+ win.__hfMediaDeferral?.disconnect();
43
+ win.__hfMediaDeferral = undefined;
44
+ if (!defersMedia())
45
+ return;
46
+ const defer = (el, startInFilm) => {
47
+ const start = parseStrictFiniteTimingNumber(el.getAttribute("data-start"));
48
+ if (start != null && lengthIsAuthored(el) && startInFilm(el) > 0)
49
+ el.preload = "none";
50
+ };
51
+ win.__hfMediaDeferral = new MutationObserver((records) => {
52
+ const startInFilm = createRuntimeStartTimeResolver({}).resolveMediaStartForElement;
53
+ for (const record of records)
54
+ for (const node of record.addedNodes) {
55
+ if (node.nodeType !== 1)
56
+ continue;
57
+ const el = node;
58
+ if (el.matches("video, audio"))
59
+ defer(el, startInFilm);
60
+ for (const media of el.querySelectorAll("video, audio"))
61
+ defer(media, startInFilm);
62
+ }
63
+ });
64
+ win.__hfMediaDeferral.observe(document.documentElement, { childList: true, subtree: true });
65
+ }
@@ -20,7 +20,7 @@
20
20
  * when the compiler stamped this document, else its author id. The two are
21
21
  * the same string whenever no collision forced a suffix.
22
22
  */
23
- export declare function readMediaRenderId(media: Element): string | null;
23
+ export declare function readMediaRenderId(media: Pick<Element, "getAttribute" | "id">): string | null;
24
24
  /**
25
25
  * Affixes of the sibling id. Exported so the engine can build the same id
26
26
  * inside `page.evaluate`, where it cannot import: it passes these through as
@@ -0,0 +1,9 @@
1
+ export declare const SKIPPED_CLIP = "[data-start]:not(video, audio, img, [data-hf-upcoming], [data-hf-autostamped])[style*=\"visibility: hidden\"]";
2
+ export declare const CLIP_HIDDEN_ATTR = "data-hf-clip-hidden";
3
+ export declare function showHiddenClips(): () => void;
4
+ export declare function defersMedia(): boolean;
5
+ /** True in Studio's preview, where hidden clips' images are neither fetched nor decoded until due. */
6
+ export declare function skipsHiddenImages(): boolean;
7
+ export declare function hideTimedClipsUntilFirstPass(): void;
8
+ /** True when this call lifted the rule; callers then re-register what skipped hidden elements (grading). */
9
+ export declare function revealTimedClipsAfterFirstPass(): boolean;
@@ -0,0 +1,74 @@
1
+ import { RUNTIME_STAMPED_ATTR, STUDIO_PREVIEW_CAPTURE_MODE, STUDIO_PREVIEW_MARK_META, STUDIO_PREVIEW_UPCOMING_ATTR, } from "../studioPreviewMark.js";
2
+ // Hides timed non-media clips from script evaluation until the first visibility pass decides them;
3
+ // before it, a paused page painted every clip at once. Media is left to init's media pass.
4
+ // The rule and its flag live on the page, so every runtime copy shares them.
5
+ const HIDE_ATTR = "data-hf-first-pass-hide";
6
+ const HIDE_UNTIL_FIRST_PASS = "[data-start]:not(video, audio, img) { visibility: hidden !important; }";
7
+ const PREVIEW_HIDE_UNTIL_FIRST_PASS = 'img[loading="lazy"] { display: none !important; }';
8
+ const SKIP_ATTR = "data-hf-skip-hidden-images";
9
+ export const SKIPPED_CLIP = `[data-start]:not(video, audio, img, [${STUDIO_PREVIEW_UPCOMING_ATTR}], [${RUNTIME_STAMPED_ATTR}])[style*="visibility: hidden"]`;
10
+ const SKIP_HIDDEN_IMAGES = `${SKIPPED_CLIP} img { display: none !important; }`;
11
+ const STUDIO_PREVIEW_MARK = `meta[name="${STUDIO_PREVIEW_MARK_META}"]`;
12
+ export const CLIP_HIDDEN_ATTR = "data-hf-clip-hidden";
13
+ const CONTENTS_ATTR = "data-hf-hidden-clip-contents";
14
+ const HIDDEN_CLIP = `[${CLIP_HIDDEN_ATTR}][style*="visibility: hidden"]`;
15
+ const HIDE_HIDDEN_CLIP_CONTENTS = `${HIDDEN_CLIP} * { visibility: hidden !important; }`;
16
+ const FILTER_OUTPUT_LAYERS = [HIDDEN_CLIP, `${HIDDEN_CLIP} *`]
17
+ .flatMap((layer) => [layer, `${layer}::before`, `${layer}::after`])
18
+ .join(", ");
19
+ const HIDE_FILTER_OUTPUT = `${FILTER_OUTPUT_LAYERS} { filter: none !important; }`;
20
+ export function showHiddenClips() {
21
+ const hidden = Array.from(document.querySelectorAll(`[${CLIP_HIDDEN_ATTR}]`));
22
+ for (const el of hidden)
23
+ el.style.visibility = "visible";
24
+ return () => {
25
+ for (const el of hidden)
26
+ el.style.visibility = "hidden";
27
+ };
28
+ }
29
+ function appendStyle(parent, attr, css) {
30
+ const style = document.createElement("style");
31
+ style.setAttribute(attr, "");
32
+ style.textContent = css;
33
+ parent.appendChild(style);
34
+ }
35
+ export function defersMedia() {
36
+ return document.querySelector(STUDIO_PREVIEW_MARK) !== null;
37
+ }
38
+ /** True in Studio's preview, where hidden clips' images are neither fetched nor decoded until due. */
39
+ export function skipsHiddenImages() {
40
+ return document.querySelector(`style[${SKIP_ATTR}]`) !== null;
41
+ }
42
+ export function hideTimedClipsUntilFirstPass() {
43
+ if (typeof document === "undefined")
44
+ return;
45
+ const parent = document.head ?? document.documentElement;
46
+ if (!parent)
47
+ return;
48
+ const mark = document.querySelector(STUDIO_PREVIEW_MARK);
49
+ const preview = mark !== null;
50
+ const capture = mark?.getAttribute("content") === STUDIO_PREVIEW_CAPTURE_MODE;
51
+ if (preview && !capture && !skipsHiddenImages())
52
+ appendStyle(parent, SKIP_ATTR, SKIP_HIDDEN_IMAGES);
53
+ if (!document.querySelector(`style[${CONTENTS_ATTR}]`))
54
+ appendStyle(parent, CONTENTS_ATTR, `${HIDE_HIDDEN_CLIP_CONTENTS} ${HIDE_FILTER_OUTPUT}`);
55
+ const win = window;
56
+ // A runtime that already initialised may never run another pass to lift a new rule.
57
+ if (win.__hfFirstPassHidden || win.__hyperframeRuntimeBootstrapped)
58
+ return;
59
+ const css = preview
60
+ ? `${HIDE_UNTIL_FIRST_PASS} ${PREVIEW_HIDE_UNTIL_FIRST_PASS}`
61
+ : HIDE_UNTIL_FIRST_PASS;
62
+ appendStyle(parent, HIDE_ATTR, css);
63
+ win.__hfFirstPassHidden = true;
64
+ }
65
+ /** True when this call lifted the rule; callers then re-register what skipped hidden elements (grading). */
66
+ export function revealTimedClipsAfterFirstPass() {
67
+ const win = window;
68
+ if (!win.__hfFirstPassHidden)
69
+ return false;
70
+ win.__hfFirstPassHidden = false;
71
+ for (const style of document.querySelectorAll(`style[${HIDE_ATTR}]`))
72
+ style.remove();
73
+ return true;
74
+ }
@@ -1,4 +1,5 @@
1
1
  export declare const STUDIO_PREVIEW_MARK_META = "hyperframes-studio-preview";
2
+ export declare const STUDIO_PREVIEW_CAPTURE_MODE = "capture";
2
3
  export declare const STUDIO_PREVIEW_UPCOMING_ATTR = "data-hf-upcoming";
3
4
  export declare const STUDIO_PREVIEW_LAZY_ATTR = "data-hf-preview-lazy";
4
5
  export declare const STUDIO_PREVIEW_ERRORS = "__hfPreviewErrors";
@@ -1,4 +1,5 @@
1
1
  export const STUDIO_PREVIEW_MARK_META = "hyperframes-studio-preview";
2
+ export const STUDIO_PREVIEW_CAPTURE_MODE = "capture";
2
3
  export const STUDIO_PREVIEW_UPCOMING_ATTR = "data-hf-upcoming";
3
4
  export const STUDIO_PREVIEW_LAZY_ATTR = "data-hf-preview-lazy";
4
5
  export const STUDIO_PREVIEW_ERRORS = "__hfPreviewErrors";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/core",
3
- "version": "0.8.188",
3
+ "version": "0.8.190",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -385,9 +385,9 @@
385
385
  "linkedom": "^0.18.12",
386
386
  "postcss": "^8.5.8",
387
387
  "wawoff2": "^2.0.1",
388
- "@hyperframes/parsers": "0.8.188",
389
- "@hyperframes/studio-server": "0.8.188",
390
- "@hyperframes/lint": "0.8.188"
388
+ "@hyperframes/lint": "0.8.190",
389
+ "@hyperframes/parsers": "0.8.190",
390
+ "@hyperframes/studio-server": "0.8.190"
391
391
  },
392
392
  "devDependencies": {
393
393
  "@fontsource/archivo-black": "^5.2.8",