Git Product home page Git Product logo

cloudinary / js-url-gen Goto Github PK

View Code? Open in Web Editor NEW
47.0 20.0 9.0 3.79 MB

Cloudinary's base javascript library, including URL generation.

Home Page: https://www.cloudinary.com

License: MIT License

JavaScript 15.21% HTML 56.67% TypeScript 26.82% Shell 0.02% CSS 0.59% Handlebars 0.70%
sdk cloudinary-api cloudinary-sdk image-manipulation video-manipulation javascript-library javascript cloudinary-javascript-library transformations cloudinary-sdks

js-url-gen's Introduction

Cloudinary URL-Gen SDK

Build Status

About

The Cloudinary URL-Gen SDK allows you to quickly and easily integrate your application with Cloudinary. Effortlessly optimize and transform your cloud's assets.

This SDK can also be used with popular frontend frameworks.

Additional documentation

This Readme provides basic installation and usage information. For the complete documentation, see the URL-Gen SDK Guide and the URL-Gen Reference.

NOTE: When using the url-gen library, an additional transformation-builder-sdk library is installed as a dependency. This library handles the transformation generation part of the URL and as such, all transformation actions are imported from this library. Therefore, you can import all transformations either from @cloudinary/url-gen (as demonstrated in the documentation), or directly from the transformation-builder-sdk library, for example:

import {scale} from '@cloudinary/transformation-builder-sdk/actions/resize';

You can find all available transformations in the Transformation Builder reference.

Table of Contents

Key Features

Version Support

Note!

This SDK is cross-platform, but only the Node.js versions are worth mentioning

SDK Version Node.js 14 Node.js 16
1.x V V

Installation

Install using your favorite package manager (yarn, npm)

npm install @cloudinary/url-gen
yarn add @cloudinary/url-gen 

Usage

Setup

// Import the Cloudinary class
import {Cloudinary} from '@cloudinary/url-gen';

// Create your instance
const cld = new Cloudinary({
  cloud: {
    cloudName: 'demo'
  },
  url: {
    secure: true // force https, set to false to force http
  }
});

Transform and Optimize Assets

// Create a new instance if you haven't (see above for the details)
const cld = new Cloudinary({/*...*/})

// Let's create a new image
const myImage = cld.image('sample');

// Import the resize transformation and apply it to myImage
import {Resize} from '@cloudinary/url-gen/actions/resize';

// Resize the image to 100x100
myImage.resize(Resize.scale().width(100).height(100));

// When we're done, we can apply all our changes and create a URL.
const myURL = myImage.toURL();

// https://res.cloudinary.com/demo/image/upload/c_scale,w_100,h_100/sample
console.log(myURL);

Generate Image and Video URLs

The library supports transformations on both images and videos. Please use the appropriate method, as per below:

- Use `cld.image()` to generate image URLs and transformations
- Use `cld.video()` to generate video URLs and transformations

Both the image() and video() methods allow you to use toURL() to generate the final, transformed asset URL.

File upload

This SDK does not provide file upload functionality, however there are several methods of uploading from the client side.

Transpilation

@cloudinary/url-gen is shipped as untranspiled ES6 code. @cloudinary/url-gen is optimized around bundle size, as such we do not transpile our distributed modules, we leave the decision of what browsers to support, and what transpilations to apply, to you, the user.

Testing with Jest

As mentioned above, we're shipping @cloudinary/url-gen with ES6 code, as this provides great tree-shaking potential. it also requires a few adjustments when testing.

In jest.config, you'll need to add these lines to allow babel to transpile our code.

{
  "transform": {
    "node_modules/@cloudinary/url-gen": "babel-jest",
    "node_modules/@cloudinary/transformation-builder-sdk": "babel-jest"
  },
  "transformIgnorePatterns": ["/node_modules/(?!(@cloudinary/url-gen|@cloudinary/transformation-builder-sdk))"]
}

Make sure to install babel-jest: npm install babel-jest

You'll also need to ensure you have a babel.config.js file (and not a .babelrc), and that it's configured properly to transpile code,

As an example:

module.exports = {
  "presets": [
    "@babel/preset-env"
  ]
};

