astro 2.1.3 → 2.1.4
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/dist/@types/typed-emitter.d.ts +1 -2
- package/dist/assets/consts.js +8 -0
- package/dist/assets/image-endpoint.js +1 -1
- package/dist/assets/internal.d.ts +2 -1
- package/dist/assets/internal.js +10 -5
- package/dist/assets/services/service.d.ts +10 -1
- package/dist/assets/services/service.js +35 -29
- package/dist/assets/services/sharp.d.ts +1 -1
- package/dist/assets/services/sharp.js +5 -4
- package/dist/assets/services/squoosh.d.ts +1 -1
- package/dist/assets/services/squoosh.js +7 -4
- package/dist/assets/services/vendor/squoosh/codecs.js +2 -0
- package/dist/assets/services/vendor/squoosh/image-pool.js +2 -0
- package/dist/assets/services/vendor/squoosh/impl.js +2 -0
- package/dist/assets/utils/metadata.js +2 -5
- package/dist/assets/vendor/image-size/detector.d.ts +3 -0
- package/dist/assets/vendor/image-size/detector.js +28 -0
- package/dist/assets/vendor/image-size/index.d.ts +11 -0
- package/dist/assets/vendor/image-size/index.js +93 -0
- package/dist/assets/vendor/image-size/readUInt.d.ts +4 -0
- package/dist/assets/vendor/image-size/readUInt.js +9 -0
- package/dist/assets/vendor/image-size/types/bmp.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/bmp.js +14 -0
- package/dist/assets/vendor/image-size/types/cur.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/cur.js +16 -0
- package/dist/assets/vendor/image-size/types/dds.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/dds.js +14 -0
- package/dist/assets/vendor/image-size/types/gif.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/gif.js +16 -0
- package/dist/assets/vendor/image-size/types/icns.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/icns.js +87 -0
- package/dist/assets/vendor/image-size/types/ico.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/ico.js +42 -0
- package/dist/assets/vendor/image-size/types/interface.d.ts +14 -0
- package/dist/assets/vendor/image-size/types/interface.js +0 -0
- package/dist/assets/vendor/image-size/types/j2c.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/j2c.js +14 -0
- package/dist/assets/vendor/image-size/types/jp2.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/jp2.js +56 -0
- package/dist/assets/vendor/image-size/types/jpg.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/jpg.js +95 -0
- package/dist/assets/vendor/image-size/types/ktx.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/ktx.js +15 -0
- package/dist/assets/vendor/image-size/types/png.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/png.js +33 -0
- package/dist/assets/vendor/image-size/types/pnm.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/pnm.js +72 -0
- package/dist/assets/vendor/image-size/types/psd.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/psd.js +14 -0
- package/dist/assets/vendor/image-size/types/svg.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/svg.js +91 -0
- package/dist/assets/vendor/image-size/types/tiff.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/tiff.js +81 -0
- package/dist/assets/vendor/image-size/types/webp.d.ts +2 -0
- package/dist/assets/vendor/image-size/types/webp.js +51 -0
- package/dist/assets/vendor/image-size/types.d.ts +19 -0
- package/dist/assets/vendor/image-size/types.js +37 -0
- package/dist/assets/vendor/queue/queue.d.ts +39 -0
- package/dist/assets/vendor/queue/queue.js +187 -0
- package/dist/assets/vite-plugin-assets.js +4 -0
- package/dist/cli/check/index.js +43 -2
- package/dist/cli/check/print.d.ts +1 -1
- package/dist/content/error-map.js +4 -1
- package/dist/content/server-listeners.d.ts +1 -1
- package/dist/content/types-generator.d.ts +3 -3
- package/dist/content/types-generator.js +3 -0
- package/dist/content/utils.d.ts +2 -2
- package/dist/content/utils.js +2 -0
- package/dist/content/vite-plugin-content-assets.d.ts +1 -1
- package/dist/content/vite-plugin-content-virtual-mod.js +4 -1
- package/dist/core/add/index.d.ts +1 -1
- package/dist/core/add/index.js +11 -9
- package/dist/core/app/index.js +4 -1
- package/dist/core/app/node.d.ts +1 -1
- package/dist/core/build/generate.d.ts +1 -1
- package/dist/core/build/generate.js +5 -1
- package/dist/core/build/index.js +4 -0
- package/dist/core/build/plugin.js +1 -0
- package/dist/core/build/plugins/plugin-css.d.ts +1 -1
- package/dist/core/build/plugins/plugin-pages.d.ts +1 -1
- package/dist/core/build/static-build.d.ts +1 -1
- package/dist/core/build/static-build.js +4 -1
- package/dist/core/compile/cache.d.ts +1 -1
- package/dist/core/compile/style.d.ts +1 -1
- package/dist/core/config/schema.d.ts +36 -36
- package/dist/core/config/schema.js +9 -1
- package/dist/core/config/timer.js +9 -0
- package/dist/core/config/tsconfig.js +4 -0
- package/dist/core/config/vite-load.js +3 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.js +35 -1
- package/dist/core/create-vite.js +30 -3
- package/dist/core/dev/container.js +1 -0
- package/dist/core/dev/dev.d.ts +1 -1
- package/dist/core/dev/dev.js +2 -1
- package/dist/core/endpoint/index.d.ts +1 -1
- package/dist/core/endpoint/index.js +1 -0
- package/dist/core/errors/dev/utils.d.ts +1 -1
- package/dist/core/errors/dev/utils.js +2 -1
- package/dist/core/errors/dev/vite.d.ts +1 -1
- package/dist/core/errors/dev/vite.js +1 -0
- package/dist/core/errors/errors-data.js +486 -3
- package/dist/core/errors/errors.js +2 -0
- package/dist/core/errors/overlay.js +16 -5
- package/dist/core/errors/utils.d.ts +1 -1
- package/dist/core/logger/console.js +1 -1
- package/dist/core/logger/node.js +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/module-loader/loader.d.ts +3 -3
- package/dist/core/render/dev/css.js +2 -1
- package/dist/core/render/dev/environment.js +1 -0
- package/dist/core/render/dev/index.js +1 -0
- package/dist/core/render/dev/resolve.js +1 -6
- package/dist/core/render/dev/vite.js +13 -1
- package/dist/core/render/index.d.ts +1 -1
- package/dist/core/render/result.d.ts +1 -1
- package/dist/core/render/result.js +4 -0
- package/dist/core/render/route-cache.d.ts +1 -1
- package/dist/core/render/route-cache.js +1 -0
- package/dist/core/routing/manifest/create.js +4 -1
- package/dist/core/sync/index.d.ts +1 -1
- package/dist/core/sync/index.js +1 -1
- package/dist/events/error.d.ts +1 -1
- package/dist/integrations/index.d.ts +1 -1
- package/dist/jsx/renderer.js +1 -0
- package/dist/runtime/client/visible.prebuilt.d.ts +1 -1
- package/dist/runtime/client/visible.prebuilt.js +1 -1
- package/dist/runtime/server/hydration.js +1 -0
- package/dist/runtime/server/render/scope.js +5 -0
- package/dist/runtime/server/scripts.js +2 -2
- package/dist/vite-plugin-astro/compile.d.ts +2 -2
- package/dist/vite-plugin-astro/compile.js +1 -0
- package/dist/vite-plugin-astro/index.js +7 -1
- package/dist/vite-plugin-astro-server/base.d.ts +1 -1
- package/dist/vite-plugin-astro-server/common.d.ts +1 -1
- package/dist/vite-plugin-astro-server/response.js +2 -2
- package/dist/vite-plugin-config-alias/index.d.ts +2 -7
- package/dist/vite-plugin-config-alias/index.js +32 -41
- package/dist/vite-plugin-env/index.js +1 -0
- package/dist/vite-plugin-inject-env-ts/index.d.ts +2 -2
- package/dist/vite-plugin-inject-env-ts/index.js +2 -0
- package/dist/vite-plugin-jsx/index.d.ts +1 -1
- package/dist/vite-plugin-jsx/index.js +7 -1
- package/dist/vite-plugin-jsx/tag.js +7 -0
- package/dist/vite-plugin-markdown/index.js +12 -4
- package/dist/vite-plugin-scanner/index.d.ts +1 -1
- package/dist/vite-plugin-scripts/page-ssr.d.ts +1 -1
- package/package.json +5 -6
- package/src/content/template/types.d.ts +12 -1
- package/tsconfigs/base.json +4 -1
|
@@ -22,7 +22,7 @@ export type EventMap = {
|
|
|
22
22
|
* myEmitter.emit("error", "x") // <- Will catch this type error;
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
|
-
interface TypedEventEmitter<Events extends EventMap> {
|
|
25
|
+
export interface TypedEventEmitter<Events extends EventMap> {
|
|
26
26
|
addListener<E extends keyof Events>(event: E, listener: Events[E]): this;
|
|
27
27
|
on<E extends keyof Events>(event: E, listener: Events[E]): this;
|
|
28
28
|
once<E extends keyof Events>(event: E, listener: Events[E]): this;
|
|
@@ -39,4 +39,3 @@ interface TypedEventEmitter<Events extends EventMap> {
|
|
|
39
39
|
getMaxListeners(): number;
|
|
40
40
|
setMaxListeners(maxListeners: number): this;
|
|
41
41
|
}
|
|
42
|
-
export default TypedEventEmitter;
|
package/dist/assets/consts.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
const VIRTUAL_MODULE_ID = "astro:assets";
|
|
2
2
|
const VIRTUAL_SERVICE_ID = "virtual:image-service";
|
|
3
3
|
const VALID_INPUT_FORMATS = [
|
|
4
|
+
// TODO: `image-size` does not support the following formats, so users can't import them.
|
|
5
|
+
// However, it would be immensely useful to add, for three reasons:
|
|
6
|
+
// - `heic` and `heif` are common formats, especially among Apple users.
|
|
7
|
+
// - AVIF is a common format on the web that's bound to become more and more common.
|
|
8
|
+
// - It's totally reasonable for an user's provided image service to want to support more image types.
|
|
9
|
+
//'heic',
|
|
10
|
+
//'heif',
|
|
11
|
+
//'avif',
|
|
4
12
|
"jpeg",
|
|
5
13
|
"jpg",
|
|
6
14
|
"png",
|
|
@@ -38,7 +38,7 @@ const get = async ({ request }) => {
|
|
|
38
38
|
"Content-Type": mime.getType(format) || "",
|
|
39
39
|
"Cache-Control": "public, max-age=31536000",
|
|
40
40
|
ETag: etag(data.toString()),
|
|
41
|
-
Date: new Date().toUTCString()
|
|
41
|
+
Date: (/* @__PURE__ */ new Date()).toUTCString()
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
} catch (err) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { StaticBuildOptions } from '../core/build/types.js';
|
|
2
|
-
import { ImageService } from './services/service.js';
|
|
2
|
+
import { type ImageService } from './services/service.js';
|
|
3
3
|
import type { ImageMetadata, ImageTransform } from './types.js';
|
|
4
4
|
export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
|
|
5
5
|
export declare function getConfiguredImageService(): Promise<ImageService>;
|
|
6
6
|
interface GetImageResult {
|
|
7
|
+
rawOptions: ImageTransform;
|
|
7
8
|
options: ImageTransform;
|
|
8
9
|
src: string;
|
|
9
10
|
attributes: Record<string, any>;
|
package/dist/assets/internal.js
CHANGED
|
@@ -6,7 +6,10 @@ function isESMImportedImage(src) {
|
|
|
6
6
|
}
|
|
7
7
|
async function getConfiguredImageService() {
|
|
8
8
|
if (!globalThis.astroAsset.imageService) {
|
|
9
|
-
const { default: service } = await import(
|
|
9
|
+
const { default: service } = await import(
|
|
10
|
+
// @ts-expect-error
|
|
11
|
+
"virtual:image-service"
|
|
12
|
+
).catch((e) => {
|
|
10
13
|
const error = new AstroError(AstroErrorData.InvalidImageService);
|
|
11
14
|
error.cause = e;
|
|
12
15
|
throw error;
|
|
@@ -18,14 +21,16 @@ async function getConfiguredImageService() {
|
|
|
18
21
|
}
|
|
19
22
|
async function getImage(options) {
|
|
20
23
|
const service = await getConfiguredImageService();
|
|
21
|
-
|
|
24
|
+
const validatedOptions = service.validateOptions ? service.validateOptions(options) : options;
|
|
25
|
+
let imageURL = service.getURL(validatedOptions);
|
|
22
26
|
if (isLocalService(service) && globalThis.astroAsset.addStaticImage) {
|
|
23
|
-
imageURL = globalThis.astroAsset.addStaticImage(
|
|
27
|
+
imageURL = globalThis.astroAsset.addStaticImage(validatedOptions);
|
|
24
28
|
}
|
|
25
29
|
return {
|
|
26
|
-
options,
|
|
30
|
+
rawOptions: options,
|
|
31
|
+
options: validatedOptions,
|
|
27
32
|
src: imageURL,
|
|
28
|
-
attributes: service.getHTMLAttributes !== void 0 ? service.getHTMLAttributes(
|
|
33
|
+
attributes: service.getHTMLAttributes !== void 0 ? service.getHTMLAttributes(validatedOptions) : {}
|
|
29
34
|
};
|
|
30
35
|
}
|
|
31
36
|
function getStaticImageList() {
|
|
@@ -20,6 +20,15 @@ interface SharedServiceProps {
|
|
|
20
20
|
* In most cases, you'll want to return directly what your user supplied you, minus the attributes that were used to generate the image.
|
|
21
21
|
*/
|
|
22
22
|
getHTMLAttributes?: (options: ImageTransform) => Record<string, any>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate and return the options passed by the user.
|
|
25
|
+
*
|
|
26
|
+
* This method is useful to present errors to users who have entered invalid options.
|
|
27
|
+
* For instance, if they are missing a required property or have entered an invalid image format.
|
|
28
|
+
*
|
|
29
|
+
* This method should returns options, and can be used to set defaults (ex: a default output format to be used if the user didn't specify one.)
|
|
30
|
+
*/
|
|
31
|
+
validateOptions?: (options: ImageTransform) => ImageTransform;
|
|
23
32
|
}
|
|
24
33
|
export type ExternalImageService = SharedServiceProps;
|
|
25
34
|
type LocalImageTransform = {
|
|
@@ -46,7 +55,7 @@ export type BaseServiceTransform = {
|
|
|
46
55
|
src: string;
|
|
47
56
|
width?: number;
|
|
48
57
|
height?: number;
|
|
49
|
-
format
|
|
58
|
+
format: string;
|
|
50
59
|
quality?: string | null;
|
|
51
60
|
};
|
|
52
61
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AstroError, AstroErrorData } from "../../core/errors/index.js";
|
|
2
|
-
import { isRemotePath } from "../../core/path.js";
|
|
3
2
|
import { VALID_INPUT_FORMATS } from "../consts.js";
|
|
4
3
|
import { isESMImportedImage } from "../internal.js";
|
|
5
4
|
function isLocalService(service) {
|
|
@@ -16,6 +15,39 @@ function parseQuality(quality) {
|
|
|
16
15
|
return result;
|
|
17
16
|
}
|
|
18
17
|
const baseService = {
|
|
18
|
+
validateOptions(options) {
|
|
19
|
+
if (!isESMImportedImage(options.src)) {
|
|
20
|
+
let missingDimension;
|
|
21
|
+
if (!options.width && !options.height) {
|
|
22
|
+
missingDimension = "both";
|
|
23
|
+
} else if (!options.width && options.height) {
|
|
24
|
+
missingDimension = "width";
|
|
25
|
+
} else if (options.width && !options.height) {
|
|
26
|
+
missingDimension = "height";
|
|
27
|
+
}
|
|
28
|
+
if (missingDimension) {
|
|
29
|
+
throw new AstroError({
|
|
30
|
+
...AstroErrorData.MissingImageDimension,
|
|
31
|
+
message: AstroErrorData.MissingImageDimension.message(missingDimension, options.src)
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
if (!VALID_INPUT_FORMATS.includes(options.src.format)) {
|
|
36
|
+
throw new AstroError({
|
|
37
|
+
...AstroErrorData.UnsupportedImageFormat,
|
|
38
|
+
message: AstroErrorData.UnsupportedImageFormat.message(
|
|
39
|
+
options.src.format,
|
|
40
|
+
options.src.src,
|
|
41
|
+
VALID_INPUT_FORMATS
|
|
42
|
+
)
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!options.format) {
|
|
47
|
+
options.format = "webp";
|
|
48
|
+
}
|
|
49
|
+
return options;
|
|
50
|
+
},
|
|
19
51
|
getHTMLAttributes(options) {
|
|
20
52
|
let targetWidth = options.width;
|
|
21
53
|
let targetHeight = options.height;
|
|
@@ -25,7 +57,7 @@ const baseService = {
|
|
|
25
57
|
targetWidth = Math.round(targetHeight * aspectRatio);
|
|
26
58
|
} else if (targetWidth && !targetHeight) {
|
|
27
59
|
targetHeight = Math.round(targetWidth / aspectRatio);
|
|
28
|
-
} else {
|
|
60
|
+
} else if (!targetWidth && !targetHeight) {
|
|
29
61
|
targetWidth = options.src.width;
|
|
30
62
|
targetHeight = options.src.height;
|
|
31
63
|
}
|
|
@@ -41,36 +73,10 @@ const baseService = {
|
|
|
41
73
|
},
|
|
42
74
|
getURL(options) {
|
|
43
75
|
if (!isESMImportedImage(options.src)) {
|
|
44
|
-
let missingDimension;
|
|
45
|
-
if (!options.width && !options.height) {
|
|
46
|
-
missingDimension = "both";
|
|
47
|
-
} else if (!options.width && options.height) {
|
|
48
|
-
missingDimension = "width";
|
|
49
|
-
} else if (options.width && !options.height) {
|
|
50
|
-
missingDimension = "height";
|
|
51
|
-
}
|
|
52
|
-
if (missingDimension) {
|
|
53
|
-
throw new AstroError({
|
|
54
|
-
...AstroErrorData.MissingImageDimension,
|
|
55
|
-
message: AstroErrorData.MissingImageDimension.message(missingDimension, options.src)
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (!isESMImportedImage(options.src) && isRemotePath(options.src)) {
|
|
60
76
|
return options.src;
|
|
61
77
|
}
|
|
62
|
-
if (isESMImportedImage(options.src) && !VALID_INPUT_FORMATS.includes(options.src.format)) {
|
|
63
|
-
throw new AstroError({
|
|
64
|
-
...AstroErrorData.UnsupportedImageFormat,
|
|
65
|
-
message: AstroErrorData.UnsupportedImageFormat.message(
|
|
66
|
-
options.src.format,
|
|
67
|
-
options.src.src,
|
|
68
|
-
VALID_INPUT_FORMATS
|
|
69
|
-
)
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
78
|
const searchParams = new URLSearchParams();
|
|
73
|
-
searchParams.append("href",
|
|
79
|
+
searchParams.append("href", options.src.src);
|
|
74
80
|
options.width && searchParams.append("w", options.width.toString());
|
|
75
81
|
options.height && searchParams.append("h", options.height.toString());
|
|
76
82
|
options.quality && searchParams.append("q", options.quality.toString());
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
baseService,
|
|
3
|
+
parseQuality
|
|
4
|
+
} from "./service.js";
|
|
2
5
|
let sharp;
|
|
3
6
|
const qualityTable = {
|
|
4
7
|
low: 25,
|
|
@@ -16,6 +19,7 @@ async function loadSharp() {
|
|
|
16
19
|
return sharpImport;
|
|
17
20
|
}
|
|
18
21
|
const sharpService = {
|
|
22
|
+
validateOptions: baseService.validateOptions,
|
|
19
23
|
getURL: baseService.getURL,
|
|
20
24
|
parseURL: baseService.parseURL,
|
|
21
25
|
getHTMLAttributes: baseService.getHTMLAttributes,
|
|
@@ -23,9 +27,6 @@ const sharpService = {
|
|
|
23
27
|
if (!sharp)
|
|
24
28
|
sharp = await loadSharp();
|
|
25
29
|
const transform = transformOptions;
|
|
26
|
-
if (!transform.format) {
|
|
27
|
-
transform.format = "webp";
|
|
28
|
-
}
|
|
29
30
|
let result = sharp(inputBuffer, { failOnError: false, pages: -1 });
|
|
30
31
|
if (transform.height && !transform.width) {
|
|
31
32
|
result.resize({ height: transform.height });
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
baseService,
|
|
3
|
+
parseQuality
|
|
4
|
+
} from "./service.js";
|
|
2
5
|
import { processBuffer } from "./vendor/squoosh/image-pool.js";
|
|
3
6
|
const baseQuality = { low: 25, mid: 50, high: 80, max: 100 };
|
|
4
7
|
const qualityTable = {
|
|
5
8
|
avif: {
|
|
9
|
+
// Squoosh's AVIF encoder has a bit of a weird behavior where `62` is technically the maximum, and anything over is overkill
|
|
6
10
|
max: 62,
|
|
7
11
|
high: 45,
|
|
8
12
|
mid: 35,
|
|
@@ -11,17 +15,16 @@ const qualityTable = {
|
|
|
11
15
|
jpeg: baseQuality,
|
|
12
16
|
jpg: baseQuality,
|
|
13
17
|
webp: baseQuality
|
|
18
|
+
// Squoosh's PNG encoder does not support a quality setting, so we can skip that here
|
|
14
19
|
};
|
|
15
20
|
const service = {
|
|
21
|
+
validateOptions: baseService.validateOptions,
|
|
16
22
|
getURL: baseService.getURL,
|
|
17
23
|
parseURL: baseService.parseURL,
|
|
18
24
|
getHTMLAttributes: baseService.getHTMLAttributes,
|
|
19
25
|
async transform(inputBuffer, transformOptions) {
|
|
20
26
|
const transform = transformOptions;
|
|
21
27
|
let format = transform.format;
|
|
22
|
-
if (!format) {
|
|
23
|
-
format = "webp";
|
|
24
|
-
}
|
|
25
28
|
const operations = [];
|
|
26
29
|
if (transform.height && !transform.width) {
|
|
27
30
|
operations.push({
|
|
@@ -212,6 +212,7 @@ const codecs = {
|
|
|
212
212
|
avif: {
|
|
213
213
|
name: "AVIF",
|
|
214
214
|
extension: "avif",
|
|
215
|
+
// eslint-disable-next-line no-control-regex
|
|
215
216
|
detectors: [/^\x00\x00\x00 ftypavif\x00\x00\x00\x00/],
|
|
216
217
|
dec: () => instantiateEmscriptenWasm(avifDec, avifDecWasm.toString()),
|
|
217
218
|
enc: async () => {
|
|
@@ -241,6 +242,7 @@ const codecs = {
|
|
|
241
242
|
oxipng: {
|
|
242
243
|
name: "OxiPNG",
|
|
243
244
|
extension: "png",
|
|
245
|
+
// eslint-disable-next-line no-control-regex
|
|
244
246
|
detectors: [/^\x89PNG\x0D\x0A\x1A\x0A/],
|
|
245
247
|
dec: async () => {
|
|
246
248
|
await pngEncDecInit();
|
|
@@ -7,6 +7,8 @@ import execOnce from "./utils/execOnce.js";
|
|
|
7
7
|
import WorkerPool from "./utils/workerPool.js";
|
|
8
8
|
const getWorker = execOnce(() => {
|
|
9
9
|
return new WorkerPool(
|
|
10
|
+
// There will be at most 7 workers needed since each worker will take
|
|
11
|
+
// at least 1 operation type.
|
|
10
12
|
Math.max(1, Math.min(cpus().length - 1, 7)),
|
|
11
13
|
fileURLToPath(getModuleURL(import.meta.url))
|
|
12
14
|
);
|
|
@@ -85,6 +85,8 @@ async function encodeAvif(image, opts) {
|
|
|
85
85
|
const quality = opts.quality || 75;
|
|
86
86
|
const r = await m.encode(image.data, image.width, image.height, {
|
|
87
87
|
...e.defaultEncoderOptions,
|
|
88
|
+
// Think of cqLevel as the "amount" of quantization (0 to 62),
|
|
89
|
+
// so a lower value yields higher quality (0 to 100).
|
|
88
90
|
cqLevel: quality === 0 ? val : Math.round(val - quality / 100 * val)
|
|
89
91
|
});
|
|
90
92
|
return r;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
|
|
3
|
+
import imageSize from "../vendor/image-size/index.js";
|
|
4
4
|
async function imageMetadata(src, data) {
|
|
5
|
-
if (!sizeOf) {
|
|
6
|
-
sizeOf = await import("image-size").then((mod) => mod.default);
|
|
7
|
-
}
|
|
8
5
|
let file = data;
|
|
9
6
|
if (!file) {
|
|
10
7
|
try {
|
|
@@ -13,7 +10,7 @@ async function imageMetadata(src, data) {
|
|
|
13
10
|
return void 0;
|
|
14
11
|
}
|
|
15
12
|
}
|
|
16
|
-
const { width, height, type, orientation } =
|
|
13
|
+
const { width, height, type, orientation } = imageSize(file);
|
|
17
14
|
const isPortrait = (orientation || 0) >= 5;
|
|
18
15
|
if (!width || !height || !type) {
|
|
19
16
|
return void 0;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { typeHandlers } from "./types.js";
|
|
2
|
+
const keys = Object.keys(typeHandlers);
|
|
3
|
+
const firstBytes = {
|
|
4
|
+
56: "psd",
|
|
5
|
+
66: "bmp",
|
|
6
|
+
68: "dds",
|
|
7
|
+
71: "gif",
|
|
8
|
+
73: "tiff",
|
|
9
|
+
77: "tiff",
|
|
10
|
+
82: "webp",
|
|
11
|
+
105: "icns",
|
|
12
|
+
137: "png",
|
|
13
|
+
255: "jpg"
|
|
14
|
+
};
|
|
15
|
+
function detector(buffer) {
|
|
16
|
+
const byte = buffer[0];
|
|
17
|
+
if (byte in firstBytes) {
|
|
18
|
+
const type = firstBytes[byte];
|
|
19
|
+
if (type && typeHandlers[type].validate(buffer)) {
|
|
20
|
+
return type;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const finder = (key) => typeHandlers[key].validate(buffer);
|
|
24
|
+
return keys.find(finder);
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
detector
|
|
28
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { type imageType } from "./types.js";
|
|
3
|
+
import type { ISizeCalculationResult } from "./types/interface.js";
|
|
4
|
+
type CallbackFn = (e: Error | null, r?: ISizeCalculationResult) => void;
|
|
5
|
+
export default imageSize;
|
|
6
|
+
export declare function imageSize(input: Buffer | string): ISizeCalculationResult;
|
|
7
|
+
export declare function imageSize(input: string, callback: CallbackFn): void;
|
|
8
|
+
export declare const disableFS: (v: boolean) => void;
|
|
9
|
+
export declare const disableTypes: (types: imageType[]) => void;
|
|
10
|
+
export declare const setConcurrency: (c: number) => void;
|
|
11
|
+
export declare const types: string[];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import Queue from "../queue/queue.js";
|
|
4
|
+
import { detector } from "./detector.js";
|
|
5
|
+
import { typeHandlers } from "./types.js";
|
|
6
|
+
const MaxBufferSize = 512 * 1024;
|
|
7
|
+
const queue = new Queue({ concurrency: 100, autostart: true });
|
|
8
|
+
const globalOptions = {
|
|
9
|
+
disabledFS: false,
|
|
10
|
+
disabledTypes: []
|
|
11
|
+
};
|
|
12
|
+
function lookup(buffer, filepath) {
|
|
13
|
+
const type = detector(buffer);
|
|
14
|
+
if (typeof type !== "undefined") {
|
|
15
|
+
if (globalOptions.disabledTypes.indexOf(type) > -1) {
|
|
16
|
+
throw new TypeError("disabled file type: " + type);
|
|
17
|
+
}
|
|
18
|
+
if (type in typeHandlers) {
|
|
19
|
+
const size = typeHandlers[type].calculate(buffer, filepath);
|
|
20
|
+
if (size !== void 0) {
|
|
21
|
+
size.type = type;
|
|
22
|
+
return size;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
"unsupported file type: " + type + " (file: " + filepath + ")"
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
async function asyncFileToBuffer(filepath) {
|
|
31
|
+
const handle = await fs.promises.open(filepath, "r");
|
|
32
|
+
const { size } = await handle.stat();
|
|
33
|
+
if (size <= 0) {
|
|
34
|
+
await handle.close();
|
|
35
|
+
throw new Error("Empty file");
|
|
36
|
+
}
|
|
37
|
+
const bufferSize = Math.min(size, MaxBufferSize);
|
|
38
|
+
const buffer = Buffer.alloc(bufferSize);
|
|
39
|
+
await handle.read(buffer, 0, bufferSize, 0);
|
|
40
|
+
await handle.close();
|
|
41
|
+
return buffer;
|
|
42
|
+
}
|
|
43
|
+
function syncFileToBuffer(filepath) {
|
|
44
|
+
const descriptor = fs.openSync(filepath, "r");
|
|
45
|
+
const { size } = fs.fstatSync(descriptor);
|
|
46
|
+
if (size <= 0) {
|
|
47
|
+
fs.closeSync(descriptor);
|
|
48
|
+
throw new Error("Empty file");
|
|
49
|
+
}
|
|
50
|
+
const bufferSize = Math.min(size, MaxBufferSize);
|
|
51
|
+
const buffer = Buffer.alloc(bufferSize);
|
|
52
|
+
fs.readSync(descriptor, buffer, 0, bufferSize, 0);
|
|
53
|
+
fs.closeSync(descriptor);
|
|
54
|
+
return buffer;
|
|
55
|
+
}
|
|
56
|
+
var image_size_default = imageSize;
|
|
57
|
+
function imageSize(input, callback) {
|
|
58
|
+
if (Buffer.isBuffer(input)) {
|
|
59
|
+
return lookup(input);
|
|
60
|
+
}
|
|
61
|
+
if (typeof input !== "string" || globalOptions.disabledFS) {
|
|
62
|
+
throw new TypeError("invalid invocation. input should be a Buffer");
|
|
63
|
+
}
|
|
64
|
+
const filepath = path.resolve(input);
|
|
65
|
+
if (typeof callback === "function") {
|
|
66
|
+
queue.push(
|
|
67
|
+
() => asyncFileToBuffer(filepath).then(
|
|
68
|
+
(buffer) => process.nextTick(callback, null, lookup(buffer, filepath))
|
|
69
|
+
).catch(callback)
|
|
70
|
+
);
|
|
71
|
+
} else {
|
|
72
|
+
const buffer = syncFileToBuffer(filepath);
|
|
73
|
+
return lookup(buffer, filepath);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const disableFS = (v) => {
|
|
77
|
+
globalOptions.disabledFS = v;
|
|
78
|
+
};
|
|
79
|
+
const disableTypes = (types2) => {
|
|
80
|
+
globalOptions.disabledTypes = types2;
|
|
81
|
+
};
|
|
82
|
+
const setConcurrency = (c) => {
|
|
83
|
+
queue.concurrency = c;
|
|
84
|
+
};
|
|
85
|
+
const types = Object.keys(typeHandlers);
|
|
86
|
+
export {
|
|
87
|
+
image_size_default as default,
|
|
88
|
+
disableFS,
|
|
89
|
+
disableTypes,
|
|
90
|
+
imageSize,
|
|
91
|
+
setConcurrency,
|
|
92
|
+
types
|
|
93
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ICO } from "./ico.js";
|
|
2
|
+
const TYPE_CURSOR = 2;
|
|
3
|
+
const CUR = {
|
|
4
|
+
validate(buffer) {
|
|
5
|
+
if (buffer.readUInt16LE(0) !== 0) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return buffer.readUInt16LE(2) === TYPE_CURSOR;
|
|
9
|
+
},
|
|
10
|
+
calculate(buffer) {
|
|
11
|
+
return ICO.calculate(buffer);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
CUR
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const gifRegexp = /^GIF8[79]a/;
|
|
2
|
+
const GIF = {
|
|
3
|
+
validate(buffer) {
|
|
4
|
+
const signature = buffer.toString("ascii", 0, 6);
|
|
5
|
+
return gifRegexp.test(signature);
|
|
6
|
+
},
|
|
7
|
+
calculate(buffer) {
|
|
8
|
+
return {
|
|
9
|
+
height: buffer.readUInt16LE(8),
|
|
10
|
+
width: buffer.readUInt16LE(6)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
GIF
|
|
16
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const SIZE_HEADER = 4 + 4;
|
|
2
|
+
const FILE_LENGTH_OFFSET = 4;
|
|
3
|
+
const ENTRY_LENGTH_OFFSET = 4;
|
|
4
|
+
const ICON_TYPE_SIZE = {
|
|
5
|
+
ICON: 32,
|
|
6
|
+
"ICN#": 32,
|
|
7
|
+
// m => 16 x 16
|
|
8
|
+
"icm#": 16,
|
|
9
|
+
icm4: 16,
|
|
10
|
+
icm8: 16,
|
|
11
|
+
// s => 16 x 16
|
|
12
|
+
"ics#": 16,
|
|
13
|
+
ics4: 16,
|
|
14
|
+
ics8: 16,
|
|
15
|
+
is32: 16,
|
|
16
|
+
s8mk: 16,
|
|
17
|
+
icp4: 16,
|
|
18
|
+
// l => 32 x 32
|
|
19
|
+
icl4: 32,
|
|
20
|
+
icl8: 32,
|
|
21
|
+
il32: 32,
|
|
22
|
+
l8mk: 32,
|
|
23
|
+
icp5: 32,
|
|
24
|
+
ic11: 32,
|
|
25
|
+
// h => 48 x 48
|
|
26
|
+
ich4: 48,
|
|
27
|
+
ich8: 48,
|
|
28
|
+
ih32: 48,
|
|
29
|
+
h8mk: 48,
|
|
30
|
+
// . => 64 x 64
|
|
31
|
+
icp6: 64,
|
|
32
|
+
ic12: 32,
|
|
33
|
+
// t => 128 x 128
|
|
34
|
+
it32: 128,
|
|
35
|
+
t8mk: 128,
|
|
36
|
+
ic07: 128,
|
|
37
|
+
// . => 256 x 256
|
|
38
|
+
ic08: 256,
|
|
39
|
+
ic13: 256,
|
|
40
|
+
// . => 512 x 512
|
|
41
|
+
ic09: 512,
|
|
42
|
+
ic14: 512,
|
|
43
|
+
// . => 1024 x 1024
|
|
44
|
+
ic10: 1024
|
|
45
|
+
};
|
|
46
|
+
function readImageHeader(buffer, imageOffset) {
|
|
47
|
+
const imageLengthOffset = imageOffset + ENTRY_LENGTH_OFFSET;
|
|
48
|
+
return [
|
|
49
|
+
buffer.toString("ascii", imageOffset, imageLengthOffset),
|
|
50
|
+
buffer.readUInt32BE(imageLengthOffset)
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
function getImageSize(type) {
|
|
54
|
+
const size = ICON_TYPE_SIZE[type];
|
|
55
|
+
return { width: size, height: size, type };
|
|
56
|
+
}
|
|
57
|
+
const ICNS = {
|
|
58
|
+
validate(buffer) {
|
|
59
|
+
return "icns" === buffer.toString("ascii", 0, 4);
|
|
60
|
+
},
|
|
61
|
+
calculate(buffer) {
|
|
62
|
+
const bufferLength = buffer.length;
|
|
63
|
+
const fileLength = buffer.readUInt32BE(FILE_LENGTH_OFFSET);
|
|
64
|
+
let imageOffset = SIZE_HEADER;
|
|
65
|
+
let imageHeader = readImageHeader(buffer, imageOffset);
|
|
66
|
+
let imageSize = getImageSize(imageHeader[0]);
|
|
67
|
+
imageOffset += imageHeader[1];
|
|
68
|
+
if (imageOffset === fileLength) {
|
|
69
|
+
return imageSize;
|
|
70
|
+
}
|
|
71
|
+
const result = {
|
|
72
|
+
height: imageSize.height,
|
|
73
|
+
images: [imageSize],
|
|
74
|
+
width: imageSize.width
|
|
75
|
+
};
|
|
76
|
+
while (imageOffset < fileLength && imageOffset < bufferLength) {
|
|
77
|
+
imageHeader = readImageHeader(buffer, imageOffset);
|
|
78
|
+
imageSize = getImageSize(imageHeader[0]);
|
|
79
|
+
imageOffset += imageHeader[1];
|
|
80
|
+
result.images.push(imageSize);
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
export {
|
|
86
|
+
ICNS
|
|
87
|
+
};
|