@lonik/oh-image 2.8.0 → 2.10.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/dist/client.d.ts CHANGED
@@ -6,7 +6,6 @@ declare module "*$oh" {
6
6
  | "fetchPriority"
7
7
  | "decoding"
8
8
  | "loading"
9
- | "srcSet"
10
9
  | "className"
11
10
  | "sizes"
12
11
  | "style"
@@ -24,7 +23,6 @@ declare module "*$oh" {
24
23
  */
25
24
  fill?: boolean;
26
25
 
27
- breakpoints?: number[];
28
26
  }
29
27
 
30
28
  const component: React.FC<StaticImageProps>;
@@ -1,7 +1,7 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
- import * as react_jsx_runtime4 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime8 from "react/jsx-runtime";
5
5
 
6
6
  //#region src/loaders/cloudflare/cloudflare-options.d.ts
7
7
  type CloudflareTransforms = Partial<{
@@ -40,6 +40,6 @@ declare const useCloudflareContext: () => CloudflareGlobalOptions, CloudflareLoa
40
40
  ...props
41
41
  }: {
42
42
  children: React.ReactNode;
43
- } & Partial<CloudflareGlobalOptions>) => react_jsx_runtime4.JSX.Element, useCloudflareLoader: (options?: CloudflareGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
43
+ } & Partial<CloudflareGlobalOptions>) => react_jsx_runtime8.JSX.Element, useCloudflareLoader: (options?: CloudflareGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
44
44
  //#endregion
45
45
  export { CloudflareGlobalOptions, CloudflareLoaderProvider, CloudflareOptions, CloudflareTransforms, useCloudflareContext, useCloudflareLoader };
@@ -1,5 +1,5 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import * as react_jsx_runtime7 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime6 from "react/jsx-runtime";
3
3
  import { Cloudinary, CloudinaryImage } from "@cloudinary/url-gen";
4
4
 
5
5
  //#region src/loaders/cloudinary/cloudinary-options.d.ts
@@ -34,7 +34,7 @@ declare function CloudinaryLoaderProvider({
34
34
  children: React.ReactNode;
35
35
  transforms?: CloudinaryTransforms;
36
36
  placeholder?: CloudinaryTransforms;
37
- }): react_jsx_runtime7.JSX.Element;
37
+ }): react_jsx_runtime6.JSX.Element;
38
38
  declare function useCloudinaryLoader(options?: CloudinaryLoaderHookOptions | CloudinaryTransforms): (imageOptions: ImageLoaderOptions) => string;
39
39
  declare const useCloudinaryContext: () => CloudinaryLoaderContext;
40
40
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
- import * as react_jsx_runtime1 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
 
6
6
  //#region src/loaders/contentful/contentful-options.d.ts