Contributions

  • Clone this repository
  • Create a fork
  • Make your changes
  • Run tests locally npm run test
  • Build project locally npm run build
  • Push your changes
  • Await a review from the maintainers

Get Help

If you run into an issue or have a question, you can either:

Additional resources can be found here:

About Cloudinary

Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive and personalized visual-media experiences—irrespective of the viewing device.

Additional Resources

Licence

Released under the MIT license.

js-url-gen's People

Contributors

asisayag2 avatar atdcloud avatar carlevison avatar lbendavid-cloudinary avatar magdakwiecien avatar mbryla avatar mckomo-cl avatar nirmaoz avatar patrick-tolosa avatar pawelphilipczyk-cloudinary avatar reallybadnews avatar strausr avatar tpiros avatar yoadsn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-url-gen's Issues

Unable to resolve 'lodash/cloneDeep' import

Not sure if this bug is caused by my setup or how module resolution works in node (it seems like this is an unclear area), so apologies if this is a false report.

But when I try to use @cloudinary/base in my Next.js project, I get an error about failing to resolve lodash/cloneDeep, and then indeed I see that various places import it like lodash/cloneDeep: https://github.com/cloudinary/cloudinary-js-base/search?q=lodash%2FcloneDeep

but in the package dependencies, it is written as lodash.cloneDeep. Should this be switched to import cloneDeep from 'lodash.cloneDeep';?

I monkey-patched the files locally and changing the import statements to lodash.cloneDeep fixed the issue. I also was able to get the package working locally by just installing lodash to my whole project.

createCloudinaryURL breaks SSR

Since when using version 1.10.0 we were seeing the following error when trying to use SSR:

JsRuntimeException: ReferenceError: URLSearchParams is not defined
at createCloudinaryURL (server.js:2:339702) -> …URI(i).replace(/\?/g,"%3F").replace(/=/g,"%3D"),n=new URLSearchParams(this.urlConfig.queryParams);!1…
at toURL (server.js:2:341974)
at Ld (server.js:2:349424)
at SplitContent (server.js:2:575857)
at i (server.js:2:28626)
at server.js:2:29644
at t.render (server.js:2:29677)
at t.read (server.js:2:27548)
at t.renderToString (server.js:2:34395)
at Script [4]:1:16

Reverting back to 1.9.2 resolves the issue

[ List image metadata ]

Feature request for Cloudinary JS SDK

Hello! I'm using your SDKs on a react project, and I would need to be able to display the images custom metadata.

Unfortunately, I haven't found any resources about it. Only for nodeJS which isn't what I'm looking for.

Is there any way to access image metadata with CloudinaryJS? Like by doing

cloudinary.url('url/path').metadata // => [{key: value}, {key: value}, ...]

Feature Request: Allow more control over placeholder

Hi, I love this new version of the SDK so far!
But I do which that we would have more contrôl over the image placeholders.

Examples:

  • Control some props for each mode: placeholder('pixelate', [10]), placeholder('blur', [600]), ...
  • Control the transition from placeholder to definitive image: fade, speed, delay, ... (currently the image simply blinks)

Latest build causing pipeline to fail

Hi there,
I just wanted to bring up the fact that the latest Cloudinary build (Launched yesterday) is causing our pipeline build to fail. It was working fine last week, and when we tried to push new changes it failed with these errors:
image
After removing the Cloudinary dependency it works fine.

Please advise.

Thank you

How do you deconstruct a Cloudinary URL?

So, I started a job working with a system that serialized all Cloudinary URLs and stored them in the database. I would like to parse these URLs into the appropriate cloudName & publicId so that I can use the Cloudinary API to retrieve these images at any size / format.

Do you provide a utility or regex to do this?

How to set a format whitelist manually ?

Hi, I have a weird issue where only some of my images with autoFormat() are served as jp2 which just do not display at all in browsers.

To fix this I want to set a format whitelist manually

I've tried:

  • image.delivery(format('avif:webp:png:jpg'))
  • image.delivery(format(['avif', 'webp', 'png', 'jpg']))
  • image.delivery(format([avif(), webp(), png(), jpg()]))

