Skip to content

fix: support local variable fonts with weight ranges#794

Open
peteruithoven wants to merge 6 commits into
nuxt:mainfrom
peteruithoven:Feature/Variable-fonts
Open

fix: support local variable fonts with weight ranges#794
peteruithoven wants to merge 6 commits into
nuxt:mainfrom
peteruithoven:Feature/Variable-fonts

Conversation

@peteruithoven
Copy link
Copy Markdown

@peteruithoven peteruithoven commented Feb 23, 2026

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Currently local variable fonts are not supported unless a src is supplied.
Weights with ranges (e.g. ["100 900"]) and file names with ranges my-variable-font-100-900.woff2 are not supported. This means @nuxt/fonts can't connect the family configuration with the font files, which means it can't produce the font face declaration.
The current workaround is manually adding a src to the family configuration.

This PR fixes the font file detection when a variable weight range is specified.
It also expands unit tests and updates documentation.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 23, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@nuxt/fonts@794

commit: f199ac7

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Local font provider parsing now recognizes and normalizes weight ranges (e.g., "100-900") and prefers range extraction when generating slugs; single-weight extraction remains a fallback. Slug suffixes are sanitized by replacing spaces with dashes. Documentation was updated with an explicit variable-font filename example (comic-sans-ms-100-900.woff2) and an isolated "::" line was inserted before a warning block. Tests were extended to include additional variable font fixtures and assertions covering resolved weight ("100 900"), style, subsets, formats, and generated URLs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: support local variable fonts with weight ranges' directly and specifically describes the main change in the changeset - adding support for variable fonts with weight ranges in local font providers.
Description check ✅ Passed The pull request description clearly explains the problem (local variable fonts not supported without manual src configuration) and the solution (fixing font file detection for variable weight ranges).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/providers/local.ts (1)

142-142: WEIGHT_RANGE_RE may false-match non-weight digit sequences in filenames.

