@json-to-office/core-docx 0.7.0 → 0.8.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.
@@ -1969,24 +1969,175 @@ var formatDate = (date, formatString = "MMMM d, yyyy") => {
1969
1969
  return format(date, formatString);
1970
1970
  };
1971
1971
 
1972
+ // src/styles/utils/componentDefaults.ts
1973
+ import { mergeWithDefaults } from "@json-to-office/shared";
1974
+ import { mergeWithDefaults as mergeWithDefaults2 } from "@json-to-office/shared";
1975
+ function getComponentDefaults(theme) {
1976
+ return theme.componentDefaults || {};
1977
+ }
1978
+ function getHeadingDefaults(theme) {
1979
+ const defaults = getComponentDefaults(theme);
1980
+ return defaults?.heading || {};
1981
+ }
1982
+ function getHeadingDefaultsForLevel(theme, level) {
1983
+ const defaults = {};
1984
+ if (theme.styles) {
1985
+ const styleKey = `heading${level}`;
1986
+ const headingStyle = theme.styles[styleKey];
1987
+ if (headingStyle?.alignment) {
1988
+ defaults.alignment = headingStyle.alignment;
1989
+ }
1990
+ }
1991
+ return defaults;
1992
+ }
1993
+ function getTextDefaults(theme) {
1994
+ const defaults = getComponentDefaults(theme);
1995
+ return defaults?.paragraph || {};
1996
+ }
1997
+ function getImageDefaults(theme) {
1998
+ const defaults = getComponentDefaults(theme);
1999
+ return defaults?.image || {};
2000
+ }
2001
+ function getStatisticDefaults(theme) {
2002
+ const defaults = getComponentDefaults(theme);
2003
+ return defaults?.statistic || {};
2004
+ }
2005
+ function getTableDefaults(theme) {
2006
+ const defaults = getComponentDefaults(theme);
2007
+ return defaults?.table || {};
2008
+ }
2009
+ function getSectionDefaults(theme) {
2010
+ const defaults = getComponentDefaults(theme);
2011
+ return defaults?.section || {};
2012
+ }
2013
+ function getColumnsDefaults(theme) {
2014
+ const defaults = getComponentDefaults(theme);
2015
+ return defaults?.columns || {};
2016
+ }
2017
+ function getListDefaults(theme) {
2018
+ const defaults = getComponentDefaults(theme);
2019
+ return defaults?.list || {};
2020
+ }
2021
+ function resolveHeadingProps(props, theme) {
2022
+ const defaults = getHeadingDefaults(theme);
2023
+ return mergeWithDefaults(props, defaults);
2024
+ }
2025
+ function resolveParagraphProps(props, theme) {
2026
+ const defaults = getTextDefaults(theme);
2027
+ return mergeWithDefaults(props, defaults);
2028
+ }
2029
+ function resolveImageProps(props, theme) {
2030
+ const defaults = getImageDefaults(theme);
2031
+ return mergeWithDefaults(props, defaults);
2032
+ }
2033
+ function resolveStatisticProps(props, theme) {
2034
+ const defaults = getStatisticDefaults(theme);
2035
+ return mergeWithDefaults(props, defaults);
2036
+ }
2037
+ function resolveTableProps(props, theme) {
2038
+ const defaults = getTableDefaults(theme);
2039
+ return mergeWithDefaults(props, defaults);
2040
+ }
2041
+ function resolveSectionProps(props, theme) {
2042
+ const defaults = getSectionDefaults(theme);
2043
+ return mergeWithDefaults(props, defaults);
2044
+ }
2045
+ function resolveColumnsProps(props, theme) {
2046
+ const defaults = getColumnsDefaults(theme);
2047
+ return mergeWithDefaults(props, defaults);
2048
+ }
2049
+ function resolveListProps(props, theme) {
2050
+ const defaults = getListDefaults(theme);
2051
+ return mergeWithDefaults(props, defaults);
2052
+ }
2053
+ function resolveHighchartsProps(props, _theme) {
2054
+ return props;
2055
+ }
2056
+ function getCustomComponentDefaults(theme, componentName) {
2057
+ const defaults = getComponentDefaults(theme);
2058
+ return defaults?.[componentName] || {};
2059
+ }
2060
+ function resolveCustomComponentProps(props, theme, componentName) {
2061
+ const defaults = getCustomComponentDefaults(theme, componentName);
2062
+ return mergeWithDefaults(props, defaults);
2063
+ }
2064
+
2065
+ // src/styles/utils/resolveComponentTree.ts
2066
+ function resolveHeadingWithLevelDefaults(props, theme) {
2067
+ const resolved = resolveHeadingProps(props, theme);
2068
+ const level = resolved.level || 1;
2069
+ const levelDefaults = getHeadingDefaultsForLevel(theme, level);
2070
+ return {
2071
+ ...resolved,
2072
+ // Only apply level-specific defaults if no explicit alignment in original props
2073
+ ...props.alignment ? {} : levelDefaults
2074
+ };
2075
+ }
2076
+ var RESOLVER_MAP = {
2077
+ heading: resolveHeadingWithLevelDefaults,
2078
+ paragraph: resolveParagraphProps,
2079
+ image: resolveImageProps,
2080
+ statistic: resolveStatisticProps,
2081
+ table: resolveTableProps,
2082
+ section: resolveSectionProps,
2083
+ columns: resolveColumnsProps,
2084
+ list: resolveListProps,
2085
+ highcharts: resolveHighchartsProps
2086
+ };
2087
+ function resolveComponentDefaults(component, theme) {
2088
+ if (!component.props) return component;
2089
+ const resolver = RESOLVER_MAP[component.name];
2090
+ const resolvedProps = resolver ? resolver(component.props, theme) : resolveCustomComponentProps(
2091
+ component.props,
2092
+ theme,
2093
+ component.name
2094
+ );
2095
+ return { ...component, props: resolvedProps };
2096
+ }
2097
+ function resolveComponentTree(components, theme) {
2098
+ return components.map((component) => {
2099
+ const resolved = resolveComponentDefaults(component, theme);
2100
+ const children = resolved.children;
2101
+ if (children && children.length > 0) {
2102
+ return {
2103
+ ...resolved,
2104
+ children: resolveComponentTree(children, theme)
2105
+ };
2106
+ }
2107
+ return resolved;
2108
+ });
2109
+ }
2110
+
1972
2111
  // src/core/structure.ts