Is there a way to do this?
Else is that a possible feature that could be implemented?

toURL() function encodes already encoded URLs

There's a similar issue in the next-cloudinary repo, here. After running transforms on an image using cloudinary/url-gen, then running toURL() on the result, if the original image URL had encoded characters (like %20 for a space, for example), the toURL() function will double-encode them (writing %2520 in place of &20, "%25" being the character code for a percent sign).

Accessing URL of a raw file

Hi!
Is there a way to get URL of a raw file using public_id, similar to cloudinary.url() in cloudinary-core?

Thanks!
Prabs

`SyntaxError` when used with `jest`

Hi,
I am using @cloudinary/url-gen version 1.8.0 in with TypeScript with jest. I don’t get this error in the application but while running the test I get the following error:



 RUNS  app/ui/universal/header/header.test.tsx // <— This is my application file
Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
 • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 • If you need a custom transformation specify a "transform" option in your config.
 • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html

Details:

/Users/website/node_modules/@cloudinary/url-gen/actions/resize.js:52
import { ResizePadAction } from "./resize/ResizePadAction.js";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at new Script (node:vm:100:7)
    at Runtime.createScriptFromCode (/Users//website/node_modules/jest-runtime/build/index.js:1350:14)
    at Runtime._execModule (/Users/website/node_modules/jest-runtime/build/index.js:1245:25)
    at Runtime._loadModule (/Users/website/node_modules/jest-runtime/build/index.js:898:12)
    at Runtime.requireModule (/Users/website/node_modules/jest-runtime/build/index.js:746:10)
    at Runtime.requireModuleOrMock (/Users/website/node_modules/jest-runtime/build/index.js:919:21)
    at Object.<anonymous> (/Users/website/app/ui/shopping/SinglePageCatalog/ShelfPromotionVideo.tsx:3:1)
    at Runtime._execModule (/Users/website/node_modules/jest-runtime/build/index.js:1299:24)
    at Runtime._loadModule (/Users/website/node_modules/jest-runtime/build/index.js:898:12)
    at Runtime.requireModule (/Users/website/node_modules/jest-runtime/build/index.js:746:10)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I tried making the jest and babel config changes described here - https://github.com/cloudinary/js-url-gen#testing-with-jest 

But then I started getting into more errors after this, now starting from my application code - 



 FAIL  app/selectors/selector.test.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/website/app/test/jest-mock-setup.ts:2
    import "jest-styled-components";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)



I am not sure how to fix this. Do you folks have any clue? 

Here is some more info about the my platform:

"@cloudinary/react": "^1.4.2",
"@cloudinary/url-gen": "^1.8.0",
     "babel-jest": "^26.6.3",
    "jest": "^26.6.3",
"typescript": "~4.5.5",

Thanks,

Text wrapping in text overlay

Hey folks
I am referring to this particular article from the cloudinary blog
I am trying to replicate this functionality in this nextgen SDK. I can do the overlay, but cannot figure out how to make the text lines wrap
Would love some pointers.

Code that I am using
function profilePictureWithText({
  width,
  height,
  textString,
  font = 'poppins',
  fontSize,
}: ProfilePictureWithTextTransformationPropsType): ImageTransformation {
  return (
    new ImageTransformation()
      .resize(
        thumbnail()
          .width(width)
          .height(height)
          .gravity(focusOn(face()))
          .zoom(0.6)
      )
      .backgroundColor(Color.BLACK)
      .effect(gradientFade().verticalStartPoint(-0.5))
      // .overlay(source(text('My Long and aweson Text', 'montserrat_24')))
      .overlay(
        source(
          text(
            textString,
            new TextStyle(font, fontSize).textAlignment('center').lineSpacing(2)
          ).textColor(Color.WHITE)
        ).position(
          new Position()
            .gravity(compass(south()))
            .offsetY(30)
            .allowOverflow(false)
        )
      )
      .delivery(defaultImage('brooke-cagle-LCcFI_26diA-unsplash_a1xohb.jpg'))
      // .delivery(format(autoFormat())) // was not working on responsively app
      .delivery(quality(autoQuality()))
  );
}

