Summary
The font_family_without_font_face lint checker (strengthened to error severity in 0.6.109) correctly identifies @font-face declarations in simple HTML but fails to match them in complex HTML with large CSS blocks (>100 lines, multiple @keyframes, full CSS framework). This produces false-positive errors that block rendering.
In 0.6.107 and earlier, this was a warning (non-blocking), so the issue was masked.
Version
- HyperFrames: 0.6.109
- Node: v24.11.1
- OS: Windows 10
Reproduction
✅ Simple HTML — passes (0 errors)
<!DOCTYPE html>
<html><head><style>
@font-face { font-family: 'Noto Sans SC'; font-weight: 400;
src: url('file:///C:/Users/example/cache/noto-sans-sc/400-normal.woff2') format('woff2'); }
.title { font-family: 'Noto Sans SC'; }
</style></head><body>
<div data-composition-id="t" data-width="1080" data-height="1920" data-start="0" data-duration="1">
<div class="clip" data-start="0" data-duration="1"><h1 class="title">Test</h1></div>
</div>
<script>window.__hf={duration:1,seek:function(t){}};window.__timelines={};</script>
</body></html>
Result: 0 error(s), 1 warning(s) — @font-face correctly matched ✅
❌ Complex HTML — fails (false-positive error)
Same @font-face declaration, but <style> block contains ~200 lines of additional CSS (base reset, layout classes, 10+ @keyframes, component styles):
<style>
@font-face { font-family: 'Noto Sans SC'; font-weight: 400; src: url('...') format('woff2'); }
@font-face { font-family: 'Noto Sans SC'; font-weight: 700; src: url('...') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-weight: 700; src: url('...') format('woff2'); }
@keyframes fxAura { 0%,100%{opacity:.45} 50%{opacity:.8} }
@keyframes fxRingExp { 0%,100%{opacity:.3} 50%{opacity:.65} }
/* ... 8 more @keyframes ... */
*{margin:0;padding:0;box-sizing:border-box}
.clip{position:absolute;top:0;left:0;width:1080px;height:1920px}
.layer-content{position:relative;z-index:3;height:100%;color:#fff;font-size:48px}
.phase{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column}
/* ... 50+ more component class rules ... */
.ct-title { font-family: 'Noto Sans SC'; font-weight: 900; font-size: 88px; }
.ct-sub { font-family: 'Noto Sans SC'; font-size: 36px; }
</style>
Result:
✗ font_family_without_font_face: Font family used without @font-face declaration: noto sans sc.
◇ 1 error(s), 2 warning(s)
The @font-face for 'Noto Sans SC' is present (confirmed via grep "@font-face" index.html → 6 declarations including Noto Sans SC 400 + 700), but the checker doesn't find it.
Expected behavior
font_family_without_font_face should match @font-face declarations regardless of CSS block size. If @font-face { font-family: 'Noto Sans SC'; ... } exists in the same <style>, it should not error on font-family: 'Noto Sans SC' usage.
Actual behavior
In complex CSS (>100 lines with multiple @keyframes), the checker fails to match the @font-face declaration → false-positive error → npx hyperframes lint exits 1 → npx hyperframes render blocked.
Root cause hypothesis
The checker's CSS parser appears to lose track of @font-face declarations when scanning through large CSS blocks with many @keyframes / rules. The @font-face→font-family match works in <50 line CSS but breaks at ~200 lines.
Workaround
Pin to 0.6.107 (where this check is a non-blocking warning):
npx hyperframes@0.6.107 lint
npx hyperframes@0.6.107 render .
Additional context
-
CSS custom properties (var(--font-family)) are also not resolved by this checker — but that's a separate feature request. This issue is specifically: concrete @font-face with literal font-family names not matched in complex CSS.
-
The related google_fonts_import checker (also new error in 0.6.109) forces projects to move from Google Fonts <link> to local @font-face — but then font_family_without_font_face blocks them with this false positive. The two checkers are contradictory for projects using local fonts.
-
Minimal HTML with identical @font-face + font-family passes — the issue is triggered specifically by CSS block complexity/size, not by the @font-face syntax.
Summary
The
font_family_without_font_facelint checker (strengthened to error severity in 0.6.109) correctly identifies@font-facedeclarations in simple HTML but fails to match them in complex HTML with large CSS blocks (>100 lines, multiple@keyframes, full CSS framework). This produces false-positive errors that block rendering.In 0.6.107 and earlier, this was a warning (non-blocking), so the issue was masked.
Version
Reproduction
✅ Simple HTML — passes (0 errors)
Result:
0 error(s), 1 warning(s)—@font-facecorrectly matched ✅❌ Complex HTML — fails (false-positive error)
Same
@font-facedeclaration, but<style>block contains ~200 lines of additional CSS (base reset, layout classes, 10+@keyframes, component styles):Result:
The
@font-facefor'Noto Sans SC'is present (confirmed viagrep "@font-face" index.html→ 6 declarations includingNoto Sans SC400 + 700), but the checker doesn't find it.Expected behavior
font_family_without_font_faceshould match@font-facedeclarations regardless of CSS block size. If@font-face { font-family: 'Noto Sans SC'; ... }exists in the same<style>, it should not error onfont-family: 'Noto Sans SC'usage.Actual behavior
In complex CSS (>100 lines with multiple
@keyframes), the checker fails to match the@font-facedeclaration → false-positive error →npx hyperframes lintexits 1 →npx hyperframes renderblocked.Root cause hypothesis
The checker's CSS parser appears to lose track of
@font-facedeclarations when scanning through large CSS blocks with many@keyframes/ rules. The@font-face→font-familymatch works in <50 line CSS but breaks at ~200 lines.Workaround
Pin to 0.6.107 (where this check is a non-blocking warning):
npx hyperframes@0.6.107 lint npx hyperframes@0.6.107 render .Additional context
CSS custom properties (
var(--font-family)) are also not resolved by this checker — but that's a separate feature request. This issue is specifically: concrete@font-facewith literal font-family names not matched in complex CSS.The related
google_fonts_importchecker (also new error in 0.6.109) forces projects to move from Google Fonts<link>to local@font-face— but thenfont_family_without_font_faceblocks them with this false positive. The two checkers are contradictory for projects using local fonts.Minimal HTML with identical
@font-face+font-familypasses — the issue is triggered specifically by CSS block complexity/size, not by the@font-facesyntax.