1973
2112
  async function processDocument(document, theme, themeName) {
1974
2113
  const metadata = createDocumentMetadata(document.props);
2114
+ const docDefaults = document.props.componentDefaults;
2115
+ const effectiveTheme = docDefaults ? {
2116
+ ...theme,
2117
+ componentDefaults: mergeWithDefaults2(
2118
+ docDefaults,
2119
+ theme.componentDefaults || {}
2120
+ )
2121
+ } : theme;
1975
2122
  const context = createRenderContext(
1976
2123
  {
1977
2124
  metadata,
1978
2125
  sections: [],
1979
- theme,
2126
+ theme: effectiveTheme,
1980
2127
  themeName
1981
2128
  },
1982
- theme,
2129
+ effectiveTheme,
1983
2130
  themeName
1984
2131
  );
1985
- const sections = await extractSections(document.children || [], context);
2132
+ const resolvedChildren = resolveComponentTree(
2133
+ document.children || [],
2134
+ effectiveTheme
2135
+ );
2136
+ const sections = await extractSections(resolvedChildren, context);
1986
2137
  return {
1987
2138
  metadata,
1988
2139
  sections,
1989
- theme,
2140
+ theme: effectiveTheme,
1990
2141
  themeName
1991
2142
  };
1992
2143
  }
@@ -2016,19 +2167,24 @@ async function extractSections(components, context) {
2016
2167
  Math.max(component.props.level || 1, 1),
2017
2168
  6
2018
2169
  );
2019
- sectionComponents.unshift({
2020
- name: "heading",
2021
- props: {
2022
- text: component.props.title,
2023
- level: headingLevel,
2024
- pageBreak: shouldPageBreak,
2025
- // Apply zero-spacing to prevent unwanted initial line
2026
- spacing: {
2027
- before: 0,
2028
- after: 0
2029
- }
2030
- }
2031
- });
2170
+ sectionComponents.unshift(
2171
+ resolveComponentDefaults(
2172
+ {
2173
+ name: "heading",
2174
+ props: {
2175
+ text: component.props.title,
2176
+ level: headingLevel,
2177
+ pageBreak: shouldPageBreak,
2178
+ // Apply zero-spacing to prevent unwanted initial line
2179
+ spacing: {
2180
+ before: 0,
2181
+ after: 0
2182
+ }
2183
+ }
2184
+ },
2185
+ context.fullTheme
2186
+ )
2187
+ );
2032
2188
  }
