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
21 changes: 21 additions & 0 deletions packages/url-loader/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# [@cloudinary-util/url-loader-v5.3.0-beta.3](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.3.0-beta.2...@cloudinary-util/url-loader-v5.3.0-beta.3) (2024-05-23)


### Features

* Throw error if no public ID for video player options ([#159](https://github.com/cloudinary-community/cloudinary-util/issues/159)) ([973d5fa](https://github.com/cloudinary-community/cloudinary-util/commit/973d5fa05801e40d99fbdc6bdbb634839b76c120))

# [@cloudinary-util/url-loader-v5.3.0-beta.2](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.3.0-beta.1...@cloudinary-util/url-loader-v5.3.0-beta.2) (2024-05-23)


### Bug Fixes

* getVideoPlayerOptions Exports ([#158](https://github.com/cloudinary-community/cloudinary-util/issues/158)) ([980f423](https://github.com/cloudinary-community/cloudinary-util/commit/980f423790235e2c08acc1bdfbb17b2fa610f445))

# [@cloudinary-util/url-loader-v5.3.0-beta.1](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.2.2...@cloudinary-util/url-loader-v5.3.0-beta.1) (2024-05-23)


### Features

* getVideoPlayerOptions ([#156](https://github.com/cloudinary-community/cloudinary-util/issues/156)) ([da6b56d](https://github.com/cloudinary-community/cloudinary-util/commit/da6b56d591efaf767669be722c0c954720bb9463)), closes [#155](https://github.com/cloudinary-community/cloudinary-util/issues/155)

# [@cloudinary-util/url-loader-v5.2.2](https://github.com/colbyfayock/cloudinary-util/compare/@cloudinary-util/url-loader-v5.2.1...@cloudinary-util/url-loader-v5.2.2) (2024-04-09)


Expand Down
3 changes: 2 additions & 1 deletion packages/url-loader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cloudinary-util/url-loader",
"version": "5.2.2",
"version": "5.3.0-beta.3",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
Expand Down Expand Up @@ -39,6 +39,7 @@
"access": "public"
},
"dependencies": {
"@cloudinary-util/types": "workspace:*",
"@cloudinary-util/util": "workspace:*",
"@cloudinary/url-gen": "1.15.0",
"zod": "^3.22.4"
Expand Down
3 changes: 3 additions & 0 deletions packages/url-loader/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export { constructCloudinaryUrl, transformationPlugins } from './lib/cloudinary';
export type { ConstructUrlProps } from './lib/cloudinary';

export { getVideoPlayerOptions } from './lib/video-player';
export type { GetVideoPlayerOptions, GetVideoPlayerOptionsLogo } from './lib/video-player';

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

export type { AssetOptions } from './types/asset';
Expand Down
173 changes: 173 additions & 0 deletions packages/url-loader/src/lib/video-player.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { CloudinaryVideoPlayerOptionsLogo, CloudinaryVideoPlayerOptions } from '@cloudinary-util/types';
import { parseUrl } from '@cloudinary-util/util';

import { constructCloudinaryUrl, ConstructUrlProps } from './cloudinary';
import { ConfigOptions } from '../types/config';

/**
* getVideoPlayerOptions
*/

export type GetVideoPlayerOptions = Omit<CloudinaryVideoPlayerOptions, "cloud_name" | "autoplayMode" | "publicId" | "secure" | "showLogo" | "logoImageUrl" | "logoOnclickUrl"> & {
logo?: boolean | GetVideoPlayerOptionsLogo;
poster?: string | ConstructUrlProps["options"];
src: string;
quality?: string | number;
}

export interface GetVideoPlayerOptionsLogo {
imageUrl?: CloudinaryVideoPlayerOptionsLogo['logoImageUrl'];
logo?: boolean;
onClickUrl?: CloudinaryVideoPlayerOptionsLogo['logoOnclickUrl'];
}

export function getVideoPlayerOptions(options: GetVideoPlayerOptions, config: ConfigOptions) {
const {
autoplay,
controls = true,
height,
language,
languages,
logo = true,
loop = false,
muted = false,
poster,
src,
transformation,
quality = 'auto',
width,
...otherCldVidPlayerOptions
} = options;

// Configuration for Cloudinary account. Cloud name is required,
// so if one isn't present, throw.

const { cloudName } = config?.cloud || {};
const { secureDistribution, privateCdn } = config?.url || {};

if (!cloudName) {
throw new Error('A Cloudinary Cloud name is required, please make sure your environment variable is set and configured in your environment.');
}

// If the publicId/src is a URL, attempt to parse it as a Cloudinary URL
// to get the public ID alone

let publicId = src || "";

if ( publicId.startsWith('http') ) {
try {
const parts = parseUrl(src);
if ( typeof parts?.publicId === 'string' ) {
publicId = parts?.publicId;
}
} catch(e) {}
}

if ( !publicId ) {
throw new Error('Video Player requires a src, please make sure to configure your src as a public ID or Cloudinary URL.');
}

// Normalize player transformations as an array

const playerTransformations = Array.isArray(transformation) ? transformation : [transformation];

// We want to apply a quality transformation which defaults
// to auto, but we want it to be in the beginning of the
// transformations array, in the event someone
// has already passed some in, giving them the opportunity
// to override if desired

playerTransformations.unshift({
quality
});

// Provide an object configuration option for player logos

let logoOptions: CloudinaryVideoPlayerOptionsLogo = {};

if ( typeof logo === 'boolean' ) {
logoOptions.showLogo = logo;
} else if ( typeof logo === 'object' ) {
logoOptions = {
...logoOptions,
showLogo: true,
logoImageUrl: logo.imageUrl,
logoOnclickUrl: logo.onClickUrl
}
}

// Parse the value passed to 'autoplay';
// if its a boolean or a boolean passed as string ("true") set it directly to browser standard prop autoplay else fallback to default;
// if its a string and not a boolean passed as string ("true") set it to cloudinary video player autoplayMode prop else fallback to undefined;

let autoplayValue: boolean | 'true' | 'false' = false;
let autoplayModeValue: string | undefined = undefined;

if (typeof autoplay === 'boolean' || autoplay === 'true' || autoplay === 'false') {
autoplayValue = autoplay;
}

if (typeof autoplay === 'string' && autoplay !== 'true' && autoplay !== 'false') {
autoplayModeValue = autoplay;
}

// Finally construct the Player Options object

let playerOptions: CloudinaryVideoPlayerOptions = {
cloud_name: cloudName,
privateCdn,
secureDistribution,

autoplayMode: autoplayModeValue,
autoplay: autoplayValue,
controls,
language,
languages,
loop,
muted,
publicId,
width,
height,
aspectRatio: `${width}:${height}`,
transformation: playerTransformations,
...logoOptions,
...otherCldVidPlayerOptions,
};

if ( typeof poster === 'string' ) {
// If poster is a string, assume it's either a public ID
// or a remote URL, in either case pass to `publicId`
playerOptions.posterOptions = {
publicId: poster
};
} else if ( typeof poster === 'object' ) {
// If poster is an object, we can either customize the
// automatically generated image from the video or generate
// a completely new image from a separate public ID, so look
// to see if the src is explicitly set to determine whether
// or not to use the video's ID or just pass things along

if ( typeof poster.src !== 'string' ) {
playerOptions.posterOptions = {
publicId: constructCloudinaryUrl({
options: {
...poster,
src: publicId,
assetType: 'video',
format: 'auto:image',
},
config,
})
};
} else {
playerOptions.posterOptions = {
publicId: constructCloudinaryUrl({
options: poster,
config,
})
};
}
}

return playerOptions;
}
2 changes: 1 addition & 1 deletion packages/url-loader/src/types/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from 'zod';
import ICloudinaryConfigurations from '@cloudinary/url-gen/config/interfaces/Config/ICloudinaryConfigurations';
import ICloudinaryConfigurations from '@cloudinary/url-gen/config/interfaces/Config/ICloudinaryAssetConfigurations';

export interface CloudinaryConfigurationOptions extends ICloudinaryConfigurations {}

Expand Down
Loading