fix(images): make the fallbackFormat rule per-source-format - #60
Closed
dmurko wants to merge 2 commits into
Closed
Conversation
The scaffold said "**Do NOT set `fallbackFormat="webp"`**" unconditionally.
That rule generalizes from a `.png` repro and is wrong for `.webp` sources.
Ground truth, `node_modules/astro/components/Picture.astro` (verified in
both astro@6.4.8 and astro@7.1.3):
let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat; // 'png'
if (!fallbackFormat && isESMImportedImage(clonedSrc) &&
specialFormatsFallback.includes(clonedSrc.format)) {
resultFallbackFormat = clonedSrc.format;
}
`specialFormatsFallback` is `['gif','svg','jpg','jpeg']`. **`webp` is not
on it**, so a `.webp` source with no `fallbackFormat` silently transcodes
its `<img>` fallback to PNG — for photographic content routinely several
megabytes, larger than the source it replaced. Following the scaffold's
blanket rule is what causes that.
So the rule is per-source-format:
- `.jpg`/`.jpeg`/`.gif`/`.svg` -> omit (they fall back to themselves)
- `.png` -> omit (setting it fails the build with
ENOENT dist/_astro/<name>.png)
- `.webp` -> SET fallbackFormat="webp"
`skills/scaffold-sync/SKILL.md` also contradicted itself: the 0.1.2
migration-note sample output told users to apply
`formats={['webp']} fallbackFormat="webp"`, which the "Manual edits"
section two hundred lines later forbids outright. Both now state the
per-source-format rule.
Added the check to `skills/code-review` so it is enforced rather than
only documented — a rule that lives solely in CLAUDE.md is how the image
config drifted before.
Also corrected the right-sizing section's clamping claim. It said only
`widths` are clamped, which implies an oversized `width` upscales. It
does not: every `resize()` branch in
`astro/dist/assets/services/sharp.js` passes `withoutEnlargement: true`.
Nothing upscales, so a soft image means the source master is too small.
Docs-only; no scaffold file or version change (follows 4078700).
Verified the scaffold still builds and emits real WebP at 320w/640w.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
The scaffold said "Do NOT set
fallbackFormat=\"webp\"" unconditionally. That rule generalizes from a.pngrepro and is wrong for.webpsources, where following it ships a multi-megabyte PNG fallback.Ground truth
node_modules/astro/components/Picture.astro— verified in bothastro@6.4.8(the scaffold's pin) andastro@7.1.3:specialFormatsFallbackis['gif','svg','jpg','jpeg'].webpis not on it, so a.webpsource with nofallbackFormatfalls through todefaultFallbackFormat = 'png'and silently transcodes the<img>fallback to PNG — for photographic content routinely several megabytes, larger than the source it replaced.The corrected rule
fallbackFormat.jpg/.jpeg/.gif/.svg.pngENOENT … dist/_astro/<name>.png.webpfallbackFormat="webp"scaffold-synccontradicted itselfThe 0.1.2 migration-note sample output told users to apply
formats={['webp']} fallbackFormat="webp"— which the "Manual edits" section ~160 lines later forbids outright. A site following the printed output got the build-breaking combination on.pngsources. Both now state the per-source-format rule.Enforcement, not just documentation
Added the check to
skills/code-review, keyed to the source file's extension rather than flagged blanket. A rule that lives only in CLAUDE.md is how the image config drifted in the first place — theimageService: "compile"recommendation survived there for months after the config moved to"custom".Also: corrected a clamping claim
The right-sizing section said only
widthsare clamped, which implies an oversizedwidthprop upscales into a bigger, softer file. It does not — everyresize()branch inastro/dist/assets/services/sharp.jspasseswithoutEnlargement: true. Nothing upscales, so a soft image always means the source master is too small, and the fix is a bigger source rather than a bigger number.Scope
Docs-only — no scaffold file or plugin version change, following
4078700's precedent for the analogous stale-guidance fix. Verified the scaffold still builds clean and emits real WebP at 320w/640w.Found while applying #57 to site-sarifgroup (site-sarifgroup#7).
🤖 Generated with Claude Code