Summary
In @hyperframes/lint, the gsap_css_transform_conflict rule duplicates the CSS transform text in both message and fixHint whenever a single CSS declaration contains both a translate and a scale function.
Reproduced on 0.7.107 (also present in 0.7.94).
Repro
import { lintHyperframeHtml } from '@hyperframes/lint/browser';
const html = `<!doctype html><html><head>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<style>.scene-1 { transform: scale(1.08) translate3d(1.5%, 0, 0); }</style>
</head>
<body data-composition-id="repro" data-width="1920" data-height="1080" data-start="0" data-duration="5">
<div class="scene-1" data-start="0" data-duration="5">hi</div>
<script>
window.__timelines = window.__timelines || [];
const tl = gsap.timeline();
tl.to(".scene-1", { duration: 1, x: 100, scale: 1.2 });
window.__timelines.push(tl);
</script>
</body></html>`;
const res = await lintHyperframeHtml(html);
console.log(res.findings.filter(f => f.code === 'gsap_css_transform_conflict'));
Actual
".scene-1" has CSS `transform: scale(1.08) translate3d(1.5%, 0, 0) scale(1.08) translate3d(1.5%, 0, 0)`
and a GSAP tween animates x/scale. ...
The same doubling appears in fixHint ("Remove transform: scale(1.08) translate3d(1.5%, 0, 0) scale(1.08) translate3d(1.5%, 0, 0) from CSS...").
Expected
".scene-1" has CSS `transform: scale(1.08) translate3d(1.5%, 0, 0)` and a GSAP tween animates x/scale. ...
Cause
In the gsap_css_transform_conflict rule, cssTransform is built as:
const cssFromTranslate = translateProps.length > 0 ? matchCssTransform(sel, cssTranslateSelectors) : undefined;
const cssFromScale = scaleProps.length > 0 ? matchCssTransform(sel, cssScaleSelectors) : undefined;
// ...
cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(' ')
When one declaration (transform: scale(...) translate3d(...)) matches both the translate and the scale selector maps, cssFromTranslate === cssFromScale, and the join(' ') concatenates the identical string with itself.
Suggested fix
Deduplicate before joining, e.g.:
cssTransform: [...new Set([cssFromTranslate, cssFromScale].filter(Boolean))].join(' ')
Impact
Cosmetic but user-visible: the doubled text appears in linter output and in the fixHint we surface to authors, and the suggested "Remove <doubled text> from CSS" instruction does not match any string actually present in the stylesheet.
Environment
@hyperframes/lint 0.7.107 (browser entry, esbuild IIFE bundle)
- Node 22
Summary
In
@hyperframes/lint, thegsap_css_transform_conflictrule duplicates the CSS transform text in bothmessageandfixHintwhenever a single CSS declaration contains both a translate and a scale function.Reproduced on 0.7.107 (also present in 0.7.94).
Repro
Actual
The same doubling appears in
fixHint("Removetransform: scale(1.08) translate3d(1.5%, 0, 0) scale(1.08) translate3d(1.5%, 0, 0)from CSS...").Expected
Cause
In the
gsap_css_transform_conflictrule,cssTransformis built as:When one declaration (
transform: scale(...) translate3d(...)) matches both the translate and the scale selector maps,cssFromTranslate === cssFromScale, and thejoin(' ')concatenates the identical string with itself.Suggested fix
Deduplicate before joining, e.g.:
Impact
Cosmetic but user-visible: the doubled text appears in linter output and in the
fixHintwe surface to authors, and the suggested "Remove<doubled text>from CSS" instruction does not match any string actually present in the stylesheet.Environment
@hyperframes/lint0.7.107 (browser entry, esbuild IIFE bundle)