@hyperframes/lint 0.7.25 → 0.7.27
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/browser.js +16 -4
- package/dist/browser.js.map +1 -1
- package/dist/index.js +16 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/browser.js
CHANGED
|
@@ -6,7 +6,7 @@ var COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
|
|
|
6
6
|
var TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
|
|
7
7
|
var TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN = /window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
|
8
8
|
var TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines(?:\[[^\]]+\]|\.[A-Za-z_$][\w$]*)\s*=/i;
|
|
9
|
-
var WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
|
9
|
+
var WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines(?:\[\s*(?:["']([^"']+)["']|[A-Za-z_$][\w$.]*)\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
|
10
10
|
var INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
|
|
11
11
|
var TIMELINE_REGISTRY_KEY_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=/g;
|
|
12
12
|
var TIMELINE_REGISTRY_OBJECT_BODY_PATTERN = /window\.__timelines\s*=\s*\{([\s\S]*?)\}/i;
|
|
@@ -66,8 +66,15 @@ function findRootTag(source) {
|
|
|
66
66
|
const bodyEnd = bodyOpenMatch && bodyCloseMatch && bodyCloseMatch.index > bodyStart ? bodyCloseMatch.index : source.length;
|
|
67
67
|
const bodyContent = bodyOpenMatch ? source.slice(bodyStart, bodyEnd) : source;
|
|
68
68
|
const bodyTags = extractOpenTags(bodyContent);
|
|
69
|
+
let skipBefore = -1;
|
|
69
70
|
for (const tag of bodyTags) {
|
|
71
|
+
if (tag.index < skipBefore) continue;
|
|
70
72
|
if (["script", "style", "meta", "link", "title"].includes(tag.name)) continue;
|
|
73
|
+
if (tag.name === "svg" && !readAttr(tag.raw, "data-composition-id") && !readAttr(tag.raw, "data-width") && !readAttr(tag.raw, "data-height")) {
|
|
74
|
+
const closeMatch = /<\/svg\s*>/i.exec(bodyContent.slice(tag.index));
|
|
75
|
+
skipBefore = closeMatch ? tag.index + closeMatch.index + closeMatch[0].length : Infinity;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
71
78
|
return { ...tag, index: tag.index + bodyStart };
|
|
72
79
|
}
|
|
73
80
|
return null;
|
|
@@ -1621,12 +1628,14 @@ ${right.raw}`)
|
|
|
1621
1628
|
(candidate) => isHardKillSet(candidate, win.targetSelector, boundary)
|
|
1622
1629
|
);
|
|
1623
1630
|
if (hasHardKill) continue;
|
|
1631
|
+
const exitClipInfo = clipIds.get(win.targetSelector) || clipClasses.get(win.targetSelector);
|
|
1632
|
+
const fixHint = exitClipInfo ? `"${win.targetSelector}" is a clip element \u2014 the framework already manages its visibility. Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill (\`tl.set("<inner-selector>", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\`) onto that wrapper instead.` : `Add \`tl.set("${win.targetSelector}", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\` after the exit tween.`;
|
|
1624
1633
|
findings.push({
|
|
1625
1634
|
code: "gsap_exit_missing_hard_kill",
|
|
1626
1635
|
severity: "error",
|
|
1627
1636
|
message: `GSAP exit on "${win.targetSelector}" ends at the ${boundary.toFixed(2)}s clip start boundary without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.`,
|
|
1628
1637
|
selector: win.targetSelector,
|
|
1629
|
-
fixHint
|
|
1638
|
+
fixHint,
|
|
1630
1639
|
snippet: truncateSnippet(win.raw)
|
|
1631
1640
|
});
|
|
1632
1641
|
}
|
|
@@ -1896,12 +1905,15 @@ ${right.raw}`)
|
|
|
1896
1905
|
const killPattern = new RegExp(`["']#${id}["'][^)]*visibility\\s*:\\s*["']hidden["']`);
|
|
1897
1906
|
const hasKill = killPattern.test(content);
|
|
1898
1907
|
if (!hasKill) {
|
|
1908
|
+
const classes = (readAttr(tag.raw, "class") || "").split(/\s+/).filter(Boolean);
|
|
1909
|
+
const isClip = classes.includes("clip");
|
|
1910
|
+
const fixHint = isClip ? `"#${id}" is a clip element \u2014 the framework already manages its visibility. Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill (\`tl.set("<inner-selector>", { visibility: "hidden" }, <exit-end-time>)\`) onto that wrapper instead.` : `Add \`tl.set("#${id}", { visibility: "hidden" }, <exit-end-time>)\` after the scene's exit tweens.`;
|
|
1899
1911
|
findings.push({
|
|
1900
1912
|
code: "scene_layer_missing_visibility_kill",
|
|
1901
1913
|
severity: "error",
|
|
1902
1914
|
elementId: id,
|
|
1903
1915
|
message: `Scene layer "#${id}" exits via opacity tween but has no visibility: hidden hard kill. When scrubbing or when tweens conflict, the scene may remain partially visible and overlap the next scene.`,
|
|
1904
|
-
fixHint
|
|
1916
|
+
fixHint
|
|
1905
1917
|
});
|
|
1906
1918
|
}
|
|
1907
1919
|
}
|
|
@@ -3293,7 +3305,7 @@ var fontRules = [
|
|
|
3293
3305
|
code: "font_family_without_font_face",
|
|
3294
3306
|
severity: "error",
|
|
3295
3307
|
message: `Font ${undeclared.length === 1 ? "family" : "families"} used without @font-face declaration: ${undeclared.join(", ")}. These are not in the auto-resolved font list, so the renderer cannot supply them automatically. Text will fall back to a generic font, producing incorrect typography in the video.`,
|
|
3296
|
-
fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files."
|
|
3308
|
+
fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files. For an OS-bundled system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, use src: local('Exact Font Name') instead \u2014 the declaration alone satisfies this check without needing a font file."
|
|
3297
3309
|
});
|
|
3298
3310
|
return findings;
|
|
3299
3311
|
}
|