Comparing version 2.0.0 to 2.0.2
import domains from "../data/domains.js"; | ||
import subdomains from "../data/subdomains.js"; | ||
import paths from "../data/paths.js"; | ||
const cdnDomains = new Map(Object.entries(domains)); | ||
const cdnSubdomains = Object.entries(subdomains); | ||
export function getImageCdnForUrl(url) { | ||
const { hostname } = new URL(url); | ||
const { hostname, pathname } = new URL(url); | ||
if (cdnDomains.has(hostname)) { | ||
@@ -15,3 +16,8 @@ return cdnDomains.get(hostname); | ||
} | ||
for (const [prefix, cdn] of Object.entries(paths)) { | ||
if (pathname.startsWith(prefix)) { | ||
return cdn; | ||
} | ||
} | ||
return false; | ||
} |
@@ -7,2 +7,3 @@ import { getImageCdnForUrl } from "./detect.js"; | ||
import { parse as cloudinary } from "./transformers/cloudinary.js"; | ||
import { parse as cloudflare } from "./transformers/cloudflare.js"; | ||
import { parse as bunny } from "./transformers/bunny.js"; | ||
@@ -16,2 +17,3 @@ import { parse as storyblok } from "./transformers/storyblok.js"; | ||
cloudinary, | ||
cloudflare, | ||
bunny, | ||
@@ -18,0 +20,0 @@ storyblok, |
@@ -7,2 +7,3 @@ import { getImageCdnForUrl } from "./detect.js"; | ||
import { transform as cloudinary } from "./transformers/cloudinary.js"; | ||
import { transform as cloudflare } from "./transformers/cloudflare.js"; | ||
import { transform as bunny } from "./transformers/bunny.js"; | ||
@@ -18,2 +19,3 @@ import { transform as storyblok } from "./transformers/storyblok.js"; | ||
storyblok, | ||
cloudflare, | ||
}; | ||
@@ -20,0 +22,0 @@ export const cdnIsSupportedForTransform = (cdn) => cdn && cdn in transformers; |
@@ -21,5 +21,5 @@ import { getNumericParam, setParamIfDefined } from "../utils.js"; | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "width", width, true); | ||
setParamIfDefined(url, "height", height, true); | ||
setParamIfDefined(url, "width", width, true, true); | ||
setParamIfDefined(url, "height", height, true, true); | ||
return url; | ||
}; |
@@ -0,4 +1,9 @@ | ||
import { roundIfNumeric } from "../utils.js"; | ||
// Thanks Colby! | ||
const cloudinaryRegex = /https?:\/\/(?<host>[^\/]+)\/(?<cloudName>[^\/]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?<version>v\d+|\w{1,2}\/)?(?<id>[^\.^\s]+)\.?(?<format>[a-zA-Z]+$)?$/g; | ||
const parseTransforms = (transformations) => Object.fromEntries(transformations.split(",").map((t) => t.split("_"))); | ||
const cloudinaryRegex = /https?:\/\/(?<host>[^\/]+)\/(?<cloudName>[^\/]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?:(?<version>v\d+)\/)?(?<id>[^\.^\s]+)\.?(?<format>[a-zA-Z]+$)?$/g; | ||
const parseTransforms = (transformations) => { | ||
return transformations | ||
? Object.fromEntries(transformations.split(",").map((t) => t.split("_"))) | ||
: {}; | ||
}; | ||
const formatUrl = ({ host, cloudName, assetType, deliveryType, signature, transformations = {}, version, id, format, }) => { | ||
@@ -50,6 +55,6 @@ if (format) { | ||
if (width) { | ||
props.transformations.w = width?.toString(); | ||
props.transformations.w = roundIfNumeric(width).toString(); | ||
} | ||
if (height) { | ||
props.transformations.h = height?.toString(); | ||
props.transformations.h = roundIfNumeric(height).toString(); | ||
} | ||
@@ -56,0 +61,0 @@ return new URL(formatUrl(props)); |
@@ -21,4 +21,4 @@ import { getNumericParam, setParamIfDefined, setParamIfUndefined, } from "../utils.js"; | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "w", width, true); | ||
setParamIfDefined(url, "h", height, true); | ||
setParamIfDefined(url, "w", width, true, true); | ||
setParamIfDefined(url, "h", height, true, true); | ||
setParamIfDefined(url, "fm", format); | ||
@@ -25,0 +25,0 @@ setParamIfUndefined(url, "fit", "fill"); |
@@ -25,4 +25,4 @@ import { setParamIfDefined, setParamIfUndefined } from "../utils.js"; | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "w", width, true); | ||
setParamIfDefined(url, "h", height, true); | ||
setParamIfDefined(url, "w", width, true, true); | ||
setParamIfDefined(url, "h", height, true, true); | ||
setParamIfUndefined(url, "fit", "min"); | ||
@@ -29,0 +29,0 @@ if (format) { |
@@ -26,4 +26,4 @@ import { setParamIfDefined } from "../utils.js"; | ||
const url = new URL(base); | ||
setParamIfDefined(url, "width", width, true); | ||
setParamIfDefined(url, "height", height, true); | ||
setParamIfDefined(url, "width", width, true, true); | ||
setParamIfDefined(url, "height", height, true, true); | ||
setParamIfDefined(url, "crop", params?.crop); | ||
@@ -30,0 +30,0 @@ setParamIfDefined(url, "format", format); |
import { getNumericParam, setParamIfDefined, setParamIfUndefined, } from "../utils.js"; | ||
export const transform = ({ url: originalUrl, width, height }) => { | ||
const url = new URL(originalUrl); | ||
setParamIfDefined(url, "w", width, true); | ||
setParamIfDefined(url, "h", height, true); | ||
setParamIfDefined(url, "w", width, true, true); | ||
setParamIfDefined(url, "h", height, true, true); | ||
setParamIfUndefined(url, "crop", "1"); | ||
@@ -7,0 +7,0 @@ return url; |
@@ -1,3 +0,13 @@ | ||
export const setParamIfDefined = (url, key, value, deleteExisting) => { | ||
export const roundIfNumeric = (value) => { | ||
if (!value) { | ||
return value; | ||
} | ||
const num = Number(value); | ||
return isNaN(num) ? value : Math.round(num); | ||
}; | ||
export const setParamIfDefined = (url, key, value, deleteExisting, roundValue) => { | ||
if (value) { | ||
if (roundValue) { | ||
value = roundIfNumeric(value); | ||
} | ||
url.searchParams.set(key, value.toString()); | ||
@@ -4,0 +14,0 @@ } |
@@ -6,3 +6,3 @@ { | ||
"name": "unpic", | ||
"version": "2.0.0", | ||
"version": "2.0.2", | ||
"description": "Universal image CDN translator", | ||
@@ -9,0 +9,0 @@ "license": "MIT", |
@@ -10,2 +10,6 @@ # 🖼 Unpic | ||
If you'd like to use this on the web, you might want to try | ||
[Unpic img](https://github.com/ascorbic/unpic-img), a multi-framework image | ||
component, powered by Unpic. | ||
It designed to work with image URLs from sources such as CMSs and other | ||
@@ -104,2 +108,3 @@ user-generated content, where the source image may or may not be from an image | ||
- Storyblok | ||
- Cloudflare | ||
@@ -162,4 +167,6 @@ ## FAQs | ||
API functions. | ||
- at least one entry in `domains.json` or `subdomains.json` to detect the CDN | ||
- at least one entry in `domains.json`, `subdomains.json` or `paths.json` to | ||
detect the CDN | ||
- add the new CDN to the types in `src/types.ts`, and import the new source file | ||
in `src/transform.ts` | ||
- add a sample image to `examples.json` in the demo site |
@@ -9,6 +9,7 @@ "use strict"; | ||
const subdomains_js_1 = __importDefault(require("../data/subdomains.js")); | ||
const paths_js_1 = __importDefault(require("../data/paths.js")); | ||
const cdnDomains = new Map(Object.entries(domains_js_1.default)); | ||
const cdnSubdomains = Object.entries(subdomains_js_1.default); | ||
function getImageCdnForUrl(url) { | ||
const { hostname } = new URL(url); | ||
const { hostname, pathname } = new URL(url); | ||
if (cdnDomains.has(hostname)) { | ||
@@ -22,4 +23,9 @@ return cdnDomains.get(hostname); | ||
} | ||
for (const [prefix, cdn] of Object.entries(paths_js_1.default)) { | ||
if (pathname.startsWith(prefix)) { | ||
return cdn; | ||
} | ||
} | ||
return false; | ||
} | ||
exports.getImageCdnForUrl = getImageCdnForUrl; |
@@ -10,2 +10,3 @@ "use strict"; | ||
const cloudinary_js_1 = require("./transformers/cloudinary.js"); | ||
const cloudflare_js_1 = require("./transformers/cloudflare.js"); | ||
const bunny_js_1 = require("./transformers/bunny.js"); | ||
@@ -19,2 +20,3 @@ const storyblok_js_1 = require("./transformers/storyblok.js"); | ||
cloudinary: cloudinary_js_1.parse, | ||
cloudflare: cloudflare_js_1.parse, | ||
bunny: bunny_js_1.parse, | ||
@@ -21,0 +23,0 @@ storyblok: storyblok_js_1.parse, |
@@ -10,2 +10,3 @@ "use strict"; | ||
const cloudinary_js_1 = require("./transformers/cloudinary.js"); | ||
const cloudflare_js_1 = require("./transformers/cloudflare.js"); | ||
const bunny_js_1 = require("./transformers/bunny.js"); | ||
@@ -21,2 +22,3 @@ const storyblok_js_1 = require("./transformers/storyblok.js"); | ||
storyblok: storyblok_js_1.transform, | ||
cloudflare: cloudflare_js_1.transform, | ||
}; | ||
@@ -23,0 +25,0 @@ const cdnIsSupportedForTransform = (cdn) => cdn && cdn in exports.transformers; |
@@ -25,6 +25,6 @@ "use strict"; | ||
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, "width", width, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "height", height, true, true); | ||
return url; | ||
}; | ||
exports.transform = transform; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.transform = exports.generate = exports.parse = void 0; | ||
const utils_js_1 = require("../utils.js"); | ||
// Thanks Colby! | ||
const cloudinaryRegex = /https?:\/\/(?<host>[^\/]+)\/(?<cloudName>[^\/]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?<version>v\d+|\w{1,2}\/)?(?<id>[^\.^\s]+)\.?(?<format>[a-zA-Z]+$)?$/g; | ||
const parseTransforms = (transformations) => Object.fromEntries(transformations.split(",").map((t) => t.split("_"))); | ||
const cloudinaryRegex = /https?:\/\/(?<host>[^\/]+)\/(?<cloudName>[^\/]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?:(?<version>v\d+)\/)?(?<id>[^\.^\s]+)\.?(?<format>[a-zA-Z]+$)?$/g; | ||
const parseTransforms = (transformations) => { | ||
return transformations | ||
? Object.fromEntries(transformations.split(",").map((t) => t.split("_"))) | ||
: {}; | ||
}; | ||
const formatUrl = ({ host, cloudName, assetType, deliveryType, signature, transformations = {}, version, id, format, }) => { | ||
@@ -54,6 +59,6 @@ if (format) { | ||
if (width) { | ||
props.transformations.w = width?.toString(); | ||
props.transformations.w = (0, utils_js_1.roundIfNumeric)(width).toString(); | ||
} | ||
if (height) { | ||
props.transformations.h = height?.toString(); | ||
props.transformations.h = (0, utils_js_1.roundIfNumeric)(height).toString(); | ||
} | ||
@@ -60,0 +65,0 @@ return new URL(formatUrl(props)); |
@@ -25,4 +25,4 @@ "use strict"; | ||
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, "w", width, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "h", height, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "fm", format); | ||
@@ -29,0 +29,0 @@ (0, utils_js_1.setParamIfUndefined)(url, "fit", "fill"); |
@@ -29,4 +29,4 @@ "use strict"; | ||
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, "w", width, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "h", height, true, true); | ||
(0, utils_js_1.setParamIfUndefined)(url, "fit", "min"); | ||
@@ -33,0 +33,0 @@ if (format) { |
@@ -30,4 +30,4 @@ "use strict"; | ||
const url = new URL(base); | ||
(0, utils_js_1.setParamIfDefined)(url, "width", width, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "height", height, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "width", width, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "height", height, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "crop", params?.crop); | ||
@@ -34,0 +34,0 @@ (0, utils_js_1.setParamIfDefined)(url, "format", format); |
@@ -7,4 +7,4 @@ "use strict"; | ||
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, "w", width, true, true); | ||
(0, utils_js_1.setParamIfDefined)(url, "h", height, true, true); | ||
(0, utils_js_1.setParamIfUndefined)(url, "crop", "1"); | ||
@@ -11,0 +11,0 @@ return url; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getNumericParam = exports.setParamIfUndefined = exports.setParamIfDefined = void 0; | ||
const setParamIfDefined = (url, key, value, deleteExisting) => { | ||
exports.getNumericParam = exports.setParamIfUndefined = exports.setParamIfDefined = exports.roundIfNumeric = void 0; | ||
const roundIfNumeric = (value) => { | ||
if (!value) { | ||
return value; | ||
} | ||
const num = Number(value); | ||
return isNaN(num) ? value : Math.round(num); | ||
}; | ||
exports.roundIfNumeric = roundIfNumeric; | ||
const setParamIfDefined = (url, key, value, deleteExisting, roundValue) => { | ||
if (value) { | ||
if (roundValue) { | ||
value = (0, exports.roundIfNumeric)(value); | ||
} | ||
url.searchParams.set(key, value.toString()); | ||
@@ -7,0 +18,0 @@ } |
@@ -15,2 +15,3 @@ import { ImageCdn, ParsedUrl, UrlParser } from "./types.js"; | ||
cloudinary: UrlParser<import("./transformers/cloudinary.js").CloudinaryParams>; | ||
cloudflare: UrlParser<import("./transformers/cloudflare.js").CloudflareParams>; | ||
bunny: UrlParser<{ | ||
@@ -17,0 +18,0 @@ fit?: string | undefined; |
@@ -10,2 +10,3 @@ import { ImageCdn, UrlTransformer } from "./types.js"; | ||
storyblok: UrlTransformer; | ||
cloudflare: UrlTransformer; | ||
}; | ||
@@ -12,0 +13,0 @@ export declare const cdnIsSupportedForTransform: (cdn: ImageCdn | false) => cdn is ImageCdn; |
@@ -48,3 +48,3 @@ /** | ||
} | ||
export declare type ImageCdn = "contentful" | "cloudinary" | "imgix" | "shopify" | "wordpress" | "bunny" | "storyblok"; | ||
export declare type ImageCdn = "contentful" | "cloudinary" | "cloudflare" | "imgix" | "shopify" | "wordpress" | "bunny" | "storyblok"; | ||
export declare type SupportedImageCdn = ImageCdn; |
@@ -1,3 +0,4 @@ | ||
export declare const setParamIfDefined: (url: URL, key: string, value?: string | number | undefined, deleteExisting?: boolean | undefined) => void; | ||
export declare const roundIfNumeric: (value: string | number) => string | number; | ||
export declare const setParamIfDefined: (url: URL, key: string, value?: string | number | undefined, deleteExisting?: boolean | undefined, roundValue?: boolean | undefined) => void; | ||
export declare const setParamIfUndefined: (url: URL, key: string, value: string | number) => void; | ||
export declare const getNumericParam: (url: URL, key: string) => number | undefined; |
57320
56
1385
170