astro 5.16.5 → 5.16.7
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/components/Code.astro +2 -2
- package/components/Image.astro +2 -2
- package/components/Picture.astro +1 -1
- package/dist/assets/build/remote.js +1 -1
- package/dist/assets/endpoint/dev.js +40 -11
- package/dist/assets/fonts/config.d.ts +3 -0
- package/dist/assets/fonts/config.js +3 -2
- package/dist/assets/fonts/constants.js +2 -1
- package/dist/assets/fonts/core/resolve-families.js +1 -0
- package/dist/assets/fonts/definitions.d.ts +10 -2
- package/dist/assets/fonts/infra/remote-font-provider-resolver.d.ts +2 -2
- package/dist/assets/fonts/infra/unifont-font-resolver.d.ts +24 -0
- package/dist/assets/fonts/infra/unifont-font-resolver.js +59 -0
- package/dist/assets/fonts/orchestrate.d.ts +6 -4
- package/dist/assets/fonts/orchestrate.js +16 -32
- package/dist/assets/fonts/providers/entrypoints/bunny.d.ts +1 -1
- package/dist/assets/fonts/providers/entrypoints/fontshare.d.ts +1 -1
- package/dist/assets/fonts/providers/entrypoints/fontsource.d.ts +1 -1
- package/dist/assets/fonts/providers/index.d.ts +6 -8
- package/dist/assets/fonts/providers/index.js +10 -14
- package/dist/assets/fonts/types.d.ts +17 -4
- package/dist/assets/fonts/vite-plugin-fonts.js +6 -1
- package/dist/assets/services/noop.js +10 -5
- package/dist/assets/services/service.d.ts +1 -1
- package/dist/assets/services/service.js +55 -51
- package/dist/assets/types.d.ts +2 -2
- package/dist/assets/utils/index.d.ts +1 -1
- package/dist/assets/utils/index.js +8 -8
- package/dist/assets/utils/vendor/image-size/detector.d.ts +1 -1
- package/dist/assets/utils/vendor/image-size/detector.js +2 -1
- package/dist/assets/utils/vendor/image-size/types/bmp.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/gif.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/heif.js +51 -29
- package/dist/assets/utils/vendor/image-size/types/icns.js +13 -14
- package/dist/assets/utils/vendor/image-size/types/ico.js +5 -5
- package/dist/assets/utils/vendor/image-size/types/index.d.ts +3 -3
- package/dist/assets/utils/vendor/image-size/types/index.js +4 -0
- package/dist/assets/utils/vendor/image-size/types/interface.d.ts +6 -6
- package/dist/assets/utils/vendor/image-size/types/j2c.js +2 -2
- package/dist/assets/utils/vendor/image-size/types/jp2.js +5 -3
- package/dist/assets/utils/vendor/image-size/types/jpg.js +4 -4
- package/dist/assets/utils/vendor/image-size/types/jxl-stream.d.ts +2 -0
- package/dist/assets/utils/vendor/image-size/types/jxl-stream.js +36 -0
- package/dist/assets/utils/vendor/image-size/types/jxl.d.ts +2 -0
- package/dist/assets/utils/vendor/image-size/types/jxl.js +57 -0
- package/dist/assets/utils/vendor/image-size/types/ktx.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/png.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/pnm.js +5 -7
- package/dist/assets/utils/vendor/image-size/types/psd.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/tiff.js +93 -40
- package/dist/assets/utils/vendor/image-size/types/utils.d.ts +3 -2
- package/dist/assets/utils/vendor/image-size/types/utils.js +24 -22
- package/dist/assets/utils/vendor/image-size/types/webp.js +5 -6
- package/dist/assets/utils/vendor/image-size/utils/bit-reader.d.ts +10 -0
- package/dist/assets/utils/vendor/image-size/utils/bit-reader.js +41 -0
- package/dist/assets/vite-plugin-assets.js +7 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/config/entrypoint.d.ts +1 -2
- package/dist/config/entrypoint.js +1 -2
- package/dist/content/content-layer.js +3 -3
- package/dist/content/utils.js +9 -2
- package/dist/core/app/index.d.ts +1 -1
- package/dist/core/app/index.js +1 -1
- package/dist/core/config/schemas/base.d.ts +7 -0
- package/dist/core/config/schemas/relative.d.ts +9 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/runtime/server/render/astro/render.js +26 -3
- package/dist/runtime/server/render/common.d.ts +1 -0
- package/dist/runtime/server/render/common.js +8 -0
- package/dist/transitions/router.js +2 -0
- package/dist/types/public/config.d.ts +2 -2
- package/dist/types/public/context.d.ts +303 -284
- package/dist/types/public/extendables.d.ts +2 -0
- package/package.json +18 -18
- package/dist/assets/fonts/core/dedupe-font-faces.d.ts +0 -2
- package/dist/assets/fonts/core/dedupe-font-faces.js +0 -30
- package/dist/assets/fonts/core/extract-unifont-providers.d.ts +0 -10
- package/dist/assets/fonts/core/extract-unifont-providers.js +0 -28
- package/dist/assets/utils/remotePattern.d.ts +0 -1
- package/dist/assets/utils/remotePattern.js +0 -16
|
@@ -17,61 +17,64 @@ function parseQuality(quality) {
|
|
|
17
17
|
return result;
|
|
18
18
|
}
|
|
19
19
|
const sortNumeric = (a, b) => a - b;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
function verifyOptions(options) {
|
|
21
|
+
if (!options.src || !isRemoteImage(options.src) && !isESMImportedImage(options.src)) {
|
|
22
|
+
throw new AstroError({
|
|
23
|
+
...AstroErrorData.ExpectedImage,
|
|
24
|
+
message: AstroErrorData.ExpectedImage.message(
|
|
25
|
+
JSON.stringify(options.src),
|
|
26
|
+
typeof options.src,
|
|
27
|
+
JSON.stringify(options, (_, v) => v === void 0 ? null : v)
|
|
28
|
+
)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (!isESMImportedImage(options.src)) {
|
|
32
|
+
if (options.src.startsWith("/@fs/") || !isRemotePath(options.src) && !options.src.startsWith("/")) {
|
|
33
|
+
throw new AstroError({
|
|
34
|
+
...AstroErrorData.LocalImageUsedWrongly,
|
|
35
|
+
message: AstroErrorData.LocalImageUsedWrongly.message(options.src)
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
let missingDimension;
|
|
39
|
+
if (!options.width && !options.height) {
|
|
40
|
+
missingDimension = "both";
|
|
41
|
+
} else if (!options.width && options.height) {
|
|
42
|
+
missingDimension = "width";
|
|
43
|
+
} else if (options.width && !options.height) {
|
|
44
|
+
missingDimension = "height";
|
|
45
|
+
}
|
|
46
|
+
if (missingDimension) {
|
|
24
47
|
throw new AstroError({
|
|
25
|
-
...AstroErrorData.
|
|
26
|
-
message: AstroErrorData.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
...AstroErrorData.MissingImageDimension,
|
|
49
|
+
message: AstroErrorData.MissingImageDimension.message(missingDimension, options.src)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
if (!VALID_SUPPORTED_FORMATS.includes(options.src.format)) {
|
|
54
|
+
throw new AstroError({
|
|
55
|
+
...AstroErrorData.UnsupportedImageFormat,
|
|
56
|
+
message: AstroErrorData.UnsupportedImageFormat.message(
|
|
57
|
+
options.src.format,
|
|
58
|
+
options.src.src,
|
|
59
|
+
VALID_SUPPORTED_FORMATS
|
|
30
60
|
)
|
|
31
61
|
});
|
|
32
62
|
}
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
missingDimension = "height";
|
|
47
|
-
}
|
|
48
|
-
if (missingDimension) {
|
|
49
|
-
throw new AstroError({
|
|
50
|
-
...AstroErrorData.MissingImageDimension,
|
|
51
|
-
message: AstroErrorData.MissingImageDimension.message(missingDimension, options.src)
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
if (!VALID_SUPPORTED_FORMATS.includes(options.src.format)) {
|
|
56
|
-
throw new AstroError({
|
|
57
|
-
...AstroErrorData.UnsupportedImageFormat,
|
|
58
|
-
message: AstroErrorData.UnsupportedImageFormat.message(
|
|
59
|
-
options.src.format,
|
|
60
|
-
options.src.src,
|
|
61
|
-
VALID_SUPPORTED_FORMATS
|
|
62
|
-
)
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
if (options.widths && options.densities) {
|
|
66
|
-
throw new AstroError(AstroErrorData.IncompatibleDescriptorOptions);
|
|
67
|
-
}
|
|
68
|
-
if (options.src.format === "svg") {
|
|
69
|
-
options.format = "svg";
|
|
70
|
-
}
|
|
71
|
-
if (options.src.format === "svg" && options.format !== "svg" || options.src.format !== "svg" && options.format === "svg") {
|
|
72
|
-
throw new AstroError(AstroErrorData.UnsupportedImageConversion);
|
|
73
|
-
}
|
|
63
|
+
if (options.widths && options.densities) {
|
|
64
|
+
throw new AstroError(AstroErrorData.IncompatibleDescriptorOptions);
|
|
65
|
+
}
|
|
66
|
+
if (options.src.format === "svg" && options.format !== "svg" || options.src.format !== "svg" && options.format === "svg") {
|
|
67
|
+
throw new AstroError(AstroErrorData.UnsupportedImageConversion);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const baseService = {
|
|
72
|
+
propertiesToHash: DEFAULT_HASH_PROPS,
|
|
73
|
+
validateOptions(options) {
|
|
74
|
+
if (isESMImportedImage(options.src) && options.src.format === "svg") {
|
|
75
|
+
options.format = "svg";
|
|
74
76
|
}
|
|
77
|
+
verifyOptions(options);
|
|
75
78
|
if (!options.format) {
|
|
76
79
|
options.format = DEFAULT_OUTPUT_FORMAT;
|
|
77
80
|
}
|
|
@@ -234,5 +237,6 @@ function getTargetDimensions(options) {
|
|
|
234
237
|
export {
|
|
235
238
|
baseService,
|
|
236
239
|
isLocalService,
|
|
237
|
-
parseQuality
|
|
240
|
+
parseQuality,
|
|
241
|
+
verifyOptions
|
|
238
242
|
};
|
package/dist/assets/types.d.ts
CHANGED
|
@@ -72,7 +72,7 @@ export type ImageTransform = {
|
|
|
72
72
|
fit?: ImageFit | undefined;
|
|
73
73
|
position?: string | undefined;
|
|
74
74
|
[key: string]: any;
|
|
75
|
-
};
|
|
75
|
+
} & Astro.CustomImageProps;
|
|
76
76
|
export interface GetImageResult {
|
|
77
77
|
rawOptions: ImageTransform;
|
|
78
78
|
options: ImageTransform;
|
|
@@ -201,7 +201,7 @@ type ImageSharedProps<T> = T & {
|
|
|
201
201
|
layout?: never;
|
|
202
202
|
fit?: never;
|
|
203
203
|
position?: never;
|
|
204
|
-
});
|
|
204
|
+
}) & Astro.CustomImageProps;
|
|
205
205
|
export type LocalImageProps<T> = ImageSharedProps<T> & {
|
|
206
206
|
/**
|
|
207
207
|
* A reference to a local image imported through an ESM import.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* If some functions don't need to be exposed, just import the file that contains the functions.
|
|
6
6
|
*/
|
|
7
|
+
export { isRemoteAllowed, matchHostname, matchPathname, matchPattern, matchPort, matchProtocol, type RemotePattern, } from '@astrojs/internal-helpers/remote';
|
|
7
8
|
export { isESMImportedImage, isRemoteImage, resolveSrc } from './imageKind.js';
|
|
8
9
|
export { imageMetadata } from './metadata.js';
|
|
9
10
|
export {
|
|
@@ -12,6 +13,5 @@ export {
|
|
|
12
13
|
*/
|
|
13
14
|
emitESMImage, emitImageMetadata, } from './node/emitAsset.js';
|
|
14
15
|
export { getOrigQueryParams } from './queryParams.js';
|
|
15
|
-
export { isRemoteAllowed, matchHostname, matchPathname, matchPattern, matchPort, matchProtocol, type RemotePattern, } from './remotePattern.js';
|
|
16
16
|
export { inferRemoteSize } from './remoteProbe.js';
|
|
17
17
|
export { hashTransform, propsToFilename } from './transformToPath.js';
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import { isESMImportedImage, isRemoteImage, resolveSrc } from "./imageKind.js";
|
|
2
|
-
import { imageMetadata } from "./metadata.js";
|
|
3
|
-
import {
|
|
4
|
-
emitESMImage,
|
|
5
|
-
emitImageMetadata
|
|
6
|
-
} from "./node/emitAsset.js";
|
|
7
|
-
import { getOrigQueryParams } from "./queryParams.js";
|
|
8
1
|
import {
|
|
9
2
|
isRemoteAllowed,
|
|
10
3
|
matchHostname,
|
|
@@ -12,7 +5,14 @@ import {
|
|
|
12
5
|
matchPattern,
|
|
13
6
|
matchPort,
|
|
14
7
|
matchProtocol
|
|
15
|
-
} from "
|
|
8
|
+
} from "@astrojs/internal-helpers/remote";
|
|
9
|
+
import { isESMImportedImage, isRemoteImage, resolveSrc } from "./imageKind.js";
|
|
10
|
+
import { imageMetadata } from "./metadata.js";
|
|
11
|
+
import {
|
|
12
|
+
emitESMImage,
|
|
13
|
+
emitImageMetadata
|
|
14
|
+
} from "./node/emitAsset.js";
|
|
15
|
+
import { getOrigQueryParams } from "./queryParams.js";
|
|
16
16
|
import { inferRemoteSize } from "./remoteProbe.js";
|
|
17
17
|
import { hashTransform, propsToFilename } from "./transformToPath.js";
|
|
18
18
|
export {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { imageType } from './types/index.
|
|
1
|
+
import type { imageType } from './types/index.ts';
|
|
2
2
|
export declare function detector(input: Uint8Array): imageType | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { typeHandlers, types } from "./types/index.js";
|
|
2
2
|
const firstBytes = /* @__PURE__ */ new Map([
|
|
3
|
+
[0, "heif"],
|
|
3
4
|
[56, "psd"],
|
|
4
5
|
[66, "bmp"],
|
|
5
6
|
[68, "dds"],
|
|
@@ -17,7 +18,7 @@ function detector(input) {
|
|
|
17
18
|
if (type && typeHandlers.get(type).validate(input)) {
|
|
18
19
|
return type;
|
|
19
20
|
}
|
|
20
|
-
return types.find((
|
|
21
|
+
return types.find((imageType) => typeHandlers.get(imageType).validate(input));
|
|
21
22
|
}
|
|
22
23
|
export {
|
|
23
24
|
detector
|
|
@@ -13,41 +13,63 @@ const brandMap = {
|
|
|
13
13
|
hevx: "heic"
|
|
14
14
|
// heic-sequence
|
|
15
15
|
};
|
|
16
|
-
function
|
|
17
|
-
let
|
|
16
|
+
function detectType(input, start, end) {
|
|
17
|
+
let hasAvif = false;
|
|
18
|
+
let hasHeic = false;
|
|
19
|
+
let hasHeif = false;
|
|
18
20
|
for (let i = start; i <= end; i += 4) {
|
|
19
|
-
const brand = toUTF8String(
|
|
20
|
-
if (brand
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
if ("avif" in brandsDetected || "avis" in brandsDetected) {
|
|
25
|
-
return "avif";
|
|
26
|
-
} else if ("heic" in brandsDetected || "heix" in brandsDetected || "hevc" in brandsDetected || "hevx" in brandsDetected) {
|
|
27
|
-
return "heic";
|
|
28
|
-
} else if ("mif1" in brandsDetected || "msf1" in brandsDetected) {
|
|
29
|
-
return "heif";
|
|
21
|
+
const brand = toUTF8String(input, i, i + 4);
|
|
22
|
+
if (brand === "avif" || brand === "avis") hasAvif = true;
|
|
23
|
+
else if (brand === "heic" || brand === "heix" || brand === "hevc" || brand === "hevx") hasHeic = true;
|
|
24
|
+
else if (brand === "mif1" || brand === "msf1") hasHeif = true;
|
|
30
25
|
}
|
|
26
|
+
if (hasAvif) return "avif";
|
|
27
|
+
if (hasHeic) return "heic";
|
|
28
|
+
if (hasHeif) return "heif";
|
|
31
29
|
}
|
|
32
30
|
const HEIF = {
|
|
33
|
-
validate(
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
validate(input) {
|
|
32
|
+
const boxType = toUTF8String(input, 4, 8);
|
|
33
|
+
if (boxType !== "ftyp") return false;
|
|
34
|
+
const ftypBox = findBox(input, "ftyp", 0);
|
|
35
|
+
if (!ftypBox) return false;
|
|
36
|
+
const brand = toUTF8String(input, ftypBox.offset + 8, ftypBox.offset + 12);
|
|
37
|
+
return brand in brandMap;
|
|
37
38
|
},
|
|
38
|
-
calculate(
|
|
39
|
-
const metaBox = findBox(
|
|
40
|
-
const iprpBox = metaBox && findBox(
|
|
41
|
-
const ipcoBox = iprpBox && findBox(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
calculate(input) {
|
|
40
|
+
const metaBox = findBox(input, "meta", 0);
|
|
41
|
+
const iprpBox = metaBox && findBox(input, "iprp", metaBox.offset + 12);
|
|
42
|
+
const ipcoBox = iprpBox && findBox(input, "ipco", iprpBox.offset + 8);
|
|
43
|
+
if (!ipcoBox) {
|
|
44
|
+
throw new TypeError("Invalid HEIF, no ipco box found");
|
|
45
|
+
}
|
|
46
|
+
const type = detectType(input, 8, metaBox.offset);
|
|
47
|
+
const images = [];
|
|
48
|
+
let currentOffset = ipcoBox.offset + 8;
|
|
49
|
+
while (currentOffset < ipcoBox.offset + ipcoBox.size) {
|
|
50
|
+
const ispeBox = findBox(input, "ispe", currentOffset);
|
|
51
|
+
if (!ispeBox) break;
|
|
52
|
+
const rawWidth = readUInt32BE(input, ispeBox.offset + 12);
|
|
53
|
+
const rawHeight = readUInt32BE(input, ispeBox.offset + 16);
|
|
54
|
+
const clapBox = findBox(input, "clap", currentOffset);
|
|
55
|
+
let width = rawWidth;
|
|
56
|
+
let height = rawHeight;
|
|
57
|
+
if (clapBox && clapBox.offset < ipcoBox.offset + ipcoBox.size) {
|
|
58
|
+
const cropRight = readUInt32BE(input, clapBox.offset + 12);
|
|
59
|
+
width = rawWidth - cropRight;
|
|
60
|
+
}
|
|
61
|
+
images.push({ height, width });
|
|
62
|
+
currentOffset = ispeBox.offset + ispeBox.size;
|
|
63
|
+
}
|
|
64
|
+
if (images.length === 0) {
|
|
65
|
+
throw new TypeError("Invalid HEIF, no sizes found");
|
|
49
66
|
}
|
|
50
|
-
|
|
67
|
+
return {
|
|
68
|
+
width: images[0].width,
|
|
69
|
+
height: images[0].height,
|
|
70
|
+
type,
|
|
71
|
+
...images.length > 1 ? { images } : {}
|
|
72
|
+
};
|
|
51
73
|
}
|
|
52
74
|
};
|
|
53
75
|
export {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readUInt32BE, toUTF8String } from "./utils.js";
|
|
2
2
|
const SIZE_HEADER = 4 + 4;
|
|
3
3
|
const FILE_LENGTH_OFFSET = 4;
|
|
4
4
|
const ENTRY_LENGTH_OFFSET = 4;
|
|
@@ -61,22 +61,21 @@ const ICNS = {
|
|
|
61
61
|
const inputLength = input.length;
|
|
62
62
|
const fileLength = readUInt32BE(input, FILE_LENGTH_OFFSET);
|
|
63
63
|
let imageOffset = SIZE_HEADER;
|
|
64
|
-
|
|
65
|
-
let imageSize = getImageSize(imageHeader[0]);
|
|
66
|
-
imageOffset += imageHeader[1];
|
|
67
|
-
if (imageOffset === fileLength) return imageSize;
|
|
68
|
-
const result = {
|
|
69
|
-
height: imageSize.height,
|
|
70
|
-
images: [imageSize],
|
|
71
|
-
width: imageSize.width
|
|
72
|
-
};
|
|
64
|
+
const images = [];
|
|
73
65
|
while (imageOffset < fileLength && imageOffset < inputLength) {
|
|
74
|
-
imageHeader = readImageHeader(input, imageOffset);
|
|
75
|
-
imageSize = getImageSize(imageHeader[0]);
|
|
66
|
+
const imageHeader = readImageHeader(input, imageOffset);
|
|
67
|
+
const imageSize = getImageSize(imageHeader[0]);
|
|
68
|
+
images.push(imageSize);
|
|
76
69
|
imageOffset += imageHeader[1];
|
|
77
|
-
result.images.push(imageSize);
|
|
78
70
|
}
|
|
79
|
-
|
|
71
|
+
if (images.length === 0) {
|
|
72
|
+
throw new TypeError("Invalid ICNS, no sizes found");
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
width: images[0].width,
|
|
76
|
+
height: images[0].height,
|
|
77
|
+
...images.length > 1 ? { images } : {}
|
|
78
|
+
};
|
|
80
79
|
}
|
|
81
80
|
};
|
|
82
81
|
export {
|
|
@@ -25,14 +25,14 @@ const ICO = {
|
|
|
25
25
|
const nbImages = readUInt16LE(input, 4);
|
|
26
26
|
const imageSize = getImageSize(input, 0);
|
|
27
27
|
if (nbImages === 1) return imageSize;
|
|
28
|
-
const
|
|
29
|
-
for (let imageIndex =
|
|
30
|
-
|
|
28
|
+
const images = [];
|
|
29
|
+
for (let imageIndex = 0; imageIndex < nbImages; imageIndex += 1) {
|
|
30
|
+
images.push(getImageSize(input, imageIndex));
|
|
31
31
|
}
|
|
32
32
|
return {
|
|
33
|
+
width: imageSize.width,
|
|
33
34
|
height: imageSize.height,
|
|
34
|
-
images
|
|
35
|
-
width: imageSize.width
|
|
35
|
+
images
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const typeHandlers: Map<"jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "heif" | "icns" | "ktx" | "bmp" | "cur" | "dds" | "ico" | "j2c" | "jp2" | "pnm" | "psd" | "tga", import("./interface.js").IImage>;
|
|
2
|
-
export declare const types: ("jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "heif" | "icns" | "ktx" | "bmp" | "cur" | "dds" | "ico" | "j2c" | "jp2" | "pnm" | "psd" | "tga")[];
|
|
3
|
-
export type imageType = typeof types[number];
|
|
1
|
+
export declare const typeHandlers: Map<"jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "heif" | "icns" | "ktx" | "bmp" | "cur" | "dds" | "ico" | "j2c" | "jp2" | "jxl" | "jxl-stream" | "pnm" | "psd" | "tga", import("./interface.js").IImage>;
|
|
2
|
+
export declare const types: ("jpg" | "png" | "tiff" | "webp" | "gif" | "svg" | "heif" | "icns" | "ktx" | "bmp" | "cur" | "dds" | "ico" | "j2c" | "jp2" | "jxl" | "jxl-stream" | "pnm" | "psd" | "tga")[];
|
|
3
|
+
export type imageType = (typeof types)[number];
|
|
@@ -8,6 +8,8 @@ import { ICO } from "./ico.js";
|
|
|
8
8
|
import { J2C } from "./j2c.js";
|
|
9
9
|
import { JP2 } from "./jp2.js";
|
|
10
10
|
import { JPG } from "./jpg.js";
|
|
11
|
+
import { JXL } from "./jxl.js";
|
|
12
|
+
import { JXLStream } from "./jxl-stream.js";
|
|
11
13
|
import { KTX } from "./ktx.js";
|
|
12
14
|
import { PNG } from "./png.js";
|
|
13
15
|
import { PNM } from "./pnm.js";
|
|
@@ -27,6 +29,8 @@ const typeHandlers = /* @__PURE__ */ new Map([
|
|
|
27
29
|
["j2c", J2C],
|
|
28
30
|
["jp2", JP2],
|
|
29
31
|
["jpg", JPG],
|
|
32
|
+
["jxl", JXL],
|
|
33
|
+
["jxl-stream", JXLStream],
|
|
30
34
|
["ktx", KTX],
|
|
31
35
|
["png", PNG],
|
|
32
36
|
["pnm", PNM],
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
width: number
|
|
3
|
-
height: number
|
|
1
|
+
export interface ISize {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
4
|
orientation?: number;
|
|
5
5
|
type?: string;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
export type ISizeCalculationResult = {
|
|
8
8
|
images?: ISize[];
|
|
9
9
|
} & ISize;
|
|
10
|
-
export
|
|
10
|
+
export interface IImage {
|
|
11
11
|
validate: (input: Uint8Array) => boolean;
|
|
12
12
|
calculate: (input: Uint8Array) => ISizeCalculationResult;
|
|
13
|
-
}
|
|
13
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readUInt32BE } from "./utils.js";
|
|
2
2
|
const J2C = {
|
|
3
3
|
// TODO: this doesn't seem right. SIZ marker doesn't have to be right after the SOC
|
|
4
|
-
validate: (input) =>
|
|
4
|
+
validate: (input) => readUInt32BE(input, 0) === 4283432785,
|
|
5
5
|
calculate: (input) => ({
|
|
6
6
|
height: readUInt32BE(input, 12),
|
|
7
7
|
width: readUInt32BE(input, 8)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { readUInt32BE,
|
|
1
|
+
import { findBox, readUInt32BE, toUTF8String } from "./utils.js";
|
|
2
2
|
const JP2 = {
|
|
3
3
|
validate(input) {
|
|
4
|
-
|
|
4
|
+
const boxType = toUTF8String(input, 4, 8);
|
|
5
|
+
if (boxType !== "jP ") return false;
|
|
5
6
|
const ftypBox = findBox(input, "ftyp", 0);
|
|
6
7
|
if (!ftypBox) return false;
|
|
7
|
-
|
|
8
|
+
const brand = toUTF8String(input, ftypBox.offset + 8, ftypBox.offset + 12);
|
|
9
|
+
return brand === "jp2 ";
|
|
8
10
|
},
|
|
9
11
|
calculate(input) {
|
|
10
12
|
const jp2hBox = findBox(input, "jp2h", 0);
|
|
@@ -61,20 +61,20 @@ function validateInput(input, index) {
|
|
|
61
61
|
}
|
|
62
62
|
const JPG = {
|
|
63
63
|
validate: (input) => toHexString(input, 0, 2) === "ffd8",
|
|
64
|
-
calculate(
|
|
65
|
-
input =
|
|
64
|
+
calculate(_input) {
|
|
65
|
+
let input = _input.slice(4);
|
|
66
66
|
let orientation;
|
|
67
67
|
let next;
|
|
68
68
|
while (input.length) {
|
|
69
69
|
const i = readUInt16BE(input, 0);
|
|
70
|
+
validateInput(input, i);
|
|
70
71
|
if (input[i] !== 255) {
|
|
71
|
-
input = input.slice(
|
|
72
|
+
input = input.slice(1);
|
|
72
73
|
continue;
|
|
73
74
|
}
|
|
74
75
|
if (isEXIF(input)) {
|
|
75
76
|
orientation = validateExifBlock(input, i);
|
|
76
77
|
}
|
|
77
|
-
validateInput(input, i);
|
|
78
78
|
next = input[i + 1];
|
|
79
79
|
if (next === 192 || next === 193 || next === 194) {
|
|
80
80
|
const size = extractSize(input, i + 5);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BitReader } from "../utils/bit-reader.js";
|
|
2
|
+
import { toHexString } from "./utils.js";
|
|
3
|
+
function calculateImageDimension(reader, isSmallImage) {
|
|
4
|
+
if (isSmallImage) {
|
|
5
|
+
return 8 * (1 + reader.getBits(5));
|
|
6
|
+
}
|
|
7
|
+
const sizeClass = reader.getBits(2);
|
|
8
|
+
const extraBits = [9, 13, 18, 30][sizeClass];
|
|
9
|
+
return 1 + reader.getBits(extraBits);
|
|
10
|
+
}
|
|
11
|
+
function calculateImageWidth(reader, isSmallImage, widthMode, height) {
|
|
12
|
+
if (isSmallImage && widthMode === 0) {
|
|
13
|
+
return 8 * (1 + reader.getBits(5));
|
|
14
|
+
}
|
|
15
|
+
if (widthMode === 0) {
|
|
16
|
+
return calculateImageDimension(reader, false);
|
|
17
|
+
}
|
|
18
|
+
const aspectRatios = [1, 1.2, 4 / 3, 1.5, 16 / 9, 5 / 4, 2];
|
|
19
|
+
return Math.floor(height * aspectRatios[widthMode - 1]);
|
|
20
|
+
}
|
|
21
|
+
const JXLStream = {
|
|
22
|
+
validate: (input) => {
|
|
23
|
+
return toHexString(input, 0, 2) === "ff0a";
|
|
24
|
+
},
|
|
25
|
+
calculate(input) {
|
|
26
|
+
const reader = new BitReader(input, "little-endian");
|
|
27
|
+
const isSmallImage = reader.getBits(1) === 1;
|
|
28
|
+
const height = calculateImageDimension(reader, isSmallImage);
|
|
29
|
+
const widthMode = reader.getBits(3);
|
|
30
|
+
const width = calculateImageWidth(reader, isSmallImage, widthMode, height);
|
|
31
|
+
return { width, height };
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
JXLStream
|
|
36
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { JXLStream } from "./jxl-stream.js";
|
|
2
|
+
import { findBox, toUTF8String } from "./utils.js";
|
|
3
|
+
function extractCodestream(input) {
|
|
4
|
+
const jxlcBox = findBox(input, "jxlc", 0);
|
|
5
|
+
if (jxlcBox) {
|
|
6
|
+
return input.slice(jxlcBox.offset + 8, jxlcBox.offset + jxlcBox.size);
|
|
7
|
+
}
|
|
8
|
+
const partialStreams = extractPartialStreams(input);
|
|
9
|
+
if (partialStreams.length > 0) {
|
|
10
|
+
return concatenateCodestreams(partialStreams);
|
|
11
|
+
}
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
function extractPartialStreams(input) {
|
|
15
|
+
const partialStreams = [];
|
|
16
|
+
let offset = 0;
|
|
17
|
+
while (offset < input.length) {
|
|
18
|
+
const jxlpBox = findBox(input, "jxlp", offset);
|
|
19
|
+
if (!jxlpBox) break;
|
|
20
|
+
partialStreams.push(
|
|
21
|
+
input.slice(jxlpBox.offset + 12, jxlpBox.offset + jxlpBox.size)
|
|
22
|
+
);
|
|
23
|
+
offset = jxlpBox.offset + jxlpBox.size;
|
|
24
|
+
}
|
|
25
|
+
return partialStreams;
|
|
26
|
+
}
|
|
27
|
+
function concatenateCodestreams(partialCodestreams) {
|
|
28
|
+
const totalLength = partialCodestreams.reduce(
|
|
29
|
+
(acc, curr) => acc + curr.length,
|
|
30
|
+
0
|
|
31
|
+
);
|
|
32
|
+
const codestream = new Uint8Array(totalLength);
|
|
33
|
+
let position = 0;
|
|
34
|
+
for (const partial of partialCodestreams) {
|
|
35
|
+
codestream.set(partial, position);
|
|
36
|
+
position += partial.length;
|
|
37
|
+
}
|
|
38
|
+
return codestream;
|
|
39
|
+
}
|
|
40
|
+
const JXL = {
|
|
41
|
+
validate: (input) => {
|
|
42
|
+
const boxType = toUTF8String(input, 4, 8);
|
|
43
|
+
if (boxType !== "JXL ") return false;
|
|
44
|
+
const ftypBox = findBox(input, "ftyp", 0);
|
|
45
|
+
if (!ftypBox) return false;
|
|
46
|
+
const brand = toUTF8String(input, ftypBox.offset + 8, ftypBox.offset + 12);
|
|
47
|
+
return brand === "jxl ";
|
|
48
|
+
},
|
|
49
|
+
calculate(input) {
|
|
50
|
+
const codestream = extractCodestream(input);
|
|
51
|
+
if (codestream) return JXLStream.calculate(codestream);
|
|
52
|
+
throw new Error("No codestream found in JXL container");
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
JXL
|
|
57
|
+
};
|
|
@@ -22,12 +22,11 @@ const handlers = {
|
|
|
22
22
|
}
|
|
23
23
|
if (dimensions.length === 2) {
|
|
24
24
|
return {
|
|
25
|
-
height: parseInt(dimensions[1], 10),
|
|
26
|
-
width: parseInt(dimensions[0], 10)
|
|
25
|
+
height: Number.parseInt(dimensions[1], 10),
|
|
26
|
+
width: Number.parseInt(dimensions[0], 10)
|
|
27
27
|
};
|
|
28
|
-
} else {
|
|
29
|
-
throw new TypeError("Invalid PNM");
|
|
30
28
|
}
|
|
29
|
+
throw new TypeError("Invalid PNM");
|
|
31
30
|
},
|
|
32
31
|
pam: (lines) => {
|
|
33
32
|
const size = {};
|
|
@@ -38,7 +37,7 @@ const handlers = {
|
|
|
38
37
|
}
|
|
39
38
|
const [key, value] = line.split(" ");
|
|
40
39
|
if (key && value) {
|
|
41
|
-
size[key.toLowerCase()] = parseInt(value, 10);
|
|
40
|
+
size[key.toLowerCase()] = Number.parseInt(value, 10);
|
|
42
41
|
}
|
|
43
42
|
if (size.height && size.width) {
|
|
44
43
|
break;
|
|
@@ -49,9 +48,8 @@ const handlers = {
|
|
|
49
48
|
height: size.height,
|
|
50
49
|
width: size.width
|
|
51
50
|
};
|
|
52
|
-
} else {
|
|
53
|
-
throw new TypeError("Invalid PAM");
|
|
54
51
|
}
|
|
52
|
+
throw new TypeError("Invalid PAM");
|
|
55
53
|
}
|
|
56
54
|
};
|
|
57
55
|
const PNM = {
|