pdf-catalog-generator 3.1.2 → 3.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/README.md CHANGED
@@ -175,6 +175,7 @@ Generates a PDF catalog from the provided configuration.
175
175
  - `companyName` (string): Your company name
176
176
  - `companyLogo` (string | null, optional): Logo URL or base64 string
177
177
  - `template` (TemplateType, optional): Template to use (default: 'template1')
178
+ - `imageOptimization` (ImageOptimizationOptions, optional): Resize/compress supported remote image URLs before rendering. Enabled by default.
178
179
 
179
180
  **Returns:** `Promise<Uint8Array>` - PDF file as Uint8Array (works in both Node.js and browser)
180
181
 
@@ -288,6 +289,16 @@ This library is **completely schema-free** - no fields are mandatory! You can us
288
289
  interface ProductData {
289
290
  [key: string]: string | number | boolean | null | undefined;
290
291
  }
292
+
293
+ interface ImageOptimizationOptions {
294
+ enabled?: boolean;
295
+ maxWidth?: number;
296
+ maxHeight?: number;
297
+ quality?: number;
298
+ logoMaxWidth?: number;
299
+ logoMaxHeight?: number;
300
+ logoQuality?: number;
301
+ }
291
302
  ```
292
303
 
293
304
  **Dynamic Field Rendering:**
package/dist/index.d.mts CHANGED
@@ -5,11 +5,21 @@ interface ProductData {
5
5
  [key: string]: string | number | boolean | null | undefined;
6
6
  }
7
7
  type TemplateType = 'template1' | 'template2' | 'template3' | 'template4' | 'template5' | 'template6';
8
+ interface ImageOptimizationOptions {
9
+ enabled?: boolean;
10
+ maxWidth?: number;
11
+ maxHeight?: number;
12
+ quality?: number;
13
+ logoMaxWidth?: number;
14
+ logoMaxHeight?: number;
15
+ logoQuality?: number;
16
+ }
8
17
  interface CatalogConfig {
9
18
  products: ProductData[];
10
19
  companyLogo?: string | null;
11
20
  companyName: string;
12
21
  template?: TemplateType;
22
+ imageOptimization?: ImageOptimizationOptions;
13
23
  }
14
24
  interface TemplateProps {
15
25
  companyLogo?: string | null;
package/dist/index.d.ts CHANGED
@@ -5,11 +5,21 @@ interface ProductData {
5
5
  [key: string]: string | number | boolean | null | undefined;
6
6
  }
7
7
  type TemplateType = 'template1' | 'template2' | 'template3' | 'template4' | 'template5' | 'template6';
8
+ interface ImageOptimizationOptions {
9
+ enabled?: boolean;
10
+ maxWidth?: number;
11
+ maxHeight?: number;
12
+ quality?: number;
13
+ logoMaxWidth?: number;
14
+ logoMaxHeight?: number;
15
+ logoQuality?: number;
16
+ }
8
17
  interface CatalogConfig {
9
18
  products: ProductData[];
10
19
  companyLogo?: string | null;
11
20
  companyName: string;
12
21
  template?: TemplateType;
22
+ imageOptimization?: ImageOptimizationOptions;
13
23
  }
14
24
  interface TemplateProps {
15
25
  companyLogo?: string | null;
package/dist/index.js CHANGED
@@ -25,29 +25,6 @@ function _interopNamespace(e) {
25
25
  var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
26
26
 
27
27
  // src/generator.tsx
28
- var styles = renderer.StyleSheet.create({
29
- wrapper: {
30
- position: "absolute",
31
- bottom: 6,
32
- right: 10,
33
- flexDirection: "row",
34
- alignItems: "center",
35
- opacity: 0.5
36
- },
37
- label: {
38
- fontSize: 6.5,
39
- color: "#666666",
40
- letterSpacing: 0.2
41
- },
42
- link: {
43
- fontSize: 6.5,
44
- color: "#666666",
45
- textDecoration: "none",
46
- letterSpacing: 0.2
47
- }
48
- });
49
- var PoweredByTeziApp = () => /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles.wrapper, fixed: true, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Link, { style: styles.link, src: "https://teziapp.com", children: "Powered by Tezi App" }) });
50
- var PoweredByTeziApp_default = PoweredByTeziApp;
51
28
 
52
29
  // src/utils/fieldHelpers.ts
53
30
  function formatFieldName(fieldName) {
@@ -229,12 +206,12 @@ var dynamicFieldStyles = renderer.StyleSheet.create({
229
206
  flexShrink: 1
230
207
  }
231
208
  });
232
- function renderDynamicFields(fields, styles9) {
209
+ function renderDynamicFields(fields, styles8) {
233
210
  if (fields.length === 0) return null;
234
- const containerStyle = styles9?.container || { marginBottom: 8 };
235
- const rowStyle = styles9?.row || dynamicFieldStyles.detailRow;
236
- const labelStyle = styles9?.label || dynamicFieldStyles.detailLabel;
237
- const valueStyle = styles9?.value || dynamicFieldStyles.detailValue;
211
+ const containerStyle = styles8?.container || { marginBottom: 8 };
212
+ const rowStyle = styles8?.row || dynamicFieldStyles.detailRow;
213
+ const labelStyle = styles8?.label || dynamicFieldStyles.detailLabel;
214
+ const valueStyle = styles8?.value || dynamicFieldStyles.detailValue;
238
215
  return /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: containerStyle, children: fields.map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: rowStyle, children: [
239
216
  /* @__PURE__ */ jsxRuntime.jsxs(renderer.Text, { style: labelStyle, children: [
240
217
  formatFieldName(key),
@@ -278,7 +255,7 @@ function mergeTemplateConfig(config = {}) {
278
255
  ...config
279
256
  };
280
257
  }
281
- var styles2 = renderer.StyleSheet.create({
258
+ var styles = renderer.StyleSheet.create({
282
259
  productContainer: {
283
260
  flexDirection: "row",
284
261
  flexWrap: "wrap",
@@ -342,27 +319,27 @@ var styles2 = renderer.StyleSheet.create({
342
319
  }
343
320
  });
344
321
  var Template1 = ({ products }) => {
345
- return /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles2.productContainer, children: products.map((product, index) => {
322
+ return /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles.productContainer, children: products.map((product, index) => {
346
323
  const fields = extractProductFields(product);
347
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles2.productSection, children: [
348
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles2.image, src: fields.imageUrl }),
349
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles2.productTitleBox, children: [
350
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles2.productTitle, children: fields.title }),
351
- renderRating(fields.rating, styles2.productRate)
324
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles.productSection, children: [
325
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles.image, src: fields.imageUrl }),
326
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles.productTitleBox, children: [
327
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles.productTitle, children: fields.title }),
328
+ renderRating(fields.rating, styles.productRate)
352
329
  ] }),
353
- fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles2.productDescription, children: fields.description }),
330
+ fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles.productDescription, children: fields.description }),
354
331
  renderDynamicFields(fields.dynamicFields),
355
332
  renderBuyButton(
356
333
  fields.link,
357
- styles2.buyButton,
334
+ styles.buyButton,
358
335
  "Buy Now",
359
- renderPrice(fields.price, styles2.productPrice)
336
+ renderPrice(fields.price, styles.productPrice)
360
337
  )
361
338
  ] }, index);
362
339
  }) });
363
340
  };
364
341
  var Template1_default = Template1;
365
- var styles3 = renderer.StyleSheet.create({
342
+ var styles2 = renderer.StyleSheet.create({
366
343
  productContainer: {
367
344
  flexDirection: "row",
368
345
  flexWrap: "wrap",
@@ -439,14 +416,14 @@ var styles3 = renderer.StyleSheet.create({
439
416
  }
440
417
  });
441
418
  var Template2 = ({ products }) => {
442
- return /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles3.productContainer, children: products.map((product, index) => {
419
+ return /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles2.productContainer, children: products.map((product, index) => {
443
420
  const fields = extractProductFields(product);
444
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles3.productSection, children: [
445
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles3.productSectionImage, children: [
446
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles3.image, src: fields.imageUrl }),
447
- renderRating(fields.rating, styles3.productRate)
421
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles2.productSection, children: [
422
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles2.productSectionImage, children: [
423
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles2.image, src: fields.imageUrl }),
424
+ renderRating(fields.rating, styles2.productRate)
448
425
  ] }),
449
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles3.productSectionText, children: [
426
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles2.productSectionText, children: [
450
427
  /* @__PURE__ */ jsxRuntime.jsxs(
451
428
  renderer.View,
452
429
  {
@@ -456,20 +433,20 @@ var Template2 = ({ products }) => {
456
433
  justifyContent: "space-between"
457
434
  },
458
435
  children: [
459
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles3.productTitle, children: fields.title }),
460
- renderPrice(fields.price, styles3.productPrice)
436
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles2.productTitle, children: fields.title }),
437
+ renderPrice(fields.price, styles2.productPrice)
461
438
  ]
462
439
  }
463
440
  ),
464
- fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles3.productDescription, children: fields.description }),
441
+ fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles2.productDescription, children: fields.description }),
465
442
  renderDynamicFields(fields.dynamicFields),
466
- renderBuyButton(fields.link, styles3.buyButton)
443
+ renderBuyButton(fields.link, styles2.buyButton)
467
444
  ] })
468
445
  ] }, index);
469
446
  }) });
470
447
  };
471
448
  var Template2_default = Template2;
472
- var styles4 = renderer.StyleSheet.create({
449
+ var styles3 = renderer.StyleSheet.create({
473
450
  productSection: {
474
451
  width: "100%",
475
452
  height: "100vh",
@@ -549,10 +526,10 @@ var compactDynamicFieldStyles = renderer.StyleSheet.create({
549
526
  var Template3 = ({ products }) => {
550
527
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: products.map((product, index) => {
551
528
  const fields = extractProductFields(product, { maxDynamicFields: 5 });
552
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles4.productSection, children: [
553
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles4.image, src: fields.imageUrl }),
554
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles4.productDetailsBox, children: [
555
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles4.productTitle, children: fields.title }),
529
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles3.productSection, children: [
530
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles3.image, src: fields.imageUrl }),
531
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles3.productDetailsBox, children: [
532
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles3.productTitle, children: fields.title }),
556
533
  /* @__PURE__ */ jsxRuntime.jsxs(
557
534
  renderer.View,
558
535
  {
@@ -562,25 +539,25 @@ var Template3 = ({ products }) => {
562
539
  justifyContent: "space-between"
563
540
  },
564
541
  children: [
565
- renderPrice(fields.price, styles4.productPrice),
566
- renderRating(fields.rating, styles4.productRate)
542
+ renderPrice(fields.price, styles3.productPrice),
543
+ renderRating(fields.rating, styles3.productRate)
567
544
  ]
568
545
  }
569
546
  ),
570
- fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles4.productDescription, children: fields.description }),
547
+ fields.description && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles3.productDescription, children: fields.description }),
571
548
  renderDynamicFields(fields.dynamicFields, {
572
549
  row: compactDynamicFieldStyles.detailRow,
573
550
  label: compactDynamicFieldStyles.detailLabel,
574
551
  value: compactDynamicFieldStyles.detailValue
575
552
  }),
576
- renderBuyButton(fields.link, styles4.buyButton)
553
+ renderBuyButton(fields.link, styles3.buyButton)
577
554
  ] }),
578
555
  /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { break: true })
579
556
  ] }, index);
580
557
  }) });
581
558
  };
582
559
  var Template3_default = Template3;
583
- var styles5 = renderer.StyleSheet.create({
560
+ var styles4 = renderer.StyleSheet.create({
584
561
  page: {
585
562
  width: "100%",
586
563
  height: "100%",
@@ -677,21 +654,21 @@ var Template4 = ({
677
654
  )
678
655
  );
679
656
  const fields = extractProductFields(product);
680
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.page, children: [
681
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.header, children: [
682
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles5.companyName, children: companyName || "" }),
683
- companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles5.brandLogo, src: companyLogo })
657
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles4.page, children: [
658
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles4.header, children: [
659
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles4.companyName, children: companyName || "" }),
660
+ companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles4.brandLogo, src: companyLogo })
684
661
  ] }),
685
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.productContainer, children: [
686
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles5.productImage, src: fields.imageUrl }),
687
- allFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles5.detailsBox, children: renderFieldsInColumns(allFields) })
662
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles4.productContainer, children: [
663
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles4.productImage, src: fields.imageUrl }),
664
+ allFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles4.detailsBox, children: renderFieldsInColumns(allFields) })
688
665
  ] }),
689
666
  /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { break: true })
690
667
  ] }, index);
691
668
  }) });
692
669
  };
693
670
  var Template4_default = Template4;
694
- var styles6 = renderer.StyleSheet.create({
671
+ var styles5 = renderer.StyleSheet.create({
695
672
  page: {
696
673
  width: "100%",
697
674
  height: "100%",
@@ -804,22 +781,22 @@ var Template5 = ({
804
781
  const { imageUrl, title, dynamicFields } = extractProductFields(product);
805
782
  const image2Url = getImage2Url(product);
806
783
  const secondImage = image2Url || imageUrl;
807
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.page, children: [
808
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.header, children: [
809
- companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.logo, src: companyLogo }),
810
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles6.companyName, children: companyName })
784
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.page, children: [
785
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.header, children: [
786
+ companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles5.logo, src: companyLogo }),
787
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles5.companyName, children: companyName })
811
788
  ] }),
812
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.contentContainer, children: [
813
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.imageSection, children: [
814
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles6.imageWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.productImage, src: imageUrl }) }),
815
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles6.imageWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.productImage, src: secondImage }) })
789
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.contentContainer, children: [
790
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.imageSection, children: [
791
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles5.imageWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles5.productImage, src: imageUrl }) }),
792
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles5.imageWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles5.productImage, src: secondImage }) })
816
793
  ] }),
817
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.detailsSection, children: [
818
- title && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles6.productTitle, children: title }),
819
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles6.dynamicFieldsContainer, children: renderDynamicFields(dynamicFields, {
820
- row: styles6.detailRow,
821
- label: styles6.detailLabel,
822
- value: styles6.detailValue
794
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles5.detailsSection, children: [
795
+ title && /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles5.productTitle, children: title }),
796
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles5.dynamicFieldsContainer, children: renderDynamicFields(dynamicFields, {
797
+ row: styles5.detailRow,
798
+ label: styles5.detailLabel,
799
+ value: styles5.detailValue
823
800
  }) })
824
801
  ] })
825
802
  ] }),
@@ -828,7 +805,7 @@ var Template5 = ({
828
805
  }) });
829
806
  };
830
807
  var Template5_default = Template5;
831
- var styles7 = renderer.StyleSheet.create({
808
+ var styles6 = renderer.StyleSheet.create({
832
809
  page: {
833
810
  width: "100%",
834
811
  height: "100%",
@@ -969,26 +946,26 @@ var Template6 = ({
969
946
  const { imageUrl, title, dynamicFields } = extractProductFields(product);
970
947
  const image2Url = getImage2Url2(product);
971
948
  const secondImage = image2Url || imageUrl;
972
- return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.page, children: [
973
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.leftColumn, children: [
974
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles7.imageFull, src: imageUrl }),
975
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.specsOverlay, children: [
976
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.specsHeader, children: [
977
- companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles7.miniLogo, src: companyLogo }),
978
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles7.designNumber, children: title || "Specifications" })
949
+ return /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.page, children: [
950
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.leftColumn, children: [
951
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.imageFull, src: imageUrl }),
952
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.specsOverlay, children: [
953
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.specsHeader, children: [
954
+ companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.miniLogo, src: companyLogo }),
955
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles6.designNumber, children: title || "Specifications" })
979
956
  ] }),
980
957
  renderDynamicFields(dynamicFields, {
981
- row: styles7.fieldRow,
982
- label: styles7.fieldLabel,
983
- value: styles7.fieldValue
958
+ row: styles6.fieldRow,
959
+ label: styles6.fieldLabel,
960
+ value: styles6.fieldValue
984
961
  })
985
962
  ] })
986
963
  ] }),
987
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.rightColumn, children: [
988
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles7.rightImageContainer, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles7.rightImage, src: secondImage }) }),
989
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles7.footer, children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.footerContent, children: [
990
- companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles7.footerLogo, src: companyLogo }),
991
- /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles7.footerText, children: companyName })
964
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.rightColumn, children: [
965
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles6.rightImageContainer, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.rightImage, src: secondImage }) }),
966
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles6.footer, children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles6.footerContent, children: [
967
+ companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles6.footerLogo, src: companyLogo }),
968
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles6.footerText, children: companyName })
992
969
  ] }) })
993
970
  ] }),
994
971
  /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { break: true })
@@ -996,7 +973,7 @@ var Template6 = ({
996
973
  }) });
997
974
  };
998
975
  var Template6_default = Template6;
999
- var styles8 = renderer.StyleSheet.create({
976
+ var styles7 = renderer.StyleSheet.create({
1000
977
  page: {
1001
978
  flexDirection: "column",
1002
979
  backgroundColor: "#FFFFFF"
@@ -1028,8 +1005,137 @@ renderer.Font.registerEmojiSource({
1028
1005
  format: "png",
1029
1006
  url: "https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/"
1030
1007
  });
1008
+ function normalizeImageSource(imageSource) {
1009
+ const trimmedImageSource = imageSource.trim();
1010
+ if (trimmedImageSource.startsWith("data:")) {
1011
+ return trimmedImageSource;
1012
+ }
1013
+ if (trimmedImageSource.startsWith("http://") || trimmedImageSource.startsWith("https://")) {
1014
+ return trimmedImageSource;
1015
+ }
1016
+ let mimeType = "image/png";
1017
+ const base64Start = trimmedImageSource.substring(0, 20).toLowerCase();
1018
+ if (base64Start.includes("ivborw0kggo") || trimmedImageSource.startsWith("iVBORw0KGgo")) {
1019
+ mimeType = "image/png";
1020
+ } else if (base64Start.includes("/9j/4aaq") || trimmedImageSource.startsWith("/9j/4AAQ")) {
1021
+ mimeType = "image/jpeg";
1022
+ } else if (base64Start.includes("r0lgodlh") || trimmedImageSource.startsWith("R0lGODlh")) {
1023
+ mimeType = "image/gif";
1024
+ } else if (base64Start.includes("uklgr") || trimmedImageSource.startsWith("UklGR")) {
1025
+ mimeType = "image/webp";
1026
+ }
1027
+ return `data:${mimeType};base64,${trimmedImageSource}`;
1028
+ }
1029
+ var IMAGE_FIELD_NAMES_LOWER = /* @__PURE__ */ new Set([
1030
+ "image",
1031
+ "imageurl",
1032
+ "img",
1033
+ "photo",
1034
+ "picture",
1035
+ "image2",
1036
+ "imageurl2",
1037
+ "img2",
1038
+ "photo2",
1039
+ "picture2"
1040
+ ]);
1041
+ var DEFAULT_IMAGE_OPTIMIZATION = {
1042
+ enabled: true,
1043
+ maxWidth: 900,
1044
+ maxHeight: 900,
1045
+ quality: 70,
1046
+ logoMaxWidth: 400,
1047
+ logoMaxHeight: 400,
1048
+ logoQuality: 70
1049
+ };
1050
+ function getImageOptimizationOptions(options) {
1051
+ return {
1052
+ ...DEFAULT_IMAGE_OPTIMIZATION,
1053
+ ...options
1054
+ };
1055
+ }
1056
+ function getNumericSearchParam(url, key) {
1057
+ const rawValue = url.searchParams.get(key);
1058
+ if (rawValue === null || rawValue.trim() === "") {
1059
+ return null;
1060
+ }
1061
+ const numericValue = Number(rawValue);
1062
+ return Number.isFinite(numericValue) ? numericValue : null;
1063
+ }
1064
+ function optimizeImageUrl(imageSource, options, imageKind) {
1065
+ if (!options.enabled) {
1066
+ return normalizeImageSource(imageSource);
1067
+ }
1068
+ const normalizedSource = normalizeImageSource(imageSource);
1069
+ if (!normalizedSource.startsWith("http://") && !normalizedSource.startsWith("https://")) {
1070
+ return normalizedSource;
1071
+ }
1072
+ let url;
1073
+ try {
1074
+ url = new URL(normalizedSource);
1075
+ } catch {
1076
+ return normalizedSource;
1077
+ }
1078
+ const hostname = url.hostname.toLowerCase();
1079
+ const isImgixStyleHost = hostname.includes("unsplash.com") || hostname.includes("imgix.net") || hostname.includes("builder.io") || hostname.includes("sanity.io");
1080
+ if (!isImgixStyleHost) {
1081
+ return normalizedSource;
1082
+ }
1083
+ const maxWidth = imageKind === "logo" ? options.logoMaxWidth : options.maxWidth;
1084
+ const maxHeight = imageKind === "logo" ? options.logoMaxHeight : options.maxHeight;
1085
+ const quality = imageKind === "logo" ? options.logoQuality : options.quality;
1086
+ url.searchParams.set("auto", "format,compress");
1087
+ url.searchParams.set("fit", "max");
1088
+ const currentWidth = getNumericSearchParam(url, "w");
1089
+ if (currentWidth === null || currentWidth > maxWidth) {
1090
+ url.searchParams.set("w", String(maxWidth));
1091
+ }
1092
+ const currentHeight = getNumericSearchParam(url, "h");
1093
+ if (currentHeight === null || currentHeight > maxHeight) {
1094
+ url.searchParams.set("h", String(maxHeight));
1095
+ }
1096
+ const currentQuality = getNumericSearchParam(url, "q");
1097
+ if (currentQuality === null || currentQuality > quality) {
1098
+ url.searchParams.set("q", String(quality));
1099
+ }
1100
+ return url.toString();
1101
+ }
1102
+ function normalizeProductImages(products, options) {
1103
+ const imageCache = /* @__PURE__ */ new Map();
1104
+ const normalizeCachedImage = (value, imageKind) => {
1105
+ const cacheKey = `${imageKind}:${value}`;
1106
+ const cachedValue = imageCache.get(cacheKey);
1107
+ if (cachedValue) {
1108
+ return cachedValue;
1109
+ }
1110
+ const normalizedValue = optimizeImageUrl(value, options, imageKind);
1111
+ imageCache.set(cacheKey, normalizedValue);
1112
+ return normalizedValue;
1113
+ };
1114
+ return products.map((product) => {
1115
+ const normalizedProduct = { ...product };
1116
+ for (const [key, value] of Object.entries(product)) {
1117
+ if (typeof value === "string" && value.trim() !== "" && IMAGE_FIELD_NAMES_LOWER.has(key.toLowerCase())) {
1118
+ normalizedProduct[key] = normalizeCachedImage(value, "product");
1119
+ }
1120
+ }
1121
+ return normalizedProduct;
1122
+ });
1123
+ }
1124
+ async function renderPdfToUint8Array(doc) {
1125
+ const isNodeRuntime = typeof process !== "undefined" && typeof process.versions?.node === "string";
1126
+ if (isNodeRuntime && typeof renderer.renderToBuffer === "function") {
1127
+ const buffer = await renderer.renderToBuffer(doc);
1128
+ return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1129
+ }
1130
+ const blob = await renderer.pdf(doc).toBlob();
1131
+ const arrayBuffer = await blob.arrayBuffer();
1132
+ return new Uint8Array(arrayBuffer);
1133
+ }
1031
1134
  async function generateProductCatalog(config) {
1032
- const { products, companyLogo, companyName, template = "template1" } = config;
1135
+ const { products, companyLogo, companyName, template = "template1", imageOptimization } = config;
1136
+ const optimizationOptions = getImageOptimizationOptions(imageOptimization);
1137
+ const normalizedProducts = normalizeProductImages(products, optimizationOptions);
1138
+ const normalizedCompanyLogo = companyLogo ? optimizeImageUrl(companyLogo, optimizationOptions, "logo") : companyLogo;
1033
1139
  let TemplateComponent;
1034
1140
  switch (template) {
1035
1141
  case "template1":
@@ -1054,49 +1160,36 @@ async function generateProductCatalog(config) {
1054
1160
  TemplateComponent = Template1_default;
1055
1161
  }
1056
1162
  if (template === "template4") {
1057
- const doc2 = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.Page, { size: "A4", style: styles8.page, children: [
1058
- /* @__PURE__ */ jsxRuntime.jsx(
1059
- Template4_default,
1060
- {
1061
- products,
1062
- companyLogo,
1063
- companyName
1064
- }
1065
- ),
1066
- /* @__PURE__ */ jsxRuntime.jsx(PoweredByTeziApp_default, {})
1067
- ] }) });
1068
- const blob2 = await renderer.pdf(doc2).toBlob();
1069
- const arrayBuffer2 = await blob2.arrayBuffer();
1070
- return new Uint8Array(arrayBuffer2);
1163
+ const doc2 = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Page, { size: "A4", style: styles7.page, children: /* @__PURE__ */ jsxRuntime.jsx(
1164
+ Template4_default,
1165
+ {
1166
+ products: normalizedProducts,
1167
+ companyLogo: normalizedCompanyLogo,
1168
+ companyName
1169
+ }
1170
+ ) }) });
1171
+ return renderPdfToUint8Array(doc2);
1071
1172
  }
1072
1173
  if (template === "template5" || template === "template6") {
1073
1174
  const Template = template === "template5" ? Template5_default : Template6_default;
1074
- const doc2 = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.Page, { size: "A4", orientation: "landscape", style: styles8.page, children: [
1075
- /* @__PURE__ */ jsxRuntime.jsx(
1076
- Template,
1077
- {
1078
- products,
1079
- companyLogo,
1080
- companyName
1081
- }
1082
- ),
1083
- /* @__PURE__ */ jsxRuntime.jsx(PoweredByTeziApp_default, {})
1084
- ] }) });
1085
- const blob2 = await renderer.pdf(doc2).toBlob();
1086
- const arrayBuffer2 = await blob2.arrayBuffer();
1087
- return new Uint8Array(arrayBuffer2);
1175
+ const doc2 = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Page, { size: "A4", orientation: "landscape", style: styles7.page, children: /* @__PURE__ */ jsxRuntime.jsx(
1176
+ Template,
1177
+ {
1178
+ products: normalizedProducts,
1179
+ companyLogo: normalizedCompanyLogo,
1180
+ companyName
1181
+ }
1182
+ ) }) });
1183
+ return renderPdfToUint8Array(doc2);
1088
1184
  }
1089
- const doc = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.Page, { size: "A4", style: styles8.page, children: [
1090
- /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles8.header, children: [
1091
- companyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles8.logoSection, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles8.logo, src: companyLogo }) }),
1092
- /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles8.storeNameSection, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles8.storeName, children: companyName }) })
1185
+ const doc = /* @__PURE__ */ jsxRuntime.jsx(renderer.Document, { children: /* @__PURE__ */ jsxRuntime.jsxs(renderer.Page, { size: "A4", style: styles7.page, children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsxs(renderer.View, { style: styles7.header, children: [
1187
+ normalizedCompanyLogo && /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles7.logoSection, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Image, { style: styles7.logo, src: normalizedCompanyLogo }) }),
1188
+ /* @__PURE__ */ jsxRuntime.jsx(renderer.View, { style: styles7.storeNameSection, children: /* @__PURE__ */ jsxRuntime.jsx(renderer.Text, { style: styles7.storeName, children: companyName }) })
1093
1189
  ] }),
1094
- /* @__PURE__ */ jsxRuntime.jsx(TemplateComponent, { products }),
1095
- /* @__PURE__ */ jsxRuntime.jsx(PoweredByTeziApp_default, {})
1190
+ /* @__PURE__ */ jsxRuntime.jsx(TemplateComponent, { products: normalizedProducts })
1096
1191
  ] }) });
1097
- const blob = await renderer.pdf(doc).toBlob();
1098
- const arrayBuffer = await blob.arrayBuffer();
1099
- return new Uint8Array(arrayBuffer);
1192
+ return renderPdfToUint8Array(doc);
1100
1193
  }
1101
1194
  function parseExcelFile(buffer) {
1102
1195
  const workbook = XLSX__namespace.read(buffer, {