@webstudio-is/image 0.56.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/image-loaders.js +3 -1
- package/lib/image-loaders.js +3 -1
- package/lib/types/image-dev.stories.d.ts +2 -2
- package/lib/types/image-loaders.d.ts +2 -1
- package/lib/types/image.d.ts +1 -1
- package/package.json +12 -10
- package/src/image-loaders.ts +9 -5
- package/src/image-optimize.test.ts +17 -7
package/lib/cjs/image-loaders.js
CHANGED
|
@@ -41,8 +41,10 @@ const cloudflareImageLoader = (loaderOptions) => ({ width, src, quality }) => {
|
|
|
41
41
|
"Width must be only from allowed values"
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
|
+
const cdnUrl = loaderOptions?.cdnUrl ?? "/";
|
|
45
|
+
const imageUrl = `${cdnUrl}${src}`;
|
|
44
46
|
const options = `width=${width},quality=${quality},format=auto`;
|
|
45
|
-
const pathname = `/cdn-cgi/image/${options}/${
|
|
47
|
+
const pathname = `/cdn-cgi/image/${options}/${imageUrl}`;
|
|
46
48
|
if (loaderOptions?.resizeOrigin != null) {
|
|
47
49
|
const url = new URL(pathname, loaderOptions.resizeOrigin);
|
|
48
50
|
return url.href;
|
package/lib/image-loaders.js
CHANGED
|
@@ -7,8 +7,10 @@ const cloudflareImageLoader = (loaderOptions) => ({ width, src, quality }) => {
|
|
|
7
7
|
"Width must be only from allowed values"
|
|
8
8
|
);
|
|
9
9
|
}
|
|
10
|
+
const cdnUrl = loaderOptions?.cdnUrl ?? "/";
|
|
11
|
+
const imageUrl = `${cdnUrl}${src}`;
|
|
10
12
|
const options = `width=${width},quality=${quality},format=auto`;
|
|
11
|
-
const pathname = `/cdn-cgi/image/${options}/${
|
|
13
|
+
const pathname = `/cdn-cgi/image/${options}/${imageUrl}`;
|
|
12
14
|
if (loaderOptions?.resizeOrigin != null) {
|
|
13
15
|
const url = new URL(pathname, loaderOptions.resizeOrigin);
|
|
14
16
|
return url.href;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type * as React from "react";
|
|
2
2
|
import type { ComponentMeta, ComponentStory } from "@storybook/react";
|
|
3
|
-
declare const _default: ComponentMeta<React.ForwardRefExoticComponent<
|
|
3
|
+
declare const _default: ComponentMeta<React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLImageElement> & React.ImgHTMLAttributes<HTMLImageElement> & {
|
|
4
4
|
quality?: number | undefined;
|
|
5
5
|
optimize?: boolean | undefined;
|
|
6
6
|
loader: import("./image-optimize").ImageLoader;
|
|
7
|
-
}, "
|
|
7
|
+
}, "ref"> & React.RefAttributes<HTMLImageElement>>>;
|
|
8
8
|
export default _default;
|
|
9
9
|
/**
|
|
10
10
|
* Load images depending on image width and device per pixel ratio.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { type ImageLoader } from "./image-optimize";
|
|
2
2
|
export type CloudflareImageLoaderOptions = {
|
|
3
3
|
resizeOrigin?: string | null;
|
|
4
|
+
cdnUrl?: string;
|
|
4
5
|
};
|
|
5
6
|
/**
|
|
6
7
|
* Default image loader in case of no loader provided
|
|
7
8
|
* https://developers.cloudflare.com/images/image-resizing/url-format/
|
|
8
9
|
**/
|
|
9
|
-
export declare const cloudflareImageLoader: (
|
|
10
|
+
export declare const cloudflareImageLoader: (loaderOptions: CloudflareImageLoaderOptions | null) => ImageLoader;
|
|
10
11
|
type LocalImageLoaderOptions = {
|
|
11
12
|
publicPath?: string;
|
|
12
13
|
};
|
package/lib/types/image.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ type ImageProps = ComponentProps<typeof defaultTag> & {
|
|
|
6
6
|
optimize?: boolean;
|
|
7
7
|
loader: ImageLoader;
|
|
8
8
|
};
|
|
9
|
-
export declare const Image: import("react").ForwardRefExoticComponent<
|
|
9
|
+
export declare const Image: import("react").ForwardRefExoticComponent<Omit<ImageProps, "ref"> & import("react").RefAttributes<HTMLImageElement>>;
|
|
10
10
|
export {};
|
package/package.json
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/image",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Image optimization",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"react": "^
|
|
9
|
+
"react": "^18.2.0",
|
|
10
10
|
"warn-once": "^0.1.1",
|
|
11
|
-
"@webstudio-is/generate-arg-types": "^0.
|
|
11
|
+
"@webstudio-is/generate-arg-types": "^0.58.0"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@jest/globals": "^29.3.1",
|
|
15
15
|
"@storybook/react": "^6.5.16",
|
|
16
|
-
"@types/react": "^
|
|
16
|
+
"@types/react": "^18.0.35",
|
|
17
17
|
"jest": "^29.3.1",
|
|
18
|
+
"react": "^18.2.0",
|
|
19
|
+
"react-dom": "^18.2.0",
|
|
18
20
|
"typescript": "5.0.3",
|
|
19
|
-
"@webstudio-is/jest-config": "^1.0.
|
|
21
|
+
"@webstudio-is/jest-config": "^1.0.5",
|
|
20
22
|
"@webstudio-is/scripts": "^0.0.0",
|
|
21
23
|
"@webstudio-is/storybook-config": "^0.0.0",
|
|
22
|
-
"@webstudio-is/tsconfig": "^1.0.
|
|
24
|
+
"@webstudio-is/tsconfig": "^1.0.5"
|
|
23
25
|
},
|
|
24
26
|
"peerDependencies": {
|
|
25
|
-
"react": "^
|
|
26
|
-
"react-dom": "^
|
|
27
|
+
"react": "^18.2.0",
|
|
28
|
+
"react-dom": "^18.2.0"
|
|
27
29
|
},
|
|
28
30
|
"module": "./lib/index.js",
|
|
29
31
|
"exports": {
|
|
@@ -41,13 +43,13 @@
|
|
|
41
43
|
"private": false,
|
|
42
44
|
"sideEffects": false,
|
|
43
45
|
"scripts": {
|
|
44
|
-
"typecheck": "tsc --noEmit",
|
|
46
|
+
"typecheck": "tsc --noEmit --emitDeclarationOnly false",
|
|
45
47
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
46
48
|
"checks": "pnpm typecheck && pnpm lint && pnpm test",
|
|
47
49
|
"dev": "build-package --watch",
|
|
48
50
|
"build": "build-package",
|
|
49
51
|
"build:args": "generate-arg-types './src/*.tsx !./src/**/*.stories.tsx !./src/**/*.ws.tsx' && prettier --write \"**/*.props.ts\"",
|
|
50
|
-
"dts": "tsc --
|
|
52
|
+
"dts": "tsc --declarationDir lib/types",
|
|
51
53
|
"lint": "eslint ./src --ext .ts,.tsx --max-warnings 0",
|
|
52
54
|
"storybook:run": "start-storybook -p 6006",
|
|
53
55
|
"storybook:build": "build-storybook",
|
package/src/image-loaders.ts
CHANGED
|
@@ -2,17 +2,18 @@ import warnOnce from "warn-once";
|
|
|
2
2
|
import { allSizes, type ImageLoader } from "./image-optimize";
|
|
3
3
|
|
|
4
4
|
export type CloudflareImageLoaderOptions = {
|
|
5
|
+
// origin of transformation wrapper
|
|
5
6
|
resizeOrigin?: string | null;
|
|
7
|
+
// origin of cdn serving image
|
|
8
|
+
cdnUrl?: string;
|
|
6
9
|
};
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Default image loader in case of no loader provided
|
|
10
13
|
* https://developers.cloudflare.com/images/image-resizing/url-format/
|
|
11
14
|
**/
|
|
12
|
-
export const cloudflareImageLoader
|
|
13
|
-
|
|
14
|
-
) => ImageLoader =
|
|
15
|
-
(loaderOptions) =>
|
|
15
|
+
export const cloudflareImageLoader =
|
|
16
|
+
(loaderOptions: CloudflareImageLoaderOptions | null): ImageLoader =>
|
|
16
17
|
({ width, src, quality }) => {
|
|
17
18
|
if (process.env.NODE_ENV !== "production") {
|
|
18
19
|
warnOnce(
|
|
@@ -21,9 +22,12 @@ export const cloudflareImageLoader: (
|
|
|
21
22
|
);
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
const cdnUrl = loaderOptions?.cdnUrl ?? "/";
|
|
26
|
+
const imageUrl = `${cdnUrl}${src}`;
|
|
27
|
+
|
|
24
28
|
const options = `width=${width},quality=${quality},format=auto`;
|
|
25
29
|
// Cloudflare docs say that we don't need to urlencode the path params
|
|
26
|
-
const pathname = `/cdn-cgi/image/${options}/${
|
|
30
|
+
const pathname = `/cdn-cgi/image/${options}/${imageUrl}`;
|
|
27
31
|
|
|
28
32
|
if (loaderOptions?.resizeOrigin != null) {
|
|
29
33
|
const url = new URL(pathname, loaderOptions.resizeOrigin);
|
|
@@ -7,11 +7,14 @@ describe("Image optimizations applied", () => {
|
|
|
7
7
|
const imgAttr = getImageAttributes({
|
|
8
8
|
optimize: true,
|
|
9
9
|
width: 100,
|
|
10
|
-
src: "
|
|
10
|
+
src: "logo.webp",
|
|
11
11
|
srcSet: undefined,
|
|
12
12
|
sizes: undefined,
|
|
13
13
|
quality: 100,
|
|
14
|
-
loader: cloudflareImageLoader({
|
|
14
|
+
loader: cloudflareImageLoader({
|
|
15
|
+
resizeOrigin: null,
|
|
16
|
+
cdnUrl: "https://webstudio.is/",
|
|
17
|
+
}),
|
|
15
18
|
});
|
|
16
19
|
|
|
17
20
|
expect(imgAttr).toMatchInlineSnapshot(`
|
|
@@ -27,11 +30,14 @@ describe("Image optimizations applied", () => {
|
|
|
27
30
|
const imgAttr = getImageAttributes({
|
|
28
31
|
optimize: true,
|
|
29
32
|
width: undefined,
|
|
30
|
-
src: "
|
|
33
|
+
src: "logo.webp",
|
|
31
34
|
srcSet: undefined,
|
|
32
35
|
sizes: undefined,
|
|
33
36
|
quality: 90,
|
|
34
|
-
loader: cloudflareImageLoader({
|
|
37
|
+
loader: cloudflareImageLoader({
|
|
38
|
+
resizeOrigin: null,
|
|
39
|
+
cdnUrl: "https://webstudio.is/",
|
|
40
|
+
}),
|
|
35
41
|
});
|
|
36
42
|
|
|
37
43
|
expect(imgAttr).toMatchInlineSnapshot(`
|
|
@@ -47,11 +53,14 @@ describe("Image optimizations applied", () => {
|
|
|
47
53
|
const imgAttr = getImageAttributes({
|
|
48
54
|
optimize: true,
|
|
49
55
|
width: undefined,
|
|
50
|
-
src: "
|
|
56
|
+
src: "logo.webp",
|
|
51
57
|
srcSet: undefined,
|
|
52
58
|
sizes: "100vw",
|
|
53
59
|
quality: 70,
|
|
54
|
-
loader: cloudflareImageLoader({
|
|
60
|
+
loader: cloudflareImageLoader({
|
|
61
|
+
resizeOrigin: null,
|
|
62
|
+
cdnUrl: "https://webstudio.is/",
|
|
63
|
+
}),
|
|
55
64
|
});
|
|
56
65
|
|
|
57
66
|
expect(imgAttr).toMatchInlineSnapshot(`
|
|
@@ -67,12 +76,13 @@ describe("Image optimizations applied", () => {
|
|
|
67
76
|
const imgAttr = getImageAttributes({
|
|
68
77
|
optimize: true,
|
|
69
78
|
width: undefined,
|
|
70
|
-
src: "
|
|
79
|
+
src: "logo.webp",
|
|
71
80
|
srcSet: undefined,
|
|
72
81
|
sizes: "100vw",
|
|
73
82
|
quality: 70,
|
|
74
83
|
loader: cloudflareImageLoader({
|
|
75
84
|
resizeOrigin: "https://resize-origin.is",
|
|
85
|
+
cdnUrl: "https://webstudio.is/",
|
|
76
86
|
}),
|
|
77
87
|
});
|
|
78
88
|
|