astro 2.0.18 → 2.1.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/README.md +3 -3
- package/client-base.d.ts +27 -0
- package/client-image.d.ts +48 -0
- package/components/Image.astro +28 -0
- package/dist/@types/astro.d.ts +101 -1
- package/dist/assets/consts.d.ts +4 -0
- package/dist/assets/consts.js +20 -0
- package/dist/assets/image-endpoint.d.ts +5 -0
- package/dist/assets/image-endpoint.js +50 -0
- package/dist/assets/index.d.ts +4 -0
- package/dist/assets/index.js +10 -0
- package/dist/assets/internal.d.ts +36 -0
- package/dist/assets/internal.js +70 -0
- package/dist/assets/services/service.d.ts +71 -0
- package/dist/assets/services/service.js +88 -0
- package/dist/assets/services/sharp.d.ts +3 -0
- package/dist/assets/services/sharp.js +57 -0
- package/dist/assets/services/squoosh.d.ts +3 -0
- package/dist/assets/services/squoosh.js +56 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_enc.d.js +11 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.js +1628 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_dec.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.js +1850 -0
- package/dist/assets/services/vendor/squoosh/avif/avif_node_enc.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/codecs.d.ts +158 -0
- package/dist/assets/services/vendor/squoosh/codecs.js +284 -0
- package/dist/assets/services/vendor/squoosh/copy-wasm.d.ts +1 -0
- package/dist/assets/services/vendor/squoosh/copy-wasm.js +24 -0
- package/dist/assets/services/vendor/squoosh/emscripten-types.d.js +0 -0
- package/dist/assets/services/vendor/squoosh/emscripten-utils.d.ts +9 -0
- package/dist/assets/services/vendor/squoosh/emscripten-utils.js +33 -0
- package/dist/assets/services/vendor/squoosh/image-pool.d.ts +4 -0
- package/dist/assets/services/vendor/squoosh/image-pool.js +94 -0
- package/dist/assets/services/vendor/squoosh/image.d.ts +14 -0
- package/dist/assets/services/vendor/squoosh/image.js +27 -0
- package/dist/assets/services/vendor/squoosh/image_data.d.ts +9 -0
- package/dist/assets/services/vendor/squoosh/image_data.js +22 -0
- package/dist/assets/services/vendor/squoosh/impl.d.ts +22 -0
- package/dist/assets/services/vendor/squoosh/impl.js +110 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_enc.d.js +11 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.js +1631 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_dec.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.js +1737 -0
- package/dist/assets/services/vendor/squoosh/mozjpeg/mozjpeg_node_enc.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng.d.ts +10 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng.js +89 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_oxipng_bg.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_png.d.ts +15 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_png.js +138 -0
- package/dist/assets/services/vendor/squoosh/png/squoosh_png_bg.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/resize/squoosh_resize.d.ts +15 -0
- package/dist/assets/services/vendor/squoosh/resize/squoosh_resize.js +95 -0
- package/dist/assets/services/vendor/squoosh/resize/squoosh_resize_bg.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/rotate/rotate.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/utils/execOnce.d.ts +1 -0
- package/dist/assets/services/vendor/squoosh/utils/execOnce.js +14 -0
- package/dist/assets/services/vendor/squoosh/utils/workerPool.d.ts +22 -0
- package/dist/assets/services/vendor/squoosh/utils/workerPool.js +95 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_enc.d.js +4 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.js +1473 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_dec.wasm +0 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.d.ts +2 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.js +1640 -0
- package/dist/assets/services/vendor/squoosh/webp/webp_node_enc.wasm +0 -0
- package/dist/assets/types.d.ts +119 -0
- package/dist/assets/types.js +0 -0
- package/dist/assets/utils/etag.d.ts +12 -0
- package/dist/assets/utils/etag.js +28 -0
- package/dist/assets/utils/metadata.d.ts +6 -0
- package/dist/assets/utils/metadata.js +30 -0
- package/dist/assets/utils/queryParams.d.ts +2 -0
- package/dist/assets/utils/queryParams.js +16 -0
- package/dist/assets/utils/transformToPath.d.ts +2 -0
- package/dist/assets/utils/transformToPath.js +17 -0
- package/dist/assets/vite-plugin-assets.d.ts +5 -0
- package/dist/assets/vite-plugin-assets.js +187 -0
- package/dist/cli/check/index.d.ts +81 -2
- package/dist/cli/check/index.js +190 -44
- package/dist/cli/index.js +39 -16
- package/dist/cli/telemetry.js +1 -1
- package/dist/content/consts.d.ts +0 -1
- package/dist/content/consts.js +1 -3
- package/dist/content/internal.d.ts +7 -0
- package/dist/content/internal.js +27 -5
- package/dist/content/template/virtual-mod.d.mts +1 -0
- package/dist/content/types-generator.js +25 -10
- package/dist/content/utils.d.ts +16 -13
- package/dist/content/utils.js +29 -6
- package/dist/content/vite-plugin-content-assets.d.ts +3 -1
- package/dist/content/vite-plugin-content-assets.js +10 -6
- package/dist/content/vite-plugin-content-imports.js +54 -27
- package/dist/content/vite-plugin-content-virtual-mod.js +7 -4
- package/dist/core/app/index.js +104 -134
- package/dist/core/build/generate.js +30 -5
- package/dist/core/build/index.d.ts +2 -0
- package/dist/core/build/index.js +16 -0
- package/dist/core/build/plugins/plugin-ssr.js +3 -5
- package/dist/core/config/config.js +2 -1
- package/dist/core/config/schema.d.ts +64 -8
- package/dist/core/config/schema.js +17 -3
- package/dist/core/config/settings.js +3 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.js +36 -68
- package/dist/core/create-vite.js +5 -1
- package/dist/core/dev/dev.d.ts +2 -2
- package/dist/core/dev/dev.js +24 -4
- package/dist/core/errors/dev/vite.js +6 -1
- package/dist/core/errors/errors-data.d.ts +17 -1
- package/dist/core/errors/errors-data.js +16 -0
- package/dist/core/messages.js +2 -2
- package/dist/core/path.d.ts +1 -0
- package/dist/core/path.js +4 -0
- package/dist/core/preview/index.d.ts +3 -1
- package/dist/core/preview/index.js +16 -1
- package/dist/core/render/dev/environment.js +1 -5
- package/dist/core/render/environment.js +1 -2
- package/dist/core/render/result.js +13 -35
- package/dist/core/sync/index.d.ts +18 -5
- package/dist/core/sync/index.js +13 -1
- package/dist/integrations/index.js +12 -1
- package/dist/runtime/server/render/component.js +1 -1
- package/dist/runtime/server/response.js +11 -30
- package/dist/vite-plugin-astro-postprocess/index.js +1 -1
- package/dist/vite-plugin-astro-server/plugin.js +1 -1
- package/dist/vite-plugin-env/index.js +4 -4
- package/dist/vite-plugin-inject-env-ts/index.js +17 -2
- package/dist/vite-plugin-markdown/content-entry-type.d.ts +7 -0
- package/dist/vite-plugin-markdown/content-entry-type.js +39 -0
- package/dist/vite-plugin-markdown/index.js +70 -4
- package/dist/vite-plugin-ssr-manifest/index.d.ts +2 -0
- package/dist/vite-plugin-ssr-manifest/index.js +25 -0
- package/package.json +26 -8
- package/src/content/template/types.d.ts +18 -9
- package/src/content/template/virtual-mod.mjs +6 -0
- package/tsconfigs/base.json +6 -1
|
Binary file
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
interface DecodeModule extends EmscriptenWasm.Module {
|
|
3
|
+
decode: (data: Uint8Array) => ImageData;
|
|
4
|
+
}
|
|
5
|
+
export interface ResizeOptions {
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
method: 'triangle' | 'catrom' | 'mitchell' | 'lanczos3';
|
|
9
|
+
premultiply: boolean;
|
|
10
|
+
linearRGB: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RotateOptions {
|
|
13
|
+
numRotations: number;
|
|
14
|
+
}
|
|
15
|
+
import type { MozJPEGModule as MozJPEGEncodeModule } from './mozjpeg/mozjpeg_enc';
|
|
16
|
+
import type { WebPModule as WebPEncodeModule } from './webp/webp_enc';
|
|
17
|
+
import type { AVIFModule as AVIFEncodeModule } from './avif/avif_enc';
|
|
18
|
+
import ImageData from './image_data.js';
|
|
19
|
+
export declare const preprocessors: {
|
|
20
|
+
readonly resize: {
|
|
21
|
+
readonly name: "Resize";
|
|
22
|
+
readonly description: "Resize the image before compressing";
|
|
23
|
+
readonly instantiate: () => Promise<(buffer: Uint8Array, input_width: number, input_height: number, { width, height, method, premultiply, linearRGB }: ResizeOptions) => ImageData>;
|
|
24
|
+
readonly defaultOptions: {
|
|
25
|
+
readonly method: "lanczos3";
|
|
26
|
+
readonly fitMethod: "stretch";
|
|
27
|
+
readonly premultiply: true;
|
|
28
|
+
readonly linearRGB: true;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
readonly rotate: {
|
|
32
|
+
readonly name: "Rotate";
|
|
33
|
+
readonly description: "Rotate image";
|
|
34
|
+
readonly instantiate: () => Promise<(buffer: Uint8Array, width: number, height: number, { numRotations }: RotateOptions) => Promise<ImageData>>;
|
|
35
|
+
readonly defaultOptions: {
|
|
36
|
+
readonly numRotations: 0;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export declare const codecs: {
|
|
41
|
+
readonly mozjpeg: {
|
|
42
|
+
readonly name: "MozJPEG";
|
|
43
|
+
readonly extension: "jpg";
|
|
44
|
+
readonly detectors: readonly [RegExp];
|
|
45
|
+
readonly dec: () => Promise<DecodeModule>;
|
|
46
|
+
readonly enc: () => Promise<MozJPEGEncodeModule>;
|
|
47
|
+
readonly defaultEncoderOptions: {
|
|
48
|
+
readonly quality: 75;
|
|
49
|
+
readonly baseline: false;
|
|
50
|
+
readonly arithmetic: false;
|
|
51
|
+
readonly progressive: true;
|
|
52
|
+
readonly optimize_coding: true;
|
|
53
|
+
readonly smoothing: 0;
|
|
54
|
+
readonly color_space: 3;
|
|
55
|
+
readonly quant_table: 3;
|
|
56
|
+
readonly trellis_multipass: false;
|
|
57
|
+
readonly trellis_opt_zero: false;
|
|
58
|
+
readonly trellis_opt_table: false;
|
|
59
|
+
readonly trellis_loops: 1;
|
|
60
|
+
readonly auto_subsample: true;
|
|
61
|
+
readonly chroma_subsample: 2;
|
|
62
|
+
readonly separate_chroma_quality: false;
|
|
63
|
+
readonly chroma_quality: 75;
|
|
64
|
+
};
|
|
65
|
+
readonly autoOptimize: {
|
|
66
|
+
readonly option: "quality";
|
|
67
|
+
readonly min: 0;
|
|
68
|
+
readonly max: 100;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
readonly webp: {
|
|
72
|
+
readonly name: "WebP";
|
|
73
|
+
readonly extension: "webp";
|
|
74
|
+
readonly detectors: readonly [RegExp];
|
|
75
|
+
readonly dec: () => Promise<DecodeModule>;
|
|
76
|
+
readonly enc: () => Promise<WebPEncodeModule>;
|
|
77
|
+
readonly defaultEncoderOptions: {
|
|
78
|
+
readonly quality: 75;
|
|
79
|
+
readonly target_size: 0;
|
|
80
|
+
readonly target_PSNR: 0;
|
|
81
|
+
readonly method: 4;
|
|
82
|
+
readonly sns_strength: 50;
|
|
83
|
+
readonly filter_strength: 60;
|
|
84
|
+
readonly filter_sharpness: 0;
|
|
85
|
+
readonly filter_type: 1;
|
|
86
|
+
readonly partitions: 0;
|
|
87
|
+
readonly segments: 4;
|
|
88
|
+
readonly pass: 1;
|
|
89
|
+
readonly show_compressed: 0;
|
|
90
|
+
readonly preprocessing: 0;
|
|
91
|
+
readonly autofilter: 0;
|
|
92
|
+
readonly partition_limit: 0;
|
|
93
|
+
readonly alpha_compression: 1;
|
|
94
|
+
readonly alpha_filtering: 1;
|
|
95
|
+
readonly alpha_quality: 100;
|
|
96
|
+
readonly lossless: 0;
|
|
97
|
+
readonly exact: 0;
|
|
98
|
+
readonly image_hint: 0;
|
|
99
|
+
readonly emulate_jpeg_size: 0;
|
|
100
|
+
readonly thread_level: 0;
|
|
101
|
+
readonly low_memory: 0;
|
|
102
|
+
readonly near_lossless: 100;
|
|
103
|
+
readonly use_delta_palette: 0;
|
|
104
|
+
readonly use_sharp_yuv: 0;
|
|
105
|
+
};
|
|
106
|
+
readonly autoOptimize: {
|
|
107
|
+
readonly option: "quality";
|
|
108
|
+
readonly min: 0;
|
|
109
|
+
readonly max: 100;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
readonly avif: {
|
|
113
|
+
readonly name: "AVIF";
|
|
114
|
+
readonly extension: "avif";
|
|
115
|
+
readonly detectors: readonly [RegExp];
|
|
116
|
+
readonly dec: () => Promise<DecodeModule>;
|
|
117
|
+
readonly enc: () => Promise<AVIFEncodeModule>;
|
|
118
|
+
readonly defaultEncoderOptions: {
|
|
119
|
+
readonly cqLevel: 33;
|
|
120
|
+
readonly cqAlphaLevel: -1;
|
|
121
|
+
readonly denoiseLevel: 0;
|
|
122
|
+
readonly tileColsLog2: 0;
|
|
123
|
+
readonly tileRowsLog2: 0;
|
|
124
|
+
readonly speed: 6;
|
|
125
|
+
readonly subsample: 1;
|
|
126
|
+
readonly chromaDeltaQ: false;
|
|
127
|
+
readonly sharpness: 0;
|
|
128
|
+
readonly tune: 0;
|
|
129
|
+
};
|
|
130
|
+
readonly autoOptimize: {
|
|
131
|
+
readonly option: "cqLevel";
|
|
132
|
+
readonly min: 62;
|
|
133
|
+
readonly max: 0;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
readonly oxipng: {
|
|
137
|
+
readonly name: "OxiPNG";
|
|
138
|
+
readonly extension: "png";
|
|
139
|
+
readonly detectors: readonly [RegExp];
|
|
140
|
+
readonly dec: () => Promise<{
|
|
141
|
+
decode: (buffer: Buffer | Uint8Array) => any;
|
|
142
|
+
}>;
|
|
143
|
+
readonly enc: () => Promise<{
|
|
144
|
+
encode: (buffer: Uint8ClampedArray | ArrayBuffer, width: number, height: number, opts: {
|
|
145
|
+
level: number;
|
|
146
|
+
}) => any;
|
|
147
|
+
}>;
|
|
148
|
+
readonly defaultEncoderOptions: {
|
|
149
|
+
readonly level: 2;
|
|
150
|
+
};
|
|
151
|
+
readonly autoOptimize: {
|
|
152
|
+
readonly option: "level";
|
|
153
|
+
readonly min: 6;
|
|
154
|
+
readonly max: 1;
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import { getModuleURL, instantiateEmscriptenWasm, pathify } from "./emscripten-utils.js";
|
|
3
|
+
import mozEnc from "./mozjpeg/mozjpeg_node_enc.js";
|
|
4
|
+
const mozEncWasm = new URL("./mozjpeg/mozjpeg_node_enc.wasm", getModuleURL(import.meta.url));
|
|
5
|
+
import mozDec from "./mozjpeg/mozjpeg_node_dec.js";
|
|
6
|
+
const mozDecWasm = new URL("./mozjpeg/mozjpeg_node_dec.wasm", getModuleURL(import.meta.url));
|
|
7
|
+
import webpEnc from "./webp/webp_node_enc.js";
|
|
8
|
+
const webpEncWasm = new URL("./webp/webp_node_enc.wasm", getModuleURL(import.meta.url));
|
|
9
|
+
import webpDec from "./webp/webp_node_dec.js";
|
|
10
|
+
const webpDecWasm = new URL("./webp/webp_node_dec.wasm", getModuleURL(import.meta.url));
|
|
11
|
+
import avifEnc from "./avif/avif_node_enc.js";
|
|
12
|
+
const avifEncWasm = new URL("./avif/avif_node_enc.wasm", getModuleURL(import.meta.url));
|
|
13
|
+
import avifDec from "./avif/avif_node_dec.js";
|
|
14
|
+
const avifDecWasm = new URL("./avif/avif_node_dec.wasm", getModuleURL(import.meta.url));
|
|
15
|
+
import * as pngEncDec from "./png/squoosh_png.js";
|
|
16
|
+
const pngEncDecWasm = new URL("./png/squoosh_png_bg.wasm", getModuleURL(import.meta.url));
|
|
17
|
+
const pngEncDecInit = () => pngEncDec.default(fsp.readFile(pathify(pngEncDecWasm.toString())));
|
|
18
|
+
import * as oxipng from "./png/squoosh_oxipng.js";
|
|
19
|
+
const oxipngWasm = new URL("./png/squoosh_oxipng_bg.wasm", getModuleURL(import.meta.url));
|
|
20
|
+
const oxipngInit = () => oxipng.default(fsp.readFile(pathify(oxipngWasm.toString())));
|
|
21
|
+
import * as resize from "./resize/squoosh_resize.js";
|
|
22
|
+
const resizeWasm = new URL("./resize/squoosh_resize_bg.wasm", getModuleURL(import.meta.url));
|
|
23
|
+
const resizeInit = () => resize.default(fsp.readFile(pathify(resizeWasm.toString())));
|
|
24
|
+
const rotateWasm = new URL("./rotate/rotate.wasm", getModuleURL(import.meta.url));
|
|
25
|
+
import ImageData from "./image_data.js";
|
|
26
|
+
global.ImageData = ImageData;
|
|
27
|
+
function resizeNameToIndex(name) {
|
|
28
|
+
switch (name) {
|
|
29
|
+
case "triangle":
|
|
30
|
+
return 0;
|
|
31
|
+
case "catrom":
|
|
32
|
+
return 1;
|
|
33
|
+
case "mitchell":
|
|
34
|
+
return 2;
|
|
35
|
+
case "lanczos3":
|
|
36
|
+
return 3;
|
|
37
|
+
default:
|
|
38
|
+
throw Error(`Unknown resize algorithm "${name}"`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function resizeWithAspect({
|
|
42
|
+
input_width,
|
|
43
|
+
input_height,
|
|
44
|
+
target_width,
|
|
45
|
+
target_height
|
|
46
|
+
}) {
|
|
47
|
+
if (!target_width && !target_height) {
|
|
48
|
+
throw Error("Need to specify at least width or height when resizing");
|
|
49
|
+
}
|
|
50
|
+
if (target_width && target_height) {
|
|
51
|
+
return { width: target_width, height: target_height };
|
|
52
|
+
}
|
|
53
|
+
if (!target_width) {
|
|
54
|
+
return {
|
|
55
|
+
width: Math.round(input_width / input_height * target_height),
|
|
56
|
+
height: target_height
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
width: target_width,
|
|
61
|
+
height: Math.round(input_height / input_width * target_width)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const preprocessors = {
|
|
65
|
+
resize: {
|
|
66
|
+
name: "Resize",
|
|
67
|
+
description: "Resize the image before compressing",
|
|
68
|
+
instantiate: async () => {
|
|
69
|
+
await resizeInit();
|
|
70
|
+
return (buffer, input_width, input_height, { width, height, method, premultiply, linearRGB }) => {
|
|
71
|
+
;
|
|
72
|
+
({ width, height } = resizeWithAspect({
|
|
73
|
+
input_width,
|
|
74
|
+
input_height,
|
|
75
|
+
target_width: width,
|
|
76
|
+
target_height: height
|
|
77
|
+
}));
|
|
78
|
+
const imageData = new ImageData(
|
|
79
|
+
resize.resize(
|
|
80
|
+
buffer,
|
|
81
|
+
input_width,
|
|
82
|
+
input_height,
|
|
83
|
+
width,
|
|
84
|
+
height,
|
|
85
|
+
resizeNameToIndex(method),
|
|
86
|
+
premultiply,
|
|
87
|
+
linearRGB
|
|
88
|
+
),
|
|
89
|
+
width,
|
|
90
|
+
height
|
|
91
|
+
);
|
|
92
|
+
resize.cleanup();
|
|
93
|
+
return imageData;
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
defaultOptions: {
|
|
97
|
+
method: "lanczos3",
|
|
98
|
+
fitMethod: "stretch",
|
|
99
|
+
premultiply: true,
|
|
100
|
+
linearRGB: true
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
rotate: {
|
|
104
|
+
name: "Rotate",
|
|
105
|
+
description: "Rotate image",
|
|
106
|
+
instantiate: async () => {
|
|
107
|
+
return async (buffer, width, height, { numRotations }) => {
|
|
108
|
+
const degrees = numRotations * 90 % 360;
|
|
109
|
+
const sameDimensions = degrees === 0 || degrees === 180;
|
|
110
|
+
const size = width * height * 4;
|
|
111
|
+
const instance = (await WebAssembly.instantiate(await fsp.readFile(pathify(rotateWasm.toString())))).instance;
|
|
112
|
+
const { memory } = instance.exports;
|
|
113
|
+
const additionalPagesNeeded = Math.ceil(
|
|
114
|
+
(size * 2 - memory.buffer.byteLength + 8) / (64 * 1024)
|
|
115
|
+
);
|
|
116
|
+
if (additionalPagesNeeded > 0) {
|
|
117
|
+
memory.grow(additionalPagesNeeded);
|
|
118
|
+
}
|
|
119
|
+
const view = new Uint8ClampedArray(memory.buffer);
|
|
120
|
+
view.set(buffer, 8);
|
|
121
|
+
instance.exports.rotate(width, height, degrees);
|
|
122
|
+
return new ImageData(
|
|
123
|
+
view.slice(size + 8, size * 2 + 8),
|
|
124
|
+
sameDimensions ? width : height,
|
|
125
|
+
sameDimensions ? height : width
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
defaultOptions: {
|
|
130
|
+
numRotations: 0
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const codecs = {
|
|
135
|
+
mozjpeg: {
|
|
136
|
+
name: "MozJPEG",
|
|
137
|
+
extension: "jpg",
|
|
138
|
+
detectors: [/^\xFF\xD8\xFF/],
|
|
139
|
+
dec: () => instantiateEmscriptenWasm(mozDec, mozDecWasm.toString()),
|
|
140
|
+
enc: () => instantiateEmscriptenWasm(
|
|
141
|
+
mozEnc,
|
|
142
|
+
mozEncWasm.toString()
|
|
143
|
+
),
|
|
144
|
+
defaultEncoderOptions: {
|
|
145
|
+
quality: 75,
|
|
146
|
+
baseline: false,
|
|
147
|
+
arithmetic: false,
|
|
148
|
+
progressive: true,
|
|
149
|
+
optimize_coding: true,
|
|
150
|
+
smoothing: 0,
|
|
151
|
+
color_space: 3,
|
|
152
|
+
quant_table: 3,
|
|
153
|
+
trellis_multipass: false,
|
|
154
|
+
trellis_opt_zero: false,
|
|
155
|
+
trellis_opt_table: false,
|
|
156
|
+
trellis_loops: 1,
|
|
157
|
+
auto_subsample: true,
|
|
158
|
+
chroma_subsample: 2,
|
|
159
|
+
separate_chroma_quality: false,
|
|
160
|
+
chroma_quality: 75
|
|
161
|
+
},
|
|
162
|
+
autoOptimize: {
|
|
163
|
+
option: "quality",
|
|
164
|
+
min: 0,
|
|
165
|
+
max: 100
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
webp: {
|
|
169
|
+
name: "WebP",
|
|
170
|
+
extension: "webp",
|
|
171
|
+
detectors: [/^RIFF....WEBPVP8[LX ]/s],
|
|
172
|
+
dec: () => instantiateEmscriptenWasm(webpDec, webpDecWasm.toString()),
|
|
173
|
+
enc: () => instantiateEmscriptenWasm(
|
|
174
|
+
webpEnc,
|
|
175
|
+
webpEncWasm.toString()
|
|
176
|
+
),
|
|
177
|
+
defaultEncoderOptions: {
|
|
178
|
+
quality: 75,
|
|
179
|
+
target_size: 0,
|
|
180
|
+
target_PSNR: 0,
|
|
181
|
+
method: 4,
|
|
182
|
+
sns_strength: 50,
|
|
183
|
+
filter_strength: 60,
|
|
184
|
+
filter_sharpness: 0,
|
|
185
|
+
filter_type: 1,
|
|
186
|
+
partitions: 0,
|
|
187
|
+
segments: 4,
|
|
188
|
+
pass: 1,
|
|
189
|
+
show_compressed: 0,
|
|
190
|
+
preprocessing: 0,
|
|
191
|
+
autofilter: 0,
|
|
192
|
+
partition_limit: 0,
|
|
193
|
+
alpha_compression: 1,
|
|
194
|
+
alpha_filtering: 1,
|
|
195
|
+
alpha_quality: 100,
|
|
196
|
+
lossless: 0,
|
|
197
|
+
exact: 0,
|
|
198
|
+
image_hint: 0,
|
|
199
|
+
emulate_jpeg_size: 0,
|
|
200
|
+
thread_level: 0,
|
|
201
|
+
low_memory: 0,
|
|
202
|
+
near_lossless: 100,
|
|
203
|
+
use_delta_palette: 0,
|
|
204
|
+
use_sharp_yuv: 0
|
|
205
|
+
},
|
|
206
|
+
autoOptimize: {
|
|
207
|
+
option: "quality",
|
|
208
|
+
min: 0,
|
|
209
|
+
max: 100
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
avif: {
|
|
213
|
+
name: "AVIF",
|
|
214
|
+
extension: "avif",
|
|
215
|
+
detectors: [/^\x00\x00\x00 ftypavif\x00\x00\x00\x00/],
|
|
216
|
+
dec: () => instantiateEmscriptenWasm(avifDec, avifDecWasm.toString()),
|
|
217
|
+
enc: async () => {
|
|
218
|
+
return instantiateEmscriptenWasm(
|
|
219
|
+
avifEnc,
|
|
220
|
+
avifEncWasm.toString()
|
|
221
|
+
);
|
|
222
|
+
},
|
|
223
|
+
defaultEncoderOptions: {
|
|
224
|
+
cqLevel: 33,
|
|
225
|
+
cqAlphaLevel: -1,
|
|
226
|
+
denoiseLevel: 0,
|
|
227
|
+
tileColsLog2: 0,
|
|
228
|
+
tileRowsLog2: 0,
|
|
229
|
+
speed: 6,
|
|
230
|
+
subsample: 1,
|
|
231
|
+
chromaDeltaQ: false,
|
|
232
|
+
sharpness: 0,
|
|
233
|
+
tune: 0
|
|
234
|
+
},
|
|
235
|
+
autoOptimize: {
|
|
236
|
+
option: "cqLevel",
|
|
237
|
+
min: 62,
|
|
238
|
+
max: 0
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
oxipng: {
|
|
242
|
+
name: "OxiPNG",
|
|
243
|
+
extension: "png",
|
|
244
|
+
detectors: [/^\x89PNG\x0D\x0A\x1A\x0A/],
|
|
245
|
+
dec: async () => {
|
|
246
|
+
await pngEncDecInit();
|
|
247
|
+
return {
|
|
248
|
+
decode: (buffer) => {
|
|
249
|
+
const imageData = pngEncDec.decode(buffer);
|
|
250
|
+
pngEncDec.cleanup();
|
|
251
|
+
return imageData;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
},
|
|
255
|
+
enc: async () => {
|
|
256
|
+
await pngEncDecInit();
|
|
257
|
+
await oxipngInit();
|
|
258
|
+
return {
|
|
259
|
+
encode: (buffer, width, height, opts) => {
|
|
260
|
+
const simplePng = pngEncDec.encode(
|
|
261
|
+
new Uint8Array(buffer),
|
|
262
|
+
width,
|
|
263
|
+
height
|
|
264
|
+
);
|
|
265
|
+
const imageData = oxipng.optimise(simplePng, opts.level, false);
|
|
266
|
+
oxipng.cleanup();
|
|
267
|
+
return imageData;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
defaultEncoderOptions: {
|
|
272
|
+
level: 2
|
|
273
|
+
},
|
|
274
|
+
autoOptimize: {
|
|
275
|
+
option: "level",
|
|
276
|
+
min: 6,
|
|
277
|
+
max: 1
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
export {
|
|
282
|
+
codecs,
|
|
283
|
+
preprocessors
|
|
284
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function copyWasmFiles(dir: URL): Promise<void>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
async function copyWasmFiles(dir) {
|
|
5
|
+
const src = new URL("./", import.meta.url);
|
|
6
|
+
await copyDir(fileURLToPath(src), fileURLToPath(dir));
|
|
7
|
+
}
|
|
8
|
+
async function copyDir(src, dest) {
|
|
9
|
+
const itemNames = await fs.readdir(src);
|
|
10
|
+
await Promise.all(itemNames.map(async (srcName) => {
|
|
11
|
+
const srcPath = path.join(src, srcName);
|
|
12
|
+
const destPath = path.join(dest, srcName);
|
|
13
|
+
const s = await fs.stat(srcPath);
|
|
14
|
+
if (s.isFile() && /.wasm$/.test(srcPath)) {
|
|
15
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
16
|
+
await fs.copyFile(srcPath, destPath);
|
|
17
|
+
} else if (s.isDirectory()) {
|
|
18
|
+
await copyDir(srcPath, destPath);
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
copyWasmFiles
|
|
24
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function pathify(path: string): string;
|
|
2
|
+
export declare function instantiateEmscriptenWasm<T extends EmscriptenWasm.Module>(factory: EmscriptenWasm.ModuleFactory<T>, path: string, workerJS?: string): Promise<T>;
|
|
3
|
+
export declare function dirname(url: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* On certain serverless hosts, our ESM bundle is transpiled to CJS before being run, which means
|
|
6
|
+
* import.meta.url is undefined, so we'll fall back to __dirname in those cases
|
|
7
|
+
* We should be able to remove this once https://github.com/netlify/zip-it-and-ship-it/issues/750 is fixed
|
|
8
|
+
*/
|
|
9
|
+
export declare function getModuleURL(url: string | undefined): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
2
|
+
function pathify(path) {
|
|
3
|
+
if (path.startsWith("file://")) {
|
|
4
|
+
path = fileURLToPath(path);
|
|
5
|
+
}
|
|
6
|
+
return path;
|
|
7
|
+
}
|
|
8
|
+
function instantiateEmscriptenWasm(factory, path, workerJS = "") {
|
|
9
|
+
return factory({
|
|
10
|
+
locateFile(requestPath) {
|
|
11
|
+
if (requestPath.endsWith(".wasm"))
|
|
12
|
+
return pathify(path);
|
|
13
|
+
if (requestPath.endsWith(".worker.js"))
|
|
14
|
+
return pathify(workerJS);
|
|
15
|
+
return requestPath;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function dirname(url) {
|
|
20
|
+
return url.substring(0, url.lastIndexOf("/"));
|
|
21
|
+
}
|
|
22
|
+
function getModuleURL(url) {
|
|
23
|
+
if (!url) {
|
|
24
|
+
return pathToFileURL(__dirname).toString();
|
|
25
|
+
}
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
dirname,
|
|
30
|
+
getModuleURL,
|
|
31
|
+
instantiateEmscriptenWasm,
|
|
32
|
+
pathify
|
|
33
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { OutputFormat } from '../../../types.js';
|
|
3
|
+
import type { Operation } from './image.js';
|
|
4
|
+
export declare function processBuffer(buffer: Buffer, operations: Operation[], encoding: OutputFormat, quality?: number): Promise<Uint8Array>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { isMainThread } from "node:worker_threads";
|
|
2
|
+
import { cpus } from "os";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { getModuleURL } from "./emscripten-utils.js";
|
|
5
|
+
import * as impl from "./impl.js";
|
|
6
|
+
import execOnce from "./utils/execOnce.js";
|
|
7
|
+
import WorkerPool from "./utils/workerPool.js";
|
|
8
|
+
const getWorker = execOnce(() => {
|
|
9
|
+
return new WorkerPool(
|
|
10
|
+
Math.max(1, Math.min(cpus().length - 1, 7)),
|
|
11
|
+
fileURLToPath(getModuleURL(import.meta.url))
|
|
12
|
+
);
|
|
13
|
+
});
|
|
14
|
+
function handleJob(params) {
|
|
15
|
+
switch (params.operation) {
|
|
16
|
+
case "decode":
|
|
17
|
+
return impl.decodeBuffer(params.buffer);
|
|
18
|
+
case "resize":
|
|
19
|
+
return impl.resize({
|
|
20
|
+
image: params.imageData,
|
|
21
|
+
width: params.width,
|
|
22
|
+
height: params.height
|
|
23
|
+
});
|
|
24
|
+
case "rotate":
|
|
25
|
+
return impl.rotate(params.imageData, params.numRotations);
|
|
26
|
+
case "encodeavif":
|
|
27
|
+
return impl.encodeAvif(params.imageData, { quality: params.quality });
|
|
28
|
+
case "encodejpeg":
|
|
29
|
+
return impl.encodeJpeg(params.imageData, { quality: params.quality });
|
|
30
|
+
case "encodepng":
|
|
31
|
+
return impl.encodePng(params.imageData);
|
|
32
|
+
case "encodewebp":
|
|
33
|
+
return impl.encodeWebp(params.imageData, { quality: params.quality });
|
|
34
|
+
default:
|
|
35
|
+
throw Error(`Invalid job "${params.operation}"`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function processBuffer(buffer, operations, encoding, quality) {
|
|
39
|
+
const worker = await getWorker();
|
|
40
|
+
let imageData = await worker.dispatchJob({
|
|
41
|
+
operation: "decode",
|
|
42
|
+
buffer
|
|
43
|
+
});
|
|
44
|
+
for (const operation of operations) {
|
|
45
|
+
if (operation.type === "rotate") {
|
|
46
|
+
imageData = await worker.dispatchJob({
|
|
47
|
+
operation: "rotate",
|
|
48
|
+
imageData,
|
|
49
|
+
numRotations: operation.numRotations
|
|
50
|
+
});
|
|
51
|
+
} else if (operation.type === "resize") {
|
|
52
|
+
imageData = await worker.dispatchJob({
|
|
53
|
+
operation: "resize",
|
|
54
|
+
imageData,
|
|
55
|
+
height: operation.height,
|
|
56
|
+
width: operation.width
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
switch (encoding) {
|
|
61
|
+
case "avif":
|
|
62
|
+
return await worker.dispatchJob({
|
|
63
|
+
operation: "encodeavif",
|
|
64
|
+
imageData,
|
|
65
|
+
quality
|
|
66
|
+
});
|
|
67
|
+
case "jpeg":
|
|
68
|
+
case "jpg":
|
|
69
|
+
return await worker.dispatchJob({
|
|
70
|
+
operation: "encodejpeg",
|
|
71
|
+
imageData,
|
|
72
|
+
quality
|
|
73
|
+
});
|
|
74
|
+
case "png":
|
|
75
|
+
return await worker.dispatchJob({
|
|
76
|
+
operation: "encodepng",
|
|
77
|
+
imageData
|
|
78
|
+
});
|
|
79
|
+
case "webp":
|
|
80
|
+
return await worker.dispatchJob({
|
|
81
|
+
operation: "encodewebp",
|
|
82
|
+
imageData,
|
|
83
|
+
quality
|
|
84
|
+
});
|
|
85
|
+
default:
|
|
86
|
+
throw Error(`Unsupported encoding format`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!isMainThread) {
|
|
90
|
+
WorkerPool.useThisThreadAsWorker(handleJob);
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
processBuffer
|
|
94
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { OutputFormat } from '../../../types.js';
|
|
3
|
+
type RotateOperation = {
|
|
4
|
+
type: 'rotate';
|
|
5
|
+
numRotations: number;
|
|
6
|
+
};
|
|
7
|
+
type ResizeOperation = {
|
|
8
|
+
type: 'resize';
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
};
|
|
12
|
+
export type Operation = RotateOperation | ResizeOperation;
|
|
13
|
+
export declare function processBuffer(buffer: Buffer, operations: Operation[], encoding: OutputFormat, quality?: number): Promise<Uint8Array>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as impl from "./impl.js";
|
|
2
|
+
async function processBuffer(buffer, operations, encoding, quality) {
|
|
3
|
+
let imageData = await impl.decodeBuffer(buffer);
|
|
4
|
+
for (const operation of operations) {
|
|
5
|
+
if (operation.type === "rotate") {
|
|
6
|
+
imageData = await impl.rotate(imageData, operation.numRotations);
|
|
7
|
+
} else if (operation.type === "resize") {
|
|
8
|
+
imageData = await impl.resize({ image: imageData, width: operation.width, height: operation.height });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
switch (encoding) {
|
|
12
|
+
case "avif":
|
|
13
|
+
return await impl.encodeAvif(imageData, { quality });
|
|
14
|
+
case "jpeg":
|
|
15
|
+
case "jpg":
|
|
16
|
+
return await impl.encodeJpeg(imageData, { quality });
|
|
17
|
+
case "png":
|
|
18
|
+
return await impl.encodePng(imageData);
|
|
19
|
+
case "webp":
|
|
20
|
+
return await impl.encodeWebp(imageData, { quality });
|
|
21
|
+
default:
|
|
22
|
+
throw Error(`Unsupported encoding format`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
processBuffer
|
|
27
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export default class ImageData {
|
|
3
|
+
static from(input: ImageData): ImageData;
|
|
4
|
+
private _data;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
get data(): Buffer;
|
|
8
|
+
constructor(data: Buffer | Uint8Array | Uint8ClampedArray, width: number, height: number);
|
|
9
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class ImageData {
|
|
2
|
+
static from(input) {
|
|
3
|
+
return new ImageData(input.data || input._data, input.width, input.height);
|
|
4
|
+
}
|
|
5
|
+
get data() {
|
|
6
|
+
if (Object.prototype.toString.call(this._data) === "[object Object]") {
|
|
7
|
+
return Buffer.from(Object.values(this._data));
|
|
8
|
+
}
|
|
9
|
+
if (this._data instanceof Buffer || this._data instanceof Uint8Array || this._data instanceof Uint8ClampedArray) {
|
|
10
|
+
return Buffer.from(this._data);
|
|
11
|
+
}
|
|
12
|
+
throw new Error("invariant");
|
|
13
|
+
}
|
|
14
|
+
constructor(data, width, height) {
|
|
15
|
+
this._data = data;
|
|
16
|
+
this.width = width;
|
|
17
|
+
this.height = height;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
ImageData as default
|
|
22
|
+
};
|