fix: render piece SVGs at export resolution for crisp high-res output - #219
Merged
Conversation
BilgeGates
force-pushed
the
fix/high-res-piece-export
branch
from
August 3, 2026 10:26
f0a5ee8 to
fc3ca28
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the SVG export pipeline so embedded piece SVGs are resized to an intended export pixel size before being inlined, improving sharpness when the overall SVG is rasterized at high resolution.
Changes:
- Passes a computed target size into
imageToEmbeddableDataURL()so fetched SVG pieces can be resized before base64-inlining. - Adds
intrinsicPxOf()(with tests) and resize/clamp logic for inlined SVG sources. - Includes broad formatting changes (quotes/trailing commas) in the touched utils.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/shared/utils/svgExporter.ts | Computes a target piece size and forwards it into the piece inlining path during SVG generation. |
| src/shared/utils/pieceUtils.ts | Adds intrinsic-size detection and conditional resizing for fetched SVG piece sources; updates data URL caching keying. |
| src/shared/utils/pieceUtils.test.ts | Adds unit tests for intrinsicPxOf() parsing/conversion behavior. |
Suppressed comments (3)
src/shared/utils/svgExporter.ts:4
- This file was reformatted with double quotes and trailing commas, but the repo Prettier config sets
singleQuote: trueandtrailingComma: "none"(.prettierrc). This will keep the file inconsistent with the rest ofsrc/shared/utilsand can break format/lint checks; please run Prettier or revert to the configured style.
This issue also appears on line 82 of the same file.
import { ChessBoard, isChessBoard } from '@app-types';
import {
getDisplayCoordinates,
src/shared/utils/pieceUtils.ts:5
- This file now uses double quotes and trailing commas, which conflicts with the repo Prettier config (
singleQuote: true,trailingComma: "none"in .prettierrc) and the surrounding utils code. Please reformat with the repo formatter to avoid churn and potential CI format failures.
import { PIECE_SET_POPULARITY, PIECE_SETS as ALL_PIECE_SETS } from '@constants';
import type { PieceSet } from '@app-types';
import { logger } from './logger';
// Types
src/shared/utils/svgExporter.ts:82
pieceOutputPxis currently calculated using constants that effectively assume the 4× (1200 DPI) preset and ignoreexportQuality. For lower quality presets this oversizes the embedded piece SVGs (larger base64, more memory/CPU) and no longer matches the actual raster target square size used bycalculateRenderSurfaceSize().
throw new Error('Invalid FEN: unable to parse board');
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+214
to
+225
| function resizePieceSvg(svgText: string, targetPx: number): string { | ||
| const size = String(Math.round(targetPx)); | ||
| const resized = svgText.replace(/<svg([^>]*?)>/i, (_match, attrs: string) => { | ||
| let next = attrs; | ||
| next = next.replace(/\s+width\s*=\s*"[^"]*"/i, ` width="${size}"`); | ||
| next = next.replace(/\s+height\s*=\s*"[^"]*"/i, ` height="${size}"`); | ||
| if (!/\swidth\s*=/.test(next)) next += ` width="${size}"`; | ||
| if (!/\sheight\s*=/.test(next)) next += ` height="${size}"`; | ||
| return `<svg${next}>`; | ||
| }); | ||
| return resized === svgText ? svgText : resized; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
High-res export now renders the embedded piece SVGs at the target output pixel size instead of their source intrinsic size. Sets with a low intrinsic resolution (e.g.
californiaat 100px) were upscaled by browsers that rasterize nested SVG at its intrinsic size, which produces a soft image in high-DPI exports; the pieces are now resized to the computed output size (clamped 64–2048px) while never shrinking below the set's own artwork, so rasterization stays sharp in any browser and larger sets keep their supersampling advantage.Checklist
pnpm validatepasses locallyany/@ts-ignore/ non-null!introduced