Video transformation options as an Object instead of method chain

Hi,
I currently in process of migrating from cloudinary-core to @cloudinary/url-gen, and one of the biggest challenge I am facing is around video transformations.

In my current implementation, I store all the transformations as an array of objects in database and use cloudinary.url method to inject the json for transformation.

const transformation = [
  {
    overlay: { text: "some text", fontSize: 40},
    gravity: "south",
    x: 100,
    y: 600,
    startOffset: "15",
    endOffset: "20",
    color: "#ffffff"
  }
]

const url = cloudinary.url("videoPublicId", {
  resource_type: "video",
  transformation,
  sourceTypes: ["mp4"]
})

Is there a way to do something similar using @cloudinary/url-gen? Or, do I have to resort to the method chain?

Any help is much appreciated!

Thanks!

Prabs

Double encoding of comma in createCloudinaryURL()

In the createCloudinaryURL method, the comma , character in the publicID is being encoded twice.

This results in %2C being transformed into %252C, which causes issues when trying to access images with a comma in their publicID.

This issue is causing 404 errors when trying to access images with a comma in their publicID, as the double-encoded comma does not match the actual publicID of the image.

https://github.com/cloudinary/js-url-gen/blob/master/src/assets/CloudinaryFile.ts

the issue is in these lines of code

const publicID = this.publicID
  .replace(/,/g, '%2C');

const safeURL = encodeURI(url)
  .replace(/\?/g, '%3F')
  .replace(/=/g, '%3D')

A fix could be to replace the double encoded characters so single encoded

const safeURL = encodeURI(url)
  .replace(/\?/g, '%3F')
  .replace(/=/g, '%3D')
  .replace(/%252C/g, '%2C');

I've tested this fix in my application(s) with multiple characters, commas, and slashes, and it seems to work correctly.

How to create an auto upload image url with this?

Hi, I'm looking at how to create this but using this library, instead of hardcoding it like this:

   const cloudinaryUrl = `https://res.cloudinary.com/${cloudName}/image/upload/${mapping}/${publicID}`;

Question / Feature Request

I was wondering if there was a way to show an image preview of my file saved on Cloudinary. It might be made available for specific document types e.g. .pdf, images, .docx, etc. If this doesn't already exist, I hope it can be added to Cloudinary as this would make the package even more awesome.

Output Url Generation approach compared to the V1 pkg

Hi,
Really want this to work so we can have a smaller bundle.

I tried to convert parts of an app to use this SDK and compared the old SDK urls side by side - here are some examples:
(-old, +new)

-https://rs.wescover.com/c_pad,h_250,w_250/v1/wescover-image-store/e3toavbx0drg7xxozw8c.jpg
+https://rs.wescover.com/c_pad,h_250,w_250/f_jpg/v1/wescover-image-store/e3toavbx0drg7xxozw8c

-https://rs.wescover.com/c_limit,f_auto,q_auto,w_500/v1/wescover-image-store/lhxpyb380gvknqrmdxbj
+https://rs.wescover.com/c_limit,w_500/q_auto/f_auto/v1/wescover-image-store/lhxpyb380gvknqrmdxbj

As you can see, the URLs are not exactly compatible - usage of the / approach vs , and appending an extension vs using the f_ modifier - make the old URLs and new not compatible.

I know the output image will be the same! So why is this important?

Some sites (like us) have been using the old URLs for years, with many (many) images already crawled by search engines (like Google) and in use.
Swapping all URLs suddenly, even if the same image is produced would cause a massive re-crawl of all images since the URL means "another image". The result is:

  1. Huge waste of crawl budget
  2. Huge waste of transfer bandwidth from Cloudinary (which costs$$)
  3. Possible transformations if Cloudinary thinks those new URLs need a new transform (even if the output is identical)
  4. Possible, image ranking could be lost since there is no such thing as "image 404" to advertise to google.

This means for us, URL equivalency, given the same transformation needs is extremely important.

WDYT?

`cloudName` required unnecessarily

In

