Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 139 additions & 77 deletions packages/url-loader/src/constants/parameters.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,6 @@
import { z } from 'zod';

/** Angle - a */

export const angle = {
qualifier: 'a',
schema: z.union([
z.string(),
z.number()
])
.describe(JSON.stringify({
text: 'Rotates or flips an asset by the specified number of degrees or automatically according to its orientation or available metadata.',
url: 'https://cloudinary.com/documentation/transformation_reference#a_angle'
})),
}


/** Aspect Ratio */

export const aspectRatioModesEnum = z.enum([
'vflip',
'hflip',
'ignore',
'auto_right',
'auto_left',
]);

export const aspectRatio = {
qualifier: 'ar',
schema: z.union([
z.number(),
aspectRatioModesEnum,
z.string(),
])
.describe(JSON.stringify({
text: 'Crops or resizes the asset to a new aspect ratio.',
url: 'https://cloudinary.com/documentation/transformation_reference#ar_aspect_ratio'
})),
}


/** Crop */
/** enum */

export const cropModesEnum = z.enum([
'fill',
Expand All @@ -58,18 +19,6 @@ export const cropModesEnum = z.enum([
'imagga_crop',
]);

export const crop = {
qualifier: 'c',
schema: cropModesEnum
.describe(JSON.stringify({
text: 'Mode to use when cropping an asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#c_crop_resize'
})),
}


/** Flags */

export const flagsEnum = z.enum([
'animated',
'any_format',
Expand Down Expand Up @@ -114,6 +63,63 @@ export const flagsEnum = z.enum([
'waveform',
]);

/** Angle - a */

export const angle = {
qualifier: 'a',
schema: z.union([
z.string(),
z.number()
])
.describe(JSON.stringify({
text: 'Rotates or flips an asset by the specified number of degrees or automatically according to its orientation or available metadata.',
url: 'https://cloudinary.com/documentation/transformation_reference#a_angle'
})),
}


/** Aspect Ratio */

export const aspectRatioModesEnum = z.enum([
'vflip',
'hflip',
'ignore',
'auto_right',
'auto_left',
]);

const aspectRatioSchema = z.union([
z.number(),
aspectRatioModesEnum,
z.string(),
]);

export const aspectRatio = {
qualifier: 'ar',
schema: aspectRatioSchema
.describe(JSON.stringify({
text: 'Crops or resizes the asset to a new aspect ratio.',
url: 'https://cloudinary.com/documentation/transformation_reference#ar_aspect_ratio'
})),
}


/** Crop */

const cropSchema = cropModesEnum;

export const crop = {
qualifier: 'c',
schema: cropSchema
.describe(JSON.stringify({
text: 'Mode to use when cropping an asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#c_crop_resize'
})),
}


/** Flags */

export const flags = {
qualifier: 'fl',
schema: z.union([
Expand All @@ -126,12 +132,25 @@ export const flags = {
}))
}

/** Format */

export const format = {
qualifier: 'f',
// @TODO: enum
Comment thread
colbyfayock marked this conversation as resolved.
schema: z.string()
.describe(JSON.stringify({
text: 'Converts (if necessary) and delivers an asset in the specified format regardless of the file extension used in the delivery URL.',
url: 'https://cloudinary.com/documentation/transformation_reference#f_format'
})),
}

/** Gravity */

const gravitySchema = z.string();

export const gravity = {
qualifier: 'g',
schema: z.string()
schema: gravitySchema
.describe(JSON.stringify({
text: 'Determines which part of an asset to focus on. Note: Default of auto is applied for supported crop modes only.',
url: 'https://cloudinary.com/documentation/transformation_reference#g_gravity'
Expand All @@ -141,12 +160,14 @@ export const gravity = {

/** Height */

const heightSchema = z.union([
z.number(),
z.string()
])

export const height = {
qualifier: 'h',
schema: z.union([
z.number(),
z.string()
])
schema: heightSchema
.describe(JSON.stringify({
text: 'A qualifier that determines the height of a transformed asset or an overlay.',
url: 'https://cloudinary.com/documentation/transformation_reference#h_height',
Expand All @@ -156,32 +177,20 @@ export const height = {

/** Width */

const widthSchema = z.union([
z.number(),
z.string()
]);

export const width = {
qualifier: 'w',
schema: z.union([
z.number(),
z.string()
])
schema: widthSchema
.describe(JSON.stringify({
text: 'A qualifier that sets the desired width of an asset using a specified value, or automatically based on the available width.',
url: 'https://cloudinary.com/documentation/transformation_reference#w_width',
})),
}


/** Width Resize */

export const widthResize = {
schema: z.union([
z.string(),
z.number()
])
.describe(JSON.stringify({
text: 'Width to resize the asset after all transformations are applied. Useful for responsive resizing.',
})),
}


/** X */

export const x = {
Expand Down Expand Up @@ -214,10 +223,63 @@ export const y = {

/** Zoom */

const zoomSchema = z.string()

export const zoom = {
schema: z.string()
schema: zoomSchema
.describe(JSON.stringify({
text: 'Controls how close to crop to the detected coordinates when using face-detection, custom-coordinate, or object-specific gravity.',
url: 'https://cloudinary.com/documentation/transformation_reference#z_zoom'
})),
}
}


/** Base Resizing */

export const baseAspectRatio = {
schema: aspectRatioSchema
.describe(JSON.stringify({
text: 'Crops or resizes the asset to a new aspect ratio. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#ar_aspect_ratio'
})),
};

export const baseCrop = {
schema: cropSchema
.describe(JSON.stringify({
text: 'Mode to use when cropping an asset. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#c_crop_resize'
})),
};

export const baseGravity = {
schema: gravitySchema
.describe(JSON.stringify({
text: 'Determines which part of an asset to focus on. Note: Default of auto is applied for supported crop modes only. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#g_gravity'
})),
};

export const baseHeight = {
schema: heightSchema
.describe(JSON.stringify({
text: 'A qualifier that determines the height of a transformed asset or an overlay. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#h_height',
})),
};

export const baseWidth = {
schema: widthSchema
.describe(JSON.stringify({
text: 'A qualifier that sets the desired width of an asset using a specified value, or automatically based on the available width. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#w_width',
})),
};

export const baseZoom = {
schema: zoomSchema
.describe(JSON.stringify({
text: 'Controls how close to crop to the detected coordinates when using face-detection, custom-coordinate, or object-specific gravity. This option is applied to the base layer / original asset.',
url: 'https://cloudinary.com/documentation/transformation_reference#z_zoom'
})),
};
4 changes: 2 additions & 2 deletions packages/url-loader/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { constructCloudinaryUrl, transformationPlugins } from './lib/cloudinary';
export type { ConstructUrlProps, PluginOptionsResize, PluginOptions, PluginResults } from './lib/cloudinary';
export type { ConstructUrlProps } from './lib/cloudinary';

export { effects, position, primary, text } from './constants/qualifiers';

Expand All @@ -9,5 +9,5 @@ export type { VideoOptions } from './types/video';

export type { AnalyticsOptions, CloudinaryAnalyticsOptions } from './types/analytics';
export type { ConfigOptions, CloudinaryConfigurationOptions } from './types/config';
export type { PluginSettings, PluginOverrides } from './types/plugins';
export type { PluginSettings, PluginOptions, PluginResults } from './types/plugins';
export type { Qualifier, QualiferConverters } from './types/qualifiers';
39 changes: 10 additions & 29 deletions packages/url-loader/src/lib/cloudinary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { videoOptionsSchema } from '../types/video';
import { analyticsOptionsSchema } from '../types/analytics';
import { configOptionsSchema } from '../types/config';

import { TransformationPlugin } from '../types/plugins';
import { TransformationPlugin, PluginResults, PluginOptions } from '../types/plugins';


export const transformationPlugins = [
Expand All @@ -42,14 +42,19 @@ export const transformationPlugins = [
replacePlugin,
restorePlugin,

// Cropping needs to be before any other general transformations
// as it provides the option of 2-step resizing where someone
// can resize the "base" canvas as well as the final resize
// mechanism commonly used for responsive resizing
croppingPlugin,

// Raw transformations should always come before
// other arguments to avoid conflicting with
// added options via the component

rawTransformationsPlugin,

abrPlugin,
croppingPlugin,
defaultImagePlugin,
effectsPlugin,
fillBackgroundPlugin,
Expand Down Expand Up @@ -98,21 +103,6 @@ export const constructUrlPropsSchema = z.object({

export type ConstructUrlProps = z.infer<typeof constructUrlPropsSchema>;

export interface PluginOptionsResize {
crop?: string;
width?: string | number;
}

export interface PluginOptions {
format?: string;
resize?: PluginOptionsResize;
width?: string | number;
}

export interface PluginResults {
options?: PluginOptions;
}

export function constructCloudinaryUrl({ options, config = {}, analytics }: ConstructUrlProps): string {
// If someone is explicitly passing in undefined for analytics via the analytics option,
// ensure that the URL Gen SDK option is being passed in as false as well
Expand Down Expand Up @@ -219,23 +209,14 @@ export function constructCloudinaryUrl({ options, config = {}, analytics }: Cons

const { options: pluginOptions } = results || { options: undefined };

if ( pluginOptions?.format && options ) {
pluginEffects.format = pluginOptions.format;
}

if ( pluginOptions?.width && options ) {
pluginEffects.resize = {
width: pluginOptions?.width
};
}
Object.assign(pluginEffects, pluginOptions);
});

// We want to perform any resizing at the end of the end of the transformation
// sets to allow consistent use of positioning / sizing, especially responsively

if ( pluginEffects?.resize && !options.strictTransformations ) {
const { width, crop = 'limit' } = pluginEffects.resize;
cldAsset.effect(`c_${crop},w_${width}`);
if ( typeof pluginEffects.resize === 'string' ) {
cldAsset.addTransformation(pluginEffects.resize);
}

cldAsset.setDeliveryType(options?.deliveryType || 'upload');
Expand Down
10 changes: 10 additions & 0 deletions packages/url-loader/src/lib/transformations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,14 @@ export function constructTransformation({ prefix, qualifier, value, converters }

export function promptArrayToString(promptArray: Array<string>) {
return `(${promptArray.join(';')})`;
}

/**
* normalizeNumberParameter
* @TODO: move into util
*/

export function normalizeNumberParameter(param: number | string | undefined) {
if ( typeof param !== 'string' ) return param;
return parseInt(param)
}
Loading