wasm-image-optimization 1.0.1 → 1.0.3

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/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # wasm-image-optimization
2
2
 
3
+ - The 'avif' version is available here
4
+ https://www.npmjs.com/package/wasm-image-optimization-avif
5
+
3
6
  - Cloudflare workers
4
7
  `import { optimizeImage } from 'wasm-image-optimization';`
5
8
  - Next.js(Webpack)
@@ -29,10 +32,25 @@ optimizeImage({image: ArrayBuffer, width?: number, height?:number,quality?: numb
29
32
 
30
33
  # usage
31
34
 
32
- Next.js image optimization with Cloudflare
35
+ ## Next.js image optimization with Cloudflare
36
+
37
+ ### Parameters
38
+
39
+ | Name | Type | Description |
40
+ | ---- | ------ | -------------------------- |
41
+ | url | string | Image URL |
42
+ | q | number | Quality |
43
+ | w | number | Width |
44
+ | type | string | Output type(webp/png/jpeg) |
45
+
46
+ https://github.com/SoraKumo001/cloudflare-workers-image-optimization
47
+
48
+ https://xxx.yyy.workers.dev/?url=https://xxx.png&q=80&w=200
49
+
50
+ ### Source code
33
51
 
34
52
  ```ts
35
- import { optimizeImage } from 'wasm-image-optimization';
53
+ import { optimizeImage } from "wasm-image-optimization";
36
54
 
37
55
  const isValidUrl = (url: string) => {
38
56
  try {
@@ -48,54 +66,64 @@ const handleRequest = async (
48
66
  _env: {},
49
67
  ctx: ExecutionContext
50
68
  ): Promise<Response> => {
51
- const accept = request.headers.get('accept');
69
+ const url = new URL(request.url);
70
+ const params = url.searchParams;
71
+ const type = ["webp", "png", "jpeg"].find((v) => v === params.get("type")) as
72
+ | "webp"
73
+ | "png"
74
+ | "jpeg"
75
+ | undefined;
76
+ const accept = request.headers.get("accept");
52
77
  const isWebp =
53
78
  accept
54
- ?.split(',')
79
+ ?.split(",")
55
80
  .map((format) => format.trim())
56
- .some((format) => ['image/webp', '*/*', 'image/*'].includes(format)) ?? true;
57
-
58
- const url = new URL(request.url);
81
+ .some((format) => ["image/webp", "*/*", "image/*"].includes(format)) ??
82
+ true;
59
83
 
60
- const params = url.searchParams;
61
- const imageUrl = params.get('url');
84
+ const imageUrl = params.get("url");
62
85
  if (!imageUrl || !isValidUrl(imageUrl)) {
63
- return new Response('url is required', { status: 400 });
86
+ return new Response("url is required", { status: 400 });
64
87
  }
65
88
 
66
89
  const cache = caches.default;
67
- url.searchParams.append('webp', isWebp.toString());
90
+ url.searchParams.append("webp", isWebp.toString());
68
91
  const cacheKey = new Request(url.toString());
69
92
  const cachedResponse = await cache.match(cacheKey);
70
93
  if (cachedResponse) {
71
94
  return cachedResponse;
72
95
  }
73
96
 
74
- const width = params.get('w');
75
- const quality = params.get('q');
97
+ const width = params.get("w");
98
+ const quality = params.get("q");
76
99
 
77
- const [srcImage, contentType] = await fetch(imageUrl, { cf: { cacheKey: imageUrl } })
100
+ const [srcImage, contentType] = await fetch(imageUrl, {
101
+ cf: { cacheKey: imageUrl },
102
+ })
78
103
  .then(async (res) =>
79
- res.ok ? ([await res.arrayBuffer(), res.headers.get('content-type')] as const) : []
104
+ res.ok
105
+ ? ([await res.arrayBuffer(), res.headers.get("content-type")] as const)
106
+ : []
80
107
  )
81
108
  .catch(() => []);
82
109
 
83
110
  if (!srcImage) {
84
- return new Response('image not found', { status: 404 });
111
+ return new Response("image not found", { status: 404 });
85
112
  }
86
113
 
87
- if (contentType && ['image/svg+xml', 'image/gif'].includes(contentType)) {
114
+ if (contentType && ["image/svg+xml", "image/gif"].includes(contentType)) {
88
115
  const response = new Response(srcImage, {
89
116
  headers: {
90
- 'Content-Type': contentType,
91
- 'Cache-Control': 'public, max-age=31536000, immutable',
117
+ "Content-Type": contentType,
118
+ "Cache-Control": "public, max-age=31536000, immutable",
92
119
  },
93
120
  });
94
121
  ctx.waitUntil(cache.put(cacheKey, response.clone()));
95
122
  return response;
96
123
  }
97
124
 
98
- const format = isWebp ? 'webp' : contentType === 'image/jpeg' ? 'jpeg' : 'png';
125
+ const format =
126
+ type ?? (isWebp ? "webp" : contentType === "image/jpeg" ? "jpeg" : "png");
99
127
  const image = await optimizeImage({
100
128
  image: srcImage,
101
129
  width: width ? parseInt(width) : undefined,
@@ -104,8 +132,8 @@ const handleRequest = async (
104
132
  });
105
133
  const response = new Response(image, {
106
134
  headers: {
107
- 'Content-Type': `image/${format}`,
108
- 'Cache-Control': 'public, max-age=31536000, immutable',
135
+ "Content-Type": `image/${format}`,
136
+ "Cache-Control": "public, max-age=31536000, immutable",
109
137
  date: new Date().toUTCString(),
110
138
  },
111
139
  });
@@ -126,8 +154,118 @@ export default {
126
154
  */
127
155
  const config = {
128
156
  images: {
129
- path: 'https://xxx.yyy.workers.dev/',
157
+ path: "https://xxx.yyy.workers.dev/",
130
158
  },
131
159
  };
132
160
  export default config;
133
161
  ```
162
+
163
+ ## Deno Deploy
164
+
165
+ ### Parameters
166
+
167
+ | Name | Type | Description |
168
+ | ---- | ------ | -------------------------- |
169
+ | url | string | Image URL |
170
+ | q | number | Quality |
171
+ | w | number | Width |
172
+ | type | string | Output type(webp/png/jpeg) |
173
+
174
+ https://xxxx.deno.dev/?url=https://xxx.png&q=80&w=200
175
+
176
+ ### Source code
177
+
178
+ https://github.com/SoraKumo001/deno-wasm-image-optimization
179
+
180
+ ```ts
181
+ import { optimizeImage } from "npm:wasm-image-optimization/esm";
182
+
183
+ const isValidUrl = (url: string) => {
184
+ try {
185
+ new URL(url);
186
+ return true;
187
+ } catch (_e) {
188
+ return false;
189
+ }
190
+ };
191
+
192
+ const cache = await caches.open("image-cache");
193
+
194
+ Deno.serve(async (request) => {
195
+ const cached = await cache.match(request);
196
+ if (cached) {
197
+ return cached;
198
+ }
199
+
200
+ const url = new URL(request.url);
201
+ const params = url.searchParams;
202
+ const type = ["webp", "png", "jpeg"].find((v) => v === params.get("type")) as
203
+ | "webp"
204
+ | "png"
205
+ | "jpeg"
206
+ | undefined;
207
+ const accept = request.headers.get("accept");
208
+ const isWebp =
209
+ accept
210
+ ?.split(",")
211
+ .map((format) => format.trim())
212
+ .some((format) => ["image/webp", "*/*", "image/*"].includes(format)) ??
213
+ true;
214
+
215
+ const imageUrl = params.get("url");
216
+ if (!imageUrl || !isValidUrl(imageUrl)) {
217
+ return new Response("url is required", { status: 400 });
218
+ }
219
+
220
+ url.searchParams.append("webp", isWebp.toString());
221
+ const cacheKey = new Request(url.toString());
222
+ const cachedResponse = await cache.match(cacheKey);
223
+ if (cachedResponse) {
224
+ return cachedResponse;
225
+ }
226
+
227
+ const width = params.get("w");
228
+ const quality = params.get("q");
229
+
230
+ const [srcImage, contentType] = await fetch(imageUrl)
231
+ .then(async (res) =>
232
+ res.ok
233
+ ? ([await res.arrayBuffer(), res.headers.get("content-type")] as const)
234
+ : []
235
+ )
236
+ .catch(() => []);
237
+
238
+ if (!srcImage) {
239
+ return new Response("image not found", { status: 404 });
240
+ }
241
+
242
+ if (contentType && ["image/svg+xml", "image/gif"].includes(contentType)) {
243
+ const response = new Response(srcImage, {
244
+ headers: {
245
+ "Content-Type": contentType,
246
+ "Cache-Control": "public, max-age=31536000, immutable",
247
+ },
248
+ });
249
+ cache.put(request, response.clone());
250
+ return response;
251
+ }
252
+
253
+ const format =
254
+ type ?? (isWebp ? "webp" : contentType === "image/jpeg" ? "jpeg" : "png");
255
+ const image = await optimizeImage({
256
+ image: srcImage,
257
+ width: width ? parseInt(width) : undefined,
258
+ quality: quality ? parseInt(quality) : undefined,
259
+ format,
260
+ });
261
+ const response = new Response(image, {
262
+ headers: {
263
+ "Content-Type": `image/${format}`,
264
+ "Cache-Control": "public, max-age=31536000, immutable",
265
+ date: new Date().toUTCString(),
266
+ },
267
+ });
268
+ cache.put(request, response.clone());
269
+ return response;
270
+ });
271
+ ```
@@ -1,7 +1,7 @@
1
1
  export declare const optimizeImage: ({ image, width, height, quality, format, }: {
2
2
  image: BufferSource;
3
- width?: number | undefined;
4
- height?: number | undefined;
5
- quality?: number | undefined;
6
- format?: "jpeg" | "png" | "webp" | undefined;
3
+ width?: number;
4
+ height?: number;
5
+ quality?: number;
6
+ format?: "jpeg" | "png" | "webp" | "avif";
7
7
  }) => Promise<Uint8Array | null>;
package/dist/cjs/index.js CHANGED
@@ -4,12 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.optimizeImage = void 0;
7
- const libImage_1 = __importDefault(require("../workers/libImage"));
8
- const path_1 = __importDefault(require("path"));
9
7
  const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const libImage_1 = __importDefault(require("../workers/libImage"));
10
10
  const libImage = (0, libImage_1.default)({
11
- wasmBinary: fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../esm/libImage.wasm')),
11
+ wasmBinary: fs_1.default.readFileSync(path_1.default.resolve(__dirname, "../esm/libImage.wasm")),
12
12
  });
13
- const optimizeImage = async ({ image, width = 0, height = 0, quality = 100, format = 'webp', }) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));
13
+ const optimizeImage = async ({ image, width = 0, height = 0, quality = 100, format = "webp", }) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));
14
14
  exports.optimizeImage = optimizeImage;
