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.
Files changed (82) hide show
  1. package/components/Code.astro +2 -2
  2. package/components/Image.astro +2 -2
  3. package/components/Picture.astro +1 -1
  4. package/dist/assets/build/remote.js +1 -1
  5. package/dist/assets/endpoint/dev.js +40 -11
  6. package/dist/assets/fonts/config.d.ts +3 -0
  7. package/dist/assets/fonts/config.js +3 -2
  8. package/dist/assets/fonts/constants.js +2 -1
  9. package/dist/assets/fonts/core/resolve-families.js +1 -0
  10. package/dist/assets/fonts/definitions.d.ts +10 -2
  11. package/dist/assets/fonts/infra/remote-font-provider-resolver.d.ts +2 -2
  12. package/dist/assets/fonts/infra/unifont-font-resolver.d.ts +24 -0
  13. package/dist/assets/fonts/infra/unifont-font-resolver.js +59 -0
  14. package/dist/assets/fonts/orchestrate.d.ts +6 -4
  15. package/dist/assets/fonts/orchestrate.js +16 -32
  16. package/dist/assets/fonts/providers/entrypoints/bunny.d.ts +1 -1
  17. package/dist/assets/fonts/providers/entrypoints/fontshare.d.ts +1 -1
  18. package/dist/assets/fonts/providers/entrypoints/fontsource.d.ts +1 -1
  19. package/dist/assets/fonts/providers/index.d.ts +6 -8
  20. package/dist/assets/fonts/providers/index.js +10 -14
  21. package/dist/assets/fonts/types.d.ts +17 -4
  22. package/dist/assets/fonts/vite-plugin-fonts.js +6 -1
  23. package/dist/assets/services/noop.js +10 -5
  24. package/dist/assets/services/service.d.ts +1 -1
  25. package/dist/assets/services/service.js +55 -51
  26. package/dist/assets/types.d.ts +2 -2
  27. package/dist/assets/utils/index.d.ts +1 -1
  28. package/dist/assets/utils/index.js +8 -8
  29. package/dist/assets/utils/vendor/image-size/detector.d.ts +1 -1
  30. package/dist/assets/utils/vendor/image-size/detector.js +2 -1
  31. package/dist/assets/utils/vendor/image-size/types/bmp.js +1 -1
  32. package/dist/assets/utils/vendor/image-size/types/gif.js +1 -1
  33. package/dist/assets/utils/vendor/image-size/types/heif.js +51 -29
  34. package/dist/assets/utils/vendor/image-size/types/icns.js +13 -14
  35. package/dist/assets/utils/vendor/image-size/types/ico.js +5 -5
  36. package/dist/assets/utils/vendor/image-size/types/index.d.ts +3 -3
  37. package/dist/assets/utils/vendor/image-size/types/index.js +4 -0
  38. package/dist/assets/utils/vendor/image-size/types/interface.d.ts +6 -6
  39. package/dist/assets/utils/vendor/image-size/types/j2c.js +2 -2
  40. package/dist/assets/utils/vendor/image-size/types/jp2.js +5 -3
  41. package/dist/assets/utils/vendor/image-size/types/jpg.js +4 -4
  42. package/dist/assets/utils/vendor/image-size/types/jxl-stream.d.ts +2 -0
  43. package/dist/assets/utils/vendor/image-size/types/jxl-stream.js +36 -0
  44. package/dist/assets/utils/vendor/image-size/types/jxl.d.ts +2 -0
  45. package/dist/assets/utils/vendor/image-size/types/jxl.js +57 -0
  46. package/dist/assets/utils/vendor/image-size/types/ktx.js +1 -1
  47. package/dist/assets/utils/vendor/image-size/types/png.js +1 -1
  48. package/dist/assets/utils/vendor/image-size/types/pnm.js +5 -7
  49. package/dist/assets/utils/vendor/image-size/types/psd.js +1 -1
  50. package/dist/assets/utils/vendor/image-size/types/tiff.js +93 -40
  51. package/dist/assets/utils/vendor/image-size/types/utils.d.ts +3 -2
  52. package/dist/assets/utils/vendor/image-size/types/utils.js +24 -22
  53. package/dist/assets/utils/vendor/image-size/types/webp.js +5 -6
  54. package/dist/assets/utils/vendor/image-size/utils/bit-reader.d.ts +10 -0
  55. package/dist/assets/utils/vendor/image-size/utils/bit-reader.js +41 -0
  56. package/dist/assets/vite-plugin-assets.js +7 -0
  57. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  58. package/dist/config/entrypoint.d.ts +1 -2
  59. package/dist/config/entrypoint.js +1 -2
  60. package/dist/content/content-layer.js +3 -3
  61. package/dist/content/utils.js +9 -2
  62. package/dist/core/app/index.d.ts +1 -1
  63. package/dist/core/app/index.js +1 -1
  64. package/dist/core/config/schemas/base.d.ts +7 -0
  65. package/dist/core/config/schemas/relative.d.ts +9 -0
  66. package/dist/core/constants.js +1 -1
  67. package/dist/core/dev/dev.js +1 -1
  68. package/dist/core/messages.js +2 -2
  69. package/dist/runtime/server/render/astro/render.js +26 -3
  70. package/dist/runtime/server/render/common.d.ts +1 -0
  71. package/dist/runtime/server/render/common.js +8 -0
  72. package/dist/transitions/router.js +2 -0
  73. package/dist/types/public/config.d.ts +2 -2
  74. package/dist/types/public/context.d.ts +303 -284
  75. package/dist/types/public/extendables.d.ts +2 -0
  76. package/package.json +18 -18
  77. package/dist/assets/fonts/core/dedupe-font-faces.d.ts +0 -2
  78. package/dist/assets/fonts/core/dedupe-font-faces.js +0 -30
  79. package/dist/assets/fonts/core/extract-unifont-providers.d.ts +0 -10
  80. package/dist/assets/fonts/core/extract-unifont-providers.js +0 -28
  81. package/dist/assets/utils/remotePattern.d.ts +0 -1
  82. 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