The regex ([1-9]00)-([1-9]00) has no boundary assertions, so a filename like MyFont-2005-300.woff2 (where 200 and 300 are substring matches within 2005-300) would still match 200)-(300 — actually wait, 2005-300 would match 500-300? Let me re-check: [1-9]00 matches exactly 3 digits, and the regex engine will try every position. In 2005-300, it would find 200 at position 0, then require -, but position 3 is 5. It would then try 005 which fails [1-9]. Moving on, 05- fails. So 5-3 fails. It would eventually not match 2005-300.

However, consider font-v200-300dpi.woff2 — the regex would match 200-300 within it, incorrectly treating it as a weight range. Adding word-boundary or non-digit assertions would make this more robust.

Proposed hardening
-const WEIGHT_RANGE_RE = /(?<weightRange>([1-9]00)-([1-9]00))/i;
+const WEIGHT_RANGE_RE = /(?<![0-9])(?<weightRange>([1-9]00)-([1-9]00))(?![0-9])/

This uses lookbehind/lookahead to ensure the weight digits aren't part of a larger number.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/local.ts` at line 142, The current WEIGHT_RANGE_RE (const
WEIGHT_RANGE_RE) can match weight-like substrings embedded inside larger numbers
in filenames; update the regex to require non-digit boundaries around the weight
range by adding a negative lookbehind (?<!\d) before and a negative lookahead
(?!\d) after the named group (?<weightRange>([1-9]00)-([1-9]00)) so only
standalone three-digit weight ranges like "200-300" are captured (adjust the
pattern in src/providers/local.ts where WEIGHT_RANGE_RE is declared).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/content/1.get-started/4.providers.md`:
- Line 14: The documentation example for font filenames is incorrect: update the
example `comic-sans-ms-100-900.woff2 (100 900/italic/cyrillic)` to accurately
reflect defaults by changing the annotation to `comic-sans-ms-100-900.woff2 (100
900/normal/latin)` or alternatively change the filename to include explicit
suffixes like `comic-sans-ms-100-900-italic-cyrillic.woff2 (100
900/italic/cyrillic)` so the stated style/subset matches the filename; also fix
the grammar by replacing the phrase "will lookup" with "will look up" where the
behavior of `font-family` lookup is described.

In `@src/providers/local.ts`:
- Around line 38-40: The slug construction in src/providers/local.ts has
stylistic lint errors: remove the unnecessary parentheses around the single
arrow parameter in the map callback, fix indentation to align the map callback
and join call consistently (use 4 spaces per indent level), and remove the
unexpected trailing comma after the map array element. Locate the slug
assignment that uses fontFamilyToSlug(family) and suffixes.map(...) and update
the map callback to use a single unparenthesized parameter (e.g., suffix =>
...), adjust indentation to match surrounding code, and ensure no trailing comma
remains before the closing bracket/join.
- Line 142: Remove the unnecessary case-insensitive flag and the trailing
semicolon on the WEIGHT_RANGE_RE declaration: update the const WEIGHT_RANGE_RE
regex (symbol: WEIGHT_RANGE_RE) to omit the `i` flag (digits/hyphens are
case-invariant) and drop the semicolon to satisfy the project's no-semicolons
lint rule.
- Around line 161-170: Remove all stray semicolons and fix brace style in the
weight parsing block so the closing brace of the if sits on its own line and the
else begins on the next line; update the code around WEIGHT_RANGE_RE,
weightRange and weight to follow project style (no semicolons, proper newline
before else). Also eliminate the no-op replace call (.replace(/[\s._]+/, '-'))
or adjust WEIGHT_RANGE_RE to allow alternate separators if you intended to
accept spaces/dots/underscores, and ensure SINGLE_WEIGHT_RE usage remains
unchanged for the fallback.

In `@test/providers/local.test.ts`:
- Around line 158-192: The test has ESLint style issues: in
test/providers/local.test.ts update the promise then callback to use an
unparenthesized single parameter (change .then((r) => r.fonts) to .then(r =>
r.fonts)) and remove the trailing semicolon at the end of the expect assertion;
locate the call to provider.resolveFont in the test and adjust the .then
callback and final line terminator accordingly so the file conforms to project
lint rules.

---

Nitpick comments:
In `@src/providers/local.ts`:
- Line 142: The current WEIGHT_RANGE_RE (const WEIGHT_RANGE_RE) can match
weight-like substrings embedded inside larger numbers in filenames; update the
regex to require non-digit boundaries around the weight range by adding a
negative lookbehind (?<!\d) before and a negative lookahead (?!\d) after the
named group (?<weightRange>([1-9]00)-([1-9]00)) so only standalone three-digit
weight ranges like "200-300" are captured (adjust the pattern in
src/providers/local.ts where WEIGHT_RANGE_RE is declared).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ebc1f4 and cf67f9d.

📒 Files selected for processing (3)
  • docs/content/1.get-started/4.providers.md
  • src/providers/local.ts
  • test/providers/local.test.ts

Comment thread docs/content/1.get-started/4.providers.md Outdated
Comment thread src/providers/local.ts Outdated
Comment thread src/providers/local.ts Outdated
Comment thread src/providers/local.ts Outdated
Comment thread test/providers/local.test.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
docs/content/1.get-started/4.providers.md (1)

14-14: ⚠️ Potential issue | 🟡 Minor

"will lookup" → "will look up"

The grammar issue flagged in the previous review remains unaddressed. "lookup" is a noun; the verb form is "look up".

✏️ Proposed fix
-`font-family` values with spaces and/or caps will lookup hyphenated lowercase filenames as well
+`font-family` values with spaces and/or caps will look up hyphenated lowercase filenames as well
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/1.get-started/4.providers.md` at line 14, The sentence uses the
incorrect verb "will lookup"; change the phrase "will lookup hyphenated
lowercase filenames as well" to the correct verb form "will look up hyphenated
lowercase filenames as well" in the paragraph describing filename lookup
behavior (the sentence mentioning `font-family: 'Comic Sans MS'` and
`comic-sans-ms.woff2`) so the documentation uses proper grammar.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/content/1.get-started/4.providers.md`:
- Line 14: The sentence uses the incorrect verb "will lookup"; change the phrase
"will lookup hyphenated lowercase filenames as well" to the correct verb form
"will look up hyphenated lowercase filenames as well" in the paragraph
describing filename lookup behavior (the sentence mentioning `font-family:
'Comic Sans MS'` and `comic-sans-ms.woff2`) so the documentation uses proper
grammar.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf67f9d and 08a9dae.

📒 Files selected for processing (1)
  • docs/content/1.get-started/4.providers.md

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Feb 24, 2026

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 69.30%. Comparing base (7ebc1f4) to head (f199ac7).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/providers/local.ts 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #794      +/-   ##
==========================================
+ Coverage   68.47%   69.30%   +0.83%     
==========================================
  Files           9        9              
  Lines         295      303       +8     
  Branches       67       70       +3     
==========================================
+ Hits          202      210       +8     
  Misses         75       75              
  Partials       18       18              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@peteruithoven
Copy link
Copy Markdown
Author

I feel like that coverage complaint is mostly on lines predating my additions. But I was a bit worried about support for weights like extra-light, so I've adjusted a unit test to cover this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No variable font local provider unit tests? Using local fonts with variable weight

2 participants