@json-to-office/core-docx 2.4.0 → 2.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/ir/compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA6C3D,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,wBAAwB,CAAC;AAuC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAEL,KAAK,MAAM,EAqCZ,MAAM,SAAS,CAAC;AAiBjB,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,EAAE,SAAS,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;IACrD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AA8FD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,UAAU,EAClB,QAAQ,GAAE,iBAAiB,EAAO,EAClC,MAAM,GAAE,cAA0B,EAClC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,iBAAiB,CAgHnB"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/ir/compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA6C3D,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,wBAAwB,CAAC;AAuC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAEL,KAAK,MAAM,EAqCZ,MAAM,SAAS,CAAC;AAiBjB,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,QAAQ,EAAE,SAAS,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC;IACrD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AA8FD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,UAAU,EAClB,QAAQ,GAAE,iBAAiB,EAAO,EAClC,MAAM,GAAE,cAA0B,EAClC,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,iBAAiB,CAgHnB"}
@@ -9,6 +9,7 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/themes/defaults.ts
12
+ import { designColors } from "@json-to-office/shared";
12
13
  function ensureThemeDefaults(theme) {
13
14
  return {
14
15
  ...theme,
@@ -41,10 +42,13 @@ function ensureThemeDefaults(theme) {
41
42
  };
42
43
  }
43
44
  function getThemeColors(theme) {
44
- return {
45
- ...DEFAULT_COLORS,
46
- ...theme.colors || {}
47
- };
45
+ return designColors(
46
+ {
47
+ ...DEFAULT_COLORS,
48
+ ...theme.colors || {}
49
+ },
50
+ theme.palette
51
+ );
48
52
  }
49
53
  function getThemeFonts(theme) {
50
54
  return {
@@ -873,6 +877,10 @@ var init_themes = __esm({
873
877
  });
874
878
 
875
879
  // src/styles/utils/colorUtils.ts
880
+ import {
881
+ DEFAULT_CHART_THEME_COLORS,
882
+ resolveDesignColor
883
+ } from "@json-to-office/shared";
876
884
  function resolveColor(colorValue, theme) {
877
885
  if (colorValue.startsWith("#")) {
878
886
  const hexValue = colorValue.slice(1);
@@ -886,7 +894,11 @@ function resolveColor(colorValue, theme) {
886
894
  const colors = getThemeColors(theme);
887
895
  const resolvedColor = colors[colorValue];
888
896
  if (typeof resolvedColor === "string") {
889
- return resolveColor(resolvedColor, theme);
897
+ const hex = resolveDesignColor(colorValue, colors);
898
+ if (hex) return hex.toUpperCase();
899
+ throw new Error(
900
+ `Unresolvable theme color: "${colorValue}" (missing reference or cycle).`
901
+ );
890
902
  }
891
903
  if (/^[0-9A-Fa-f]{6}$/.test(colorValue)) {
892
904
  return colorValue.toUpperCase();
@@ -895,6 +907,15 @@ function resolveColor(colorValue, theme) {
895
907
  `Invalid color value: "${colorValue}". Must be a hex color with # prefix (e.g., "#000000") or a valid theme color name.`
896
908
  );
897
909
  }
910
+ function chartPaletteValues(theme) {
911
+ const explicit = theme.palette?.chart;
912
+ if (explicit) return [...explicit];
913
+ const colors = getThemeColors(theme);
914
+ return DEFAULT_CHART_THEME_COLORS.flatMap((token) => {
915
+ const value = colors[token];
916
+ return typeof value === "string" && value.length > 0 ? [value] : [];
917
+ });
918
+ }
898
919
  var init_colorUtils = __esm({
899
920
  "src/styles/utils/colorUtils.ts"() {
900
921
  "use strict";
@@ -984,6 +1005,8 @@ function resolveFontProperties(theme, fontRef) {
984
1005
  size: fontDef.size,
985
1006
  color: fontDef.color,
986
1007
  bold: fontDef.bold,
1008
+ fontWeight: fontDef.fontWeight,
1009
+ case: fontDef.case,
987
1010
  italic: fontDef.italic,
988
1011
  underline: fontDef.underline,
989
1012
  alignment: fontDef.alignment,
@@ -2044,6 +2067,9 @@ function runOptions(formatting) {
2044
2067
  options.underline = formatting.underline ? { type: formatting.underline.type } : void 0;
2045
2068
  }
2046
2069
  if (formatting.strike !== void 0) options.strike = formatting.strike;
2070
+ if (formatting.allCaps !== void 0) options.allCaps = formatting.allCaps;
2071
+ if (formatting.smallCaps !== void 0)
2072
+ options.smallCaps = formatting.smallCaps;
2047
2073
  if (formatting.scalePercent !== void 0) {
2048
2074
  options.scale = formatting.scalePercent;
2049
2075
  }
@@ -2734,6 +2760,44 @@ var init_styles2 = __esm({
2734
2760
  }
2735
2761
  });
2736
2762
 
2763
+ // src/utils/normalizeTextCase.ts
2764
+ function normalizeTextCase(zip) {
2765
+ let changed = false;
2766
+ for (const entry of zip.getEntries()) {
2767
+ if (!WORD_XML.test(entry.entryName)) continue;
2768
+ const xml = entry.getData().toString("utf8");
2769
+ if (!ANY_CASE_FLAG.test(xml)) continue;
2770
+ const normalized = xml.replace(RUN_PROPERTIES, completeCaseFlags);
2771
+ if (normalized === xml) continue;
2772
+ zip.updateFile(entry, Buffer.from(normalized, "utf8"));
2773
+ changed = true;
2774
+ }
2775
+ return changed;
2776
+ }
2777
+ function completeCaseFlags(runProperties3) {
2778
+ const flag = CASE_FLAG.exec(runProperties3);
2779
+ if (!flag) return runProperties3;
2780
+ const isCaps = flag[1] === "caps";
2781
+ const opposite = `<w:${isCaps ? "smallCaps" : "caps"} w:val="false"/>`;
2782
+ if (runProperties3.includes(`<w:${isCaps ? "smallCaps" : "caps"}`)) {
2783
+ return runProperties3;
2784
+ }
2785
+ return runProperties3.replace(
2786
+ flag[0],
2787
+ isCaps ? `${flag[0]}${opposite}` : `${opposite}${flag[0]}`
2788
+ );
2789
+ }
2790
+ var WORD_XML, ANY_CASE_FLAG, RUN_PROPERTIES, CASE_FLAG;
2791
+ var init_normalizeTextCase = __esm({
2792
+ "src/utils/normalizeTextCase.ts"() {
2793
+ "use strict";
2794
+ WORD_XML = /^word\/.*\.xml$/;
2795
+ ANY_CASE_FLAG = /<w:(?:caps|smallCaps)\b/;
2796
+ RUN_PROPERTIES = /<w:rPr\b[^>]*>[\s\S]*?<\/w:rPr>/g;
2797
+ CASE_FLAG = /<w:(caps|smallCaps)\b[^>]*(?:\/>|>[\s\S]*?<\/w:\1>)/;
2798
+ }
2799
+ });
2800
+
2737
2801
  // src/utils/packageDocument.ts
2738
2802
  import AdmZip from "adm-zip";
2739
2803
  function resolveGenerationDate(options) {
@@ -2802,6 +2866,7 @@ function canonicalizeRelationshipIds(zip) {
2802
2866
  }
2803
2867
  function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
2804
2868
  const zip = new AdmZip(buffer);
2869
+ normalizeTextCase(zip);
2805
2870
  canonicalizeRelationshipIds(zip);
2806
2871
  const isoTimestamp = generatedAt.toISOString();
2807
2872
  const coreProperties3 = zip.getEntry("docProps/core.xml");
@@ -2818,10 +2883,15 @@ function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
2818
2883
  }
2819
2884
  return zip.toBuffer();
2820
2885
  }
2886
+ function normalizeDocxCaseBuffer(buffer) {
2887
+ const zip = new AdmZip(buffer);
2888
+ return normalizeTextCase(zip) ? zip.toBuffer() : buffer;
2889
+ }
2821
2890
  var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID;
2822
2891
  var init_packageDocument = __esm({
2823
2892
  "src/utils/packageDocument.ts"() {
2824
2893
  "use strict";
2894
+ init_normalizeTextCase();
2825
2895
  DEFAULT_GENERATION_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
2826
2896
  STABLE_RELATIONSHIP_ID = /^rId\d+$/;
2827
2897
  }
@@ -2880,7 +2950,8 @@ function createDocxJsRenderer() {
2880
2950
  const document = buildDocument(ir, resources);
2881
2951
  const packed = await Packer.toBuffer(document);
2882
2952
  const fixed = fixFloatingImageIdsInBuffer(packed);
2883
- if (renderOptions?.deterministic === false) return new Uint8Array(fixed);
2953
+ if (renderOptions?.deterministic === false)
2954
+ return new Uint8Array(normalizeDocxCaseBuffer(fixed));
2884
2955
  return new Uint8Array(
2885
2956
  canonicalizeDocxBuffer(
2886
2957
  fixed,
@@ -4159,7 +4230,8 @@ async function createOfficeOpenDocxRenderer() {
4159
4230
  spliceChartParts(zip, charts);
4160
4231
  raw = zip.toBuffer();
4161
4232
  }
4162
- if (options?.deterministic === false) return new Uint8Array(raw);
4233
+ if (options?.deterministic === false)
4234
+ return new Uint8Array(normalizeDocxCaseBuffer(raw));
4163
4235
  return new Uint8Array(
4164
4236
  canonicalizeDocxBuffer(
4165
4237
  raw,
@@ -4518,6 +4590,7 @@ init_themes();
4518
4590
  import { applyExportMode } from "@json-to-office/shared";
4519
4591
 
4520
4592
  // src/themes/overrides.ts
4593
+ import { mergeWithDefaults } from "@json-to-office/shared";
4521
4594
  function applyThemeOverrides(theme, overrides) {
4522
4595
  if (!overrides) return theme;
4523
4596
  const fonts = { ...theme.fonts };
@@ -4531,12 +4604,87 @@ function applyThemeOverrides(theme, overrides) {
4531
4604
  }
4532
4605
  return {
4533
4606
  ...theme,
4607
+ ...Object.fromEntries(
4608
+ ["palette", "typography", "spacing", "chrome", "motif"].flatMap(
4609
+ (name) => {
4610
+ const key = name;
4611
+ return overrides[key] === void 0 ? [] : [[key, mergeWithDefaults(overrides[key], theme[key] ?? {})]];
4612
+ }
4613
+ )
4614
+ ),
4534
4615
  colors: { ...theme.colors, ...overrides.colors ?? {} },
4535
4616
  fonts,
4536
4617
  ...Object.keys(styles).length > 0 && { styles }
4537
4618
  };
4538
4619
  }
4539
4620
 
4621
+ // src/themes/design-system.ts
4622
+ init_defaults();
4623
+ import {
4624
+ designCanvas,
4625
+ resolveTypeRoles,
4626
+ validateDesignColors
4627
+ } from "@json-to-office/shared";
4628
+ function resolveDocxDesignSystem(theme) {
4629
+ validateDesignColors(theme, getThemeColors(theme));
4630
+ if (!theme.typography && !theme.spacing) return theme;
4631
+ const canvas = designCanvas("docx", theme.page.size);
4632
+ const roles = resolveTypeRoles(theme, canvas, theme.fonts.body.size ?? 11);
4633
+ const styles = { ...theme.styles };
4634
+ for (const [name, role] of Object.entries(roles)) {
4635
+ const spacing = {
4636
+ ...role.spaceBefore !== void 0 && { before: role.spaceBefore },
4637
+ ...role.spaceAfter !== void 0 && { after: role.spaceAfter }
4638
+ };
4639
+ styles[name] = {
4640
+ font: role.face ?? "body",
4641
+ size: role.size,
4642
+ ...role.weight !== void 0 && { fontWeight: role.weight },
4643
+ ...role.color !== void 0 && { color: role.color },
4644
+ ...role.case !== void 0 && { case: role.case },
4645
+ ...role.lineHeight !== void 0 && {
4646
+ lineSpacing: { type: "multiple", value: role.lineHeight }
4647
+ },
4648
+ ...role.tracking !== void 0 && {
4649
+ characterSpacing: {
4650
+ type: role.tracking < 0 ? "condensed" : "expanded",
4651
+ value: Math.abs(role.tracking) * role.size / 5
4652
+ }
4653
+ },
4654
+ ...Object.keys(spacing).length && { spacing },
4655
+ ...styles[name]
4656
+ };
4657
+ }
4658
+ const gap = theme.spacing?.blockGap?.normal ?? theme.spacing?.basePt;
4659
+ const scale = theme.typography?.scale?.[canvas];
4660
+ if (scale || gap !== void 0) {
4661
+ styles.normal = {
4662
+ ...scale && { size: scale.base },
4663
+ ...gap !== void 0 && { spacing: { after: gap } },
4664
+ ...styles.normal
4665
+ };
4666
+ }
4667
+ const space = theme.spacing?.canvas?.[canvas];
4668
+ const safe = space?.safeAreaIn;
4669
+ return {
4670
+ ...theme,
4671
+ styles,
4672
+ page: {
4673
+ ...theme.page,
4674
+ margins: {
4675
+ ...theme.page.margins,
4676
+ ...safe !== void 0 && {
4677
+ top: safe * 1440,
4678
+ bottom: safe * 1440,
4679
+ left: safe * 1440,
4680
+ right: safe * 1440
4681
+ },
4682
+ ...space?.gutterIn !== void 0 && { gutter: space.gutterIn * 1440 }
4683
+ }
4684
+ }
4685
+ };
4686
+ }
4687
+
4540
4688
  // src/core/generationContext.ts
4541
4689
  function defaultNamedThemeLookup(themeName, customThemes, warnings) {
4542
4690
  if (customThemes) {
@@ -4569,6 +4717,7 @@ function resolveThemeContext(documentIn, options = {}) {
4569
4717
  if (themeOverrides) {
4570
4718
  theme = applyThemeOverrides(theme, themeOverrides);
4571
4719
  }
4720
+ theme = resolveDocxDesignSystem(theme);
4572
4721
  const mode = applyExportMode({ doc: document, theme, fonts });
4573
4722
  for (const w of mode.warnings) {
4574
4723
  if (warnings) {
@@ -5216,7 +5365,6 @@ import {
5216
5365
 
5217
5366
  // src/components/highcharts.ts
5218
5367
  init_colorUtils();
5219
- import { DEFAULT_CHART_THEME_COLORS } from "@json-to-office/shared";
5220
5368
  var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
5221
5369
  async function generateChart(config, servicesConfig) {
5222
5370
  if (!isNodeEnvironment()) {
@@ -5270,11 +5418,10 @@ function toChartColor(value, theme) {
5270
5418
  function withThemeColors(config, theme) {
5271
5419
  const options = config.options;
5272
5420
  if (!options || options.colors || !theme?.colors) return config;
5273
- const themeColors = theme.colors;
5274
- const palette = DEFAULT_CHART_THEME_COLORS.map((token) => {
5275
- const value = themeColors[token];
5276
- return typeof value === "string" && value.length > 0 ? toChartColor(value, theme) : void 0;
5277
- }).filter((c) => c !== void 0);
5421
+ const palette = chartPaletteValues(theme).flatMap((value) => {
5422
+ const color = toChartColor(value, theme);
5423
+ return color ? [color] : [];
5424
+ });
5278
5425
  if (palette.length === 0) return config;
5279
5426
  return {
5280
5427
  ...config,
@@ -5520,10 +5667,7 @@ init_colorUtils();
5520
5667
  import {
5521
5668
  FeatureRequirementCollector
5522
5669
  } from "@json-to-office/shared/rendering";
5523
- import {
5524
- synthesizeFamilyName,
5525
- DEFAULT_CHART_THEME_COLORS as DEFAULT_CHART_THEME_COLORS2
5526
- } from "@json-to-office/shared";
5670
+ import { capsFormatting as capsFormatting2, synthesizeFamilyName as synthesizeFamilyName2 } from "@json-to-office/shared";
5527
5671
  import {
5528
5672
  isNativeVisualProps as isNativeVisualProps4
5529
5673
  } from "@json-to-office/shared-docx";
@@ -6039,6 +6183,7 @@ function resolveColors(entries, at, deps) {
6039
6183
  init_themes();
6040
6184
  init_colorUtils();
6041
6185
  init_styleHelpers();
6186
+ import { capsFormatting, synthesizeFamilyName } from "@json-to-office/shared";
6042
6187
  var RIGHT_MARGIN_TAB_TWIPS = 9026 * 2;
6043
6188
  var STATISTIC_NUMBER_STYLE_ID = "StatisticNumber";
6044
6189
  var STATISTIC_DESCRIPTION_STYLE_ID = "StatisticDescription";
@@ -6047,25 +6192,8 @@ var STATISTIC_SIZE_POINTS = {
6047
6192
  medium: 28,
6048
6193
  large: 40
6049
6194
  };
6050
- function isValidStyleName(name) {
6051
- return [
6052
- "normal",
6053
- "heading1",
6054
- "heading2",
6055
- "heading3",
6056
- "heading4",
6057
- "heading5",
6058
- "heading6",
6059
- "title",
6060
- "subtitle"
6061
- ].includes(name);
6062
- }
6063
6195
  function getStyleSafe(theme, styleName) {
6064
- if (!isValidStyleName(styleName)) {
6065
- console.warn(`Invalid style name: ${styleName}`);
6066
- return void 0;
6067
- }
6068
- return theme.styles?.[styleName];
6196
+ return theme.styles && Object.hasOwn(theme.styles, styleName) ? theme.styles[styleName] : void 0;
6069
6197
  }
6070
6198
  function resolveStyleWithBaseStyle(theme, styleName, visited = /* @__PURE__ */ new Set()) {
6071
6199
  if (visited.has(styleName)) {
@@ -6122,9 +6250,17 @@ function resolveSpacing(spacing) {
6122
6250
  ...spacing?.after ? { afterTwips: pointsToTwips(spacing.after) } : {}
6123
6251
  };
6124
6252
  }
6253
+ function weightedFamily(props) {
6254
+ return props.fontWeight === void 0 ? void 0 : synthesizeFamilyName(
6255
+ props.family || "Arial",
6256
+ props.fontWeight,
6257
+ props.italic === true
6258
+ );
6259
+ }
6125
6260
  function convertRunProperties(merged, theme, defaultColor, defaultSize) {
6261
+ const weighted = weightedFamily(merged);
6126
6262
  return {
6127
- fontFamily: merged.family || "Arial",
6263
+ fontFamily: weighted?.family ?? merged.family ?? "Arial",
6128
6264
  sizeHalfPoints: (merged.size || defaultSize || 11) * 2,
6129
6265
  color: {
6130
6266
  hex: resolveColor(
@@ -6134,6 +6270,8 @@ function convertRunProperties(merged, theme, defaultColor, defaultSize) {
6134
6270
  },
6135
6271
  ...merged.bold !== void 0 && { bold: merged.bold },
6136
6272
  ...merged.italic !== void 0 && { italic: merged.italic },
6273
+ ...weighted && { bold: weighted.bold, italic: weighted.italic },
6274
+ ...merged.case !== void 0 && capsFormatting(merged.case),
6137
6275
  ...merged.underline !== void 0 && merged.underline && { underline: { type: "single" } },
6138
6276
  ...merged.characterSpacing && {
6139
6277
  characterSpacingTwentieths: merged.characterSpacing.type === "condensed" ? -merged.characterSpacing.value : merged.characterSpacing.value
@@ -6206,12 +6344,15 @@ function convertBorders(borders3, theme) {
6206
6344
  return Object.keys(converted).length > 0 ? converted : void 0;
6207
6345
  }
6208
6346
  function fallbackRun(fontProps, theme, defaultColor, defaultSize) {
6347
+ const weighted = weightedFamily(fontProps);
6209
6348
  return {
6210
- fontFamily: fontProps.family || "Arial",
6349
+ fontFamily: weighted?.family ?? fontProps.family ?? "Arial",
6211
6350
  sizeHalfPoints: (fontProps.size || defaultSize) * 2,
6212
6351
  color: { hex: resolveColor(fontProps.color || defaultColor, theme) },
6213
6352
  ...fontProps.bold !== void 0 && { bold: fontProps.bold },
6214
6353
  ...fontProps.italic !== void 0 && { italic: fontProps.italic },
6354
+ ...weighted && { bold: weighted.bold, italic: weighted.italic },
6355
+ ...fontProps.case !== void 0 && capsFormatting(fontProps.case),
6215
6356
  ...fontProps.underline !== void 0 && fontProps.underline && { underline: { type: "single" } }
6216
6357
  };
6217
6358
  }
@@ -6241,6 +6382,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6241
6382
  size: normalStyle?.size,
6242
6383
  color: normalStyle?.color,
6243
6384
  bold: normalStyle?.bold,
6385
+ fontWeight: normalStyle?.fontWeight,
6386
+ case: normalStyle?.case,
6244
6387
  italic: normalStyle?.italic,
6245
6388
  underline: normalStyle?.underline,
6246
6389
  characterSpacing: normalStyle?.characterSpacing,
@@ -6280,6 +6423,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6280
6423
  size: headingStyle.size,
6281
6424
  color: headingStyle.color,
6282
6425
  bold: headingStyle.bold,
6426
+ fontWeight: headingStyle.fontWeight,
6427
+ case: headingStyle.case,
6283
6428
  italic: headingStyle.italic,
6284
6429
  underline: headingStyle.underline,
6285
6430
  characterSpacing: headingStyle.characterSpacing,
@@ -6340,6 +6485,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6340
6485
  size: headingStyle.size,
6341
6486
  color: headingStyle.color,
6342
6487
  bold: headingStyle.bold,
6488
+ fontWeight: headingStyle.fontWeight,
6489
+ case: headingStyle.case,
6343
6490
  italic: headingStyle.italic,
6344
6491
  underline: headingStyle.underline,
6345
6492
  characterSpacing: headingStyle.characterSpacing,
@@ -6401,6 +6548,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6401
6548
  size: titleStyle.size,
6402
6549
  color: titleStyle.color,
6403
6550
  bold: titleStyle.bold,
6551
+ fontWeight: titleStyle.fontWeight,
6552
+ case: titleStyle.case,
6404
6553
  italic: titleStyle.italic,
6405
6554
  underline: titleStyle.underline,
6406
6555
  characterSpacing: titleStyle.characterSpacing,
@@ -6456,6 +6605,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6456
6605
  size: subtitleStyle.size,
6457
6606
  color: subtitleStyle.color,
6458
6607
  bold: subtitleStyle.bold,
6608
+ fontWeight: subtitleStyle.fontWeight,
6609
+ case: subtitleStyle.case,
6459
6610
  italic: subtitleStyle.italic,
6460
6611
  underline: subtitleStyle.underline,
6461
6612
  characterSpacing: subtitleStyle.characterSpacing,
@@ -6578,6 +6729,8 @@ function createDocumentStyles(themeNameOrObject = "minimal", language) {
6578
6729
  size: customStyle.size,
6579
6730
  color: customStyle.color,
6580
6731
  bold: customStyle.bold,
6732
+ fontWeight: customStyle.fontWeight,
6733
+ case: customStyle.case,
6581
6734
  italic: customStyle.italic,
6582
6735
  underline: customStyle.underline,
6583
6736
  characterSpacing: customStyle.characterSpacing,
@@ -8453,6 +8606,7 @@ function compileChromeParagraph(component, scope) {
8453
8606
  italic: font.italic ?? false,
8454
8607
  ...font.underline !== void 0 ? { underline: font.underline } : {},
8455
8608
  ...font.fontWeight !== void 0 ? { fontWeight: font.fontWeight } : {},
8609
+ ...font.case !== void 0 ? { case: font.case } : {},
8456
8610
  ...font.lineSpacing !== void 0 ? { lineSpacing: font.lineSpacing } : {}
8457
8611
  }
8458
8612
  };
@@ -9756,7 +9910,11 @@ function isoDateTime(date) {
9756
9910
  }
9757
9911
  function runFormatting3(font, props, ctx) {
9758
9912
  const hasWeightRequest = font.fontWeight != null || font.bold === true;
9759
- const effectiveFamily = font.family ?? (hasWeightRequest ? resolveBodyFamily(ctx.theme) : void 0);
9913
+ const roleName = props.themeStyle;
9914
+ const role = roleName ? ctx.theme.typography?.roles?.[roleName] : void 0;
9915
+ const roleStyles = ctx.theme.styles;
9916
+ const roleFamily = role && roleName ? resolveFontFamily(ctx.theme, roleStyles?.[roleName]?.font ?? role.face) : void 0;
9917
+ const effectiveFamily = font.family ?? (hasWeightRequest ? roleFamily ?? resolveBodyFamily(ctx.theme) : void 0);
9760
9918
  const weighted = applyFontWeightAlias({
9761
9919
  fontFamily: effectiveFamily,
9762
9920
  bold: font.bold,
@@ -9764,7 +9922,7 @@ function runFormatting3(font, props, ctx) {
9764
9922
  fontWeight: font.fontWeight
9765
9923
  });
9766
9924
  const formatting = {};
9767
- if (font.family || weighted.font && weighted.font !== effectiveFamily) {
9925
+ if (font.family || hasWeightRequest && roleFamily || weighted.font && weighted.font !== effectiveFamily) {
9768
9926
  formatting.fontFamily = weighted.font;
9769
9927
  }
9770
9928
  if (font.size) formatting.sizeHalfPoints = pointsToHalfPoints(font.size);
@@ -9776,6 +9934,8 @@ function runFormatting3(font, props, ctx) {
9776
9934
  formatting.underline = font.underline ? { type: "single" } : void 0;
9777
9935
  }
9778
9936
  if (font.scale) formatting.scalePercent = font.scale;
9937
+ if (font.case !== void 0)
9938
+ Object.assign(formatting, capsFormatting2(font.case));
9779
9939
  if (font.characterSpacing) {
9780
9940
  const { type, value } = font.characterSpacing;
9781
9941
  formatting.characterSpacingTwentieths = type === "condensed" ? -value : value;
@@ -9789,7 +9949,7 @@ function applyFontWeightAlias(opts) {
9789
9949
  return { bold: opts.bold, italic: opts.italic };
9790
9950
  }
9791
9951
  const weight = opts.fontWeight ?? (opts.bold === true ? 700 : void 0);
9792
- const synth = synthesizeFamilyName(
9952
+ const synth = synthesizeFamilyName2(
9793
9953
  opts.fontFamily,
9794
9954
  weight,
9795
9955
  opts.italic === true
@@ -10128,15 +10288,13 @@ function compileChart(component, scope) {
10128
10288
  }
10129
10289
  const colors = Array.isArray(props.chartColors) ? props.chartColors.map(
10130
10290
  (color) => resolveColor(String(color), ctx.theme)
10131
- ) : DEFAULT_CHART_THEME_COLORS2.map((token) => {
10132
- const value = ctx.theme?.colors?.[token];
10133
- if (typeof value !== "string" || value.length === 0) return void 0;
10291
+ ) : chartPaletteValues(ctx.theme).flatMap((value) => {
10134
10292
  try {
10135
- return resolveColor(token, ctx.theme);
10293
+ return [resolveColor(value, ctx.theme)];
10136
10294
  } catch {
10137
- return void 0;
10295
+ return [];
10138
10296
  }
10139
- }).filter((color) => color !== void 0);
10297
+ });
10140
10298
  const page = getPageSetup(ctx.theme);
10141
10299
  const contentWidthInches = (page.size.width - page.margin.left - page.margin.right) / 1440;
10142
10300
  const widthInches = typeof props.width === "number" ? props.width : contentWidthInches;
@@ -11203,8 +11361,8 @@ var formatDate = (date, formatString = "MMMM d, yyyy") => {
11203
11361
  };
11204
11362
 
11205
11363
  // src/styles/utils/componentDefaults.ts
11206
- import { mergeWithDefaults } from "@json-to-office/shared";
11207
11364
  import { mergeWithDefaults as mergeWithDefaults2 } from "@json-to-office/shared";
11365
+ import { mergeWithDefaults as mergeWithDefaults3 } from "@json-to-office/shared";
11208
11366
  function getComponentDefaults(theme) {
11209
11367
  return theme.componentDefaults || {};
11210
11368
  }
@@ -11253,35 +11411,35 @@ function getListDefaults(theme) {
11253
11411
  }
11254
11412
  function resolveHeadingProps(props, theme) {
11255
11413
  const defaults = getHeadingDefaults(theme);
11256
- return mergeWithDefaults(props, defaults);
11414
+ return mergeWithDefaults2(props, defaults);
11257
11415
  }
11258
11416
  function resolveParagraphProps(props, theme) {
11259
11417
  const defaults = getTextDefaults(theme);
11260
- return mergeWithDefaults(props, defaults);
11418
+ return mergeWithDefaults2(props, defaults);
11261
11419
  }
11262
11420
  function resolveImageProps(props, theme) {
11263
11421
  const defaults = getImageDefaults(theme);
11264
- return mergeWithDefaults(props, defaults);
11422
+ return mergeWithDefaults2(props, defaults);
11265
11423
  }
11266
11424
  function resolveStatisticProps(props, theme) {
11267
11425
  const defaults = getStatisticDefaults(theme);
11268
- return mergeWithDefaults(props, defaults);
11426
+ return mergeWithDefaults2(props, defaults);
11269
11427
  }
11270
11428
  function resolveTableProps(props, theme) {
11271
11429
  const defaults = getTableDefaults(theme);
11272
- return mergeWithDefaults(props, defaults);
11430
+ return mergeWithDefaults2(props, defaults);
11273
11431
  }
11274
11432
  function resolveSectionProps(props, theme) {
11275
11433
  const defaults = getSectionDefaults(theme);
11276
- return mergeWithDefaults(props, defaults);
11434
+ return mergeWithDefaults2(props, defaults);
11277
11435
  }
11278
11436
  function resolveColumnsProps(props, theme) {
11279
11437
  const defaults = getColumnsDefaults(theme);
11280
- return mergeWithDefaults(props, defaults);
11438
+ return mergeWithDefaults2(props, defaults);
11281
11439
  }
11282
11440
  function resolveListProps(props, theme) {
11283
11441
  const defaults = getListDefaults(theme);
11284
- return mergeWithDefaults(props, defaults);
11442
+ return mergeWithDefaults2(props, defaults);
11285
11443
  }
11286
11444
  function resolveHighchartsProps(props, _theme) {
11287
11445
  return props;
@@ -11295,7 +11453,7 @@ function getCustomComponentDefaults(theme, componentName) {
11295
11453
  }
11296
11454
  function resolveCustomComponentProps(props, theme, componentName) {
11297
11455
  const defaults = getCustomComponentDefaults(theme, componentName);
11298
- return mergeWithDefaults(props, defaults);
11456
+ return mergeWithDefaults2(props, defaults);
11299
11457
  }
11300
11458
 
11301
11459
  // src/styles/utils/resolveComponentTree.ts
@@ -11348,7 +11506,7 @@ function resolveComponentTree(components, theme) {
11348
11506
  // src/core/structure.ts
11349
11507
  function resolveDocumentTree(document, theme) {
11350
11508
  const docDefaults = document.props.componentDefaults;
11351
- const mergedComponentDefaults = docDefaults ? mergeWithDefaults2(docDefaults, theme.componentDefaults || {}) : void 0;
11509
+ const mergedComponentDefaults = docDefaults ? mergeWithDefaults3(docDefaults, theme.componentDefaults || {}) : void 0;
11352
11510
  const docNoProofWords = document.props.noProofWords;
11353
11511
  const mergedNoProofWords = docNoProofWords || theme.noProofWords ? Array.from(
11354
11512
  /* @__PURE__ */ new Set([...theme.noProofWords || [], ...docNoProofWords || []])
@@ -11489,6 +11647,7 @@ import {
11489
11647
  normalizeHighchartsChart
11490
11648
  } from "@json-to-office/quality";
11491
11649
  import { DEFAULT_DOCX_RENDERER_ID as DEFAULT_DOCX_RENDERER_ID2 } from "@json-to-office/shared-docx";
11650
+ import { designColors as designColors2, resolveDesignColor as resolveDesignColor2 } from "@json-to-office/shared";
11492
11651
 
11493
11652
  // src/json/normalizer.ts
11494
11653
  function normalizeComponent(component) {
@@ -12020,16 +12179,27 @@ function prepareDocxQualityDocument(document, options = {}) {
12020
12179
  };
12021
12180
  };
12022
12181
  const paletteHexes = {};
12023
- for (const [token, value] of Object.entries(
12024
- resolved.theme.colors ?? {}
12025
- )) {
12182
+ const visualColors = designColors2(
12183
+ resolved.theme.colors,
12184
+ resolved.theme.palette
12185
+ );
12186
+ const entries = {
12187
+ ...visualColors,
12188
+ ...Object.fromEntries(
12189
+ (resolved.theme.palette?.chart ?? []).map((value) => {
12190
+ const hex = resolveDesignColor2(value, visualColors);
12191
+ return [hex ? `#${hex}` : value, value];
12192
+ })
12193
+ )
12194
+ };
12195
+ for (const [token, value] of Object.entries(entries)) {
12026
12196
  if (typeof value !== "string") continue;
12027
- const hex = normalizeHex(value);
12197
+ const hex = normalizeHex(resolveDesignColor2(value, visualColors) ?? value);
12028
12198
  if (hex) paletteHexes[token] = hex;
12029
12199
  }
12030
- const paletteTokens = SERIES_COLOR_TOKENS.filter(
12031
- (token) => paletteHexes[token] !== void 0
12032
- );
12200
+ const paletteTokens = resolved.theme.palette?.chart?.map(
12201
+ (value) => `#${resolveDesignColor2(value, visualColors)}`
12202
+ ) ?? SERIES_COLOR_TOKENS.filter((token) => paletteHexes[token] !== void 0);
12033
12203
  const authoredPropsAt = (pointer) => asRecord(asRecord(nodeAtPointer(context.document, pointer))?.props);
12034
12204
  addFact({
12035
12205
  id: "docx:theme",