7
7
  type ContentfulTransforms = Partial<{
@@ -39,6 +39,6 @@ declare const useContentfulContext: () => ContentfulGlobalOptions, ContentfulLoa
39
39
  ...props
40
40
  }: {
41
41
  children: React.ReactNode;
42
- } & Partial<ContentfulGlobalOptions>) => react_jsx_runtime1.JSX.Element, useContentfulLoader: (options?: ContentfulGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
42
+ } & Partial<ContentfulGlobalOptions>) => react_jsx_runtime0.JSX.Element, useContentfulLoader: (options?: ContentfulGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
43
43
  //#endregion
44
44
  export { ContentfulGlobalOptions, ContentfulLoaderProvider, ContentfulOptions, ContentfulTransforms, useContentfulContext, useContentfulLoader };
@@ -1,7 +1,7 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
- import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime7 from "react/jsx-runtime";
5
5
 
6
6
  //#region src/loaders/imgproxy/imgproxy-options.d.ts
7
7
  type ResizeType = "fit" | "fill" | "fill-down" | "force" | "auto";
@@ -384,6 +384,6 @@ declare const useImgproxyContext: () => ImgproxyGlobalOptions, ImgproxyLoaderPro
384
384
  ...props
385
385
  }: {
386
386
  children: React.ReactNode;
387
- } & Partial<ImgproxyGlobalOptions>) => react_jsx_runtime0.JSX.Element, useImgproxyLoader: (options?: ImgproxyGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
387
+ } & Partial<ImgproxyGlobalOptions>) => react_jsx_runtime7.JSX.Element, useImgproxyLoader: (options?: ImgproxyGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
388
388
  //#endregion
389
389
  export { ImgproxyGlobalOptions, ImgproxyLoaderProvider, ImgproxyOptions, ImgproxyTransforms, useImgproxyContext, useImgproxyLoader };
@@ -1,11 +1,11 @@
1
1
  import { r as ImageProps, t as ImageLoader } from "./types-BEgZ3W30.js";
2
- import * as react_jsx_runtime5 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime4 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/react/image.d.ts
5
- declare function Image(props: ImageProps): react_jsx_runtime5.JSX.Element;
5
+ declare function Image(props: ImageProps): react_jsx_runtime4.JSX.Element;
6
6
  //#endregion
7
7
  //#region src/react/image-factory.d.ts
8
- declare function __imageFactory(defaultProps: any): (props: any) => react_jsx_runtime5.JSX.Element;
8
+ declare function __imageFactory(defaultProps: any): (props: any) => react_jsx_runtime4.JSX.Element;
9
9
  //#endregion
10
10
  //#region src/react/use-img-loaded.d.ts
11
11
  /**
@@ -47,6 +47,6 @@ declare function ImageProvider({
47
47
  ...props
48
48
  }: {
49
49
  children: React.ReactNode;
50
- } & Partial<ImageContextValue>): react_jsx_runtime5.JSX.Element;
50
+ } & Partial<ImageContextValue>): react_jsx_runtime4.JSX.Element;
51
51
  //#endregion
52
52
  export { Image as a, __imageFactory as i, useImageContext as n, useImgLoaded as r, ImageProvider as t };
package/dist/kontent.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
4
  import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
 
package/dist/netlify.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
- import * as react_jsx_runtime8 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime2 from "react/jsx-runtime";
5
5
 
6
6
  //#region src/loaders/netlify/netlify-options.d.ts
7
7
  type NetlifyTransforms = Partial<{
@@ -21,6 +21,6 @@ declare const useNetlifyContext: () => NetlifyGlobalOptions, NetlifyLoaderProvid
21
21
  ...props
22
22
  }: {
23
23
  children: React.ReactNode;
24
- } & Partial<NetlifyGlobalOptions>) => react_jsx_runtime8.JSX.Element, useNetlifyLoader: (options?: NetlifyGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
24
+ } & Partial<NetlifyGlobalOptions>) => react_jsx_runtime2.JSX.Element, useNetlifyLoader: (options?: NetlifyGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
25
25
  //#endregion
26
26
  export { NetlifyGlobalOptions, NetlifyLoaderProvider, NetlifyOptions, NetlifyTransforms, useNetlifyContext, useNetlifyLoader };
package/dist/plugin.d.ts CHANGED
@@ -2,11 +2,8 @@ import { FormatEnum } from "sharp";
2
2
  import { Plugin } from "vite";
3
3
 
4
4
  //#region src/plugin/types.d.ts
5
- interface PluginConfig extends Required<Pick<ImageOptions, "placeholder" | "breakpoints" | "format">> {
6
- /** Directory name where processed images will be output during build */
7
- distDir: string;
8
- }
9
- interface ImageOptions {
5
+
6
+ type ImageTransforms = Partial<{
10
7
  /** Target width for the processed image in pixels */
11
8
  width?: number | null;
12
9
  /** Target height for the processed image in pixels */
@@ -37,9 +34,23 @@ interface ImageOptions {
37
34
  normalize?: boolean | null;
38
35
  /** Apply threshold */
39
36
  threshold?: number | null;
37
+ /** Apply quality */
38
+ quality?: number | null;
39
+ }>;
40
+ type PlaceholderTransforms = Omit<ImageTransforms, "placeholder" | "breakpoints"> & {
41
+ show?: boolean;
42
+ };
43
+ type PluginTransforms = Omit<ImageTransforms, "breakpoints">;
44
+ type PluginPlaceholderTransforms = Omit<PlaceholderTransforms, "pl_show">;
45
+ interface PluginConfig {
46
+ distDir: string;
47
+ transforms?: PluginTransforms;
48
+ placeholder?: PluginPlaceholderTransforms;
49
+ breakpoints?: number[];
50
+ pl_show?: boolean;
40
51
  }
41
52
  //#endregion
42
53
  //#region src/plugin/plugin.d.ts
43
54
  declare function ohImage(options?: Partial<PluginConfig>): Plugin;
44
55
  //#endregion
45
- export { type ImageOptions, type PluginConfig, ohImage };
56
+ export { type ImageTransforms as ImageOptions, type PluginConfig, ohImage };
package/dist/plugin.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { basename, dirname, extname, join, parse } from "node:path";
2
2
  import queryString from "query-string";
3
+ import { extname as extname$1 } from "path";
3
4
  import { createHash } from "node:crypto";
4
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
5
6
  import pLimit from "p-limit";
@@ -8,11 +9,7 @@ import sharp from "sharp";
8
9
  //#region src/plugin/utils.ts
9
10
  function queryToOptions(processKey, uri) {
10
11
  const [path, query] = uri.split("?");
11
- if (!query || !path) return {
12
- shouldProcess: false,
13
- path: "",
14
- queryString: ""
15
- };
12
+ if (!query || !path) return { shouldProcess: false };
16
13
  const parsed = queryString.parse(query, {
17
14
  parseBooleans: true,
18
15
  parseNumbers: true,
@@ -32,21 +29,102 @@ function queryToOptions(processKey, uri) {
32
29
  gamma: "number",
33
30
  negate: "boolean",
34
31
  normalize: "boolean",
35
- threshold: "number"
32
+ threshold: "number",
33
+ quality: "number",
34
+ pl_width: "number",
35
+ pl_height: "number",
36
+ pl_format: "string",
37
+ pl_blur: "number",
38
+ pl_flip: "boolean",
39
+ pl_flop: "boolean",
40
+ pl_rotate: "number",
41
+ pl_sharpen: "number",
42
+ pl_median: "number",
43
+ pl_gamma: "number",
44
+ pl_negate: "boolean",
45
+ pl_normalize: "boolean",
46
+ pl_threshold: "number",
47
+ pl_quality: "number",
48
+ pl_show: "boolean"
36
49
  }
37
50
  });
38
- if (processKey in parsed) return {
39
- shouldProcess: true,
40
- options: parsed,
41
- path,
42
- queryString: query
51
+ if (processKey in parsed) {
52
+ const transforms = {};
53
+ const placeholder = {};
54
+ Object.entries(parsed).forEach(([key, value]) => {
55
+ if (key.startsWith("pl_")) {
56
+ const cleanKey = key.replace("pl_", "");
57
+ placeholder[cleanKey] = value;
58
+ } else {
59
+ const transformKey = key;
60
+ transforms[transformKey] = value;
61
+ }
62
+ });
63
+ return {
64
+ shouldProcess: true,
65
+ transforms,
66
+ placeholder,
67
+ path,
68
+ queryString: query
69
+ };
70
+ } else return { shouldProcess: false };
71
+ }
72
+ /** returns ext of file. removes '.' */
73
+ function getCleanExt(filepath) {
74
+ const ext = extname$1(filepath);
75
+ return ext.startsWith(".") ? ext.slice(1) : ext;
76
+ }
77
+ function resolveTransforms(options, defaults, metadata, fileFormat) {
78
+ const resolved = {
79
+ ...defaults,
80
+ ...options
81
+ };
82
+ const width = options?.width ?? defaults?.width ?? metadata.width;
83
+ const height = options?.height ?? defaults?.height ?? metadata.height;
84
+ const format = options?.format ?? defaults?.format ?? fileFormat ?? "webp";
85
+ return {
86
+ ...resolved,
87
+ width,
88
+ height,
89
+ format
90
+ };
91
+ }
92
+ function resolveShowPlaceholder(parsed, config) {
93
+ if (parsed.show || config.pl_show) return true;
94
+ return false;
95
+ }
96
+ function resolvePlaceholderTransforms(options, defaults, metadata) {
97
+ const resolved = {
98
+ ...defaults,
99
+ ...options
100
+ };
101
+ const width = options?.width ?? defaults?.width ?? metadata.width;
102
+ const height = options?.height ?? defaults?.height ?? metadata.height;
103
+ const format = options?.format ?? defaults?.format ?? "webp";
104
+ return {
105
+ ...resolved,
106
+ width,
107
+ height,
108
+ format
43
109
  };
44
- else return {
45
- shouldProcess: false,
46
- path: "",
47
- queryString: query
110
+ }
111
+ function resolveBreakpointTransforms(options, defaults, width) {
112
+ const resolved = {
113
+ ...defaults,
114
+ ...options
115
+ };
116
+ delete resolved["height"];
117
+ delete resolved["width"];
118
+ const format = "webp";
119
+ return {
120
+ ...resolved,
121
+ width,
122
+ format
48
123
  };
49
124
  }
125
+ function resolveBreakpoints(options, config) {
126
+ return options?.breakpoints ?? config.breakpoints;
127
+ }
50
128
 
51
129
  //#endregion
52
130
  //#region src/plugin/file-utils.ts
@@ -96,8 +174,6 @@ function createImageIdentifier(name, hash, dirs) {
96
174
 
97
175
  //#endregion
98
176
  //#region src/plugin/image-entries.ts
99
- const PLACEHOLDER_IMG_SIZE = 8;
100
- const PLACEHOLDER_BLUR_QUALITY = 70;
101
177
  function createImageEntries() {
102
178
  const map = /* @__PURE__ */ new Map();
103
179
  return {
@@ -111,51 +187,10 @@ function createImageEntries() {
111
187
  return map.entries();
112
188
  },
113
189
  createMainEntry(identifier, entry) {
114
- const mainEntry = {
115
- width: entry.width,
116
- height: entry.height,
117
- format: entry.format,
118
- origin: entry.origin,
119
- blur: entry.blur,
120
- flip: entry.flip,
121
- flop: entry.flop,
122
- rotate: entry.rotate,
123
- sharpen: entry.sharpen,
124
- median: entry.median,
125
- gamma: entry.gamma,
126
- negate: entry.negate,
127
- normalize: entry.normalize,
128
- threshold: entry.threshold
129
- };
130
- this.set(identifier, mainEntry);
190
+ this.set(identifier, entry);
131
191
  },
132
- createPlaceholderEntry(identifier, main) {
133
- let placeholderHeight = 0;
134
- let placeholderWidth = 0;
135
- if (main.width >= main.height) {
136
- placeholderWidth = PLACEHOLDER_IMG_SIZE;
137
- placeholderHeight = Math.max(Math.round(main.height / main.width * PLACEHOLDER_IMG_SIZE), 10);
138
- } else {
139
- placeholderWidth = Math.max(Math.round(main.width / main.height * PLACEHOLDER_IMG_SIZE), 10);
140
- placeholderHeight = PLACEHOLDER_IMG_SIZE;
141
- }
142
- const placeholderEntry = {
143
- width: placeholderWidth,
144
- height: placeholderHeight,
145
- format: main.format,
146
- blur: PLACEHOLDER_BLUR_QUALITY,
147
- origin: main.origin,
148
- flip: main.flip,
149
- flop: main.flop,
150
- rotate: main.rotate,
151
- sharpen: main.sharpen,
152
- median: main.median,
153
- gamma: main.gamma,
154
- negate: main.negate,
155
- normalize: main.normalize,
156
- threshold: main.threshold
157
- };
158
- this.set(identifier, placeholderEntry);
192
+ createPlaceholderEntry(identifier, placeholder) {
193
+ this.set(identifier, placeholder);
159
194
  },
160
195
  createSrcSetEntry(identifier, entry) {
161
196
  this.set(identifier, entry);
@@ -171,7 +206,7 @@ async function processImage(path, options) {
171
206
  width: options.width ?? void 0,
172
207
  height: options.height ?? void 0
173
208
  });
174
- if (options.format) processed = processed.toFormat(options.format);
209
+ if (options.format) processed = processed.toFormat(options.format, { quality: options.quality ?? void 0 });
175
210
  if (options.blur) processed = processed.blur(options.blur);
176
211
  if (options.flip) processed = processed.flip();
177
212
  if (options.flop) processed = processed.flop();
@@ -187,7 +222,6 @@ async function processImage(path, options) {
187
222
 
188
223
  //#endregion
189
224
  //#region src/plugin/plugin.ts
190
- const DEFAULT_IMAGE_FORMAT = "webp";
191
225
  const DEFAULT_CONFIGS = {
192
226
  distDir: "oh-images",
193
227
  breakpoints: [
@@ -203,8 +237,13 @@ const DEFAULT_CONFIGS = {
203
237
  1200,
204
238
  1920
205
239
  ],
206
- format: "webp",
207
- placeholder: true
240
+ transforms: { format: "webp" },
241
+ pl_show: true,
242
+ placeholder: {
243
+ quality: 10,
244
+ blur: 50,
245
+ format: "webp"
246
+ }
208
247
  };
209
248
  const PROCESS_KEY = "$oh";
210
249
  const SUPPORTED_IMAGE_FORMATS = /\.(jpe?g|png|webp|avif|gif|svg)(\?.*)?$/i;
@@ -252,107 +291,76 @@ function ohImage(options) {
252
291
  res.end(processed);
253
292
  });
254
293
  },
255
- load: {
256
- filter: { id: SUPPORTED_IMAGE_FORMATS },
257
- async handler(id) {
258
- try {
259
- const parsed = queryToOptions(PROCESS_KEY, id);
260
- if (!parsed.shouldProcess) return null;
261
- const origin = parsed.path;
262
- const { name, ext } = parse(parsed.path);
263
- const metadata = await sharp(parsed.path).metadata();
264
- const hash = await getFileHash(origin, parsed.queryString);
265
- const mergedOptions = {
266
- ...config,
267
- ...parsed.options
294
+ async load(id) {
295
+ if (!SUPPORTED_IMAGE_FORMATS.test(id)) return null;
296
+ try {
297
+ const parsed = queryToOptions(PROCESS_KEY, id);
298
+ if (!parsed.shouldProcess) return null;
299
+ const origin = parsed.path;
300
+ const { name } = parse(parsed.path);
301
+ const metadata = await sharp(parsed.path).metadata();
302
+ const ext = getCleanExt(parsed.path);
303
+ const hash = await getFileHash(origin, parsed.queryString);
304
+ const transforms = resolveTransforms(parsed.transforms, config.transforms, metadata, ext);
305
+ const identifier = createImageIdentifier(name, hash, {
306
+ isBuild,
307
+ devDir: DEV_DIR,
308
+ assetsDir,
309
+ distDir: config.distDir
310
+ });
311
+ const mainIdentifier = identifier.main(transforms.format);
312
+ const mainEntry = {
313
+ ...transforms,
314
+ origin
315
+ };
316
+ imageEntries.createMainEntry(mainIdentifier, mainEntry);
317
+ const src = {
318
+ width: transforms.width,
319
+ height: transforms.height,
320
+ src: mainIdentifier,
321
+ srcSet: ""
322
+ };
323
+ if (resolveShowPlaceholder(parsed.placeholder, config)) {
324
+ const placeholderTransforms = resolvePlaceholderTransforms(parsed.placeholder, config.placeholder, metadata);
325
+ const placeholderEntry = {
326
+ ...placeholderTransforms,
327
+ origin
268
328
  };
269
- const format = mergedOptions.format ?? ext.slice(1);
270
- const identifier = createImageIdentifier(name, hash, {
271
- isBuild,
272
- devDir: DEV_DIR,
273
- assetsDir,
274
- distDir: config.distDir
275
- });
276
- const mainIdentifier = identifier.main(format);
277
- imageEntries.createMainEntry(mainIdentifier, {
278
- width: mergedOptions.width,
279
- height: mergedOptions.height,
280
- format: mergedOptions.format,
281
- origin,
282
- blur: mergedOptions.blur,
283
- flip: mergedOptions.flip,
284
- flop: mergedOptions.flop,
285
- rotate: mergedOptions.rotate,
286
- sharpen: mergedOptions.sharpen,
287
- median: mergedOptions.median,
288
- gamma: mergedOptions.gamma,
289
- negate: mergedOptions.negate,
290
- normalize: mergedOptions.normalize,
291
- threshold: mergedOptions.threshold
292
- });
293
- const src = {
294
- width: metadata.width,
295
- height: metadata.height,
296
- src: mainIdentifier,
297
- srcSet: ""
298
- };
299
- if (mergedOptions.placeholder) {
300
- const placeholderIdentifier = identifier.placeholder(DEFAULT_IMAGE_FORMAT);
301
- imageEntries.createPlaceholderEntry(placeholderIdentifier, {
302
- width: metadata.width,
303
- height: metadata.height,
304
- format: DEFAULT_IMAGE_FORMAT,
305
- origin,
306
- flip: mergedOptions.flip,
307
- flop: mergedOptions.flop,
308
- rotate: mergedOptions.rotate,
309
- sharpen: mergedOptions.sharpen,
310
- median: mergedOptions.median,
311
- gamma: mergedOptions.gamma,
312
- negate: mergedOptions.negate,
313
- normalize: mergedOptions.normalize,
314
- threshold: mergedOptions.threshold
315
- });
316
- src.placeholder = placeholderIdentifier;
317
- }
318
- if (mergedOptions.breakpoints) {
319
- const srcSets = [];
320
- for (const breakpoint of mergedOptions.breakpoints) {
321
- const srcSetIdentifier = identifier.srcSet(DEFAULT_IMAGE_FORMAT, breakpoint);
322
- imageEntries.createSrcSetEntry(srcSetIdentifier, {
323
- width: breakpoint,
324
- format: DEFAULT_IMAGE_FORMAT,
325
- origin,
326
- blur: mergedOptions.blur,
327
- flip: mergedOptions.flip,
328
- flop: mergedOptions.flop,
329
- rotate: mergedOptions.rotate,
330
- sharpen: mergedOptions.sharpen,
331
- median: mergedOptions.median,
332
- gamma: mergedOptions.gamma,
333
- negate: mergedOptions.negate,
334
- normalize: mergedOptions.normalize,
335
- threshold: mergedOptions.threshold
336
- });
337
- srcSets.push(`${srcSetIdentifier} ${breakpoint}w`);
338
- }
339
- src.srcSet = srcSets.join(", ");
329
+ const placeholderIdentifier = identifier.placeholder(placeholderTransforms.format);
330
+ imageEntries.createPlaceholderEntry(placeholderIdentifier, placeholderEntry);
331
+ src.placeholder = placeholderIdentifier;
332
+ }
333
+ const breakpoints = resolveBreakpoints(transforms, config);
334
+ if (breakpoints) {
335
+ const srcSets = [];
336
+ for (const breakpoint of breakpoints) {
337
+ const breakpointTransforms = resolveBreakpointTransforms(parsed.transforms, config.transforms, breakpoint);
338
+ const srcSetIdentifier = identifier.srcSet(breakpointTransforms.format, breakpoint);
339
+ const breakpointEntry = {
340
+ ...breakpointTransforms,
341
+ origin
342
+ };
343
+ imageEntries.createSrcSetEntry(srcSetIdentifier, breakpointEntry);
344
+ srcSets.push(`${srcSetIdentifier} ${breakpoint}w`);
340
345
  }
341
- return `
346
+ src.srcSet = srcSets.join(", ");
347
+ }
348
+ return `
342
349
  import { __imageFactory } from "@lonik/oh-image/react";
343
350
 
344
351
  export default __imageFactory(${JSON.stringify({
345
- width: src.width,
346
- height: src.height,
347
- src: src.src,
348
- srcSet: src.srcSet,
349
- placeholder: src.placeholder
350
- })})
352
+ width: src.width,
353
+ height: src.height,
354
+ src: src.src,
355
+ srcSet: src.srcSet,
356
+ placeholder: src.placeholder
357
+ })})
351
358
  `;
352
- } catch (err) {
353
- console.error(`Couldn't load image with id: ${id} error:${err}`);
354
- return null;
355
- }
359
+ } catch (err) {
360
+ if (err instanceof Error) {
361
+ console.error(`Couldn't load image: ${id}. Error: ${err.message}`);
362
+ this.error(err.message);
363
+ } else this.error(String(err));
356
364
  }
357
365
  },
358
366
  async writeBundle() {
package/dist/react.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { n as ImageLoaderOptions, r as ImageProps, t as ImageLoader } from "./types-BEgZ3W30.js";
2
- import { a as Image, i as __imageFactory, n as useImageContext, r as useImgLoaded, t as ImageProvider } from "./index-CTQWBPPA.js";
2
+ import { a as Image, i as __imageFactory, n as useImageContext, r as useImgLoaded, t as ImageProvider } from "./index-5MpToMnk.js";
3
3
  export { Image, ImageLoader, ImageLoaderOptions, ImageProps, ImageProvider, __imageFactory, useImageContext, useImgLoaded };
@@ -1,7 +1,7 @@
1
1
  import { n as ImageLoaderOptions } from "./types-BEgZ3W30.js";
2
- import "./index-CTQWBPPA.js";
2
+ import "./index-5MpToMnk.js";
3
3
  import { n as BaseLoaderOptions, t as BaseGlobalLoaderOptions } from "./base-loader-options-DCLkYppY.js";
4
- import * as react_jsx_runtime2 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
5
5
 
6
6
  //#region src/loaders/wordpress/wordpress-options.d.ts
7
7
  type WordpressTransforms = Partial<{
@@ -31,6 +31,6 @@ declare const useWordpressContext: () => WordpressGlobalOptions, WordpressLoader
31
31
  ...props
32
32
  }: {
33
33
  children: React.ReactNode;
34
- } & Partial<WordpressGlobalOptions>) => react_jsx_runtime2.JSX.Element, useWordpressLoader: (options?: WordpressGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
34
+ } & Partial<WordpressGlobalOptions>) => react_jsx_runtime1.JSX.Element, useWordpressLoader: (options?: WordpressGlobalOptions | undefined) => (() => undefined) | ((imageOptions: ImageLoaderOptions) => string);
35
35
  //#endregion
36
36
  export { WordpressGlobalOptions, WordpressLoaderProvider, WordpressOptions, WordpressTransforms, useWordpressContext, useWordpressLoader };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lonik/oh-image",
3
3
  "type": "module",
4
- "version": "2.8.0",
4
+ "version": "2.10.0",
5
5
  "description": "A React component library for optimized image handling.",
6
6
  "author": "Luka Onikadze <lukonik@gmail.com>",
7
7
  "license": "MIT",