15
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cjs/index.ts"],"names":[],"mappings":";;;;;;AAAA,mEAA2C;AAC3C,gDAAwB;AACxB,4CAAoB;AAEpB,MAAM,QAAQ,GAAG,IAAA,kBAAQ,EAAC;IACxB,UAAU,EAAE,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;CAC7E,CAAC,CAAC;AAEI,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,KAAK,EACL,KAAK,GAAG,CAAC,EACT,MAAM,GAAG,CAAC,EACV,OAAO,GAAG,GAAG,EACb,MAAM,GAAG,MAAM,GAOhB,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAZ1E,QAAA,aAAa,iBAY6D","sourcesContent":["import LibImage from '../workers/libImage';\nimport path from 'path';\nimport fs from 'fs';\n\nconst libImage = LibImage({\n wasmBinary: fs.readFileSync(path.resolve(__dirname, '../esm/libImage.wasm')),\n});\n\nexport const optimizeImage = async ({\n image,\n width = 0,\n height = 0,\n quality = 100,\n format = 'webp',\n}: {\n image: BufferSource;\n width?: number;\n height?: number;\n quality?: number;\n format?: 'jpeg' | 'png' | 'webp';\n}) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cjs/index.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,mEAA2C;AAE3C,MAAM,QAAQ,GAAG,IAAA,kBAAQ,EAAC;IACxB,UAAU,EAAE,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;CAC7E,CAAC,CAAC;AAEI,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,KAAK,EACL,KAAK,GAAG,CAAC,EACT,MAAM,GAAG,CAAC,EACV,OAAO,GAAG,GAAG,EACb,MAAM,GAAG,MAAM,GAOhB,EAAE,EAAE,CACH,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAChD,CAAC;AAfS,QAAA,aAAa,iBAetB","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport LibImage from \"../workers/libImage\";\n\nconst libImage = LibImage({\n wasmBinary: fs.readFileSync(path.resolve(__dirname, \"../esm/libImage.wasm\")),\n});\n\nexport const optimizeImage = async ({\n image,\n width = 0,\n height = 0,\n quality = 100,\n format = \"webp\",\n}: {\n image: BufferSource;\n width?: number;\n height?: number;\n quality?: number;\n format?: \"jpeg\" | \"png\" | \"webp\" | \"avif\";\n}) =>\n libImage.then(({ optimize }) =>\n optimize(image, width, height, quality, format)\n );\n"]}
@@ -1,7 +1,7 @@
1
1
  export declare const optimizeImage: ({ image, width, height, quality, format, }: {
2
2
  image: BufferSource;
3
- width?: number | undefined;
4
- height?: number | undefined;
5
- quality?: number | undefined;
6
- format?: "jpeg" | "png" | "webp" | undefined;
3
+ width?: number;
4
+ height?: number;
5
+ quality?: number;
6
+ format?: "jpeg" | "png" | "webp" | "avif";
7
7
  }) => Promise<Uint8Array | null>;
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import LibImage from './libImage.js';
1
+ import LibImage from "./libImage.js";
2
2
  const libImage = LibImage();
