@json-to-office/core-docx 0.21.0 → 0.23.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.
Files changed (32) hide show
  1. package/dist/components/highcharts.d.ts.map +1 -1
  2. package/dist/components/toc/index.d.ts.map +1 -1
  3. package/dist/core/content.d.ts.map +1 -1
  4. package/dist/core/generator.d.ts.map +1 -1
  5. package/dist/core/render.d.ts.map +1 -1
  6. package/dist/core/structure.d.ts +3 -0
  7. package/dist/core/structure.d.ts.map +1 -1
  8. package/dist/index.js +430 -105
  9. package/dist/index.js.map +1 -1
  10. package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
  11. package/dist/plugin/example/index.js +427 -48
  12. package/dist/plugin/example/index.js.map +1 -1
  13. package/dist/styles/theme-resolver.d.ts +14 -2
  14. package/dist/styles/theme-resolver.d.ts.map +1 -1
  15. package/dist/styles/theme-validator.d.ts.map +1 -1
  16. package/dist/styles/utils/colorUtils.d.ts +4 -3
  17. package/dist/styles/utils/colorUtils.d.ts.map +1 -1
  18. package/dist/styles/utils/resolveComponentTree.d.ts +3 -0
  19. package/dist/styles/utils/resolveComponentTree.d.ts.map +1 -1
  20. package/dist/templates/themes/apex.docx.theme.json +1 -6
  21. package/dist/templates/themes/corporate.docx.theme.json +7 -7
  22. package/dist/templates/themes/devportal.docx.theme.json +1 -6
  23. package/dist/templates/themes/index.d.ts +13 -1
  24. package/dist/templates/themes/index.d.ts.map +1 -1
  25. package/dist/templates/themes/minimal.docx.theme.json +1 -6
  26. package/dist/templates/themes/modern.docx.theme.json +1 -6
  27. package/dist/themes/defaults.d.ts +3 -0
  28. package/dist/themes/defaults.d.ts.map +1 -1
  29. package/dist/themes/json/index.d.ts +7 -6
  30. package/dist/themes/json/index.d.ts.map +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAknBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAgBvC"}
