mirror of
https://github.com/directus/directus.git
synced 2026-01-27 16:38:04 -05:00
Allow custom transformations of assets (#6593)
* Allow custom transformations of assets This exposes one query parameter `transforms`, which is a JSON array of shard transformation operations. It also updates the asset presets. The UX for this still needs some work * Rename options to arguments for presets More explicit * options -> arguments in setting spec * Better errors for invalid JSON in asset presets * Add limit to transforms query parameter * Use flattened option for extra transforms * Fix placeholder color of code input * Allow "simple mode" aliases * Add documentation Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
68
api/src/utils/transformations.ts
Normal file
68
api/src/utils/transformations.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { isNil } from 'lodash';
|
||||
import {
|
||||
File,
|
||||
Transformation,
|
||||
TransformationParams,
|
||||
TransformationPreset,
|
||||
TransformationPresetFormat,
|
||||
TransformationPresetResize,
|
||||
} from '../types';
|
||||
|
||||
// Extract transforms from a preset
|
||||
export function resolvePreset(input: TransformationParams | TransformationPreset, file: File): Transformation[] {
|
||||
// Do the format conversion last
|
||||
return [extractResize(input), ...(input.transforms ?? []), extractToFormat(input, file)].filter(
|
||||
(transform): transform is Transformation => transform !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
function extractOptions<T extends Record<string, any>>(keys: (keyof T)[], numberKeys: (keyof T)[] = []) {
|
||||
return function (input: TransformationParams | TransformationPreset): T {
|
||||
return Object.entries(input).reduce(
|
||||
(config, [key, value]) =>
|
||||
keys.includes(key as any) && isNil(value) === false
|
||||
? {
|
||||
...config,
|
||||
[key]: numberKeys.includes(key as any) ? +value : value,
|
||||
}
|
||||
: config,
|
||||
{} as T
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
// Extract format transform from a preset
|
||||
function extractToFormat(input: TransformationParams | TransformationPreset, file: File): Transformation | undefined {
|
||||
const options = extractOptions<TransformationPresetFormat>(['format', 'quality'], ['quality'])(input);
|
||||
return Object.keys(options).length > 0
|
||||
? [
|
||||
'toFormat',
|
||||
options.format || (file.type!.split('/')[1] as any),
|
||||
{
|
||||
quality: options.quality,
|
||||
},
|
||||
]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function extractResize(input: TransformationParams | TransformationPreset): Transformation | undefined {
|
||||
const resizable = ['width', 'height'].some((key) => key in input);
|
||||
if (!resizable) return undefined;
|
||||
|
||||
return [
|
||||
'resize',
|
||||
extractOptions<TransformationPresetResize>(
|
||||
['width', 'height', 'fit', 'withoutEnlargement'],
|
||||
['width', 'height']
|
||||
)(input),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to extract a file format from an array of `Transformation`'s.
|
||||
*/
|
||||
export function maybeExtractFormat(transforms: Transformation[]): string | undefined {
|
||||
const toFormats = transforms.filter((t) => t[0] === 'toFormat');
|
||||
const lastToFormat = toFormats[toFormats.length - 1];
|
||||
return lastToFormat ? lastToFormat[1]?.toString() : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user