3
- export const optimizeImage = async ({ image, width = 0, height = 0, quality = 100, format = 'webp', }) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));
3
+ export const optimizeImage = async ({ image, width = 0, height = 0, quality = 100, format = "webp", }) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/esm/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC;AAE5B,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,KAAK,EACL,KAAK,GAAG,CAAC,EACT,MAAM,GAAG,CAAC,EACV,OAAO,GAAG,GAAG,EACb,MAAM,GAAG,MAAM,GAOhB,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC","sourcesContent":["import LibImage from './libImage.js';\n\nconst libImage = LibImage();\n\nexport const optimizeImage = async ({\n image,\n width = 0,\n height = 0,\n quality = 100,\n format = 'webp',\n}: {\n image: BufferSource;\n width?: number;\n height?: number;\n quality?: number;\n format?: 'jpeg' | 'png' | 'webp';\n}) => libImage.then(({ optimize }) => optimize(image, width, height, quality, format));\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/esm/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC;AAE5B,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,KAAK,EACL,KAAK,GAAG,CAAC,EACT,MAAM,GAAG,CAAC,EACV,OAAO,GAAG,GAAG,EACb,MAAM,GAAG,MAAM,GAOhB,EAAE,EAAE,CACH,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAChD,CAAC","sourcesContent":["import LibImage from \"./libImage.js\";\n\nconst libImage = LibImage();\n\nexport const optimizeImage = async ({\n image,\n width = 0,\n height = 0,\n quality = 100,\n format = \"webp\",\n}: {\n image: BufferSource;\n width?: number;\n height?: number;\n quality?: number;\n format?: \"jpeg\" | \"png\" | \"webp\" | \"avif\";\n}) =>\n libImage.then(({ optimize }) =>\n optimize(image, width, height, quality, format)\n );\n"]}