1
+ {"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,KAAK,EAEV,wBAAwB,EAOxB,2BAA2B,EAC5B,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,oFAAoF;IACpF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AA8nBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAgBvC"}
@@ -362,12 +362,7 @@ var init_minimal_docx_theme = __esm({
362
362
  },
363
363
  componentDefaults: {
364
364
  table: {
365
- borders: false,
366
- striped: false,
367
- headerBackground: "#fafafa",
368
- headerColor: "#000000",
369
- borderColor: "#f0f0f0",
370
- borderWidth: 0.5
365
+ borderColor: "#f0f0f0"
371
366
  },
372
367
  list: {
373
368
  format: "bullet",
@@ -450,7 +445,12 @@ var init_corporate_docx_theme = __esm({
450
445
  keepNext: true,
451
446
  alignment: "left",
452
447
  borders: {
453
- bottom: { style: "single", size: 2, color: "primary", space: 6 }
448
+ bottom: {
449
+ style: "single",
450
+ size: 2,
451
+ color: "primary",
452
+ space: 6
453
+ }
454
454
  }
455
455
  },
456
456
  heading2: {
@@ -490,12 +490,7 @@ var init_corporate_docx_theme = __esm({
490
490
  },
491
491
  componentDefaults: {
492
492
  table: {
493
- borders: true,
494
- striped: true,
495
- headerBackground: "#1a365d",
496
- headerColor: "#FFFFFF",
497
- borderColor: "#E2E8F0",
498
- borderWidth: 0.5
493
+ borderColor: "#E2E8F0"
499
494
  },
500
495
  list: {
501
496
  format: "bullet",
@@ -612,12 +607,7 @@ var init_modern_docx_theme = __esm({
612
607
  },
613
608
  componentDefaults: {
614
609
  table: {
615
- borders: true,
616
- striped: false,
617
- headerBackground: "#6D28D9",
618
- headerColor: "#FFFFFF",
619
- borderColor: "#E2E8F0",
620
- borderWidth: 0.5
610
+ borderColor: "#E2E8F0"
621
611
  },
622
612
  list: {
623
613
  format: "bullet",
@@ -638,10 +628,277 @@ var init_modern_docx_theme = __esm({
638
628
  }
639
629
  });
640
630
 
631
+ // src/templates/themes/apex.docx.theme.json
632
+ var apex_docx_theme_default;
633
+ var init_apex_docx_theme = __esm({
634
+ "src/templates/themes/apex.docx.theme.json"() {
635
+ apex_docx_theme_default = {
636
+ name: "apex",
637
+ displayName: "Apex Consulting",
638
+ description: "A premium consulting theme with deep navy, warm amber accents, and authoritative typography",
639
+ version: "2.0.0",
640
+ colors: {
641
+ primary: "#0C2340",
642
+ secondary: "#1B3A5C",
643
+ accent: "#D4A843",
644
+ text: "#1A1A2E",
645
+ background: "#FFFFFF",
646
+ border: "#D6DAE0",
647
+ textPrimary: "#1A1A2E",
648
+ textSecondary: "#4A5066",
649
+ textMuted: "#8B91A0",
650
+ borderPrimary: "#B8BCC6",
651
+ borderSecondary: "#E8EAF0",
652
+ backgroundPrimary: "#FFFFFF",
653
+ backgroundSecondary: "#F4F5F8"
654
+ },
655
+ fonts: {
656
+ heading: { family: "Georgia", size: 26 },
657
+ body: { family: "Calibri", size: 11 },
658
+ mono: { family: "Consolas", size: 10 },
659
+ light: { family: "Georgia", size: 26 }
660
+ },
661
+ page: {
662
+ size: "A4",
663
+ margins: {
664
+ top: 1440,
665
+ bottom: 1440,
666
+ left: 1200,
667
+ right: 1200,
668
+ header: 720,
669
+ footer: 720,
670
+ gutter: 0
671
+ }
672
+ },
673
+ styles: {
674
+ normal: {
675
+ font: "body",
676
+ color: "textPrimary",
677
+ lineSpacing: { type: "multiple", value: 1.4 },
678
+ alignment: "justify",
679
+ spacing: { after: 8 }
680
+ },
681
+ heading1: {
682
+ font: "heading",
683
+ size: 26,
684
+ bold: false,
685
+ color: "primary",
686
+ spacing: { before: 24, after: 12 },
687
+ keepNext: true,
688
+ alignment: "left",
689
+ borders: {
690
+ bottom: {
691
+ style: "single",
692
+ size: 2,
693
+ color: "accent",
694
+ space: 6
695
+ }
696
+ }
697
+ },
698
+ heading2: {
699
+ font: "heading",
700
+ size: 18,
701
+ bold: false,
702
+ color: "secondary",
703
+ spacing: { before: 18, after: 8 },
704
+ keepNext: true,
705
+ alignment: "left"
706
+ },
707
+ heading3: {
708
+ font: "body",
709
+ size: 13,
710
+ bold: true,
711
+ color: "accent",
712
+ spacing: { before: 12, after: 6 },
713
+ keepNext: true,
714
+ alignment: "left"
715
+ },
716
+ title: {
717
+ font: "light",
718
+ size: 36,
719
+ bold: false,
720
+ color: "primary",
721
+ alignment: "left",
722
+ spacing: { before: 0, after: 18 }
723
+ },
724
+ subtitle: {
725
+ font: "body",
726
+ size: 16,
727
+ italic: false,
728
+ color: "textSecondary",
729
+ alignment: "left",
730
+ spacing: { before: 0, after: 24 }
731
+ }
732
+ },
733
+ componentDefaults: {
734
+ table: {
735
+ borderColor: "#D6DAE0"
736
+ },
737
+ list: {
738
+ format: "bullet",
739
+ bullet: "\u2022",
740
+ indent: 3
741
+ },
742
+ image: {
743
+ alignment: "center"
744
+ },
745
+ statistic: {
746
+ alignment: "center"
747
+ },
748
+ section: {
749
+ pageBreak: false
750
+ },
751
+ heading: {
752
+ numbering: false
753
+ }
754
+ }
755
+ };
756
+ }
757
+ });
758
+
759
+ // src/templates/themes/devportal.docx.theme.json
760
+ var devportal_docx_theme_default;
761
+ var init_devportal_docx_theme = __esm({
762
+ "src/templates/themes/devportal.docx.theme.json"() {
763
+ devportal_docx_theme_default = {
764
+ name: "devportal",
765
+ displayName: "Developer Portal",
766
+ description: "A modern developer-focused theme with cool grays, teal accents, and monospace code styling",
767
+ version: "2.0.0",
768
+ colors: {
769
+ primary: "#0F172A",
770
+ secondary: "#334155",
771
+ accent: "#0D9488",
772
+ text: "#0F172A",
773
+ background: "#FFFFFF",
774
+ border: "#E2E8F0",
775
+ textPrimary: "#0F172A",
776
+ textSecondary: "#475569",
777
+ textMuted: "#94A3B8",
778
+ borderPrimary: "#CBD5E1",
779
+ borderSecondary: "#F1F5F9",
780
+ backgroundPrimary: "#FFFFFF",
781
+ backgroundSecondary: "#F8FAFC"
782
+ },
783
+ fonts: {
784
+ heading: { family: "Helvetica", size: 24 },
785
+ body: { family: "Calibri", size: 11 },
786
+ mono: { family: "Consolas", size: 10 },
787
+ light: { family: "Helvetica", size: 24 }
788
+ },
789
+ page: {
790
+ size: "A4",
791
+ margins: {
792
+ top: 1440,
793
+ bottom: 1440,
794
+ left: 1080,
795
+ right: 1080,
796
+ header: 720,
797
+ footer: 720,
798
+ gutter: 0
799
+ }
800
+ },
801
+ styles: {
802
+ normal: {
803
+ font: "body",
804
+ color: "textPrimary",
805
+ lineSpacing: { type: "multiple", value: 1.5 },
806
+ alignment: "left",
807
+ spacing: { after: 8 }
808
+ },
809
+ heading1: {
810
+ font: "heading",
811
+ size: 24,
812
+ bold: true,
813
+ color: "primary",
814
+ spacing: { before: 24, after: 12 },
815
+ keepNext: true,
816
+ alignment: "left",
817
+ borders: {
818
+ bottom: {
819
+ style: "single",
820
+ size: 1,
821
+ color: "accent",
822
+ space: 6
823
+ }
824
+ }
825
+ },
826
+ heading2: {
827
+ font: "heading",
828
+ size: 18,
829
+ bold: true,
830
+ color: "secondary",
831
+ spacing: { before: 18, after: 8 },
832
+ keepNext: true,
833
+ alignment: "left"
834
+ },
835
+ heading3: {
836
+ font: "body",
837
+ size: 13,
838
+ bold: true,
839
+ color: "accent",
840
+ spacing: { before: 12, after: 6 },
841
+ keepNext: true,
842
+ alignment: "left"
843
+ },
844
+ heading4: {
845
+ font: "body",
846
+ size: 12,
847
+ bold: true,
848
+ color: "textSecondary",
849
+ spacing: { before: 8, after: 4 },
850
+ keepNext: true
851
+ },
852
+ title: {
853
+ font: "heading",
854
+ size: 32,
855
+ bold: true,
856
+ color: "primary",
857
+ alignment: "left",
858
+ spacing: { before: 0, after: 12 }
859
+ },
860
+ subtitle: {
861
+ font: "light",
862
+ size: 16,
863
+ italic: false,
864
+ color: "textSecondary",
865
+ alignment: "left",
866
+ spacing: { before: 0, after: 24 }
867
+ }
868
+ },
869
+ componentDefaults: {
870
+ table: {
871
+ borderColor: "#E2E8F0"
872
+ },
873
+ list: {
874
+ format: "bullet",
875
+ bullet: "\u2013",
876
+ indent: 3
877
+ },
878
+ image: {
879
+ alignment: "center"
880
+ },
881
+ statistic: {
882
+ alignment: "center"
883
+ },
884
+ section: {
885
+ pageBreak: false
886
+ },
887
+ heading: {
888
+ numbering: false
889
+ }
890
+ }
891
+ };
892
+ }
893
+ });
894
+
641
895
  // src/templates/themes/index.ts
642
896
  import fs from "fs";
643
897
  import path from "path";
644
898
  import { fileURLToPath } from "url";
899
+ import {
900
+ isValidThemeConfig
901
+ } from "@json-to-office/shared-docx";
645
902
  function loadThemesFromJson() {
646
903
  if (_themesCache) {
647
904
  return _themesCache;
@@ -649,7 +906,9 @@ function loadThemesFromJson() {
649
906
  const themes2 = {
650
907
  minimal: ensureThemeDefaults(minimal_docx_theme_default),
651
908
  corporate: ensureThemeDefaults(corporate_docx_theme_default),
652
- modern: ensureThemeDefaults(modern_docx_theme_default)
909
+ modern: ensureThemeDefaults(modern_docx_theme_default),
910
+ apex: ensureThemeDefaults(apex_docx_theme_default),
911
+ devportal: ensureThemeDefaults(devportal_docx_theme_default)
653
912
  };
654
913
  try {
655
914
  const __filename2 = fileURLToPath(import.meta.url);
@@ -660,9 +919,18 @@ function loadThemesFromJson() {
660
919
  for (const themeName of themeFiles) {
661
920
  if (!themes2[themeName]) {
662
921
  try {
663
- const filePath = path.join(themesDir, `${themeName}.docx.theme.json`);
922
+ const filePath = path.join(
923
+ themesDir,
924
+ `${themeName}.docx.theme.json`
925
+ );
664
926
  const content = fs.readFileSync(filePath, "utf8");
665
927
  const parsedTheme = JSON.parse(content);
928
+ if (!isValidThemeConfig(parsedTheme)) {
929
+ console.warn(
930
+ `Skipping theme ${themeName}: does not match the theme schema.`
931
+ );
932
+ continue;
933
+ }
666
934
  themes2[themeName] = ensureThemeDefaults(parsedTheme);
667
935
  } catch (error) {
668
936
  console.warn(
@@ -678,7 +946,7 @@ function loadThemesFromJson() {
678
946
  _themesCache = themes2;
679
947
  return themes2;
680
948
  }
681
- var _themesCache, themes, getTheme, getThemeWithFallback, minimalTheme, corporateTheme, modernTheme;
949
+ var _themesCache, themes, getTheme, getThemeWithFallback, hasTheme, getThemeNames, minimalTheme, corporateTheme, modernTheme;
682
950
  var init_themes = __esm({
683
951
  "src/templates/themes/index.ts"() {
684
952
  "use strict";
@@ -686,6 +954,8 @@ var init_themes = __esm({
686
954
  init_minimal_docx_theme();
687
955
  init_corporate_docx_theme();
688
956
  init_modern_docx_theme();
957
+ init_apex_docx_theme();
958
+ init_devportal_docx_theme();
689
959
  _themesCache = null;
690
960
  themes = loadThemesFromJson();
691
961
  getTheme = (themeName) => {
@@ -700,6 +970,12 @@ var init_themes = __esm({
700
970
  }
701
971
  return theme;
702
972
  };
973
+ hasTheme = (themeName) => {
974
+ return themeName in themes;
975
+ };
976
+ getThemeNames = () => {
977
+ return Object.keys(themes);
978
+ };
703
979
  minimalTheme = themes["minimal"];
704
980
  corporateTheme = themes["corporate"];
705
981
  modernTheme = themes["modern"];
@@ -718,10 +994,13 @@ function resolveColor(colorValue, theme) {
718
994
  );
719
995
  }
720
996
  const colors = getThemeColors(theme);
721
- if (colorValue in colors) {
722
- const resolvedColor = colors[colorValue];
997
+ const resolvedColor = colors[colorValue];
998
+ if (typeof resolvedColor === "string") {
723
999
  return resolveColor(resolvedColor, theme);
724
1000
  }
1001
+ if (/^[0-9A-Fa-f]{6}$/.test(colorValue)) {
1002
+ return colorValue.toUpperCase();
1003
+ }
725
1004
  throw new Error(
726
1005
  `Invalid color value: "${colorValue}". Must be a hex color with # prefix (e.g., "#000000") or a valid theme color name.`
727
1006
  );
@@ -1308,7 +1587,8 @@ var init_loader = __esm({
1308
1587
  // src/themes/json/index.ts
1309
1588
  import {
1310
1589
  ThemeConfigSchema,
1311
- isValidThemeConfig
1590
+ isValidThemeConfig as isValidThemeConfig2,
1591
+ createMinimalTheme
1312
1592
  } from "@json-to-office/shared-docx";
1313
1593
  var themeParser, themeLoader;
1314
1594
  var init_json = __esm({
@@ -1616,8 +1896,25 @@ var init_docxImagePositioning = __esm({
1616
1896
  // src/plugin/example/index.ts
1617
1897
  import { Packer as Packer2 } from "docx";
1618
1898
 
1899
+ // src/styles/theme-resolver.ts
1900
+ init_themes();
1901
+ function resolveBuiltInTheme(themeName, options = {}) {
1902
+ if (!hasTheme(themeName)) {
1903
+ const available = [
1904
+ ...getThemeNames(),
1905
+ ...Object.keys(options.customThemes ?? {})
1906
+ ].sort();
1907
+ options.warnings?.push({
1908
+ component: "theme",
1909
+ message: `Theme "${themeName}" not found; falling back to "minimal". Available themes: ${available.join(", ")}.`,
1910
+ severity: "warning",
1911
+ context: { code: "theme_not_found", requested: themeName, available }
1912
+ });
1913
+ }
1914
+ return getThemeWithFallback(themeName);
1915
+ }
1916
+
1619
1917
  // src/plugin/createDocumentGenerator.ts
1620
- init_styles();
1621
1918
  import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
1622
1919
 
1623
1920
  // src/core/fontResolution.ts
@@ -1960,10 +2257,10 @@ var RESOLVER_MAP = {
1960
2257
  visual: resolveVisualProps
1961
2258
  };
1962
2259
  function resolveComponentDefaults(component, theme) {
1963
- if (!component.props) return component;
2260
+ const props = component.props ?? {};
1964
2261
  const resolver = RESOLVER_MAP[component.name];
1965
- const resolvedProps = resolver ? resolver(component.props, theme) : resolveCustomComponentProps(
1966
- component.props,
2262
+ const resolvedProps = resolver ? resolver(props, theme) : resolveCustomComponentProps(
2263
+ props,
1967
2264
  theme,
1968
2265
  component.name
1969
2266
  );
@@ -2027,8 +2324,11 @@ function createDocumentMetadata(props, generationDate = /* @__PURE__ */ new Date
2027
2324
  return {
2028
2325
  title: props.metadata?.title,
2029
2326
  subtitle: props.metadata?.subtitle,
2327
+ description: props.metadata?.description,
2030
2328
  author: props.metadata?.author,
2031
2329
  company: props.metadata?.company,
2330
+ version: props.metadata?.version,
2331
+ tags: props.metadata?.tags,
2032
2332
  date: props.metadata?.date ? new Date(props.metadata.date) : generationDate
2033
2333
  };
2034
2334
  }
@@ -4693,6 +4993,32 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4693
4993
  borderColor: "000000",
4694
4994
  borderSize: 1
4695
4995
  });
4996
+ const warnedCellColors = /* @__PURE__ */ new Set();
4997
+ const warnCellColor = (code, message) => {
4998
+ if (warnedCellColors.has(message)) return;
4999
+ warnedCellColors.add(message);
5000
+ console.warn(`[json-to-docx] ${code}: ${message}`);
5001
+ };
5002
+ const resolveCellColor = (value, prop) => {
5003
+ if (value === void 0 || value === "auto") return value;
5004
+ if (value === "transparent") {
5005
+ if (prop === "backgroundColor") return value;
5006
+ warnCellColor(
5007
+ "TABLE_CELL_COLOR_INVALID",
5008
+ `"transparent" is not a valid table cell "color"; ignoring it and using the table style color. It only applies to "backgroundColor".`
5009
+ );
5010
+ return void 0;
5011
+ }
5012
+ if (/^[0-9A-Fa-f]{6}$/.test(value)) return value.toUpperCase();
5013
+ try {
5014
+ return resolveColor(value, theme);
5015
+ } catch {
5016
+ const allowed = prop === "backgroundColor" ? '"auto", or "transparent" for no shading' : 'or "auto"';
5017
+ throw new Error(
5018
+ `Invalid table cell ${prop}: "${value}". Must be a hex color with # prefix (e.g. "#000000"), a theme color name, ${allowed}.`
5019
+ );
5020
+ }
5021
+ };
4696
5022
  const normalizeBorderColor = (border) => {
4697
5023
  if (border === void 0) return void 0;
4698
5024
  if (typeof border === "string") {
@@ -4829,8 +5155,14 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4829
5155
  tableDef?.padding
4830
5156
  );
4831
5157
  return {
4832
- color: cellDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,
4833
- backgroundColor: cellDef?.backgroundColor ?? columnDef?.backgroundColor ?? tableDef?.backgroundColor ?? defaults.backgroundColor,
5158
+ color: resolveCellColor(
5159
+ cellDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,
5160
+ "color"
5161
+ ),
5162
+ backgroundColor: resolveCellColor(
5163
+ cellDef?.backgroundColor ?? columnDef?.backgroundColor ?? tableDef?.backgroundColor ?? defaults.backgroundColor,
5164
+ "backgroundColor"
5165
+ ),
4834
5166
  horizontalAlignment: cellDef?.horizontalAlignment ?? columnDef?.horizontalAlignment ?? tableDef?.horizontalAlignment ?? defaults.horizontalAlignment,
4835
5167
  verticalAlignment: cellDef?.verticalAlignment ?? columnDef?.verticalAlignment ?? tableDef?.verticalAlignment ?? defaults.verticalAlignment,
4836
5168
  font: mergedFont,
@@ -4883,8 +5215,14 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4883
5215
  tableDef?.padding
4884
5216
  );
4885
5217
  return {
4886
- color: headerDef?.color ?? headerTableDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,
4887
- backgroundColor: headerDef?.backgroundColor ?? headerTableDef?.backgroundColor ?? columnDef?.backgroundColor ?? tableDef?.backgroundColor ?? defaults.backgroundColor,
5218
+ color: resolveCellColor(
5219
+ headerDef?.color ?? headerTableDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,
5220
+ "color"
5221
+ ),
5222
+ backgroundColor: resolveCellColor(
5223
+ headerDef?.backgroundColor ?? headerTableDef?.backgroundColor ?? columnDef?.backgroundColor ?? tableDef?.backgroundColor ?? defaults.backgroundColor,
5224
+ "backgroundColor"
5225
+ ),
4888
5226
  horizontalAlignment: headerDef?.horizontalAlignment ?? headerTableDef?.horizontalAlignment ?? columnDef?.horizontalAlignment ?? tableDef?.horizontalAlignment ?? defaults.horizontalAlignment,
4889
5227
  verticalAlignment: headerDef?.verticalAlignment ?? headerTableDef?.verticalAlignment ?? columnDef?.verticalAlignment ?? tableDef?.verticalAlignment ?? defaults.verticalAlignment,
4890
5228
  font: mergedFont,
@@ -5106,7 +5444,8 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
5106
5444
  void 0
5107
5445
  );
5108
5446
  const headerRow = new TableRow({
5109
- tableHeader: tableConfig.repeatHeaderOnPageBreak,
5447
+ // Headers repeat across page breaks unless explicitly disabled
5448
+ tableHeader: tableConfig.repeatHeaderOnPageBreak ?? true,
5110
5449
  height: headerHeight !== void 0 ? { value: headerHeight * 20, rule: "atLeast" } : void 0,
5111
5450
  children: await Promise.all(
5112
5451
  columns.map(async (column, colIndex) => {
@@ -6437,6 +6776,11 @@ function renderTocComponent(component, theme, context) {
6437
6776
  pageNumbersStart = pageNumbersRange.from;
6438
6777
  pageNumbersEnd = pageNumbersRange.to;
6439
6778
  }
6779
+ if (componentProps.numberingStyle !== void 0) {
6780
+ console.warn(
6781
+ `TOC numberingStyle "${componentProps.numberingStyle}" is ignored: Word's table-of-contents field has no numbering switch. TOC entries inherit numbering from the heading styles they reference.`
6782
+ );
6783
+ }
6440
6784
  const includePageNumbers = componentProps.includePageNumbers !== false;
6441
6785
  const scope = componentProps.scope ?? "auto";
6442
6786
  const effectiveScope = scope === "auto" ? context?.section?.sectionBookmarkId ? "section" : "document" : scope;
@@ -6526,6 +6870,9 @@ function renderTocComponent(component, theme, context) {
6526
6870
  return paragraphs;
6527
6871
  }
6528
6872
 
6873
+ // src/components/highcharts.ts
6874
+ init_colorUtils();
6875
+
6529
6876
  // src/utils/environment.ts
6530
6877
  function isNodeEnvironment() {
6531
6878
  return typeof process !== "undefined" && process.versions != null && process.versions.node != null && typeof process.versions.node === "string";
@@ -6575,6 +6922,7 @@ async function postJsonToService(opts) {
6575
6922
  }
6576
6923
 
6577
6924
  // src/components/highcharts.ts
6925
+ import { DEFAULT_CHART_THEME_COLORS } from "@json-to-office/shared";
6578
6926
  var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
6579
6927
  async function generateChart(config, servicesConfig) {
6580
6928
  if (!isNodeEnvironment()) {
@@ -6615,14 +6963,24 @@ Cause: ${cause}`
6615
6963
  height
6616
6964
  };
6617
6965
  }
6966
+ function toChartColor(value, theme) {
6967
+ if (/^#?[0-9A-Fa-f]{6}$/.test(value)) {
6968
+ return value.startsWith("#") ? value : `#${value}`;
6969
+ }
6970
+ try {
6971
+ return `#${resolveColor(value, theme)}`;
6972
+ } catch {
6973
+ return void 0;
6974
+ }
6975
+ }
6618
6976
  function withThemeColors(config, theme) {
6619
6977
  const options = config.options;
6620
6978
  if (!options || options.colors || !theme?.colors) return config;
6621
- const palette = [
6622
- theme.colors.primary,
6623
- theme.colors.secondary,
6624
- theme.colors.accent
6625
- ].filter((c) => typeof c === "string" && c.length > 0).map((c) => c.startsWith("#") ? c : `#${c}`);
6979
+ const themeColors = theme.colors;
6980
+ const palette = DEFAULT_CHART_THEME_COLORS.map((token) => {
6981
+ const value = themeColors[token];
6982
+ return typeof value === "string" && value.length > 0 ? toChartColor(value, theme) : void 0;
6983
+ }).filter((c) => c !== void 0);
6626
6984
  if (palette.length === 0) return config;
6627
6985
  return {
6628
6986
  ...config,
@@ -6820,6 +7178,22 @@ function getAlignment3(alignment) {
6820
7178
  return AlignmentType5.LEFT;
6821
7179
  }
6822
7180
  }
7181
+ function coreProperties(metadata) {
7182
+ const { title, subtitle, description, author, company, version, tags } = metadata;
7183
+ const customProperties = [
7184
+ ...company ? [{ name: "Company", value: company }] : [],
7185
+ ...version ? [{ name: "Version", value: version }] : []
7186
+ ];
7187
+ return {
7188
+ ...title && { title },
7189
+ ...subtitle && { subject: subtitle },
7190
+ ...description && { description },
7191
+ // Word surfaces both names; author is the only person the document knows.
7192
+ ...author && { creator: author, lastModifiedBy: author },
7193
+ ...tags && tags.length > 0 && { keywords: tags.join(", ") },
7194
+ ...customProperties.length > 0 && { customProperties }
7195
+ };
7196
+ }
6823
7197
  async function renderDocument(structure, layout, options) {
6824
7198
  return runWithGenerationDate(
6825
7199
  structure.metadata.date,
@@ -6908,6 +7282,7 @@ async function renderDocumentScoped(structure, layout, options) {
6908
7282
  return new Document({
6909
7283
  styles: createWordStyles(structure.theme, structure.language),
6910
7284
  sections,
7285
+ ...coreProperties(structure.metadata),
6911
7286
  features: {
6912
7287
  updateFields: true,
6913
7288
  // Required for TOC fields to update correctly
@@ -7325,13 +7700,13 @@ function toDosTime(date) {
7325
7700
  function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
7326
7701
  const zip = new AdmZip2(buffer);
7327
7702
  const isoTimestamp = generatedAt.toISOString();
7328
- const coreProperties = zip.getEntry("docProps/core.xml");
7329
- if (coreProperties) {
7330
- const normalized = coreProperties.getData().toString("utf8").replace(
7703
+ const coreProperties2 = zip.getEntry("docProps/core.xml");
7704
+ if (coreProperties2) {
7705
+ const normalized = coreProperties2.getData().toString("utf8").replace(
7331
7706
  /(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g,
7332
7707
  `$1${isoTimestamp}$2`
7333
7708
  );
7334
- zip.updateFile(coreProperties, Buffer.from(normalized, "utf8"));
7709
+ zip.updateFile(coreProperties2, Buffer.from(normalized, "utf8"));
7335
7710
  }
7336
7711
  const zipTimestamp = toDosTime(generatedAt);
7337
7712
  for (const entry of zip.getEntries()) {
@@ -7351,7 +7726,7 @@ async function packageDocument(document, options) {
7351
7726
  // src/plugin/createDocumentGenerator.ts
7352
7727
  function createBuilderImpl(state) {
7353
7728
  const componentMap = new Map(state.components.map((c) => [c.name, c]));
7354
- function resolveDocumentTheme(themeName) {
7729
+ function resolveDocumentTheme(themeName, warnings) {
7355
7730
  if (state.customThemes) {
7356
7731
  if (state.customThemes[themeName]) {
7357
7732
  return state.customThemes[themeName];
@@ -7366,7 +7741,10 @@ function createBuilderImpl(state) {
7366
7741
  if (state.theme) {
7367
7742
  return state.theme;
7368
7743
  }
7369
- return getThemeWithFallback(themeName);
7744
+ return resolveBuiltInTheme(themeName, {
7745
+ customThemes: state.customThemes,
7746
+ warnings
7747
+ });
7370
7748
  }
7371
7749
  async function processDocumentComponents(components, preserveSet, warningsCollector, resolvedTheme, validateEmitted, depth = 0) {
7372
7750
  if (depth > 20) {
@@ -7530,7 +7908,8 @@ function createBuilderImpl(state) {
7530
7908
  async function generate(document, options) {
7531
7909
  try {
7532
7910
  const preserveSet = resolvePreserveSet(options);
7533
- const internalDocument = document;
7911
+ const rootIn = document;
7912
+ const internalDocument = rootIn.props === void 0 ? { ...rootIn, props: {} } : rootIn;
7534
7913
  const vOpts = {
7535
7914
  ...state.validation,
7536
7915
  ...options?.validation
@@ -7567,9 +7946,9 @@ function createBuilderImpl(state) {
7567
7946
  );
7568
7947
  }
7569
7948
  };
7570
- const baseThemeName = internalDocument.props.theme || "minimal";
7571
- const docTheme = resolveDocumentTheme(baseThemeName);
7572
7949
  const warnings = [];
7950
+ const baseThemeName = internalDocument.props.theme || "minimal";
7951
+ const docTheme = resolveDocumentTheme(baseThemeName, warnings);
7573
7952
  const mode = applyExportMode({
7574
7953
  doc: internalDocument,
7575
7954
  theme: docTheme,