Comparing version 1.0.1 to 2.0.0
export default JSON.parse(`{ | ||
"imgix.net": "imgix", | ||
"files.wordpress.com": "wordpress", | ||
"b-cdn.net": "bunny" | ||
"b-cdn.net": "bunny", | ||
"storyblok.com": "storyblok" | ||
} | ||
`); |
@@ -8,2 +8,3 @@ import { getImageCdnForUrl } from "./detect.js"; | ||
import { parse as bunny } from "./transformers/bunny.js"; | ||
import { parse as storyblok } from "./transformers/storyblok.js"; | ||
export const parsers = { | ||
@@ -16,2 +17,3 @@ imgix, | ||
bunny, | ||
storyblok, | ||
}; | ||
@@ -18,0 +20,0 @@ export const cdnIsSupportedForParse = (cdn) => cdn && cdn in parsers; |
@@ -8,2 +8,3 @@ import { getImageCdnForUrl } from "./detect.js"; | ||
import { transform as bunny } from "./transformers/bunny.js"; | ||
import { transform as storyblok } from "./transformers/storyblok.js"; | ||
export const transformers = { | ||
@@ -16,2 +17,3 @@ imgix, | ||
bunny, | ||
storyblok, | ||
}; | ||
@@ -18,0 +20,0 @@ export const cdnIsSupportedForTransform = (cdn) => cdn && cdn in transformers; |
import { getNumericParam, setParamIfDefined } from "../utils.js"; | ||
export const parse = (url) => { | ||
const parsedUrl = new URL(url); | ||
const fit = parsedUrl.searchParams.get("fit") || undefined; | ||
const width = getNumericParam(parsedUrl, "width"); | ||
const height = getNumericParam(parsedUrl, "height"); | ||
const quality = getNumericParam(parsedUrl, "quality"); | ||
const params = {}; | ||
@@ -16,14 +14,12 @@ parsedUrl.searchParams.forEach((value, key) => { | ||
height, | ||
quality, | ||
base: parsedUrl.toString(), | ||
params: { fit }, | ||
params, | ||
cdn: "bunny", | ||
}; | ||
}; | ||
export const transform = ({ url: originalUrl, width, height, quality }) => { | ||
export const transform = ({ url: originalUrl, width, height }) => { | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "width", width, true); | ||
setParamIfDefined(url, "height", height, true); | ||
setParamIfDefined(url, "quality", quality); | ||
return url; | ||
}; |
@@ -13,14 +13,12 @@ import { getNumericParam, setParamIfDefined, setParamIfUndefined, } from "../utils.js"; | ||
height, | ||
quality, | ||
format, | ||
base: parsedUrl.toString(), | ||
params: { fit }, | ||
params: { fit, quality }, | ||
cdn: "contentful", | ||
}; | ||
}; | ||
export const transform = ({ url: originalUrl, width, height, quality, format }) => { | ||
export const transform = ({ url: originalUrl, width, height, format }) => { | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "w", width, true); | ||
setParamIfDefined(url, "h", height, true); | ||
setParamIfDefined(url, "q", quality); | ||
setParamIfDefined(url, "fm", format); | ||
@@ -27,0 +25,0 @@ setParamIfUndefined(url, "fit", "fill"); |
@@ -23,7 +23,6 @@ import { setParamIfDefined, setParamIfUndefined } from "../utils.js"; | ||
}; | ||
export const transform = ({ url: originalUrl, width, height, quality, format }) => { | ||
export const transform = ({ url: originalUrl, width, height, format }) => { | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "w", width, true); | ||
setParamIfDefined(url, "h", height, true); | ||
setParamIfDefined(url, "q", quality); | ||
setParamIfUndefined(url, "fit", "min"); | ||
@@ -30,0 +29,0 @@ if (format) { |
@@ -6,3 +6,3 @@ { | ||
"name": "unpic", | ||
"version": "1.0.1", | ||
"version": "2.0.0", | ||
"description": "Universal image CDN translator", | ||
@@ -9,0 +9,0 @@ "license": "MIT", |
@@ -1,3 +0,5 @@ | ||
# Unpic | ||
# 🖼 Unpic | ||
**Universal image CDN URL translator** | ||
There are many image CDNs that provide a URL API for transforming images. There | ||
@@ -19,4 +21,4 @@ is little consistency in these APIs, and it's often unclear what the API is for | ||
This library is available via URL imports for Deno and via npm. To use it in | ||
Deno, import the module from deno.land: | ||
This library is available via URL imports for Deno and via npm for Node. To use | ||
it in Deno, import the module from deno.land: | ||
@@ -101,9 +103,46 @@ ```ts | ||
- Bunny.net | ||
- Storyblok | ||
## FAQs | ||
- **Can you add support for CDN X?** Yes, please open an issue or PR. | ||
- **What is an image CDN?** An image CDN is a service that provides a URL API | ||
for transforming images. This is often used to resize images on the fly, but | ||
can also be used to apply other transforms such as cropping, rotation, | ||
compression, etc. This includes dedicated image CDNs such as Imgix and | ||
Cloudinary, CMSs such as Contentful and Sanity, general CDNs such as Bunny.net | ||
that provide an image API, but also other service providers such as Shopify. | ||
The CMSs and other service providers often use a dedicated image CDN to | ||
provide the image API, most commonly Imgix. In most cases they support the | ||
same API, but in others they may proxy the image through their own CDN, or use | ||
a different API. | ||
- **Why would I use this instead of the CDN's own SDK?** If you you know that | ||
your images will all come from one CDN, then you probably should use the CDN's | ||
own SDK. This library is designed to work with images from multiple CDNs, and | ||
to work with images that may or may not be from a CDN. It is particularly | ||
useful for images that may come from an arbitrary source, such as a CMS. It is | ||
also useful for parsing URLs that may already have transforms applied, because | ||
most CDN SDKs will not parse these URLs correctly. | ||
- **Can you add support for CDN X?** If it supports a URL API and has a public | ||
domain by which it can be identified then yes, please open an issue or PR. | ||
- **Can you add my domain to CDN X?** If you provide a service where end-users | ||
use your URLs then probably. Examples may be image providers such as Unsplash, | ||
or CMSs. If it is just your own site then probably not. You can manually | ||
specify the CDN in the arguments to `transformUrl` and `parseUrl`. | ||
- **Can you support more params?** We deliberately just support the most common | ||
params that are shared between all CDNs. If you need more params then you can | ||
use the CDN-specific API directly. | ||
- **Why do you set auto format?** If the CDN support is, and no format is | ||
specified in `transformUrl`, the library will remove any format set in the | ||
source image, changing it to auto-format. In most cases, this is what you | ||
want. Almost all browsers now support modern formats such as WebP, and setting | ||
auto-format will allow the CDN to serve the best format for the browser. If | ||
you want to force a specific format, you can set it in `transformUrl`. | ||
- **Do you support SVG, animated GIF etc?** If the CDN supports it, then yes. We | ||
don't attempt to check if a format is valid - we will just pass it through to | ||
the CDN. If the CDN doesn't support it, then it will return an error or a | ||
default. | ||
- **Do you support video, etc** No, this library is only for images. If you pass | ||
a video URL to `transformUrl`, it will return `undefined`, as it will for any | ||
URL that is not recognised as an image CDN URL. It is up to you to handle this | ||
case. | ||
@@ -110,0 +149,0 @@ ## Contributing |
@@ -6,4 +6,5 @@ "use strict"; | ||
"files.wordpress.com": "wordpress", | ||
"b-cdn.net": "bunny" | ||
"b-cdn.net": "bunny", | ||
"storyblok.com": "storyblok" | ||
} | ||
`); |
@@ -11,2 +11,3 @@ "use strict"; | ||
const bunny_js_1 = require("./transformers/bunny.js"); | ||
const storyblok_js_1 = require("./transformers/storyblok.js"); | ||
exports.parsers = { | ||
@@ -19,2 +20,3 @@ imgix: imgix_js_1.parse, | ||
bunny: bunny_js_1.parse, | ||
storyblok: storyblok_js_1.parse, | ||
}; | ||
@@ -21,0 +23,0 @@ const cdnIsSupportedForParse = (cdn) => cdn && cdn in exports.parsers; |
@@ -11,2 +11,3 @@ "use strict"; | ||
const bunny_js_1 = require("./transformers/bunny.js"); | ||
const storyblok_js_1 = require("./transformers/storyblok.js"); | ||
exports.transformers = { | ||
@@ -19,2 +20,3 @@ imgix: imgix_js_1.transform, | ||
bunny: bunny_js_1.transform, | ||
storyblok: storyblok_js_1.transform, | ||
}; | ||
@@ -21,0 +23,0 @@ const cdnIsSupportedForTransform = (cdn) => cdn && cdn in exports.transformers; |
@@ -7,6 +7,4 @@ "use strict"; | ||
const parsedUrl = new URL(url); | ||
const fit = parsedUrl.searchParams.get("fit") || undefined; | ||
const width = (0, utils_js_1.getNumericParam)(parsedUrl, "width"); | ||
const height = (0, utils_js_1.getNumericParam)(parsedUrl, "height"); | ||
const quality = (0, utils_js_1.getNumericParam)(parsedUrl, "quality"); | ||
const params = {}; | ||
@@ -20,5 +18,4 @@ parsedUrl.searchParams.forEach((value, key) => { | ||
height, | ||
quality, | ||
base: parsedUrl.toString(), | ||
params: { fit }, | ||
params, | ||
cdn: "bunny", | ||
@@ -28,9 +25,8 @@ }; | ||
exports.parse = parse; | ||
const transform = ({ url: originalUrl, width, height, quality }) => { | ||
const transform = ({ url: originalUrl, width, height }) => { | ||
const url = new URL(originalUrl); | ||
(0, utils_js_1.setParamIfDefined)(url, "width", width, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "height", height, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "quality", quality); | ||
return url; | ||
}; | ||
exports.transform = transform; |
@@ -16,6 +16,5 @@ "use strict"; | ||
height, | ||
quality, | ||
format, | ||
base: parsedUrl.toString(), | ||
params: { fit }, | ||
params: { fit, quality }, | ||
cdn: "contentful", | ||
@@ -25,7 +24,6 @@ }; | ||
exports.parse = parse; | ||
const transform = ({ url: originalUrl, width, height, quality, format }) => { | ||
const transform = ({ url: originalUrl, width, height, format }) => { | ||
const url = new URL(originalUrl); | ||
(0, utils_js_1.setParamIfDefined)(url, "w", width, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "h", height, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "q", quality); | ||
(0, utils_js_1.setParamIfDefined)(url, "fm", format); | ||
@@ -32,0 +30,0 @@ (0, utils_js_1.setParamIfUndefined)(url, "fit", "fill"); |
@@ -27,7 +27,6 @@ "use strict"; | ||
exports.parse = parse; | ||
const transform = ({ url: originalUrl, width, height, quality, format }) => { | ||
const transform = ({ url: originalUrl, width, height, format }) => { | ||
const url = new URL(originalUrl); | ||
(0, utils_js_1.setParamIfDefined)(url, "w", width, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "h", height, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "q", quality); | ||
(0, utils_js_1.setParamIfUndefined)(url, "fit", "min"); | ||
@@ -34,0 +33,0 @@ if (format) { |
@@ -1,2 +0,2 @@ | ||
import { ImageCdn, UrlString } from "./types.js"; | ||
export declare function getImageCdnForUrl(url: UrlString | URL): ImageCdn | false; | ||
import { ImageCdn } from "./types.js"; | ||
export declare function getImageCdnForUrl(url: string | URL): ImageCdn | false; |
@@ -1,2 +0,2 @@ | ||
import { ImageCdn, ParsedUrl, UrlParser, UrlString } from "./types.js"; | ||
import { ImageCdn, ParsedUrl, UrlParser } from "./types.js"; | ||
export declare const parsers: { | ||
@@ -18,2 +18,3 @@ imgix: UrlParser<Record<string, unknown>>; | ||
}>; | ||
storyblok: UrlParser<import("./transformers/storyblok.js").StoryblokParams>; | ||
}; | ||
@@ -25,3 +26,3 @@ export declare const cdnIsSupportedForParse: (cdn: ImageCdn | false) => cdn is ImageCdn; | ||
*/ | ||
export declare const getParserForUrl: <TParams extends Record<string, unknown>>(url: UrlString | URL) => UrlParser<TParams> | undefined; | ||
export declare const getParserForUrl: <TParams extends Record<string, unknown>>(url: string | URL) => UrlParser<TParams> | undefined; | ||
export declare const getParserForCdn: <TParams extends Record<string, unknown>>(cdn: ImageCdn | false | undefined) => UrlParser<TParams> | undefined; | ||
@@ -33,2 +34,2 @@ /** | ||
*/ | ||
export declare const parseUrl: <TParams = Record<string, unknown>>(url: UrlString | URL, cdn?: ImageCdn | undefined) => ParsedUrl<TParams> | undefined; | ||
export declare const parseUrl: <TParams = Record<string, unknown>>(url: string | URL, cdn?: ImageCdn | undefined) => ParsedUrl<TParams> | undefined; |
@@ -1,2 +0,2 @@ | ||
import { ImageCdn, UrlString, UrlTransformer } from "./types.js"; | ||
import { ImageCdn, UrlTransformer } from "./types.js"; | ||
export declare const transformers: { | ||
@@ -9,2 +9,3 @@ imgix: UrlTransformer; | ||
bunny: UrlTransformer; | ||
storyblok: UrlTransformer; | ||
}; | ||
@@ -15,3 +16,3 @@ export declare const cdnIsSupportedForTransform: (cdn: ImageCdn | false) => cdn is ImageCdn; | ||
*/ | ||
export declare const getTransformerForUrl: (url: UrlString | URL) => UrlTransformer | undefined; | ||
export declare const getTransformerForUrl: (url: string | URL) => UrlTransformer | undefined; | ||
/** | ||
@@ -18,0 +19,0 @@ * Returns a transformer function if the given CDN is supported |
@@ -6,3 +6,3 @@ /** | ||
/** The original URL of the image */ | ||
url: UrlString | URL; | ||
url: string | URL; | ||
/** The desired width of the image */ | ||
@@ -12,5 +12,3 @@ width?: number; | ||
height?: number; | ||
/** The desired quality of the image */ | ||
quality?: number; | ||
/** The desired format of the image */ | ||
/** The desired format of the image. Default is auto-detect */ | ||
format?: string; | ||
@@ -20,8 +18,6 @@ /** Specify a CDN rather than auto-detecting */ | ||
} | ||
export declare type UrlString = `http${"s" | ""}://${string}`; | ||
export interface UrlGeneratorOptions<TParams = Record<string, string>> { | ||
base: UrlString | URL; | ||
base: string | URL; | ||
width?: number; | ||
height?: number; | ||
quality?: number; | ||
format?: string; | ||
@@ -35,3 +31,3 @@ params?: TParams; | ||
/** The URL of the image with no transforms */ | ||
base: UrlString; | ||
base: string; | ||
/** The width of the image */ | ||
@@ -54,5 +50,5 @@ width?: number; | ||
export interface UrlParser<TParams = Record<string, unknown>> { | ||
(url: UrlString | URL): ParsedUrl<TParams>; | ||
(url: string | URL): ParsedUrl<TParams>; | ||
} | ||
export declare type ImageCdn = "contentful" | "cloudinary" | "imgix" | "shopify" | "wordpress" | "bunny"; | ||
export declare type ImageCdn = "contentful" | "cloudinary" | "imgix" | "shopify" | "wordpress" | "bunny" | "storyblok"; | ||
export declare type SupportedImageCdn = ImageCdn; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
49931
50
1178
163
0