- const baseService = {
21
- propertiesToHash: DEFAULT_HASH_PROPS,
22
- validateOptions(options) {
23
- if (!options.src || !isRemoteImage(options.src) && !isESMImportedImage(options.src)) {
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.ExpectedImage,
26
- message: AstroErrorData.ExpectedImage.message(
27
- JSON.stringify(options.src),
28
- typeof options.src,
29
- JSON.stringify(options, (_, v) => v === void 0 ? null : v)
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 (!isESMImportedImage(options.src)) {
34
- if (options.src.startsWith("/@fs/") || !isRemotePath(options.src) && !options.src.startsWith("/")) {
35
- throw new AstroError({
36
- ...AstroErrorData.LocalImageUsedWrongly,
37
- message: AstroErrorData.LocalImageUsedWrongly.message(options.src)
38
- });
39
- }
40
- let missingDimension;
41
- if (!options.width && !options.height) {
42
- missingDimension = "both";
43
- } else if (!options.width && options.height) {
44
- missingDimension = "width";
45
- } else if (options.width && !options.height) {
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
  };
@@ -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 "./remotePattern.js";
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.js';
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((fileType) => typeHandlers.get(fileType).validate(input));
21
+ return types.find((imageType) => typeHandlers.get(imageType).validate(input));
21
22
  }
22
23
  export {
23
24
  detector
@@ -1,4 +1,4 @@
1
- import { toUTF8String, readInt32LE, readUInt32LE } from "./utils.js";
1
+ import { readInt32LE, readUInt32LE, toUTF8String } from "./utils.js";
2
2
  const BMP = {
3
3
  validate: (input) => toUTF8String(input, 0, 2) === "BM",
4
4
  calculate: (input) => ({
@@ -1,4 +1,4 @@
1
- import { toUTF8String, readUInt16LE } from "./utils.js";
1
+ import { readUInt16LE, toUTF8String } from "./utils.js";
2
2
  const gifRegexp = /^GIF8[79]a/;
3
3
  const GIF = {
4
4
  validate: (input) => gifRegexp.test(toUTF8String(input, 0, 6)),
@@ -13,41 +13,63 @@ const brandMap = {
13
13
  hevx: "heic"
14
14
  // heic-sequence
15
15
  };
16
- function detectBrands(buffer, start, end) {
17
- let brandsDetected = {};
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(buffer, i, i + 4);
20
- if (brand in brandMap) {
21
- brandsDetected[brand] = 1;
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(buffer) {
34
- const ftype = toUTF8String(buffer, 4, 8);
35
- const brand = toUTF8String(buffer, 8, 12);
36
- return "ftyp" === ftype && brand in brandMap;
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(buffer) {
39
- const metaBox = findBox(buffer, "meta", 0);
40
- const iprpBox = metaBox && findBox(buffer, "iprp", metaBox.offset + 12);
41
- const ipcoBox = iprpBox && findBox(buffer, "ipco", iprpBox.offset + 8);
42
- const ispeBox = ipcoBox && findBox(buffer, "ispe", ipcoBox.offset + 8);
43
- if (ispeBox) {
44
- return {
45
- height: readUInt32BE(buffer, ispeBox.offset + 16),
46
- width: readUInt32BE(buffer, ispeBox.offset + 12),
47
- type: detectBrands(buffer, 8, metaBox.offset)
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
- throw new TypeError("Invalid HEIF, no size found");
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 { toUTF8String, readUInt32BE } from "./utils.js";
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
- let imageHeader = readImageHeader(input, imageOffset);
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
- return result;
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 imgs = [imageSize];
29
- for (let imageIndex = 1; imageIndex < nbImages; imageIndex += 1) {
30
- imgs.push(getImageSize(input, imageIndex));
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: imgs,
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 type ISize = {
2
- width: number | undefined;
3
- height: number | undefined;
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 type IImage = {
10
+ export interface IImage {
11
11
  validate: (input: Uint8Array) => boolean;
12
12
  calculate: (input: Uint8Array) => ISizeCalculationResult;
13
- };
13
+ }
@@ -1,7 +1,7 @@
1
- import { toHexString, readUInt32BE } from "./utils.js";
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) => toHexString(input, 0, 4) === "ff4fff51",
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, findBox } from "./utils.js";
1
+ import { findBox, readUInt32BE, toUTF8String } from "./utils.js";
2
2
  const JP2 = {
3
3
  validate(input) {
4
- if (readUInt32BE(input, 4) !== 1783636e3 || readUInt32BE(input, 0) < 1) return false;
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
- return readUInt32BE(input, ftypBox.offset + 4) === 1718909296;
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(input) {
65
- input = input.slice(4);
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(i);
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,2 @@
1
+ import type { IImage } from './interface.ts';
2
+ export declare const JXLStream: IImage;
@@ -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,2 @@
1
+ import type { IImage } from './interface.ts';
2
+ export declare const JXL: IImage;
@@ -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
+ };
@@ -1,4 +1,4 @@
1
- import { toUTF8String, readUInt32LE } from "./utils.js";
1
+ import { readUInt32LE, toUTF8String } from "./utils.js";
2
2
  const KTX = {
3
3
  validate: (input) => {
4
4
  const signature = toUTF8String(input, 1, 7);
@@ -1,4 +1,4 @@
1
- import { toUTF8String, readUInt32BE } from "./utils.js";
1
+ import { readUInt32BE, toUTF8String } from "./utils.js";
2
2
  const pngSignature = "PNG\r\n\n";
3
3
  const pngImageHeaderChunkName = "IHDR";
4
4
  const pngFriedChunkName = "CgBI";
@@ -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 = {
@@ -1,4 +1,4 @@
1
- import { toUTF8String, readUInt32BE } from "./utils.js";
1
+ import { readUInt32BE, toUTF8String } from "./utils.js";
2
2
  const PSD = {
3
3
  validate: (input) => toUTF8String(input, 0, 4) === "8BPS",
4
4
  calculate: (input) => ({