fix(producer): preserve @import rules during CSS composition scoping

scopeCssToComposition corrupted @import url() rules because they have
no {} block. The selector regex ([^{}@]+)\{ treated the text after @
as a selector, producing invalid CSS like:

  @[data-composition-id="x"] import url('...')

This broke font loading, CSS variable resolution, and all composition
styling in rendered output.

Fix: extract @import rules before running the scoping regex, then
prepend them back unmodified.

Also adds:
- Regression test fixture (css-import-scoping)
- Common-mistakes docs: autoplay/loop, GSAP TextPlugin, sub-composition
  positioning
- Format fix for hyperframeLinter.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Miguel Ángel
2026-03-24 18:51:05 -04:00
co-authored by Claude Opus 4.6
parent e6a643ac1d
commit d3c6228d89
7 changed files with 198 additions and 11 deletions
@@ -0,0 +1,52 @@
<template id="overlay-template">
<div data-composition-id="overlay" data-width="1080" data-height="1920">
<div class="box"></div>
<div class="title">CSS IMPORT TEST</div>
<style>
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
:root {
--test-bg: #9bbc0f;
--test-fg: #0f380f;
}
[data-composition-id="overlay"] {
position: absolute;
top: 0;
left: 0;
width: 1080px;
height: 1920px;
background-color: var(--test-bg);
font-family: 'Press Start 2P', monospace;
color: var(--test-fg);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
[data-composition-id="overlay"] .box {
width: 400px;
height: 400px;
border: 8px solid var(--test-fg);
background: var(--test-bg);
}
[data-composition-id="overlay"] .title {
font-size: 48px;
margin-top: 40px;
}
</style>
<script>
(function() {
const tl = gsap.timeline({ paused: true });
tl.from('[data-composition-id="overlay"] .box', { scale: 0, duration: 1, ease: 'power2.out' }, 0);
tl.from('[data-composition-id="overlay"] .title', { opacity: 0, y: 30, duration: 0.5 }, 0.5);
tl.set({}, {}, 5);
window.__timelines["overlay"] = tl;
})();
</script>
</div>
</template>
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1080, height=1920">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<style>
body { margin: 0; background: #000; width: 1080px; height: 1920px; overflow: hidden; }
</style>
</head>
<body>
<div id="root" data-composition-id="root" data-width="1080" data-height="1920" data-duration="5"
style="position:absolute;width:1080px;height:1920px;">
<div data-composition-id="overlay"
data-composition-src="compositions/overlay.html"
data-start="0" data-track-index="1"
data-width="1080" data-height="1920"></div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
tl.set({}, {}, 5);
window.__timelines["root"] = tl;
</script>
</body>
</html>