validateAssetForURLCreation(): void {
if (typeof this.cloudName === 'undefined') {
throw 'You must supply a cloudName when initializing the asset';
}
const suffixContainsDot = this.suffix && this.suffix.indexOf('.') >= 0;
const suffixContainsSlash = this.suffix && this.suffix.indexOf('/') >= 0;
if (suffixContainsDot || suffixContainsSlash) {
throw '`suffix`` should not include . or /';
}
}
a cloudName setting is explicitly required. However, in
function getUrlPrefix(cloudName: string, urlConfig: IURLConfig): string {
const secure = urlConfig.secure;
const privateCDN = urlConfig.privateCdn;
const cname = urlConfig.cname;
const secureDistribution = urlConfig.secureDistribution;
if (!secure && !cname) {
return `http://res.cloudinary.com/${cloudName}`;
}
if (secure && !secureDistribution && privateCDN) {
return `https://${cloudName}-res.cloudinary.com`;
}
if (secure && !secureDistribution) {
return `https://res.cloudinary.com/${cloudName}`;
}
if (secure && secureDistribution && privateCDN) {
return `https://${secureDistribution}`;
}
if (secure && secureDistribution) {
return `https://${secureDistribution}/${cloudName}`;
}
if (!secure && cname) {
return `http://${cname}/${cloudName}`;
} else {
return 'ERROR';
}
}
the cloudName isn't actually even utilized if using a secureDistribution and privateCDN.

The check for cloudName should be moved into getUrlPrefix and we should only throw when omitting the cloud name for branches where it's actually utilized.

Best way to prefetch images

Hi, I have a slider component that renders a single image at a time.
This means that each image is fetched as it should be displayed/visible.

I want to prefetch the next 2 images, but I don't know what the best way to approach this is.

I'm using the SDK V2 (with react), along with the responsive(plugin), so I would need to preserve the plugin behavior while prefetching.

Thanks

Replacing images currently stored in cloudinary

Hello. We've been implementing the url-gen package for an app that we're currently developing. I've been using it to grab some images we get from an external server provided to us by our client and transforming them with Cloudinary. However, we've been noticing that when our client updates the images, without changing the image's name, the url-gen package continues to deliver the same image that'd been stored before in our cloudinary account.

Simply put, is there a way to delete or replace an image that has been previously generated with url-gen? Or is it recommended to use another cloudinary package to handle this?

I'll add a sample of how we're using cloudinary below

const cld = new Cloudinary({
  cloud: {
    cloudName: '<our token>',
  },
})

export function resizeCarouselImage(url: string, width: number, height: number, radius: number) {
  const resizedImage = cloudinaryImage(url, width, height)
    .roundCorners(byRadius(radius))
    .toURL()
  return resizedImage
}

function cloudinaryImage(url: string, width: number, height: number) {
  const cldImage = cld.image(url).setDeliveryType('fetch')
  const modifiedImage = cldImage.resize(
    fit()
      .width(width)
      .height(height)
  )
  return modifiedImage
}

Declarative API development

The case for Declerative APIs

The current API of the SDK is imperative.
@yoadsn mentioned in #382 that some users would benefit from a declarative API as well.

Points of interest

  • The API should be consistent across methods (Meaning we can't pick and choose which APIs have a declarative counterpart)
  • The API should avoid using magical strings since we aim to provide the best dev experience even to people with weak IDEs.
  • We might relax the constraint above if we consider the declarative API for more advanced users, but this needs to be explored before deciding.

Trivial example

Imperative

new Image().resize(scale().width(100).height(100)) 

Declerative

new Image().resize(scale({
  width: 100,
  height: 100
}))

Support appending a token to the generated url?

Hi,

We are hoping to use token-based authentication to secure access to image folders to users with access to those folders.

We have implemented token generation in the backend which includes an appropriate acl of folders they should have access to.

The client side (React) gets this token after login and then the plan is to append it to all image delivery urls. Is there a way to do this with current SDK?

I was hoping there might be an option to do something like:

new Cloudinary({
  cloud: {
    cloudName: process.env.REACT_APP_CLOUDINARY_DOMAIN,
  },
  url: {
    privateCdn: true,
    secure: true,
    token: cloudinaryToken,
  },
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.