@hyperframes/producer 0.1.13 → 0.1.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/public-server.js
CHANGED
|
@@ -90223,7 +90223,7 @@ var Context = class {
|
|
|
90223
90223
|
* @param layout - The layout to set.
|
|
90224
90224
|
* @returns The layout function.
|
|
90225
90225
|
*/
|
|
90226
|
-
setLayout = (
|
|
90226
|
+
setLayout = (layout2) => this.#layout = layout2;
|
|
90227
90227
|
/**
|
|
90228
90228
|
* Gets the current layout for the response.
|
|
90229
90229
|
*
|
|
@@ -102176,6 +102176,19 @@ function lintHyperframeHtml(html, options = {}) {
|
|
|
102176
102176
|
)
|
|
102177
102177
|
});
|
|
102178
102178
|
}
|
|
102179
|
+
const clipIds = /* @__PURE__ */ new Map();
|
|
102180
|
+
const clipClasses = /* @__PURE__ */ new Map();
|
|
102181
|
+
for (const tag of tags) {
|
|
102182
|
+
const classAttr = readAttr(tag.raw, "class") || "";
|
|
102183
|
+
const classes = classAttr.split(/\s+/).filter(Boolean);
|
|
102184
|
+
if (!classes.includes("clip")) continue;
|
|
102185
|
+
const id = readAttr(tag.raw, "id");
|
|
102186
|
+
const info = { tag: tag.name, id: id || "", classes: classAttr };
|
|
102187
|
+
if (id) clipIds.set(`#${id}`, info);
|
|
102188
|
+
for (const cls of classes) {
|
|
102189
|
+
if (cls !== "clip") clipClasses.set(`.${cls}`, info);
|
|
102190
|
+
}
|
|
102191
|
+
}
|
|
102179
102192
|
const classUsage = countClassUsage(tags);
|
|
102180
102193
|
for (const script of scripts) {
|
|
102181
102194
|
const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
|
|
@@ -102218,24 +102231,39 @@ ${right2.raw}`)
|
|
|
102218
102231
|
});
|
|
102219
102232
|
}
|
|
102220
102233
|
}
|
|
102234
|
+
for (const win of gsapWindows) {
|
|
102235
|
+
const sel = win.targetSelector;
|
|
102236
|
+
const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
|
|
102237
|
+
if (!clipInfo) continue;
|
|
102238
|
+
const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id="${clipInfo.id}"` : ""} class="${clipInfo.classes}">`;
|
|
102239
|
+
pushFinding({
|
|
102240
|
+
code: "gsap_animates_clip_element",
|
|
102241
|
+
severity: "error",
|
|
102242
|
+
message: `GSAP animation targets a clip element. Selector "${sel}" resolves to element ${elDesc}. The framework manages clip visibility \u2014 animate an inner wrapper instead.`,
|
|
102243
|
+
selector: sel,
|
|
102244
|
+
elementId: clipInfo.id || void 0,
|
|
102245
|
+
fixHint: "Wrap content in a child <div> and target that with GSAP.",
|
|
102246
|
+
snippet: truncateSnippet(win.raw)
|
|
102247
|
+
});
|
|
102248
|
+
}
|
|
102221
102249
|
if (!localTimelineCompId || localTimelineCompId === rootCompositionId) {
|
|
102222
102250
|
continue;
|
|
102223
102251
|
}
|
|
102224
|
-
for (const
|
|
102225
|
-
if (!isSuspiciousGlobalSelector(
|
|
102252
|
+
for (const win of gsapWindows) {
|
|
102253
|
+
if (!isSuspiciousGlobalSelector(win.targetSelector)) {
|
|
102226
102254
|
continue;
|
|
102227
102255
|
}
|
|
102228
|
-
const className = getSingleClassSelector(
|
|
102256
|
+
const className = getSingleClassSelector(win.targetSelector);
|
|
102229
102257
|
if (className && (classUsage.get(className) || 0) < 2) {
|
|
102230
102258
|
continue;
|
|
102231
102259
|
}
|
|
102232
102260
|
pushFinding({
|
|
102233
102261
|
code: "unscoped_gsap_selector",
|
|
102234
102262
|
severity: "warning",
|
|
102235
|
-
message: `Timeline "${localTimelineCompId}" uses unscoped selector "${
|
|
102236
|
-
selector:
|
|
102237
|
-
fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${
|
|
102238
|
-
snippet: truncateSnippet(
|
|
102263
|
+
message: `Timeline "${localTimelineCompId}" uses unscoped selector "${win.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
|
|
102264
|
+
selector: win.targetSelector,
|
|
102265
|
+
fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${win.targetSelector}\` or use a unique id.`,
|
|
102266
|
+
snippet: truncateSnippet(win.raw)
|
|
102239
102267
|
});
|
|
102240
102268
|
}
|
|
102241
102269
|
}
|
|
@@ -102488,6 +102516,58 @@ ${right2.raw}`)
|
|
|
102488
102516
|
}
|
|
102489
102517
|
}
|
|
102490
102518
|
}
|
|
102519
|
+
for (const script of scripts) {
|
|
102520
|
+
const content = script.content;
|
|
102521
|
+
const hasExitTween = /\.to\s*\([^,]+,\s*\{[^}]*opacity\s*:\s*0/.test(content);
|
|
102522
|
+
const hasHardKill = /\.set\s*\([^,]+,\s*\{[^}]*(?:visibility\s*:\s*["']hidden["']|opacity\s*:\s*0)/.test(content);
|
|
102523
|
+
const hasCaptionLoop = /forEach|\.forEach\s*\(/.test(content) && /createElement|caption|group|cg-/.test(content);
|
|
102524
|
+
if (hasCaptionLoop && hasExitTween && !hasHardKill) {
|
|
102525
|
+
pushFinding({
|
|
102526
|
+
code: "caption_exit_missing_hard_kill",
|
|
102527
|
+
severity: "warning",
|
|
102528
|
+
message: "Caption exit animations (tl.to with opacity: 0) detected without a hard tl.set kill. Exit tweens can fail when karaoke word-level tweens conflict, leaving captions stuck on screen.",
|
|
102529
|
+
fixHint: 'Add `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, group.end)` after every exit tl.to animation as a deterministic kill.'
|
|
102530
|
+
});
|
|
102531
|
+
}
|
|
102532
|
+
}
|
|
102533
|
+
for (const style of styles) {
|
|
102534
|
+
const content = style.content;
|
|
102535
|
+
const captionBlocks = content.matchAll(
|
|
102536
|
+
/(\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\s*\{([^}]+)\}/gi
|
|
102537
|
+
);
|
|
102538
|
+
for (const [, selector, body] of captionBlocks) {
|
|
102539
|
+
if (!body) continue;
|
|
102540
|
+
const hasNowrap = /white-space\s*:\s*nowrap/i.test(body);
|
|
102541
|
+
const hasMaxWidth = /max-width/i.test(body);
|
|
102542
|
+
if (hasNowrap && !hasMaxWidth) {
|
|
102543
|
+
pushFinding({
|
|
102544
|
+
code: "caption_text_overflow_risk",
|
|
102545
|
+
severity: "warning",
|
|
102546
|
+
selector: (selector ?? "").trim(),
|
|
102547
|
+
message: `Caption selector "${(selector ?? "").trim()}" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,
|
|
102548
|
+
fixHint: "Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden."
|
|
102549
|
+
});
|
|
102550
|
+
}
|
|
102551
|
+
}
|
|
102552
|
+
}
|
|
102553
|
+
for (const style of styles) {
|
|
102554
|
+
const content = style.content;
|
|
102555
|
+
const captionBlocks = content.matchAll(
|
|
102556
|
+
/(\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\s*\{([^}]+)\}/gi
|
|
102557
|
+
);
|
|
102558
|
+
for (const [, selector, body] of captionBlocks) {
|
|
102559
|
+
if (!body) continue;
|
|
102560
|
+
if (/position\s*:\s*relative/i.test(body)) {
|
|
102561
|
+
pushFinding({
|
|
102562
|
+
code: "caption_container_relative_position",
|
|
102563
|
+
severity: "warning",
|
|
102564
|
+
selector: (selector ?? "").trim(),
|
|
102565
|
+
message: `Caption selector "${(selector ?? "").trim()}" uses position: relative which causes overflow and breaks caption stacking.`,
|
|
102566
|
+
fixHint: "Use position: absolute for all caption elements."
|
|
102567
|
+
});
|
|
102568
|
+
}
|
|
102569
|
+
}
|
|
102570
|
+
}
|
|
102491
102571
|
{
|
|
102492
102572
|
const externalScriptRe = /<script\b[^>]*\bsrc=["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
102493
102573
|
let match2;
|
|
@@ -102506,11 +102586,13 @@ ${right2.raw}`)
|
|
|
102506
102586
|
}
|
|
102507
102587
|
}
|
|
102508
102588
|
const errorCount = findings.filter((finding) => finding.severity === "error").length;
|
|
102509
|
-
const warningCount = findings.
|
|
102589
|
+
const warningCount = findings.filter((finding) => finding.severity === "warning").length;
|
|
102590
|
+
const infoCount = findings.filter((finding) => finding.severity === "info").length;
|
|
102510
102591
|
return {
|
|
102511
102592
|
ok: errorCount === 0,
|
|
102512
102593
|
errorCount,
|
|
102513
102594
|
warningCount,
|
|
102595
|
+
infoCount,
|
|
102514
102596
|
findings
|
|
102515
102597
|
};
|
|
102516
102598
|
}
|
|
@@ -102829,6 +102911,14 @@ function quantizeTimeToFrame(timeSeconds, fps) {
|
|
|
102829
102911
|
return frameIndex / safeFps;
|
|
102830
102912
|
}
|
|
102831
102913
|
|
|
102914
|
+
// ../../node_modules/.bun/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/analysis.js
|
|
102915
|
+
var arabicScriptRe = new RegExp("\\p{Script=Arabic}", "u");
|
|
102916
|
+
var combiningMarkRe = new RegExp("\\p{M}", "u");
|
|
102917
|
+
var decimalDigitRe = new RegExp("\\p{Nd}", "u");
|
|
102918
|
+
|
|
102919
|
+
// ../../node_modules/.bun/@chenglou+pretext@0.0.3/node_modules/@chenglou/pretext/dist/measurement.js
|
|
102920
|
+
var emojiPresentationRe = new RegExp("\\p{Emoji_Presentation}", "u");
|
|
102921
|
+
|
|
102832
102922
|
// ../engine/src/services/screenshotService.ts
|
|
102833
102923
|
var cdpSessionCache = /* @__PURE__ */ new WeakMap();
|
|
102834
102924
|
async function getCdpSession(page) {
|