Skip to content

Commit abd582b

Browse files
Revert "feat(asset-server-plugin): add background color query param for transparent images (#4999)"
This reverts commit 0fec7bc.
1 parent 0fec7bc commit abd582b

7 files changed

Lines changed: 4 additions & 278 deletions

File tree

packages/asset-server-plugin/src/asset-server.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import fs from 'fs-extra';
66
import mime from 'mime-types';
77
import path from 'path';
88

9-
import { getValidBackgroundColor, getValidFormat } from './common';
9+
import { getValidFormat } from './common';
1010
import { ImageTransformParameters, ImageTransformStrategy } from './config/image-transform-strategy';
1111
import { S3AssetStorageStrategy } from './config/s3-asset-storage-strategy';
1212
import { ASSET_SERVER_PLUGIN_INIT_OPTIONS, DEFAULT_CACHE_HEADER, loggerCtx } from './constants';
@@ -199,7 +199,6 @@ export class AssetServer {
199199
const fpx = +queryParams.fpx || undefined;
200200
const fpy = +queryParams.fpy || undefined;
201201
const format = getValidFormat(queryParams.format);
202-
const backgroundColor = getValidBackgroundColor(queryParams.bg);
203202

204203
return {
205204
width,
@@ -210,16 +209,14 @@ export class AssetServer {
210209
fpx,
211210
fpy,
212211
preset: queryParams.preset,
213-
backgroundColor,
214212
};
215213
}
216214

217215
private getFileNameFromParameters(filePath: string, params: ImageTransformParameters): string {
218-
const { width: w, height: h, mode, preset, fpx, fpy, format, quality: q, backgroundColor } = params;
216+
const { width: w, height: h, mode, preset, fpx, fpy, format, quality: q } = params;
219217
/* eslint-disable @typescript-eslint/restrict-template-expressions */
220218
const focalPoint = fpx && fpy ? `_fpx${fpx}_fpy${fpy}` : '';
221219
const quality = q ? `_q${q}` : '';
222-
const bg = backgroundColor ? `_bg${backgroundColor.replace('#', '')}` : '';
223220
const imageFormat = getValidFormat(format);
224221
let imageParamsString = '';
225222
if (w || h) {
@@ -241,9 +238,6 @@ export class AssetServer {
241238
if (quality) {
242239
imageParamsString += quality;
243240
}
244-
if (bg) {
245-
imageParamsString += bg;
246-
}
247241

248242
const decodedReqPath = this.sanitizeFilePath(filePath);
249243
if (imageParamsString !== '') {

packages/asset-server-plugin/src/common.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,3 @@ export function getValidFormat(format?: unknown): ImageTransformFormat | undefin
4040
return undefined;
4141
}
4242
}
43-
44-
/**
45-
* Validates and normalizes a background color hex string.
46-
* Accepts 3, 4, 6, or 8 character hex strings (with or without `#` prefix).
47-
* Returns the normalized hex string with `#` prefix, or `undefined` if invalid.
48-
*/
49-
export function getValidBackgroundColor(input?: unknown): string | undefined {
50-
if (typeof input !== 'string' || input.length === 0) {
51-
return undefined;
52-
}
53-
const hex = input.startsWith('#') ? input.slice(1) : input;
54-
if (/^[0-9a-fA-F]{3,4}$|^[0-9a-fA-F]{6}$|^[0-9a-fA-F]{8}$/.test(hex)) {
55-
return `#${hex.toLowerCase()}`;
56-
}
57-
return undefined;
58-
}

packages/asset-server-plugin/src/config/image-transform-strategy.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,6 @@ export interface ImageTransformParameters {
2020
fpx: number | undefined;
2121
fpy: number | undefined;
2222
preset: string | undefined;
23-
/**
24-
* @description
25-
* A hex color string (e.g. `'#ffffff'`) to be used as the background color
26-
* for images with alpha transparency. The alpha channel will be merged with
27-
* this color using Sharp's `flatten()` method.
28-
*
29-
* @since 3.8.0
30-
*/
31-
backgroundColor: string | undefined;
3223
}
3324

3425
/**

packages/asset-server-plugin/src/config/preset-only-strategy.ts

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { HexColorString, ImageTransformFormat } from '../types';
1+
import { ImageTransformFormat } from '../types';
22

33
import {
44
GetImageTransformParametersArgs,
@@ -42,22 +42,6 @@ export interface PresetOnlyStrategyOptions {
4242
* @default false
4343
*/
4444
allowFocalPoint?: boolean;
45-
/**
46-
* @description
47-
* Whether to allow the background color to be specified in the URL.
48-
* If omitted (default), the `bg` parameter is dropped.
49-
* If set to an array of hex color strings (e.g. `['#ffffff', '#000000']`),
50-
* only those colors are permitted — keeping the cache key space bounded.
51-
* If set to `'any'`, any valid hex color is accepted (explicit opt-in to an
52-
* unbounded cache surface).
53-
*
54-
* Comparison is case-insensitive, so `'#FFFFFF'` and `'#ffffff'` are
55-
* treated as the same entry.
56-
*
57-
* @default undefined
58-
* @since 3.8.0
59-
*/
60-
permittedBackgroundColors?: HexColorString[] | 'any';
6145
}
6246

6347
/**
@@ -89,7 +73,6 @@ export interface PresetOnlyStrategyOptions {
8973
* permittedQuality: [0, 50, 75, 85, 95],
9074
* permittedFormats: ['jpg', 'webp', 'avif'],
9175
* allowFocalPoint: true,
92-
* permittedBackgroundColors: ['#ffffff', '#000000'],
9376
* }),
9477
* });
9578
* ```
@@ -124,23 +107,6 @@ export class PresetOnlyStrategy implements ImageTransformStrategy {
124107
fpx: this.options.allowFocalPoint ? input.fpx : undefined,
125108
fpy: this.options.allowFocalPoint ? input.fpy : undefined,
126109
preset: input.preset,
127-
backgroundColor: this.getPermittedBackgroundColor(input.backgroundColor),
128110
};
129111
}
130-
131-
private getPermittedBackgroundColor(input: string | undefined): string | undefined {
132-
if (!input) {
133-
return undefined;
134-
}
135-
const permitted = this.options.permittedBackgroundColors;
136-
if (!permitted) {
137-
return undefined;
138-
}
139-
if (permitted === 'any') {
140-
return input;
141-
}
142-
const normalise = (c: string) => c.toLowerCase();
143-
const normalised = normalise(input);
144-
return permitted.some(c => normalise(c) === normalised) ? input : undefined;
145-
}
146112
}
Lines changed: 1 addition & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import sharp from 'sharp';
21
import { describe, expect, it } from 'vitest';
32

4-
import { getValidBackgroundColor } from './common';
5-
import { PresetOnlyStrategy } from './config/preset-only-strategy';
6-
import { Dimensions, Point, resizeToFocalPoint, transformImage } from './transform-image';
3+
import { Dimensions, Point, resizeToFocalPoint } from './transform-image';
74

85
describe('resizeToFocalPoint', () => {
96
it('no resize, crop left', () => {
@@ -70,189 +67,3 @@ describe('resizeToFocalPoint', () => {
7067
});
7168
});
7269
});
73-
74-
describe('getValidBackgroundColor', () => {
75-
it('accepts 6-char hex without #', () => {
76-
expect(getValidBackgroundColor('ffffff')).toBe('#ffffff');
77-
});
78-
79-
it('accepts 6-char hex with #', () => {
80-
expect(getValidBackgroundColor('#F0A703')).toBe('#f0a703');
81-
});
82-
83-
it('accepts 3-char shorthand hex', () => {
84-
expect(getValidBackgroundColor('fff')).toBe('#fff');
85-
});
86-
87-
it('accepts 8-char hex with alpha', () => {
88-
expect(getValidBackgroundColor('ffffff80')).toBe('#ffffff80');
89-
});
90-
91-
it('accepts 4-char shorthand hex with alpha', () => {
92-
expect(getValidBackgroundColor('fff8')).toBe('#fff8');
93-
});
94-
95-
it('returns undefined for empty string', () => {
96-
expect(getValidBackgroundColor('')).toBeUndefined();
97-
});
98-
99-
it('returns undefined for non-string input', () => {
100-
expect(getValidBackgroundColor(undefined)).toBeUndefined();
101-
expect(getValidBackgroundColor(123)).toBeUndefined();
102-
expect(getValidBackgroundColor(null)).toBeUndefined();
103-
});
104-
105-
it('returns undefined for invalid hex characters', () => {
106-
expect(getValidBackgroundColor('gggggg')).toBeUndefined();
107-
expect(getValidBackgroundColor('xyz')).toBeUndefined();
108-
});
109-
110-
it('returns undefined for wrong length hex', () => {
111-
expect(getValidBackgroundColor('ff')).toBeUndefined();
112-
expect(getValidBackgroundColor('fffff')).toBeUndefined();
113-
expect(getValidBackgroundColor('fffffffff')).toBeUndefined();
114-
});
115-
});
116-
117-
describe('transformImage with backgroundColor', () => {
118-
function createTestPngWithAlpha(width: number, height: number): Promise<Buffer> {
119-
return sharp({
120-
create: {
121-
width,
122-
height,
123-
channels: 4,
124-
background: { r: 255, g: 0, b: 0, alpha: 0.5 },
125-
},
126-
})
127-
.png()
128-
.toBuffer();
129-
}
130-
131-
it('flattens alpha channel with specified background color', async () => {
132-
const input = await createTestPngWithAlpha(10, 10);
133-
const result = await transformImage(input, {
134-
width: 10,
135-
height: 10,
136-
mode: 'resize',
137-
quality: undefined,
138-
format: 'png',
139-
fpx: undefined,
140-
fpy: undefined,
141-
preset: undefined,
142-
backgroundColor: '#ffffff',
143-
});
144-
const buffer = await result.toBuffer();
145-
const { channels, hasAlpha } = await sharp(buffer).metadata();
146-
expect(channels).toBe(3);
147-
expect(hasAlpha).toBe(false);
148-
});
149-
150-
it('preserves alpha channel when no backgroundColor is set', async () => {
151-
const input = await createTestPngWithAlpha(10, 10);
152-
const result = await transformImage(input, {
153-
width: 10,
154-
height: 10,
155-
mode: 'resize',
156-
quality: undefined,
157-
format: 'png',
158-
fpx: undefined,
159-
fpy: undefined,
160-
preset: undefined,
161-
backgroundColor: undefined,
162-
});
163-
const buffer = await result.toBuffer();
164-
const { channels, hasAlpha } = await sharp(buffer).metadata();
165-
expect(channels).toBe(4);
166-
expect(hasAlpha).toBe(true);
167-
});
168-
});
169-
170-
describe('PresetOnlyStrategy permittedBackgroundColors', () => {
171-
const presets = [{ name: 'thumb', width: 100, height: 100, mode: 'crop' as const }];
172-
const baseInput = {
173-
width: undefined,
174-
height: undefined,
175-
mode: undefined,
176-
quality: undefined,
177-
format: undefined,
178-
fpx: undefined,
179-
fpy: undefined,
180-
preset: 'thumb',
181-
backgroundColor: '#ffffff',
182-
};
183-
184-
it('drops backgroundColor when permittedBackgroundColors is omitted', () => {
185-
const strategy = new PresetOnlyStrategy({ defaultPreset: 'thumb' });
186-
const result = strategy.getImageTransformParameters({
187-
input: baseInput,
188-
availablePresets: presets,
189-
req: {} as any,
190-
});
191-
expect(result.backgroundColor).toBeUndefined();
192-
});
193-
194-
it('allows any backgroundColor when set to "any"', () => {
195-
const strategy = new PresetOnlyStrategy({
196-
defaultPreset: 'thumb',
197-
permittedBackgroundColors: 'any',
198-
});
199-
const result = strategy.getImageTransformParameters({
200-
input: baseInput,
201-
availablePresets: presets,
202-
req: {} as any,
203-
});
204-
expect(result.backgroundColor).toBe('#ffffff');
205-
});
206-
207-
it('allows a whitelisted backgroundColor', () => {
208-
const strategy = new PresetOnlyStrategy({
209-
defaultPreset: 'thumb',
210-
permittedBackgroundColors: ['#ffffff', '#000000'],
211-
});
212-
const result = strategy.getImageTransformParameters({
213-
input: baseInput,
214-
availablePresets: presets,
215-
req: {} as any,
216-
});
217-
expect(result.backgroundColor).toBe('#ffffff');
218-
});
219-
220-
it('drops a non-whitelisted backgroundColor', () => {
221-
const strategy = new PresetOnlyStrategy({
222-
defaultPreset: 'thumb',
223-
permittedBackgroundColors: ['#000000'],
224-
});
225-
const result = strategy.getImageTransformParameters({
226-
input: baseInput,
227-
availablePresets: presets,
228-
req: {} as any,
229-
});
230-
expect(result.backgroundColor).toBeUndefined();
231-
});
232-
233-
it('whitelist comparison is case-insensitive', () => {
234-
const strategy = new PresetOnlyStrategy({
235-
defaultPreset: 'thumb',
236-
permittedBackgroundColors: ['#FFFFFF'],
237-
});
238-
const result = strategy.getImageTransformParameters({
239-
input: { ...baseInput, backgroundColor: '#ffffff' },
240-
availablePresets: presets,
241-
req: {} as any,
242-
});
243-
expect(result.backgroundColor).toBe('#ffffff');
244-
});
245-
246-
it('whitelist comparison is case-insensitive with # prefix', () => {
247-
const strategy = new PresetOnlyStrategy({
248-
defaultPreset: 'thumb',
249-
permittedBackgroundColors: ['#ffffff'],
250-
});
251-
const result = strategy.getImageTransformParameters({
252-
input: { ...baseInput, backgroundColor: '#ffffff' },
253-
availablePresets: presets,
254-
req: {} as any,
255-
});
256-
expect(result.backgroundColor).toBe('#ffffff');
257-
});
258-
});

packages/asset-server-plugin/src/transform-image.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ export async function transformImage(
2424
}
2525

2626
const image = sharp(originalImage).rotate();
27-
28-
// Merge alpha transparency channel with the specified background color
29-
if (parameters.backgroundColor) {
30-
image.flatten({ background: parameters.backgroundColor });
31-
}
32-
3327
try {
3428
await applyFormat(image, parameters.format, parameters.quality);
3529
} catch (e: any) {

packages/asset-server-plugin/src/types.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,6 @@ import { ImageTransformStrategy } from './config/image-transform-strategy';
99

1010
export type ImageTransformFormat = 'jpg' | 'jpeg' | 'png' | 'webp' | 'avif';
1111

12-
/**
13-
* @description
14-
* A `#`-prefixed hex color string, e.g. `'#ffffff'` or `'#000'`.
15-
* Full hex-char validation at the type level is not feasible because
16-
* TypeScript's template literal unions exceed compiler limits for
17-
* 6- and 8-char hex strings. The `#` prefix is enforced at compile time;
18-
* hex-character and length validation is handled at runtime by
19-
* `getValidBackgroundColor()`.
20-
*
21-
* @docsCategory core plugins/AssetServerPlugin
22-
* @since 3.8.0
23-
*/
24-
export type HexColorString = `#${string}`;
25-
2612
/**
2713
* @description
2814
* Specifies the way in which an asset preview image will be resized to fit in the

0 commit comments

Comments
 (0)