@json-to-office/core-docx 4.5.0 → 5.4.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.
@@ -403,17 +403,38 @@ var init_devportal_docx_theme = __esm({
403
403
  accent5: "#8A9299",
404
404
  accent6: "#E8A18D"
405
405
  },
406
+ palette: {
407
+ rule: "#D8D5D1",
408
+ textMuted: "#737373",
409
+ onPrimary: "#FFFFFF",
410
+ surfaceInverse: "#12191F",
411
+ positive: "#2E7D4F",
412
+ negative: "#B42318",
413
+ chart: ["accent", "primary", "accent4", "accent5", "accent6", "rule"]
414
+ },
406
415
  fonts: {
407
- heading: { family: "Helvetica", size: 23 },
408
- body: { family: "Helvetica", size: 9.5 },
409
- mono: { family: "Courier New", size: 10 },
410
- light: { family: "Helvetica", size: 23 }
416
+ heading: {
417
+ family: "Helvetica",
418
+ size: 23
419
+ },
420
+ body: {
421
+ family: "Helvetica",
422
+ size: 9.5
423
+ },
424
+ mono: {
425
+ family: "Courier New",
426
+ size: 10
427
+ },
428
+ light: {
429
+ family: "Helvetica",
430
+ size: 23
431
+ }
411
432
  },
412
433
  page: {
413
434
  size: "A4",
414
435
  margins: {
415
- top: 1440,
416
- bottom: 1440,
436
+ top: 1080,
437
+ bottom: 1080,
417
438
  left: 1080,
418
439
  right: 1080,
419
440
  header: 720,
@@ -421,13 +442,183 @@ var init_devportal_docx_theme = __esm({
421
442
  gutter: 0
422
443
  }
423
444
  },
445
+ typography: {
446
+ roles: {
447
+ eyebrow: {
448
+ face: "heading",
449
+ size: 8,
450
+ weight: 700,
451
+ case: "upper",
452
+ tracking: 10,
453
+ color: "accent",
454
+ spaceAfter: 4
455
+ },
456
+ display: {
457
+ face: "heading",
458
+ weight: 700,
459
+ color: "primary",
460
+ lineHeight: 1.05,
461
+ spaceAfter: 8,
462
+ tracking: -2
463
+ },
464
+ stat: {
465
+ face: "heading",
466
+ weight: 700,
467
+ color: "accent",
468
+ lineHeight: 1
469
+ },
470
+ quote: {
471
+ face: "body",
472
+ color: "textSecondary",
473
+ lineHeight: 1.3
474
+ },
475
+ label: {
476
+ face: "body",
477
+ size: 9,
478
+ weight: 700,
479
+ color: "textSecondary",
480
+ case: "upper",
481
+ tracking: 6
482
+ },
483
+ footer: {
484
+ face: "body",
485
+ size: 8,
486
+ color: "textMuted"
487
+ },
488
+ tableHeader: {
489
+ face: "body",
490
+ size: 9,
491
+ weight: 700,
492
+ color: "secondary"
493
+ },
494
+ tableCell: {
495
+ face: "body",
496
+ size: 9.5,
497
+ color: "textPrimary"
498
+ },
499
+ chartLabel: {
500
+ face: "body",
501
+ size: 9,
502
+ weight: 400,
503
+ color: "textSecondary"
504
+ },
505
+ tracker: {
506
+ face: "body",
507
+ size: 8,
508
+ case: "upper",
509
+ tracking: 6,
510
+ color: "textMuted"
511
+ },
512
+ source: {
513
+ face: "body",
514
+ size: 8,
515
+ color: "textMuted"
516
+ }
517
+ },
518
+ scale: {
519
+ a4: {
520
+ base: 9.5,
521
+ ratio: 1.2,
522
+ baselinePt: 2
523
+ },
524
+ letter: {
525
+ base: 9.5,
526
+ ratio: 1.2,
527
+ baselinePt: 2
528
+ }
529
+ }
530
+ },
531
+ spacing: {
532
+ basePt: 7,
533
+ blockGap: {
534
+ tight: 3,
535
+ normal: 7,
536
+ loose: 14
537
+ },
538
+ canvas: {
539
+ a4: {
540
+ safeAreaIn: 0.75,
541
+ gutterIn: 0,
542
+ columns: 12
543
+ },
544
+ letter: {
545
+ safeAreaIn: 0.75,
546
+ gutterIn: 0,
547
+ columns: 12
548
+ }
549
+ }
550
+ },
551
+ chrome: {
552
+ runningHead: {
553
+ type: "tracker",
554
+ color: "textMuted",
555
+ rule: {
556
+ weightPt: 0.5,
557
+ color: "rule"
558
+ },
559
+ alignment: "right"
560
+ },
561
+ tracker: {
562
+ type: "tracker",
563
+ color: "textMuted",
564
+ alignment: "right"
565
+ },
566
+ actionTitle: {
567
+ type: "display",
568
+ color: "primary"
569
+ },
570
+ keyTakeaways: {
571
+ type: "label",
572
+ color: "primary",
573
+ rule: {
574
+ weightPt: 1,
575
+ color: "accent"
576
+ },
577
+ padPt: 8
578
+ },
579
+ sourceLine: {
580
+ type: "source",
581
+ color: "textMuted"
582
+ },
583
+ confidentialFooter: {
584
+ type: "footer",
585
+ color: "textMuted",
586
+ rule: {
587
+ weightPt: 0.5,
588
+ color: "rule"
589
+ },
590
+ alignment: "left"
591
+ },
592
+ logoSlot: {
593
+ alignment: "right"
594
+ },
595
+ cover: {
596
+ type: "display",
597
+ color: "primary",
598
+ rule: {
599
+ weightPt: 3,
600
+ color: "accent"
601
+ }
602
+ }
603
+ },
604
+ motif: {
605
+ kind: "rule",
606
+ color: "accent",
607
+ weightPt: 2,
608
+ placement: "top"
609
+ },
424
610
  styles: {
425
611
  normal: {
426
612
  font: "body",
427
613
  color: "textPrimary",
428
- lineSpacing: { type: "multiple", value: 1.3 },
614
+ lineSpacing: {
615
+ type: "multiple",
616
+ value: 1.3
617
+ },
429
618
  alignment: "left",
430
- spacing: { after: 7 }
619
+ spacing: {
620
+ after: 7
621
+ }
431
622
  },
432
623
  title: {
433
624
  font: "heading",
@@ -435,9 +626,18 @@ var init_devportal_docx_theme = __esm({
435
626
  bold: true,
436
627
  color: "primary",
437
628
  alignment: "left",
438
- lineSpacing: { type: "multiple", value: 1.02 },
439
- characterSpacing: { type: "condensed", value: 8 },
440
- spacing: { before: 0, after: 10 }
629
+ lineSpacing: {
630
+ type: "multiple",
631
+ value: 1.02
632
+ },
633
+ characterSpacing: {
634
+ type: "condensed",
635
+ value: 8
636
+ },
637
+ spacing: {
638
+ before: 0,
639
+ after: 10
640
+ }
441
641
  },
442
642
  subtitle: {
443
643
  font: "body",
@@ -445,16 +645,28 @@ var init_devportal_docx_theme = __esm({
445
645
  italic: false,
446
646
  color: "textSecondary",
447
647
  alignment: "left",
448
- lineSpacing: { type: "multiple", value: 1.25 },
449
- spacing: { before: 0, after: 12 }
648
+ lineSpacing: {
649
+ type: "multiple",
650
+ value: 1.25
651
+ },
652
+ spacing: {
653
+ before: 0,
654
+ after: 12
655
+ }
450
656
  },
451
657
  heading1: {
452
658
  font: "heading",
453
659
  size: 21,
454
660
  bold: true,
455
661
  color: "primary",
456
- lineSpacing: { type: "multiple", value: 1.15 },
457
- spacing: { before: 26, after: 12 },
662
+ lineSpacing: {
663
+ type: "multiple",
664
+ value: 1.15
665
+ },
666
+ spacing: {
667
+ before: 26,
668
+ after: 12
669
+ },
458
670
  keepNext: true,
459
671
  alignment: "left",
460
672
  borders: {
@@ -471,8 +683,14 @@ var init_devportal_docx_theme = __esm({
471
683
  size: 15.5,
472
684
  bold: true,
473
685
  color: "secondary",
474
- lineSpacing: { type: "multiple", value: 1.15 },
475
- spacing: { before: 20, after: 8 },
686
+ lineSpacing: {
687
+ type: "multiple",
688
+ value: 1.15
689
+ },
690
+ spacing: {
691
+ before: 20,
692
+ after: 8
693
+ },
476
694
  keepNext: true,
477
695
  alignment: "left"
478
696
  },
@@ -481,7 +699,10 @@ var init_devportal_docx_theme = __esm({
481
699
  size: 12.5,
482
700
  bold: true,
483
701
  color: "secondary",
484
- spacing: { before: 14, after: 6 },
702
+ spacing: {
703
+ before: 14,
704
+ after: 6
705
+ },
485
706
  keepNext: true,
486
707
  alignment: "left"
487
708
  },
@@ -490,7 +711,10 @@ var init_devportal_docx_theme = __esm({
490
711
  size: 11.5,
491
712
  bold: true,
492
713
  color: "textPrimary",
493
- spacing: { before: 12, after: 4 },
714
+ spacing: {
715
+ before: 12,
716
+ after: 4
717
+ },
494
718
  keepNext: true,
495
719
  alignment: "left"
496
720
  },
@@ -499,7 +723,10 @@ var init_devportal_docx_theme = __esm({
499
723
  size: 10.5,
500
724
  bold: true,
501
725
  color: "secondary",
502
- spacing: { before: 10, after: 4 },
726
+ spacing: {
727
+ before: 10,
728
+ after: 4
729
+ },
503
730
  keepNext: true,
504
731
  alignment: "left"
505
732
  },
@@ -508,8 +735,14 @@ var init_devportal_docx_theme = __esm({
508
735
  size: 10.5,
509
736
  bold: false,
510
737
  color: "textSecondary",
511
- characterSpacing: { type: "expanded", value: 20 },
512
- spacing: { before: 10, after: 4 },
738
+ characterSpacing: {
739
+ type: "expanded",
740
+ value: 20
741
+ },
742
+ spacing: {
743
+ before: 10,
744
+ after: 4
745
+ },
513
746
  keepNext: true,
514
747
  alignment: "left"
515
748
  },
@@ -518,24 +751,53 @@ var init_devportal_docx_theme = __esm({
518
751
  size: 11,
519
752
  bold: true,
520
753
  color: "primary",
521
- spacing: { before: 5, after: 3 },
522
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
754
+ spacing: {
755
+ before: 5,
756
+ after: 3
757
+ },
758
+ tabStops: [
759
+ {
760
+ type: "right",
761
+ position: 9746,
762
+ leader: "dot"
763
+ }
764
+ ]
523
765
  },
524
766
  TOC2: {
525
767
  font: "body",
526
768
  size: 10.5,
527
769
  color: "textPrimary",
528
- indent: { left: 240 },
529
- spacing: { after: 2 },
530
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
770
+ indent: {
771
+ left: 240
772
+ },
773
+ spacing: {
774
+ after: 2
775
+ },
776
+ tabStops: [
777
+ {
778
+ type: "right",
779
+ position: 9746,
780
+ leader: "dot"
781
+ }
782
+ ]
531
783
  },
532
784
  TOC3: {
533
785
  font: "body",
534
786
  size: 10,
535
787
  color: "textSecondary",
536
- indent: { left: 480 },
537
- spacing: { after: 2 },
538
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
788
+ indent: {
789
+ left: 480
790
+ },
791
+ spacing: {
792
+ after: 2
793
+ },
794
+ tabStops: [
795
+ {
796
+ type: "right",
797
+ position: 9746,
798
+ leader: "dot"
799
+ }
800
+ ]
539
801
  }
540
802
  },
541
803
  componentDefaults: {
@@ -543,22 +805,37 @@ var init_devportal_docx_theme = __esm({
543
805
  width: 100,
544
806
  borderColor: "#E2E0DD",
545
807
  borderSize: 0.5,
546
- hideBorders: { left: true, right: true, insideVertical: true },
808
+ hideBorders: {
809
+ left: true,
810
+ right: true,
811
+ insideVertical: true
812
+ },
547
813
  cellDefaults: {
548
- padding: { top: 3, bottom: 3 }
814
+ padding: {
815
+ top: 3,
816
+ bottom: 3
817
+ }
549
818
  },
550
819
  headerCellDefaults: {
551
- font: { bold: true },
820
+ font: {
821
+ bold: true
822
+ },
552
823
  color: "#172028",
553
824
  backgroundColor: "#F7ECE7",
554
- borderColor: { bottom: "#D8D5D1" },
555
- borderSize: { bottom: 1 }
825
+ borderColor: {
826
+ bottom: "#D8D5D1"
827
+ },
828
+ borderSize: {
829
+ bottom: 1
830
+ }
556
831
  }
557
832
  },
558
833
  list: {
559
834
  format: "bullet",
560
835
  bullet: "\u2014",
561
- spacing: { item: 2 }
836
+ spacing: {
837
+ item: 2
838
+ }
562
839
  },
563
840
  image: {
564
841
  alignment: "center"
@@ -597,7 +874,19 @@ var init_vermilion_docx_theme = __esm({
597
874
  borderPrimary: "#C7C8CA",
598
875
  borderSecondary: "#EFEAE4",
599
876
  backgroundPrimary: "#FFFFFF",
600
- backgroundSecondary: "#FAF7F5"
877
+ backgroundSecondary: "#FAF7F5",
878
+ accent4: "#F4857A",
879
+ accent5: "#F9C4BE",
880
+ accent6: "#939598"
881
+ },
882
+ palette: {
883
+ rule: "#C7C8CA",
884
+ textMuted: "#939598",
885
+ onPrimary: "#FFFFFF",
886
+ surfaceInverse: "#282829",
887
+ positive: "#2E7D4F",
888
+ negative: "#B42318",
889
+ chart: ["accent", "primary", "textMuted", "accent4", "rule", "accent5"]
601
890
  },
602
891
  fonts: {
603
892
  heading: {
@@ -620,15 +909,177 @@ var init_vermilion_docx_theme = __esm({
620
909
  page: {
621
910
  size: "A4",
622
911
  margins: {
623
- top: 1360,
624
- bottom: 1360,
625
- left: 1180,
626
- right: 1180,
912
+ top: 1152,
913
+ bottom: 1152,
914
+ left: 1152,
915
+ right: 1152,
627
916
  header: 620,
628
917
  footer: 620,
629
918
  gutter: 0
630
919
  }
631
920
  },
921
+ typography: {
922
+ roles: {
923
+ eyebrow: {
924
+ face: "heading",
925
+ size: 8,
926
+ weight: 700,
927
+ case: "upper",
928
+ tracking: 8,
929
+ color: "accent",
930
+ spaceAfter: 4
931
+ },
932
+ display: {
933
+ face: "heading",
934
+ weight: 700,
935
+ color: "accent",
936
+ lineHeight: 1.05,
937
+ spaceAfter: 8
938
+ },
939
+ stat: {
940
+ face: "heading",
941
+ weight: 700,
942
+ color: "accent",
943
+ lineHeight: 1
944
+ },
945
+ quote: {
946
+ face: "body",
947
+ color: "textSecondary",
948
+ lineHeight: 1.3
949
+ },
950
+ label: {
951
+ face: "body",
952
+ size: 9,
953
+ weight: 700,
954
+ color: "textSecondary"
955
+ },
956
+ footer: {
957
+ face: "body",
958
+ size: 8,
959
+ color: "textMuted"
960
+ },
961
+ tableHeader: {
962
+ face: "body",
963
+ size: 9.5,
964
+ weight: 700,
965
+ color: "accent"
966
+ },
967
+ tableCell: {
968
+ face: "body",
969
+ size: 9.5,
970
+ color: "textPrimary"
971
+ },
972
+ chartLabel: {
973
+ face: "body",
974
+ size: 9,
975
+ weight: 400,
976
+ color: "textSecondary"
977
+ },
978
+ tracker: {
979
+ face: "body",
980
+ size: 8,
981
+ case: "upper",
982
+ tracking: 6,
983
+ color: "textMuted"
984
+ },
985
+ source: {
986
+ face: "body",
987
+ size: 8,
988
+ color: "textMuted"
989
+ }
990
+ },
991
+ scale: {
992
+ a4: {
993
+ base: 10.5,
994
+ ratio: 1.25,
995
+ baselinePt: 2
996
+ },
997
+ letter: {
998
+ base: 10.5,
999
+ ratio: 1.25,
1000
+ baselinePt: 2
1001
+ }
1002
+ }
1003
+ },
1004
+ spacing: {
1005
+ basePt: 8,
1006
+ blockGap: {
1007
+ tight: 4,
1008
+ normal: 8,
1009
+ loose: 16
1010
+ },
1011
+ canvas: {
1012
+ a4: {
1013
+ safeAreaIn: 0.8,
1014
+ gutterIn: 0,
1015
+ columns: 12
1016
+ },
1017
+ letter: {
1018
+ safeAreaIn: 0.8,
1019
+ gutterIn: 0,
1020
+ columns: 12
1021
+ }
1022
+ }
1023
+ },
1024
+ chrome: {
1025
+ runningHead: {
1026
+ type: "tracker",
1027
+ color: "textMuted",
1028
+ rule: {
1029
+ weightPt: 0.5,
1030
+ color: "rule"
1031
+ },
1032
+ alignment: "right"
1033
+ },
1034
+ tracker: {
1035
+ type: "tracker",
1036
+ color: "textMuted",
1037
+ alignment: "right"
1038
+ },
1039
+ actionTitle: {
1040
+ type: "display",
1041
+ color: "primary"
1042
+ },
1043
+ keyTakeaways: {
1044
+ type: "label",
1045
+ color: "primary",
1046
+ rule: {
1047
+ weightPt: 1.5,
1048
+ color: "accent"
1049
+ },
1050
+ padPt: 8
1051
+ },
1052
+ sourceLine: {
1053
+ type: "source",
1054
+ color: "textMuted"
1055
+ },
1056
+ confidentialFooter: {
1057
+ type: "footer",
1058
+ color: "textMuted",
1059
+ rule: {
1060
+ weightPt: 0.5,
1061
+ color: "rule"
1062
+ },
1063
+ alignment: "left"
1064
+ },
1065
+ logoSlot: {
1066
+ alignment: "right"
1067
+ },
1068
+ cover: {
1069
+ type: "display",
1070
+ color: "primary",
1071
+ rule: {
1072
+ weightPt: 4,
1073
+ color: "accent"
1074
+ }
1075
+ }
1076
+ },
1077
+ motif: {
1078
+ kind: "rule",
1079
+ color: "accent",
1080
+ weightPt: 4,
1081
+ placement: "top"
1082
+ },
632
1083
  styles: {
633
1084
  normal: {
634
1085
  font: "body",
@@ -761,23 +1212,40 @@ var init_vermilion_docx_theme = __esm({
761
1212
  insideVertical: true
762
1213
  },
763
1214
  cellDefaults: {
764
- font: { size: 9.5 },
765
- padding: { top: 7, bottom: 7 },
1215
+ font: {
1216
+ size: 9.5
1217
+ },
1218
+ padding: {
1219
+ top: 7,
1220
+ bottom: 7
1221
+ },
766
1222
  verticalAlignment: "middle"
767
1223
  },
768
1224
  headerCellDefaults: {
769
1225
  color: "#EF4130",
770
- font: { size: 9.5, bold: true },
771
- padding: { top: 0, bottom: 8 },
1226
+ font: {
1227
+ size: 9.5,
1228
+ bold: true
1229
+ },
1230
+ padding: {
1231
+ top: 0,
1232
+ bottom: 8
1233
+ },
772
1234
  verticalAlignment: "bottom",
773
- borderColor: { bottom: "#EF4130" },
774
- borderSize: { bottom: 0.5 }
1235
+ borderColor: {
1236
+ bottom: "#EF4130"
1237
+ },
1238
+ borderSize: {
1239
+ bottom: 0.5
1240
+ }
775
1241
  }
776
1242
  },
777
1243
  list: {
778
1244
  format: "bullet",
779
1245
  bullet: "\u2014",
780
- spacing: { item: 2 }
1246
+ spacing: {
1247
+ item: 2
1248
+ }
781
1249
  },
782
1250
  image: {
783
1251
  alignment: "center"
@@ -5303,7 +5771,10 @@ import {
5303
5771
  import {
5304
5772
  clampVisualDpi,
5305
5773
  DEFAULT_VISUAL_DPI,
5306
- MAX_RASTERIZE_BATCH_SLIDES
5774
+ MAX_RASTERIZE_BATCH_SLIDES,
5775
+ createLimiter,
5776
+ resolveServiceUrl as resolveServiceUrl2,
5777
+ postJsonToService as postJsonToService2
5307
5778
  } from "@json-to-office/shared";
5308
5779
  import {
5309
5780
  isNativeVisualProps
@@ -5317,54 +5788,8 @@ function isNodeEnvironment() {
5317
5788
  return typeof process !== "undefined" && process.versions != null && process.versions.node != null && typeof process.versions.node === "string";
5318
5789
  }
5319
5790
 
5320
- // src/utils/serviceClient.ts
5321
- var DEFAULT_TIMEOUT_MS = 3e4;
5322
- function resolveServiceUrl(propsUrl, servicesUrl, defaultUrl) {
5323
- const raw = (propsUrl || servicesUrl || defaultUrl).trim();
5324
- const withScheme = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
5325
- return withScheme.replace(/\/+$/, "");
5326
- }
5327
- var SERVICE_UNAVAILABLE_CODE = "SERVICE_UNAVAILABLE";
5328
- function serviceUnavailable(message) {
5329
- return Object.assign(new Error(message), { code: SERVICE_UNAVAILABLE_CODE });
5330
- }
5331
- async function postJsonToService(opts) {
5332
- const resolvedHeaders = typeof opts.headers === "function" ? await opts.headers(opts.body) : opts.headers;
5333
- const headers = {
5334
- "Content-Type": "application/json",
5335
- ...resolvedHeaders
5336
- };
5337
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
5338
- const controller = new AbortController();
5339
- const timer = setTimeout(() => controller.abort(), timeoutMs);
5340
- let response;
5341
- try {
5342
- response = await fetch(`${opts.url}${opts.path}`, {
5343
- method: "POST",
5344
- headers,
5345
- body: JSON.stringify(opts.body),
5346
- signal: controller.signal
5347
- });
5348
- } catch (error) {
5349
- if (error?.name === "AbortError") {
5350
- throw serviceUnavailable(
5351
- `${opts.serviceLabel} timed out after ${timeoutMs}ms at ${opts.url}.`
5352
- );
5353
- }
5354
- const cause = error instanceof Error ? error.message : String(error);
5355
- throw serviceUnavailable(opts.onUnreachable(opts.url, cause));
5356
- } finally {
5357
- clearTimeout(timer);
5358
- }
5359
- if (!response.ok) {
5360
- throw new Error(
5361
- `${opts.serviceLabel} returned ${response.status}: ${response.statusText}`
5362
- );
5363
- }
5364
- return response;
5365
- }
5366
-
5367
5791
  // src/components/visual.ts
5792
+ import { resolveServiceUrl, postJsonToService } from "@json-to-office/shared";
5368
5793
  var DEFAULT_RASTERIZE_SERVER_URL = "http://localhost:7802";
5369
5794
  var PIXELS_PER_INCH = 96;
5370
5795
  function buildVisualPresentation(props) {
@@ -5466,26 +5891,6 @@ Cause: ${cause}`
5466
5891
  return result;
5467
5892
  }
5468
5893
 
5469
- // src/utils/promiseLimiter.ts
5470
- function createLimiter(max) {
5471
- let active = 0;
5472
- const queue = [];
5473
- const release = () => {
5474
- active--;
5475
- queue.shift()?.();
5476
- };
5477
- return async function limit(fn) {
5478
- while (active >= max)
5479
- await new Promise((resolve2) => queue.push(resolve2));
5480
- active++;
5481
- try {
5482
- return await fn();
5483
- } finally {
5484
- release();
5485
- }
5486
- };
5487
- }
5488
-
5489
5894
  // src/core/prerasterizeVisuals.ts
5490
5895
  var DEFAULT_FALLBACK_CONCURRENCY = 4;
5491
5896
  var BATCH_TIMEOUT_BASE_MS = 3e4;
@@ -5654,7 +6059,7 @@ async function prerasterizeVisuals(root, serviceConfig, options = {}) {
5654
6059
  await rasterizeIndividually(unique);
5655
6060
  return map;
5656
6061
  }
5657
- const serverUrl = resolveServiceUrl(
6062
+ const serverUrl = resolveServiceUrl2(
5658
6063
  void 0,
5659
6064
  serviceConfig?.serverUrl,
5660
6065
  DEFAULT_RASTERIZE_SERVER_URL
@@ -5662,7 +6067,7 @@ async function prerasterizeVisuals(root, serviceConfig, options = {}) {
5662
6067
  const postBatch = async (chunk, fonts) => {
5663
6068
  let response;
5664
6069
  try {
5665
- response = await postJsonToService({
6070
+ response = await postJsonToService2({
5666
6071
  url: serverUrl,
5667
6072
  path: "/rasterize/batch",
5668
6073
  body: {
@@ -5788,7 +6193,8 @@ function containsComponent(root, name) {
5788
6193
  // src/core/desugarExternals.ts
5789
6194
  import {
5790
6195
  clampVisualDpi as clampVisualDpi2,
5791
- DEFAULT_VISUAL_DPI as DEFAULT_VISUAL_DPI2
6196
+ DEFAULT_VISUAL_DPI as DEFAULT_VISUAL_DPI2,
6197
+ limitChartRequest
5792
6198
  } from "@json-to-office/shared";
5793
6199
  import {
5794
6200
  isNativeVisualProps as isNativeVisualProps2
@@ -5804,30 +6210,42 @@ import {
5804
6210
  chartPointsPerPixel,
5805
6211
  POINTS_PER_PIXEL_96DPI,
5806
6212
  withChartFontFaceCss,
5807
- withChartTypography
6213
+ withChartTypography,
6214
+ resolveServiceUrl as resolveServiceUrl3,
6215
+ postJsonToService as postJsonToService3,
6216
+ chartRequestKey,
6217
+ dedupeChartRequest,
6218
+ recordChartRetry
5808
6219
  } from "@json-to-office/shared";
5809
6220
  var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
6221
+ function effectiveChartServerUrl(props, servicesConfig) {
6222
+ return resolveServiceUrl3(
6223
+ props.serverUrl,
6224
+ servicesConfig?.serverUrl,
6225
+ DEFAULT_EXPORT_SERVER_URL
6226
+ );
6227
+ }
5810
6228
  function assertExportServerAllowed(serverUrl, servicesConfig, warnings) {
5811
6229
  const notice = remoteExportNotice(serverUrl, servicesConfig?.allowRemote);
5812
- if (notice)
5813
- warnings?.push({
5814
- component: "highcharts",
5815
- severity: "warning",
5816
- message: notice,
5817
- context: { code: REMOTE_EXPORT_WARNING, serverUrl }
5818
- });
6230
+ if (!notice || !warnings) return;
6231
+ const alreadySaid = warnings.some(
6232
+ (warning) => warning.context?.code === REMOTE_EXPORT_WARNING && warning.context?.serverUrl === serverUrl
6233
+ );
6234
+ if (alreadySaid) return;
6235
+ warnings.push({
6236
+ component: "highcharts",
6237
+ severity: "warning",
6238
+ message: notice,
6239
+ context: { code: REMOTE_EXPORT_WARNING, serverUrl }
6240
+ });
5819
6241
  }
5820
- async function generateChart(config, servicesConfig, warnings) {
6242
+ async function generateChart(config, servicesConfig, warnings, cache) {
5821
6243
  if (!isNodeEnvironment()) {
5822
6244
  throw new Error(
5823
6245
  "Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
5824
6246
  );
5825
6247
  }
5826
- const serverUrl = resolveServiceUrl(
5827
- config.serverUrl,
5828
- servicesConfig?.serverUrl,
5829
- DEFAULT_EXPORT_SERVER_URL
5830
- );
6248
+ const serverUrl = effectiveChartServerUrl(config, servicesConfig);
5831
6249
  assertExportServerAllowed(serverUrl, servicesConfig, warnings);
5832
6250
  const requestBody = {
5833
6251
  infile: config.options,
@@ -5838,11 +6256,21 @@ async function generateChart(config, servicesConfig, warnings) {
5838
6256
  // byte-identical to before for callers that omit it.
5839
6257
  ...config.resources ? { resources: config.resources } : {}
5840
6258
  };
5841
- const response = await postJsonToService({
6259
+ return dedupeChartRequest(
6260
+ cache,
6261
+ chartRequestKey(serverUrl, requestBody),
6262
+ () => postChart(serverUrl, requestBody, config, servicesConfig)
6263
+ );
6264
+ }
6265
+ async function postChart(serverUrl, requestBody, config, servicesConfig) {
6266
+ const response = await postJsonToService3({
5842
6267
  url: serverUrl,
5843
6268
  path: "/export",
5844
6269
  body: requestBody,
5845
6270
  headers: servicesConfig?.headers,
6271
+ timeoutMs: servicesConfig?.timeoutMs,
6272
+ retries: servicesConfig?.retries,
6273
+ onRetry: recordChartRetry,
5846
6274
  serviceLabel: "Highcharts export server",
5847
6275
  onUnreachable: (url, cause) => `Highcharts Export Server is not running at ${url}. Start it with: npx highcharts-export-server --enableServer true
5848
6276
  Cause: ${cause}`
@@ -5941,13 +6369,13 @@ function withChartFontFaces(config, theme, faces) {
5941
6369
  theme.fonts.heading.family
5942
6370
  ]);
5943
6371
  }
5944
- async function renderChartToImageProps(props, theme, servicesConfig, chartFonts, warnings) {
6372
+ async function renderChartToImageProps(props, theme, servicesConfig, chartFonts, warnings, cache) {
5945
6373
  const config = withChartFontFaces(
5946
6374
  withThemeTypography(withThemeColors(props, theme), theme),
5947
6375
  theme,
5948
6376
  chartFonts
5949
6377
  );
5950
- const chart = await generateChart(config, servicesConfig, warnings);
6378
+ const chart = await generateChart(config, servicesConfig, warnings, cache);
5951
6379
  const hasConfigDimensions = config.width !== void 0 || config.height !== void 0;
5952
6380
  return {
5953
6381
  base64: chart.base64DataUri,
@@ -5967,6 +6395,7 @@ async function desugarExternals(document, options) {
5967
6395
  ...options.visualFonts ? { fonts: options.visualFonts } : {}
5968
6396
  }
5969
6397
  ).catch(() => /* @__PURE__ */ new Map());
6398
+ const chartCache = /* @__PURE__ */ new Map();
5970
6399
  return transformComponents(document, async (node) => {
5971
6400
  if (node.enabled === false) return void 0;
5972
6401
  if (node.name === "visual") {
@@ -5981,14 +6410,21 @@ async function desugarExternals(document, options) {
5981
6410
  });
5982
6411
  }
5983
6412
  if (node.name === "highcharts") {
6413
+ const props = node.props;
6414
+ const chartConfig = options.services?.highcharts;
5984
6415
  return withNodeIdentity(node, {
5985
6416
  name: "image",
5986
- props: await renderChartToImageProps(
5987
- node.props,
5988
- options.theme,
5989
- options.services?.highcharts,
5990
- options.chartFonts,
5991
- options.warnings
6417
+ props: await limitChartRequest(
6418
+ effectiveChartServerUrl(props, chartConfig),
6419
+ chartConfig?.concurrency,
6420
+ () => renderChartToImageProps(
6421
+ props,
6422
+ options.theme,
6423
+ chartConfig,
6424
+ options.chartFonts,
6425
+ options.warnings,
6426
+ chartCache
6427
+ )
5992
6428
  )
5993
6429
  });
5994
6430
  }