Skip to content

Fix gradient dropping optional arguments set to 0 - #89

Merged
11bit merged 1 commit into
mainfrom
fix-gradient-explicit-optional-args
Aug 21, 2026
Merged

Fix gradient dropping optional arguments set to 0#89
11bit merged 1 commit into
mainfrom
fix-gradient-explicit-optional-args

Conversation

@11bit

@11bit 11bit commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #88, which introduced progressive_blur with explicit undefined checks rather than the truthiness checks gradient uses. This brings gradient in line — and it turns out to be a real bug fix, not just a style change.

The bug

color, direction, start and stop were guarded with if (value) and rendered with value || "", so any falsy value was treated as "not provided":

Input Before After
{ opacity: 0.5, stop: 0 } gr:0.5 — imgproxy applies the default stop of 1.0 gr:0.5::::0
{ opacity: 0.5, start: 0 } gr:0.5 gr:0.5:::0
{ opacity: 0.5, direction: 0 } gr:0.5 gr:0.5::0

The stop: 0 case is the damaging one: the caller asks for a gradient that stops immediately and gets one spanning the whole image instead. start: 0 and direction: 0 happen to coincide with imgproxy's defaults, so those were harmless in effect but still dropped the caller's input.

Falsy values were also skipping validation entirely — start: null from a vanilla-JS caller rendered as an empty argument instead of raising.

The fix

if (value !== undefined) for validation, value ?? "" for rendering. Nothing else changes: omitted arguments still render empty and trailing : are still trimmed.

Behavior change worth noting

{ opacity: 0.5, color: "" } now throws gradient.color must be 3, 6 or 8 characters long (with alpha) instead of silently rendering an empty argument. An empty string was never a valid hex color, so this surfaces a caller bug rather than hiding it — but it is a new exception on input that previously "worked", hence the patch changeset.

Verification

  • tsc --noEmit clean, eslint src tests clean
  • vitest run → 97 files / 1100 tests passing (5 new, covering stop: 0, start: 0, direction: 0, start: null and color: "")
  • No existing test needed changing

Out of scope

The same truthiness pattern appears in resize, trim, size, watermark, watermarkSize, unsharpMasking and pngOptions. I have not audited whether any of them drops a meaningful 0 the way gradient did — worth a separate look.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G8Aa3xeVUCaxKtQJDzZhMo

`color`, `direction`, `start` and `stop` were validated and rendered
based on truthiness, so an explicit `0` was silently dropped and
imgproxy applied the default instead. For `stop: 0` this changed the
resulting image: `gr:0.5` means `stop` is `1.0`, not `0`.

Check for `undefined` instead, matching the `progressive_blur` option.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8Aa3xeVUCaxKtQJDzZhMo
@11bit
11bit merged commit a97d0ef into main Aug 21, 2026
1 check passed
@11bit
11bit deleted the fix-gradient-explicit-optional-args branch August 21, 2026 07:40
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.

1 participant