hyperframes 0.8.43 → 0.8.44
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 +90 -66
- package/dist/fontLocalizeCli.js +84 -58
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/renderSetupWorker.js +42 -19
- package/dist/studio/assets/{hyperframes-player-mDAHKhe5.js → hyperframes-player-CGyk8TWh.js} +1 -1
- package/dist/studio/assets/{index-CfHgkH4-.js → index-BxkyaA8I.js} +1 -1
- package/dist/studio/assets/{index-B_TY4ev_.js → index-C0pBR1qO.js} +1 -1
- package/dist/studio/assets/{index-DnsLHxGU.js → index-CoX2WO-f.js} +3 -3
- 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.44" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -55088,9 +55088,9 @@ var init_dist2 = __esm({
|
|
|
55088
55088
|
UHD_SQUARE_MIN = 2160;
|
|
55089
55089
|
UHD_RECT_MIN = 3840;
|
|
55090
55090
|
OK = { ok: true };
|
|
55091
|
-
HTML_BODY_CSS_WIDTH_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?width:\s*(\d+)px[^}]*?height:\s*(\d+)px/i;
|
|
55092
|
-
HTML_BODY_CSS_HEIGHT_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?height:\s*(\d+)px[^}]*?width:\s*(\d+)px/i;
|
|
55093
|
-
VIEWPORT_META_SIZE_RE =
|
|
55091
|
+
HTML_BODY_CSS_WIDTH_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?width:\s*)(\d+)px([^}]*?height:\s*)(\d+)px/i;
|
|
55092
|
+
HTML_BODY_CSS_HEIGHT_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?height:\s*)(\d+)px([^}]*?width:\s*)(\d+)px/i;
|
|
55093
|
+
VIEWPORT_META_SIZE_RE = /(<meta[^>]*name=["']viewport["'][^>]*content=["']width=)(\d+)(,\s*height=)(\d+)/i;
|
|
55094
55094
|
FONT_ALIAS_MAP = {
|
|
55095
55095
|
// ── Canonical bundled fonts (self-referencing) ────────────────────────
|
|
55096
55096
|
inter: "inter",
|
|
@@ -71226,6 +71226,31 @@ function getEncoderPreset(quality, format = "mp4", hdr) {
|
|
|
71226
71226
|
}
|
|
71227
71227
|
return { ...base2, pixelFormat: "yuv420p" };
|
|
71228
71228
|
}
|
|
71229
|
+
function resolveLockedGopSize(options) {
|
|
71230
|
+
if (options.lockGopForChunkConcat !== true) return null;
|
|
71231
|
+
if (typeof options.gopSize !== "number" || !Number.isFinite(options.gopSize) || options.gopSize <= 0) {
|
|
71232
|
+
throw new Error(
|
|
71233
|
+
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
71234
|
+
);
|
|
71235
|
+
}
|
|
71236
|
+
return Math.floor(options.gopSize);
|
|
71237
|
+
}
|
|
71238
|
+
function appendLockedGopArgs(args, gopSize) {
|
|
71239
|
+
args.push(
|
|
71240
|
+
"-g",
|
|
71241
|
+
String(gopSize),
|
|
71242
|
+
"-keyint_min",
|
|
71243
|
+
String(gopSize),
|
|
71244
|
+
"-sc_threshold",
|
|
71245
|
+
"0",
|
|
71246
|
+
"-force_key_frames",
|
|
71247
|
+
`expr:eq(mod(n,${gopSize}),0)`
|
|
71248
|
+
);
|
|
71249
|
+
}
|
|
71250
|
+
function lockedGopCodecParams(codec, gopSize) {
|
|
71251
|
+
const shared = "scenecut=0:open-gop=0:repeat-headers=1";
|
|
71252
|
+
return codec === "h264" ? shared : `keyint=${gopSize}:min-keyint=${gopSize}:${shared}`;
|
|
71253
|
+
}
|
|
71229
71254
|
function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
71230
71255
|
const {
|
|
71231
71256
|
fps,
|
|
@@ -71293,36 +71318,15 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
71293
71318
|
args.push("-c:v", encoderName, "-preset", preset2);
|
|
71294
71319
|
if (bitrate) args.push("-b:v", bitrate);
|
|
71295
71320
|
else args.push("-crf", String(quality));
|
|
71296
|
-
const
|
|
71297
|
-
|
|
71298
|
-
if (
|
|
71299
|
-
if (typeof options.gopSize !== "number" || !Number.isFinite(options.gopSize) || options.gopSize <= 0) {
|
|
71300
|
-
throw new Error(
|
|
71301
|
-
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
71302
|
-
);
|
|
71303
|
-
}
|
|
71304
|
-
gop = Math.floor(options.gopSize);
|
|
71305
|
-
args.push(
|
|
71306
|
-
"-g",
|
|
71307
|
-
String(gop),
|
|
71308
|
-
"-keyint_min",
|
|
71309
|
-
String(gop),
|
|
71310
|
-
"-sc_threshold",
|
|
71311
|
-
"0",
|
|
71312
|
-
"-force_key_frames",
|
|
71313
|
-
`expr:eq(mod(n,${gop}),0)`
|
|
71314
|
-
);
|
|
71315
|
-
}
|
|
71321
|
+
const gop = resolveLockedGopSize(options);
|
|
71322
|
+
const lockGop = gop !== null;
|
|
71323
|
+
if (gop !== null) appendLockedGopArgs(args, gop);
|
|
71316
71324
|
if (codec === "h264" || codec === "h265" && lockGop) {
|
|
71317
71325
|
args.push("-bf", "0");
|
|
71318
71326
|
}
|
|
71319
71327
|
const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
|
|
71320
71328
|
const colorParams = codec === "h265" && options.hdr ? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams : "colorprim=bt709:transfer=bt709:colormatrix=bt709";
|
|
71321
|
-
|
|
71322
|
-
if (lockGop) {
|
|
71323
|
-
const shared = "scenecut=0:open-gop=0:repeat-headers=1";
|
|
71324
|
-
gopParams = codec === "h264" ? shared : `keyint=${gop}:min-keyint=${gop}:${shared}`;
|
|
71325
|
-
}
|
|
71329
|
+
const gopParams = gop !== null ? lockedGopCodecParams(codec, gop) : "";
|
|
71326
71330
|
const joinParams = (...parts) => parts.filter((p2) => p2.length > 0).join(":");
|
|
71327
71331
|
if (preset2 === "ultrafast") {
|
|
71328
71332
|
args.push(xParamsFlag, joinParams("aq-mode=3", colorParams, gopParams));
|
|
@@ -71341,15 +71345,10 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
71341
71345
|
args.push("-deadline", preset2 === "ultrafast" ? "realtime" : "good");
|
|
71342
71346
|
args.push("-row-mt", "1");
|
|
71343
71347
|
appendVp9CpuUsedArg(args, vp9CpuUsed);
|
|
71344
|
-
const
|
|
71345
|
-
|
|
71346
|
-
|
|
71347
|
-
|
|
71348
|
-
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
71349
|
-
);
|
|
71350
|
-
}
|
|
71351
|
-
const gop = Math.floor(options.gopSize);
|
|
71352
|
-
args.push("-g", String(gop), "-keyint_min", String(gop), "-auto-alt-ref", "0");
|
|
71348
|
+
const vp9Gop = resolveLockedGopSize(options);
|
|
71349
|
+
const lockGopVp9 = vp9Gop !== null;
|
|
71350
|
+
if (vp9Gop !== null) {
|
|
71351
|
+
args.push("-g", String(vp9Gop), "-keyint_min", String(vp9Gop), "-auto-alt-ref", "0");
|
|
71353
71352
|
}
|
|
71354
71353
|
if (pixelFormat === "yuva420p") {
|
|
71355
71354
|
if (!lockGopVp9) {
|
|
@@ -71896,15 +71895,18 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
71896
71895
|
args.push("-c:v", encoderName, "-preset", preset2);
|
|
71897
71896
|
if (bitrate) args.push("-b:v", bitrate);
|
|
71898
71897
|
else args.push("-crf", String(quality));
|
|
71899
|
-
|
|
71898
|
+
const lockedGop = resolveLockedGopSize(options);
|
|
71899
|
+
if (lockedGop !== null) appendLockedGopArgs(args, lockedGop);
|
|
71900
|
+
if (codec === "h264" || lockedGop !== null) {
|
|
71900
71901
|
args.push("-bf", "0");
|
|
71901
71902
|
}
|
|
71902
71903
|
const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
|
|
71903
71904
|
const colorParams = options.rawInputFormat && options.hdr ? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams : "colorprim=bt709:transfer=bt709:colormatrix=bt709";
|
|
71905
|
+
const gopParams = lockedGop !== null ? `:${lockedGopCodecParams(codec, lockedGop)}` : "";
|
|
71904
71906
|
if (preset2 === "ultrafast") {
|
|
71905
|
-
args.push(xParamsFlag, `aq-mode=3:${colorParams}`);
|
|
71907
|
+
args.push(xParamsFlag, `aq-mode=3:${colorParams}${gopParams}`);
|
|
71906
71908
|
} else {
|
|
71907
|
-
args.push(xParamsFlag, `aq-mode=3:aq-strength=0.8:deblock=1,1:${colorParams}`);
|
|
71909
|
+
args.push(xParamsFlag, `aq-mode=3:aq-strength=0.8:deblock=1,1:${colorParams}${gopParams}`);
|
|
71908
71910
|
}
|
|
71909
71911
|
if (codec === "h265") {
|
|
71910
71912
|
args.push("-tag:v", "hvc1");
|
|
@@ -72135,6 +72137,7 @@ var init_streamingEncoder = __esm({
|
|
|
72135
72137
|
init_dist3();
|
|
72136
72138
|
init_vp9Options();
|
|
72137
72139
|
init_renderProvenance();
|
|
72140
|
+
init_chunkEncoder();
|
|
72138
72141
|
}
|
|
72139
72142
|
});
|
|
72140
72143
|
|
|
@@ -80437,12 +80440,12 @@ function findVisibleMarkupCommentLeak(source) {
|
|
|
80437
80440
|
function readHtmlBodyCssSize(source) {
|
|
80438
80441
|
const widthFirst = source.match(HTML_BODY_CSS_WIDTH_FIRST_RE);
|
|
80439
80442
|
if (widthFirst) {
|
|
80440
|
-
const [, width = "", height = ""] = widthFirst;
|
|
80443
|
+
const [, , width = "", , height = ""] = widthFirst;
|
|
80441
80444
|
return { width, height };
|
|
80442
80445
|
}
|
|
80443
80446
|
const heightFirst = source.match(HTML_BODY_CSS_HEIGHT_FIRST_RE);
|
|
80444
80447
|
if (heightFirst) {
|
|
80445
|
-
const [, height = "", width = ""] = heightFirst;
|
|
80448
|
+
const [, , height = "", , width = ""] = heightFirst;
|
|
80446
80449
|
return { width, height };
|
|
80447
80450
|
}
|
|
80448
80451
|
return null;
|
|
@@ -80450,18 +80453,39 @@ function readHtmlBodyCssSize(source) {
|
|
|
80450
80453
|
function readViewportMetaSize(source) {
|
|
80451
80454
|
const match = source.match(VIEWPORT_META_SIZE_RE);
|
|
80452
80455
|
if (!match) return null;
|
|
80453
|
-
const [, width = "", height = ""] = match;
|
|
80456
|
+
const [, , width = "", , height = ""] = match;
|
|
80454
80457
|
return { width, height };
|
|
80455
80458
|
}
|
|
80456
80459
|
function describeSizeMismatch(label2, size, dataWidth, dataHeight) {
|
|
80457
80460
|
if (!size || size.width === dataWidth && size.height === dataHeight) return null;
|
|
80458
80461
|
return `${label2} is ${size.width}x${size.height}`;
|
|
80459
80462
|
}
|
|
80460
|
-
function
|
|
80461
|
-
|
|
80462
|
-
|
|
80463
|
-
|
|
80464
|
-
|
|
80463
|
+
function describeRootDimensionsDrift(source, dataWidth, dataHeight) {
|
|
80464
|
+
const bodyCssMismatch = describeSizeMismatch(
|
|
80465
|
+
"html/body CSS",
|
|
80466
|
+
readHtmlBodyCssSize(source),
|
|
80467
|
+
dataWidth,
|
|
80468
|
+
dataHeight
|
|
80469
|
+
);
|
|
80470
|
+
const viewportMismatch = describeSizeMismatch(
|
|
80471
|
+
"the viewport meta",
|
|
80472
|
+
readViewportMetaSize(source),
|
|
80473
|
+
dataWidth,
|
|
80474
|
+
dataHeight
|
|
80475
|
+
);
|
|
80476
|
+
if (!bodyCssMismatch && !viewportMismatch) return null;
|
|
80477
|
+
const declared = `Root composition declares data-width="${dataWidth}" data-height="${dataHeight}"`;
|
|
80478
|
+
if (!bodyCssMismatch) {
|
|
80479
|
+
return {
|
|
80480
|
+
message: `${declared}, but ${viewportMismatch}. The viewport meta has no effect on capture \u2014 the renderer sizes the viewport from the root's own data-width/data-height \u2014 so this is stale metadata, not a clipping risk.`,
|
|
80481
|
+
fixHint: "update the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
80482
|
+
};
|
|
80483
|
+
}
|
|
80484
|
+
const mismatches = viewportMismatch ? `${bodyCssMismatch} and ${viewportMismatch}` : bodyCssMismatch;
|
|
80485
|
+
return {
|
|
80486
|
+
message: `${declared}, but ${mismatches}. The scaffolded body clips the composition at its old size.`,
|
|
80487
|
+
fixHint: "update html/body CSS and the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
80488
|
+
};
|
|
80465
80489
|
}
|
|
80466
80490
|
function tweensVolumeInSameCall(script, id) {
|
|
80467
80491
|
const selector = new RegExp(`#${escapeRegExp4(id)}(?![\\w-])`, "g");
|
|
@@ -82803,22 +82827,24 @@ var init_dist4 = __esm({
|
|
|
82803
82827
|
// root. `hyperframes check`'s layout audits can't see it: they measure
|
|
82804
82828
|
// against the root's own (already-correct) rect, not the body's.
|
|
82805
82829
|
//
|
|
82806
|
-
//
|
|
82807
|
-
//
|
|
82808
|
-
|
|
82809
|
-
|
|
82830
|
+
// Sub-compositions are exempt: loadExternalCompositions (packages/core/src/
|
|
82831
|
+
// runtime/compositionLoader.ts) mounts only the matched <template>/<body>
|
|
82832
|
+
// subtree, so a sub-comp's own <html>/<head>/<meta viewport> never reach
|
|
82833
|
+
// the rendering document, even when it's a full standalone document.
|
|
82834
|
+
({ rootTag, source, options }) => {
|
|
82835
|
+
if (!rootTag || options.isSubComposition) return [];
|
|
82810
82836
|
const dataWidth = readAttr(rootTag.raw, "data-width");
|
|
82811
82837
|
const dataHeight = readAttr(rootTag.raw, "data-height");
|
|
82812
82838
|
if (!dataWidth || !dataHeight) return [];
|
|
82813
|
-
const
|
|
82814
|
-
if (
|
|
82839
|
+
const drift = describeRootDimensionsDrift(source, dataWidth, dataHeight);
|
|
82840
|
+
if (!drift) return [];
|
|
82815
82841
|
return [
|
|
82816
82842
|
{
|
|
82817
82843
|
code: "root_dimensions_mismatch",
|
|
82818
82844
|
severity: "warning",
|
|
82819
|
-
message:
|
|
82845
|
+
message: drift.message,
|
|
82820
82846
|
elementId: readAttr(rootTag.raw, "id") || void 0,
|
|
82821
|
-
fixHint:
|
|
82847
|
+
fixHint: drift.fixHint,
|
|
82822
82848
|
snippet: truncateSnippet(rootTag.raw)
|
|
82823
82849
|
}
|
|
82824
82850
|
];
|
|
@@ -150156,19 +150182,16 @@ function applyResolutionPreset(destDir, resolution) {
|
|
|
150156
150182
|
changed = true;
|
|
150157
150183
|
}
|
|
150158
150184
|
}
|
|
150159
|
-
|
|
150160
|
-
|
|
150161
|
-
html = html.replace(bodyCssRe, `$1${width}px$2${height}px`);
|
|
150185
|
+
if (HTML_BODY_CSS_WIDTH_FIRST_RE.test(html)) {
|
|
150186
|
+
html = html.replace(HTML_BODY_CSS_WIDTH_FIRST_RE, `$1${width}px$3${height}px`);
|
|
150162
150187
|
changed = true;
|
|
150163
150188
|
}
|
|
150164
|
-
|
|
150165
|
-
|
|
150166
|
-
html = html.replace(bodyCssReverseRe, `$1${height}px$2${width}px`);
|
|
150189
|
+
if (HTML_BODY_CSS_HEIGHT_FIRST_RE.test(html)) {
|
|
150190
|
+
html = html.replace(HTML_BODY_CSS_HEIGHT_FIRST_RE, `$1${height}px$3${width}px`);
|
|
150167
150191
|
changed = true;
|
|
150168
150192
|
}
|
|
150169
|
-
|
|
150170
|
-
|
|
150171
|
-
html = html.replace(viewportRe, `$1width=${width}, height=${height}`);
|
|
150193
|
+
if (VIEWPORT_META_SIZE_RE.test(html)) {
|
|
150194
|
+
html = html.replace(VIEWPORT_META_SIZE_RE, `$1${width}$3${height}`);
|
|
150172
150195
|
changed = true;
|
|
150173
150196
|
}
|
|
150174
150197
|
if (changed) writeFileSync29(file, html, "utf-8");
|
|
@@ -150260,6 +150283,7 @@ var init_init = __esm({
|
|
|
150260
150283
|
init_ffmpeg();
|
|
150261
150284
|
init_version();
|
|
150262
150285
|
init_dist3();
|
|
150286
|
+
init_dist2();
|
|
150263
150287
|
examples3 = [
|
|
150264
150288
|
["Create a project with the interactive wizard", "hyperframes init my-video"],
|
|
150265
150289
|
["Pick a starter example", "hyperframes init my-video --example warm-grain"],
|
package/dist/fontLocalizeCli.js
CHANGED
|
@@ -50355,9 +50355,9 @@ var init_dist = __esm({
|
|
|
50355
50355
|
COMPOSITION_ATTRIBUTES.legacyTrack
|
|
50356
50356
|
]);
|
|
50357
50357
|
OK = { ok: true };
|
|
50358
|
-
HTML_BODY_CSS_WIDTH_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?width:\s*(\d+)px[^}]*?height:\s*(\d+)px/i;
|
|
50359
|
-
HTML_BODY_CSS_HEIGHT_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?height:\s*(\d+)px[^}]*?width:\s*(\d+)px/i;
|
|
50360
|
-
VIEWPORT_META_SIZE_RE =
|
|
50358
|
+
HTML_BODY_CSS_WIDTH_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?width:\s*)(\d+)px([^}]*?height:\s*)(\d+)px/i;
|
|
50359
|
+
HTML_BODY_CSS_HEIGHT_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?height:\s*)(\d+)px([^}]*?width:\s*)(\d+)px/i;
|
|
50360
|
+
VIEWPORT_META_SIZE_RE = /(<meta[^>]*name=["']viewport["'][^>]*content=["']width=)(\d+)(,\s*height=)(\d+)/i;
|
|
50361
50361
|
FONT_ALIAS_MAP = {
|
|
50362
50362
|
// ── Canonical bundled fonts (self-referencing) ────────────────────────
|
|
50363
50363
|
inter: "inter",
|
|
@@ -60405,6 +60405,31 @@ function getEncoderPreset(quality, format = "mp4", hdr) {
|
|
|
60405
60405
|
}
|
|
60406
60406
|
return { ...base2, pixelFormat: "yuv420p" };
|
|
60407
60407
|
}
|
|
60408
|
+
function resolveLockedGopSize(options) {
|
|
60409
|
+
if (options.lockGopForChunkConcat !== true) return null;
|
|
60410
|
+
if (typeof options.gopSize !== "number" || !Number.isFinite(options.gopSize) || options.gopSize <= 0) {
|
|
60411
|
+
throw new Error(
|
|
60412
|
+
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
60413
|
+
);
|
|
60414
|
+
}
|
|
60415
|
+
return Math.floor(options.gopSize);
|
|
60416
|
+
}
|
|
60417
|
+
function appendLockedGopArgs(args, gopSize) {
|
|
60418
|
+
args.push(
|
|
60419
|
+
"-g",
|
|
60420
|
+
String(gopSize),
|
|
60421
|
+
"-keyint_min",
|
|
60422
|
+
String(gopSize),
|
|
60423
|
+
"-sc_threshold",
|
|
60424
|
+
"0",
|
|
60425
|
+
"-force_key_frames",
|
|
60426
|
+
`expr:eq(mod(n,${gopSize}),0)`
|
|
60427
|
+
);
|
|
60428
|
+
}
|
|
60429
|
+
function lockedGopCodecParams(codec, gopSize) {
|
|
60430
|
+
const shared = "scenecut=0:open-gop=0:repeat-headers=1";
|
|
60431
|
+
return codec === "h264" ? shared : `keyint=${gopSize}:min-keyint=${gopSize}:${shared}`;
|
|
60432
|
+
}
|
|
60408
60433
|
function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
60409
60434
|
const {
|
|
60410
60435
|
fps,
|
|
@@ -60472,36 +60497,15 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
60472
60497
|
args.push("-c:v", encoderName, "-preset", preset2);
|
|
60473
60498
|
if (bitrate) args.push("-b:v", bitrate);
|
|
60474
60499
|
else args.push("-crf", String(quality));
|
|
60475
|
-
const
|
|
60476
|
-
|
|
60477
|
-
if (
|
|
60478
|
-
if (typeof options.gopSize !== "number" || !Number.isFinite(options.gopSize) || options.gopSize <= 0) {
|
|
60479
|
-
throw new Error(
|
|
60480
|
-
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
60481
|
-
);
|
|
60482
|
-
}
|
|
60483
|
-
gop = Math.floor(options.gopSize);
|
|
60484
|
-
args.push(
|
|
60485
|
-
"-g",
|
|
60486
|
-
String(gop),
|
|
60487
|
-
"-keyint_min",
|
|
60488
|
-
String(gop),
|
|
60489
|
-
"-sc_threshold",
|
|
60490
|
-
"0",
|
|
60491
|
-
"-force_key_frames",
|
|
60492
|
-
`expr:eq(mod(n,${gop}),0)`
|
|
60493
|
-
);
|
|
60494
|
-
}
|
|
60500
|
+
const gop = resolveLockedGopSize(options);
|
|
60501
|
+
const lockGop = gop !== null;
|
|
60502
|
+
if (gop !== null) appendLockedGopArgs(args, gop);
|
|
60495
60503
|
if (codec === "h264" || codec === "h265" && lockGop) {
|
|
60496
60504
|
args.push("-bf", "0");
|
|
60497
60505
|
}
|
|
60498
60506
|
const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
|
|
60499
60507
|
const colorParams = codec === "h265" && options.hdr ? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams : "colorprim=bt709:transfer=bt709:colormatrix=bt709";
|
|
60500
|
-
|
|
60501
|
-
if (lockGop) {
|
|
60502
|
-
const shared = "scenecut=0:open-gop=0:repeat-headers=1";
|
|
60503
|
-
gopParams = codec === "h264" ? shared : `keyint=${gop}:min-keyint=${gop}:${shared}`;
|
|
60504
|
-
}
|
|
60508
|
+
const gopParams = gop !== null ? lockedGopCodecParams(codec, gop) : "";
|
|
60505
60509
|
const joinParams = (...parts) => parts.filter((p) => p.length > 0).join(":");
|
|
60506
60510
|
if (preset2 === "ultrafast") {
|
|
60507
60511
|
args.push(xParamsFlag, joinParams("aq-mode=3", colorParams, gopParams));
|
|
@@ -60520,15 +60524,10 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
|
|
|
60520
60524
|
args.push("-deadline", preset2 === "ultrafast" ? "realtime" : "good");
|
|
60521
60525
|
args.push("-row-mt", "1");
|
|
60522
60526
|
appendVp9CpuUsedArg(args, vp9CpuUsed);
|
|
60523
|
-
const
|
|
60524
|
-
|
|
60525
|
-
|
|
60526
|
-
|
|
60527
|
-
`[chunkEncoder] lockGopForChunkConcat=true requires a positive integer gopSize (received ${String(options.gopSize)})`
|
|
60528
|
-
);
|
|
60529
|
-
}
|
|
60530
|
-
const gop = Math.floor(options.gopSize);
|
|
60531
|
-
args.push("-g", String(gop), "-keyint_min", String(gop), "-auto-alt-ref", "0");
|
|
60527
|
+
const vp9Gop = resolveLockedGopSize(options);
|
|
60528
|
+
const lockGopVp9 = vp9Gop !== null;
|
|
60529
|
+
if (vp9Gop !== null) {
|
|
60530
|
+
args.push("-g", String(vp9Gop), "-keyint_min", String(vp9Gop), "-auto-alt-ref", "0");
|
|
60532
60531
|
}
|
|
60533
60532
|
if (pixelFormat === "yuva420p") {
|
|
60534
60533
|
if (!lockGopVp9) {
|
|
@@ -61075,15 +61074,18 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
61075
61074
|
args.push("-c:v", encoderName, "-preset", preset2);
|
|
61076
61075
|
if (bitrate) args.push("-b:v", bitrate);
|
|
61077
61076
|
else args.push("-crf", String(quality));
|
|
61078
|
-
|
|
61077
|
+
const lockedGop = resolveLockedGopSize(options);
|
|
61078
|
+
if (lockedGop !== null) appendLockedGopArgs(args, lockedGop);
|
|
61079
|
+
if (codec === "h264" || lockedGop !== null) {
|
|
61079
61080
|
args.push("-bf", "0");
|
|
61080
61081
|
}
|
|
61081
61082
|
const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
|
|
61082
61083
|
const colorParams = options.rawInputFormat && options.hdr ? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams : "colorprim=bt709:transfer=bt709:colormatrix=bt709";
|
|
61084
|
+
const gopParams = lockedGop !== null ? `:${lockedGopCodecParams(codec, lockedGop)}` : "";
|
|
61083
61085
|
if (preset2 === "ultrafast") {
|
|
61084
|
-
args.push(xParamsFlag, `aq-mode=3:${colorParams}`);
|
|
61086
|
+
args.push(xParamsFlag, `aq-mode=3:${colorParams}${gopParams}`);
|
|
61085
61087
|
} else {
|
|
61086
|
-
args.push(xParamsFlag, `aq-mode=3:aq-strength=0.8:deblock=1,1:${colorParams}`);
|
|
61088
|
+
args.push(xParamsFlag, `aq-mode=3:aq-strength=0.8:deblock=1,1:${colorParams}${gopParams}`);
|
|
61087
61089
|
}
|
|
61088
61090
|
if (codec === "h265") {
|
|
61089
61091
|
args.push("-tag:v", "hvc1");
|
|
@@ -61314,6 +61316,7 @@ var init_streamingEncoder = __esm({
|
|
|
61314
61316
|
init_dist2();
|
|
61315
61317
|
init_vp9Options();
|
|
61316
61318
|
init_renderProvenance();
|
|
61319
|
+
init_chunkEncoder();
|
|
61317
61320
|
}
|
|
61318
61321
|
});
|
|
61319
61322
|
|
|
@@ -69430,12 +69433,12 @@ function findVisibleMarkupCommentLeak(source) {
|
|
|
69430
69433
|
function readHtmlBodyCssSize(source) {
|
|
69431
69434
|
const widthFirst = source.match(HTML_BODY_CSS_WIDTH_FIRST_RE);
|
|
69432
69435
|
if (widthFirst) {
|
|
69433
|
-
const [, width = "", height = ""] = widthFirst;
|
|
69436
|
+
const [, , width = "", , height = ""] = widthFirst;
|
|
69434
69437
|
return { width, height };
|
|
69435
69438
|
}
|
|
69436
69439
|
const heightFirst = source.match(HTML_BODY_CSS_HEIGHT_FIRST_RE);
|
|
69437
69440
|
if (heightFirst) {
|
|
69438
|
-
const [, height = "", width = ""] = heightFirst;
|
|
69441
|
+
const [, , height = "", , width = ""] = heightFirst;
|
|
69439
69442
|
return { width, height };
|
|
69440
69443
|
}
|
|
69441
69444
|
return null;
|
|
@@ -69443,18 +69446,39 @@ function readHtmlBodyCssSize(source) {
|
|
|
69443
69446
|
function readViewportMetaSize(source) {
|
|
69444
69447
|
const match = source.match(VIEWPORT_META_SIZE_RE);
|
|
69445
69448
|
if (!match) return null;
|
|
69446
|
-
const [, width = "", height = ""] = match;
|
|
69449
|
+
const [, , width = "", , height = ""] = match;
|
|
69447
69450
|
return { width, height };
|
|
69448
69451
|
}
|
|
69449
69452
|
function describeSizeMismatch(label, size, dataWidth, dataHeight) {
|
|
69450
69453
|
if (!size || size.width === dataWidth && size.height === dataHeight) return null;
|
|
69451
69454
|
return `${label} is ${size.width}x${size.height}`;
|
|
69452
69455
|
}
|
|
69453
|
-
function
|
|
69454
|
-
|
|
69455
|
-
|
|
69456
|
-
|
|
69457
|
-
|
|
69456
|
+
function describeRootDimensionsDrift(source, dataWidth, dataHeight) {
|
|
69457
|
+
const bodyCssMismatch = describeSizeMismatch(
|
|
69458
|
+
"html/body CSS",
|
|
69459
|
+
readHtmlBodyCssSize(source),
|
|
69460
|
+
dataWidth,
|
|
69461
|
+
dataHeight
|
|
69462
|
+
);
|
|
69463
|
+
const viewportMismatch = describeSizeMismatch(
|
|
69464
|
+
"the viewport meta",
|
|
69465
|
+
readViewportMetaSize(source),
|
|
69466
|
+
dataWidth,
|
|
69467
|
+
dataHeight
|
|
69468
|
+
);
|
|
69469
|
+
if (!bodyCssMismatch && !viewportMismatch) return null;
|
|
69470
|
+
const declared = `Root composition declares data-width="${dataWidth}" data-height="${dataHeight}"`;
|
|
69471
|
+
if (!bodyCssMismatch) {
|
|
69472
|
+
return {
|
|
69473
|
+
message: `${declared}, but ${viewportMismatch}. The viewport meta has no effect on capture \u2014 the renderer sizes the viewport from the root's own data-width/data-height \u2014 so this is stale metadata, not a clipping risk.`,
|
|
69474
|
+
fixHint: "update the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
69475
|
+
};
|
|
69476
|
+
}
|
|
69477
|
+
const mismatches = viewportMismatch ? `${bodyCssMismatch} and ${viewportMismatch}` : bodyCssMismatch;
|
|
69478
|
+
return {
|
|
69479
|
+
message: `${declared}, but ${mismatches}. The scaffolded body clips the composition at its old size.`,
|
|
69480
|
+
fixHint: "update html/body CSS and the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
69481
|
+
};
|
|
69458
69482
|
}
|
|
69459
69483
|
function tweensVolumeInSameCall(script, id) {
|
|
69460
69484
|
const selector = new RegExp(`#${escapeRegExp3(id)}(?![\\w-])`, "g");
|
|
@@ -71075,22 +71099,24 @@ var init_dist3 = __esm({
|
|
|
71075
71099
|
// root. `hyperframes check`'s layout audits can't see it: they measure
|
|
71076
71100
|
// against the root's own (already-correct) rect, not the body's.
|
|
71077
71101
|
//
|
|
71078
|
-
//
|
|
71079
|
-
//
|
|
71080
|
-
|
|
71081
|
-
|
|
71102
|
+
// Sub-compositions are exempt: loadExternalCompositions (packages/core/src/
|
|
71103
|
+
// runtime/compositionLoader.ts) mounts only the matched <template>/<body>
|
|
71104
|
+
// subtree, so a sub-comp's own <html>/<head>/<meta viewport> never reach
|
|
71105
|
+
// the rendering document, even when it's a full standalone document.
|
|
71106
|
+
({ rootTag, source, options }) => {
|
|
71107
|
+
if (!rootTag || options.isSubComposition) return [];
|
|
71082
71108
|
const dataWidth = readAttr(rootTag.raw, "data-width");
|
|
71083
71109
|
const dataHeight = readAttr(rootTag.raw, "data-height");
|
|
71084
71110
|
if (!dataWidth || !dataHeight) return [];
|
|
71085
|
-
const
|
|
71086
|
-
if (
|
|
71111
|
+
const drift = describeRootDimensionsDrift(source, dataWidth, dataHeight);
|
|
71112
|
+
if (!drift) return [];
|
|
71087
71113
|
return [
|
|
71088
71114
|
{
|
|
71089
71115
|
code: "root_dimensions_mismatch",
|
|
71090
71116
|
severity: "warning",
|
|
71091
|
-
message:
|
|
71117
|
+
message: drift.message,
|
|
71092
71118
|
elementId: readAttr(rootTag.raw, "id") || void 0,
|
|
71093
|
-
fixHint:
|
|
71119
|
+
fixHint: drift.fixHint,
|
|
71094
71120
|
snippet: truncateSnippet(rootTag.raw)
|
|
71095
71121
|
}
|
|
71096
71122
|
];
|
|
@@ -99807,8 +99833,8 @@ async function runFontLocalize(io, localize) {
|
|
|
99807
99833
|
}
|
|
99808
99834
|
|
|
99809
99835
|
// src/version.ts
|
|
99810
|
-
var VERSION = true ? "0.8.
|
|
99811
|
-
var PRODUCER_VERSION = true ? "0.8.
|
|
99836
|
+
var VERSION = true ? "0.8.44" : "0.0.0-dev";
|
|
99837
|
+
var PRODUCER_VERSION = true ? "0.8.44" : "0.0.0-dev";
|
|
99812
99838
|
|
|
99813
99839
|
// src/fontLocalizeCli.ts
|
|
99814
99840
|
async function readStdin() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.
|
|
1
|
+
"use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.44/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=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),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,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||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(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(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
position: relative;
|
|
@@ -54938,9 +54938,9 @@ var LEGACY_TIMING_ATTRIBUTES = Object.freeze([
|
|
|
54938
54938
|
COMPOSITION_ATTRIBUTES.derivedEnd,
|
|
54939
54939
|
COMPOSITION_ATTRIBUTES.legacyTrack
|
|
54940
54940
|
]);
|
|
54941
|
-
var HTML_BODY_CSS_WIDTH_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?width:\s*(\d+)px[^}]*?height:\s*(\d+)px/i;
|
|
54942
|
-
var HTML_BODY_CSS_HEIGHT_FIRST_RE = /html\s*,\s*body\s*\{[^}]*?height:\s*(\d+)px[^}]*?width:\s*(\d+)px/i;
|
|
54943
|
-
var VIEWPORT_META_SIZE_RE =
|
|
54941
|
+
var HTML_BODY_CSS_WIDTH_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?width:\s*)(\d+)px([^}]*?height:\s*)(\d+)px/i;
|
|
54942
|
+
var HTML_BODY_CSS_HEIGHT_FIRST_RE = /(html\s*,\s*body\s*\{[^}]*?height:\s*)(\d+)px([^}]*?width:\s*)(\d+)px/i;
|
|
54943
|
+
var VIEWPORT_META_SIZE_RE = /(<meta[^>]*name=["']viewport["'][^>]*content=["']width=)(\d+)(,\s*height=)(\d+)/i;
|
|
54944
54944
|
function parseProgram2(script) {
|
|
54945
54945
|
try {
|
|
54946
54946
|
return parse3(script, { ecmaVersion: "latest", sourceType: "script" });
|
|
@@ -57143,12 +57143,12 @@ function findVisibleMarkupCommentLeak(source) {
|
|
|
57143
57143
|
function readHtmlBodyCssSize(source) {
|
|
57144
57144
|
const widthFirst = source.match(HTML_BODY_CSS_WIDTH_FIRST_RE);
|
|
57145
57145
|
if (widthFirst) {
|
|
57146
|
-
const [, width = "", height = ""] = widthFirst;
|
|
57146
|
+
const [, , width = "", , height = ""] = widthFirst;
|
|
57147
57147
|
return { width, height };
|
|
57148
57148
|
}
|
|
57149
57149
|
const heightFirst = source.match(HTML_BODY_CSS_HEIGHT_FIRST_RE);
|
|
57150
57150
|
if (heightFirst) {
|
|
57151
|
-
const [, height = "", width = ""] = heightFirst;
|
|
57151
|
+
const [, , height = "", , width = ""] = heightFirst;
|
|
57152
57152
|
return { width, height };
|
|
57153
57153
|
}
|
|
57154
57154
|
return null;
|
|
@@ -57156,18 +57156,39 @@ function readHtmlBodyCssSize(source) {
|
|
|
57156
57156
|
function readViewportMetaSize(source) {
|
|
57157
57157
|
const match = source.match(VIEWPORT_META_SIZE_RE);
|
|
57158
57158
|
if (!match) return null;
|
|
57159
|
-
const [, width = "", height = ""] = match;
|
|
57159
|
+
const [, , width = "", , height = ""] = match;
|
|
57160
57160
|
return { width, height };
|
|
57161
57161
|
}
|
|
57162
57162
|
function describeSizeMismatch(label, size, dataWidth, dataHeight) {
|
|
57163
57163
|
if (!size || size.width === dataWidth && size.height === dataHeight) return null;
|
|
57164
57164
|
return `${label} is ${size.width}x${size.height}`;
|
|
57165
57165
|
}
|
|
57166
|
-
function
|
|
57167
|
-
|
|
57168
|
-
|
|
57169
|
-
|
|
57170
|
-
|
|
57166
|
+
function describeRootDimensionsDrift(source, dataWidth, dataHeight) {
|
|
57167
|
+
const bodyCssMismatch = describeSizeMismatch(
|
|
57168
|
+
"html/body CSS",
|
|
57169
|
+
readHtmlBodyCssSize(source),
|
|
57170
|
+
dataWidth,
|
|
57171
|
+
dataHeight
|
|
57172
|
+
);
|
|
57173
|
+
const viewportMismatch = describeSizeMismatch(
|
|
57174
|
+
"the viewport meta",
|
|
57175
|
+
readViewportMetaSize(source),
|
|
57176
|
+
dataWidth,
|
|
57177
|
+
dataHeight
|
|
57178
|
+
);
|
|
57179
|
+
if (!bodyCssMismatch && !viewportMismatch) return null;
|
|
57180
|
+
const declared = `Root composition declares data-width="${dataWidth}" data-height="${dataHeight}"`;
|
|
57181
|
+
if (!bodyCssMismatch) {
|
|
57182
|
+
return {
|
|
57183
|
+
message: `${declared}, but ${viewportMismatch}. The viewport meta has no effect on capture \u2014 the renderer sizes the viewport from the root's own data-width/data-height \u2014 so this is stale metadata, not a clipping risk.`,
|
|
57184
|
+
fixHint: "update the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
57185
|
+
};
|
|
57186
|
+
}
|
|
57187
|
+
const mismatches = viewportMismatch ? `${bodyCssMismatch} and ${viewportMismatch}` : bodyCssMismatch;
|
|
57188
|
+
return {
|
|
57189
|
+
message: `${declared}, but ${mismatches}. The scaffolded body clips the composition at its old size.`,
|
|
57190
|
+
fixHint: "update html/body CSS and the meta viewport to match, or scaffold with `hyperframes init --resolution portrait`"
|
|
57191
|
+
};
|
|
57171
57192
|
}
|
|
57172
57193
|
var coreRules = [
|
|
57173
57194
|
// id_requires_css_escape
|
|
@@ -57224,22 +57245,24 @@ var coreRules = [
|
|
|
57224
57245
|
// root. `hyperframes check`'s layout audits can't see it: they measure
|
|
57225
57246
|
// against the root's own (already-correct) rect, not the body's.
|
|
57226
57247
|
//
|
|
57227
|
-
//
|
|
57228
|
-
//
|
|
57229
|
-
|
|
57230
|
-
|
|
57248
|
+
// Sub-compositions are exempt: loadExternalCompositions (packages/core/src/
|
|
57249
|
+
// runtime/compositionLoader.ts) mounts only the matched <template>/<body>
|
|
57250
|
+
// subtree, so a sub-comp's own <html>/<head>/<meta viewport> never reach
|
|
57251
|
+
// the rendering document, even when it's a full standalone document.
|
|
57252
|
+
({ rootTag, source, options }) => {
|
|
57253
|
+
if (!rootTag || options.isSubComposition) return [];
|
|
57231
57254
|
const dataWidth = readAttr(rootTag.raw, "data-width");
|
|
57232
57255
|
const dataHeight = readAttr(rootTag.raw, "data-height");
|
|
57233
57256
|
if (!dataWidth || !dataHeight) return [];
|
|
57234
|
-
const
|
|
57235
|
-
if (
|
|
57257
|
+
const drift = describeRootDimensionsDrift(source, dataWidth, dataHeight);
|
|
57258
|
+
if (!drift) return [];
|
|
57236
57259
|
return [
|
|
57237
57260
|
{
|
|
57238
57261
|
code: "root_dimensions_mismatch",
|
|
57239
57262
|
severity: "warning",
|
|
57240
|
-
message:
|
|
57263
|
+
message: drift.message,
|
|
57241
57264
|
elementId: readAttr(rootTag.raw, "id") || void 0,
|
|
57242
|
-
fixHint:
|
|
57265
|
+
fixHint: drift.fixHint,
|
|
57243
57266
|
snippet: truncateSnippet(rootTag.raw)
|
|
57244
57267
|
}
|
|
57245
57268
|
];
|