fix: prevent resizing of original file with withoutEnlargement on update (#12291)

This PR updates `generateFileData` to skip applying `resizeOptions`
after updating an image if `resizeOptions.withoutEnlargement` is `true`
and the original image size is smaller than the dimensions defined in
`resizeOptions`.

This prevents unintended re-resizing of already resized images when
updating or modifying metadata without uploading a new file.

This change ensures that:

- Resizing is skipped if withoutEnlargement: true

- Resizing still occurs if withoutEnlargement: false or unset

This resolves an issue where images were being resized again
unnecessarily when updating an upload.

Fixes #12280
This commit is contained in:
Patrik
2025-05-20 09:43:53 -04:00
committed by GitHub
parent 81d333f4b0
commit 1235a183ff
5 changed files with 76 additions and 2 deletions

View File

@@ -43,6 +43,33 @@ export async function cropImage({
sharpOptions.animated = true
}
const { height: originalHeight, width: originalWidth } = dimensions
const newWidth = Number(widthInPixels)
const newHeight = Number(heightInPixels)
const dimensionsChanged = originalWidth !== newWidth || originalHeight !== newHeight
if (!dimensionsChanged) {
let adjustedHeight = originalHeight
if (fileIsAnimatedType) {
const animatedMetadata = await sharp(
file.tempFilePath || file.data,
sharpOptions,
).metadata()
adjustedHeight = animatedMetadata.pages ? animatedMetadata.height : originalHeight
}
return {
data: file.data,
info: {
height: adjustedHeight,
size: file.size,
width: originalWidth,
},
}
}
const formattedCropData = {
height: Number(heightInPixels),
left: percentToPixel(x, dimensions.width),

View File

@@ -241,7 +241,7 @@ export const generateFileData = async <T>({
})
// Apply resize after cropping to ensure it conforms to resizeOptions
if (resizeOptions) {
if (resizeOptions && !resizeOptions.withoutEnlargement) {
const resizedAfterCrop = await sharp(croppedImage)
.resize({
fit: resizeOptions?.fit || 'cover',

View File

@@ -30,6 +30,7 @@ import {
relationSlug,
unstoredMediaSlug,
versionSlug,
withoutEnlargeSlug,
} from './shared.js'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
@@ -490,6 +491,19 @@ export default buildConfigWithDefaults({
staticDir: path.resolve(dirname, './media/enlarge'),
},
},
{
slug: withoutEnlargeSlug,
fields: [],
upload: {
resizeOptions: {
width: 1000,
height: undefined,
fit: 'inside',
withoutEnlargement: true,
},
staticDir: path.resolve(dirname, './media/without-enlarge'),
},
},
{
slug: reduceSlug,
fields: [],

View File

@@ -38,6 +38,7 @@ import {
relationSlug,
withMetadataSlug,
withOnlyJPEGMetadataSlug,
withoutEnlargeSlug,
withoutMetadataSlug,
} from './shared.js'
import { startMockCorsServer } from './startMockCorsServer.js'
@@ -69,6 +70,7 @@ let uploadsTwo: AdminUrlUtil
let customUploadFieldURL: AdminUrlUtil
let hideFileInputOnCreateURL: AdminUrlUtil
let bestFitURL: AdminUrlUtil
let withoutEnlargementResizeOptionsURL: AdminUrlUtil
let consoleErrorsFromPage: string[] = []
let collectErrorsFromPage: () => boolean
let stopCollectingErrorsFromPage: () => boolean
@@ -104,6 +106,7 @@ describe('Uploads', () => {
customUploadFieldURL = new AdminUrlUtil(serverURL, customUploadFieldSlug)
hideFileInputOnCreateURL = new AdminUrlUtil(serverURL, hideFileInputOnCreateSlug)
bestFitURL = new AdminUrlUtil(serverURL, 'best-fit')
withoutEnlargementResizeOptionsURL = new AdminUrlUtil(serverURL, withoutEnlargeSlug)
const context = await browser.newContext()
page = await context.newPage()
@@ -1257,7 +1260,7 @@ describe('Uploads', () => {
})
// without focal point update this generated size was equal to 1736
expect(redDoc.sizes.focalTest.filesize).toEqual(1598)
expect(redDoc.sizes.focalTest.filesize).toEqual(1586)
})
test('should resize image after crop if resizeOptions defined', async () => {
@@ -1355,6 +1358,35 @@ describe('Uploads', () => {
await expect(page.locator('.file-field .file-details__remove')).toBeHidden()
})
test('should skip applying resizeOptions after updating an image if resizeOptions.withoutEnlargement is true and the original image size is smaller than the dimensions defined in resizeOptions', async () => {
await page.goto(withoutEnlargementResizeOptionsURL.create)
const fileChooserPromise = page.waitForEvent('filechooser')
await page.getByText('Select a file').click()
const fileChooser = await fileChooserPromise
await wait(1000)
await fileChooser.setFiles(path.join(dirname, 'test-image.jpg'))
await page.waitForSelector('button#action-save')
await page.locator('button#action-save').click()
await expect(page.locator('.payload-toast-container')).toContainText('successfully')
await wait(1000)
await page.locator('.file-field__edit').click()
// no need to make any changes to the image if resizeOptions.withoutEnlargement is actually being respected now
await page.locator('button:has-text("Apply Changes")').click()
await page.waitForSelector('button#action-save')
await page.locator('button#action-save').click()
await expect(page.locator('.payload-toast-container')).toContainText('successfully')
await wait(1000)
const resizeOptionMedia = page.locator('.file-meta .file-meta__size-type')
// expect the image to be the original size since the original image is smaller than the dimensions defined in resizeOptions
await expect(resizeOptionMedia).toContainText('800x800')
})
describe('imageSizes best fit', () => {
test('should select adminThumbnail if one exists', async () => {
await page.goto(bestFitURL.create)

View File

@@ -3,6 +3,7 @@ export const mediaSlug = 'media'
export const relationSlug = 'relation'
export const audioSlug = 'audio'
export const enlargeSlug = 'enlarge'
export const withoutEnlargeSlug = 'without-enlarge'
export const focalNoSizesSlug = 'focal-no-sizes'
export const focalOnlySlug = 'focal-only'
export const reduceSlug = 'reduce'