Files
directus/api/src/utils/transformations.ts
Tim 2c9ff3bca6 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>
2021-07-21 15:57:47 -04:00

69 lines
2.1 KiB
TypeScript

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;
}