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:
@@ -43,6 +43,33 @@ export async function cropImage({
|
|||||||
sharpOptions.animated = true
|
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 = {
|
const formattedCropData = {
|
||||||
height: Number(heightInPixels),
|
height: Number(heightInPixels),
|
||||||
left: percentToPixel(x, dimensions.width),
|
left: percentToPixel(x, dimensions.width),
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ export const generateFileData = async <T>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Apply resize after cropping to ensure it conforms to resizeOptions
|
// Apply resize after cropping to ensure it conforms to resizeOptions
|
||||||
if (resizeOptions) {
|
if (resizeOptions && !resizeOptions.withoutEnlargement) {
|
||||||
const resizedAfterCrop = await sharp(croppedImage)
|
const resizedAfterCrop = await sharp(croppedImage)
|
||||||
.resize({
|
.resize({
|
||||||
fit: resizeOptions?.fit || 'cover',
|
fit: resizeOptions?.fit || 'cover',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
relationSlug,
|
relationSlug,
|
||||||
unstoredMediaSlug,
|
unstoredMediaSlug,
|
||||||
versionSlug,
|
versionSlug,
|
||||||
|
withoutEnlargeSlug,
|
||||||
} from './shared.js'
|
} from './shared.js'
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
@@ -490,6 +491,19 @@ export default buildConfigWithDefaults({
|
|||||||
staticDir: path.resolve(dirname, './media/enlarge'),
|
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,
|
slug: reduceSlug,
|
||||||
fields: [],
|
fields: [],
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import {
|
|||||||
relationSlug,
|
relationSlug,
|
||||||
withMetadataSlug,
|
withMetadataSlug,
|
||||||
withOnlyJPEGMetadataSlug,
|
withOnlyJPEGMetadataSlug,
|
||||||
|
withoutEnlargeSlug,
|
||||||
withoutMetadataSlug,
|
withoutMetadataSlug,
|
||||||
} from './shared.js'
|
} from './shared.js'
|
||||||
import { startMockCorsServer } from './startMockCorsServer.js'
|
import { startMockCorsServer } from './startMockCorsServer.js'
|
||||||
@@ -69,6 +70,7 @@ let uploadsTwo: AdminUrlUtil
|
|||||||
let customUploadFieldURL: AdminUrlUtil
|
let customUploadFieldURL: AdminUrlUtil
|
||||||
let hideFileInputOnCreateURL: AdminUrlUtil
|
let hideFileInputOnCreateURL: AdminUrlUtil
|
||||||
let bestFitURL: AdminUrlUtil
|
let bestFitURL: AdminUrlUtil
|
||||||
|
let withoutEnlargementResizeOptionsURL: AdminUrlUtil
|
||||||
let consoleErrorsFromPage: string[] = []
|
let consoleErrorsFromPage: string[] = []
|
||||||
let collectErrorsFromPage: () => boolean
|
let collectErrorsFromPage: () => boolean
|
||||||
let stopCollectingErrorsFromPage: () => boolean
|
let stopCollectingErrorsFromPage: () => boolean
|
||||||
@@ -104,6 +106,7 @@ describe('Uploads', () => {
|
|||||||
customUploadFieldURL = new AdminUrlUtil(serverURL, customUploadFieldSlug)
|
customUploadFieldURL = new AdminUrlUtil(serverURL, customUploadFieldSlug)
|
||||||
hideFileInputOnCreateURL = new AdminUrlUtil(serverURL, hideFileInputOnCreateSlug)
|
hideFileInputOnCreateURL = new AdminUrlUtil(serverURL, hideFileInputOnCreateSlug)
|
||||||
bestFitURL = new AdminUrlUtil(serverURL, 'best-fit')
|
bestFitURL = new AdminUrlUtil(serverURL, 'best-fit')
|
||||||
|
withoutEnlargementResizeOptionsURL = new AdminUrlUtil(serverURL, withoutEnlargeSlug)
|
||||||
|
|
||||||
const context = await browser.newContext()
|
const context = await browser.newContext()
|
||||||
page = await context.newPage()
|
page = await context.newPage()
|
||||||
@@ -1257,7 +1260,7 @@ describe('Uploads', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// without focal point update this generated size was equal to 1736
|
// 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 () => {
|
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()
|
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', () => {
|
describe('imageSizes best fit', () => {
|
||||||
test('should select adminThumbnail if one exists', async () => {
|
test('should select adminThumbnail if one exists', async () => {
|
||||||
await page.goto(bestFitURL.create)
|
await page.goto(bestFitURL.create)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export const mediaSlug = 'media'
|
|||||||
export const relationSlug = 'relation'
|
export const relationSlug = 'relation'
|
||||||
export const audioSlug = 'audio'
|
export const audioSlug = 'audio'
|
||||||
export const enlargeSlug = 'enlarge'
|
export const enlargeSlug = 'enlarge'
|
||||||
|
export const withoutEnlargeSlug = 'without-enlarge'
|
||||||
export const focalNoSizesSlug = 'focal-no-sizes'
|
export const focalNoSizesSlug = 'focal-no-sizes'
|
||||||
export const focalOnlySlug = 'focal-only'
|
export const focalOnlySlug = 'focal-only'
|
||||||
export const reduceSlug = 'reduce'
|
export const reduceSlug = 'reduce'
|
||||||
|
|||||||
Reference in New Issue
Block a user