2033
2189
  sections.push({
2034
2190
  title: component.props?.title,
@@ -2068,18 +2224,23 @@ async function flattenComponents(components, context) {
2068
2224
  Math.max(component.props.level || 1, 1),
2069
2225
  6
2070
2226
  );
2071
- flattened.push({
2072
- name: "heading",
2073
- props: {
2074
- text: component.props.title,
2075
- level: headingLevel,
2076
- // Apply zero-spacing to prevent unwanted initial line
2077
- spacing: {
2078
- before: 0,
2079
- after: 0
2080
- }
2081
- }
2082
- });
2227
+ flattened.push(
2228
+ resolveComponentDefaults(
2229
+ {
2230
+ name: "heading",
2231
+ props: {
2232
+ text: component.props.title,
2233
+ level: headingLevel,
2234
+ // Apply zero-spacing to prevent unwanted initial line
2235
+ spacing: {
2236
+ before: 0,
2237
+ after: 0
2238
+ }
2239
+ }
2240
+ },
2241
+ context.fullTheme
2242
+ )
2243
+ );
2083
2244
  }
2084
2245
  flattened.push(...await flattenComponents(component.children, context));
2085
2246
  } else {
@@ -3844,93 +4005,6 @@ async function renderComponentWithCache(component, theme, themeName, context, by
3844
4005
  return rendered;
3845
4006
  }
3846
4007
 
3847
- // src/styles/utils/componentDefaults.ts
3848
- function getComponentDefaults(theme) {
3849
- return theme.componentDefaults || {};
3850
- }
3851
- function getHeadingDefaults(theme) {
3852
- const defaults = getComponentDefaults(theme);
3853
- return defaults?.heading || {};
3854
- }
3855
- function getHeadingDefaultsForLevel(theme, level) {
3856
- const defaults = {};
3857
- if (theme.styles) {
3858
- const styleKey = `heading${level}`;
3859
- const headingStyle = theme.styles[styleKey];
3860
- if (headingStyle?.alignment) {
3861
- defaults.alignment = headingStyle.alignment;
3862
- }
3863
- }
3864
- return defaults;
3865
- }
3866
- function getTextDefaults(theme) {
3867
- const defaults = getComponentDefaults(theme);
3868
- return defaults?.paragraph || {};
3869
- }
3870
- function getImageDefaults(theme) {
3871
- const defaults = getComponentDefaults(theme);
3872
- return defaults?.image || {};
3873
- }
3874
- function getStatisticDefaults(theme) {
3875
- const defaults = getComponentDefaults(theme);
3876
- return defaults?.statistic || {};
3877
- }
3878
- function getColumnsDefaults(theme) {
3879
- const defaults = getComponentDefaults(theme);
3880
- return defaults?.columns || {};
3881
- }
3882
- function getListDefaults(theme) {
3883
- const defaults = getComponentDefaults(theme);
3884
- return defaults?.list || {};
3885
- }
3886
- function deepMerge(target, source) {
3887
- const output = { ...target };
3888
- if (isObject(target) && isObject(source)) {
3889
- Object.keys(source).forEach((key) => {
3890
- if (isObject(source[key])) {
3891
- if (!(key in target)) {
3892
- output[key] = source[key];
3893
- } else {
3894
- output[key] = deepMerge(target[key], source[key]);
3895
- }
3896
- } else {
3897
- output[key] = source[key];
3898
- }
3899
- });
3900
- }
3901
- return output;
3902
- }
3903
- function isObject(item) {
3904
- return item !== null && typeof item === "object" && !Array.isArray(item);
3905
- }
3906
- function mergeWithDefaults(userConfig, themeDefaults) {
3907
- return deepMerge(themeDefaults, userConfig);
3908
- }
3909
- function resolveHeadingProps(props, theme) {
3910
- const defaults = getHeadingDefaults(theme);
3911
- return mergeWithDefaults(props, defaults);
3912
- }
3913
- function resolveParagraphProps(props, theme) {
3914
- const defaults = getTextDefaults(theme);
3915
- return mergeWithDefaults(props, defaults);
3916
- }
3917
- function resolveImageProps(props, theme) {
3918
- const defaults = getImageDefaults(theme);
3919
- return mergeWithDefaults(props, defaults);
3920
- }
3921
- function resolveStatisticProps(props, theme) {
3922
- const defaults = getStatisticDefaults(theme);
3923
- return mergeWithDefaults(props, defaults);
3924
- }
3925
- function resolveColumnsProps(props, theme) {
3926
- const defaults = getColumnsDefaults(theme);
3927
- return mergeWithDefaults(props, defaults);
3928
- }
3929
- function resolveListProps(props, theme) {
3930
- const defaults = getListDefaults(theme);
3931
- return mergeWithDefaults(props, defaults);
3932
- }
3933
-
3934
4008
  // src/core/content.ts
3935
4009
  import {
3936
4010
  Paragraph,
@@ -5144,35 +5218,28 @@ function createFooterElement(children, _options) {
5144
5218
  // src/components/heading.ts
5145
5219
  function renderHeadingComponent(component, theme, themeName) {
5146
5220
  if (!isHeadingComponent(component)) return [];
5147
- const resolvedConfig = resolveHeadingProps(component.props, theme);
5148
- const level = resolvedConfig.level || 1;
5149
- const levelDefaults = getHeadingDefaultsForLevel(theme, level);
5150
- const finalConfig = {
5151
- ...resolvedConfig,
5152
- // Only apply level defaults if no explicit alignment was provided in the original props
5153
- ...component.props.alignment ? {} : levelDefaults
5154
- };
5155
- const bookmarkId = component.id || globalBookmarkRegistry.generateId(finalConfig.text, "heading");
5221
+ const config = component.props;
5222
+ const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
5156
5223
  const header = createHeading(
5157
- finalConfig.text,
5158
- finalConfig.level || 1,
5224
+ config.text,
5225
+ config.level || 1,
5159
5226
  theme,
5160
5227
  themeName,
5161
5228
  {
5162
- alignment: finalConfig.alignment,
5163
- spacing: finalConfig.spacing,
5164
- lineSpacing: finalConfig.lineSpacing,
5165
- columnBreak: finalConfig.columnBreak,
5229
+ alignment: config.alignment,
5230
+ spacing: config.spacing,
5231
+ lineSpacing: config.lineSpacing,
5232
+ columnBreak: config.columnBreak,
5166
5233
  // Local font overrides
5167
- fontFamily: finalConfig.font?.family,
5168
- fontSize: finalConfig.font?.size,
5169
- fontColor: finalConfig.font?.color,
5170
- bold: finalConfig.font?.bold,
5171
- italic: finalConfig.font?.italic,
5172
- underline: finalConfig.font?.underline,
5234
+ fontFamily: config.font?.family,
5235
+ fontSize: config.font?.size,
5236
+ fontColor: config.font?.color,
5237
+ bold: config.font?.bold,
5238
+ italic: config.font?.italic,
5239
+ underline: config.font?.underline,
5173
5240
  // Pagination control
5174
- keepNext: finalConfig.keepNext,
5175
- keepLines: finalConfig.keepLines,
5241
+ keepNext: config.keepNext,
5242
+ keepLines: config.keepLines,
5176
5243
  // Bookmark ID for internal linking
5177
5244
  bookmarkId
5178
5245
  }
@@ -5217,7 +5284,7 @@ function parseMarkdownList(text) {
5217
5284
  }
5218
5285
  function renderParagraphComponent(component, theme, themeName) {
5219
5286
  if (!isParagraphComponent(component)) return [];
5220
- const resolvedConfig = resolveParagraphProps(component.props, theme);
5287
+ const resolvedConfig = component.props;
5221
5288
  const listData = parseMarkdownList(resolvedConfig.text);
5222
5289
  if (listData) {
5223
5290
  const reference = globalNumberingRegistry.generateReference("markdown-list");
@@ -5402,7 +5469,7 @@ function fillMissingLevels(levels, maxLevel) {
5402
5469
  }
5403
5470
  function renderListComponent(component, theme, themeName) {
5404
5471
  if (!isListComponent(component)) return [];
5405
- const resolvedConfig = resolveListProps(component.props, theme);
5472
+ const resolvedConfig = component.props;
5406
5473
  const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
5407
5474
  const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
5408
5475
  if (!globalNumberingRegistry.has(reference)) {
@@ -5433,7 +5500,7 @@ function renderListComponent(component, theme, themeName) {
5433
5500
  // src/components/image.ts
5434
5501
  async function renderImageComponent(component, theme, themeName) {
5435
5502
  if (!isImageComponent(component)) return [];
5436
- const resolvedConfig = resolveImageProps(component.props, theme);
5503
+ const resolvedConfig = component.props;
5437
5504
  const imageSource = resolvedConfig.base64 || resolvedConfig.path;
5438
5505
  if (!imageSource) {
5439
5506
  throw new Error(
@@ -5793,7 +5860,6 @@ async function renderColumnsComponent(component, theme, themeName, context) {
5793
5860
  if (context.parent && isTextBoxComponent(context.parent)) {
5794
5861
  return await renderColumnsAsTable(component, theme, themeName, context);
5795
5862
  }
5796
- resolveColumnsProps(component.props, theme);
5797
5863
  const elements = [];
5798
5864
  if (component.children) {
5799
5865
  for (const child of component.children) {
@@ -5905,9 +5971,9 @@ async function renderColumnsAsTable(component, theme, themeName, context) {
5905
5971
  }
5906
5972
 
5907
5973
  // src/components/statistic.ts
5908
- function renderStatisticComponent(component, theme) {
5974
+ function renderStatisticComponent(component, _theme) {
5909
5975
  if (!isStatisticComponent(component)) return [];
5910
- const resolvedConfig = resolveStatisticProps(component.props, theme);
5976
+ const resolvedConfig = component.props;
5911
5977
  return createStatistic(
5912
5978
  {
5913
5979
  number: resolvedConfig.number,