* fix(pdf): register Noto punctuation fallback for missing glyphs
- Problem: U+2022 bullet characters render as garbled glyphs when the body
font (e.g. IBM Plex Serif) lacks the glyph and no PDF fallback is registered.
- Fix: append Noto Serif/Sans to the PDF fallback stack as a general-purpose
punctuation source covering General Punctuation (U+2000–U+206F).
- Verification: pnpm --filter @reactive-resume/fonts test;
pnpm --filter @reactive-resume/pdf test src/hooks/use-register-fonts.test.ts
* test(fonts): clarify zh-CN fallback test description
- Problem: getPdfFallbackFontFamilies("Times-Roman", { locale: "zh-CN" }) now
returns ["Noto Serif SC", "Noto Serif"] (the general-purpose punctuation
fallback is appended), so the test description "returns only the Simplified
Chinese font for zh-CN (unchanged behavior)" is no longer accurate.
- Fix: rename the test to describe that it uses the Simplified Chinese font
plus the punctuation fallback. The assertion is unchanged.
- Verification: pnpm --filter @reactive-resume/fonts test -> 45/45 passing.
---------
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
* fix: use language-specific Noto fonts for CJK PDF fallback
* feat: extend fallback to Arabic/Hebrew/Thai
---------
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Introduce createRtlStyleHelpers and a single rtl flag on RenderProvider,
migrate every template page to mirrored layout styles, and rename
alignRight to alignEnd. Fix plain rich text rendering via PdfText
paragraph renderers and map legacy Times New Roman to Times-Roman.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(fonts): restore legacy local font names via metric-compatible aliases
Closes#2989.
In v5.0.x the Puppeteer renderer resolved fonts like 'Times New Roman'
or 'Arial' through the browser's font stack. The v5.1 migration to
@react-pdf/renderer requires every font to be Font.register()-ed; the
legacy local-font names were not carried over, so resumes upgraded
from v5.0.x had their typography silently replaced with IBM Plex Serif,
changing line breaks, page counts and overall layout.
This adds a render-time alias layer mapping the old names to
metric-compatible web fonts already shipped in the webfont list:
Times New Roman → Tinos
Cambria → Tinos
Arial → Arimo
Garamond → EB Garamond
Calibri → Source Sans 3
- packages/fonts:
- new `legacyFontAliases` map and `resolveLegacyFontAlias` helper.
- `getFont` falls back to the alias map when the direct lookup misses,
so any caller that asked 'is this a known family?' now answers
truthfully for the legacy names.
- `getFontDisplayName` is intentionally unchanged: the typography
sidebar keeps showing the user's original choice ('Times New Roman'),
while the renderer transparently swaps in the alias target.
- packages/pdf/use-register-fonts:
- `resolvePdfFontFamily` returns the alias target when one applies,
so `Font.register` runs against the right web font and templates
receive a family name they can actually render.
Backwards compatible: families that were never aliased (Roboto, IBM
Plex Serif, the standard PDF fonts, ...) take exactly the same code
path as before. The CJK glyph fallback added in #2986 / PR #3013
continues to apply on top of the resolved primary family.
* fix(fonts): use Carlito (not Source Sans 3) as Calibri alias
Per maintainer review feedback: Carlito is metric-compatible with
Calibri, while Source Sans 3 only matches visually. Switching gives
upgraded resumes the same line widths, line breaks and page counts
they had under v5.0.x.
- packages/fonts/webfontlist.json: add Carlito (Google Fonts, weights
400/700 + italics) so it's a registerable target.
- packages/scripts/fonts/generate.ts: add a getMetricCompatibleFonts
helper and merge it into the output, mirroring how Computer Modern
fonts are appended. This way regenerating the list (`pnpm generate`)
re-emits Carlito automatically and dedupes if it ever enters the
Google Fonts popularity slice.
- packages/fonts/src/index.ts: alias `Calibri → Carlito`.
- packages/fonts/src/index.test.ts: update alias test cases.