@json-to-office/core-docx 0.7.0 → 0.9.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.
- package/dist/components/columns.d.ts.map +1 -1
- package/dist/components/heading.d.ts.map +1 -1
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/paragraph.d.ts.map +1 -1
- package/dist/components/statistic.d.ts +1 -1
- package/dist/components/statistic.d.ts.map +1 -1
- package/dist/core/content.d.ts +7 -0
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/fontResolution.d.ts +15 -0
- package/dist/core/fontResolution.d.ts.map +1 -0
- package/dist/core/generator.d.ts +11 -3
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/structure.d.ts.map +1 -1
- package/dist/index.js +411 -192
- package/dist/index.js.map +1 -1
- package/dist/plugin/createDocumentGenerator.d.ts +3 -1
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.js +374 -176
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/styles/utils/componentDefaults.d.ts +1 -6
- package/dist/styles/utils/componentDefaults.d.ts.map +1 -1
- package/dist/styles/utils/resolveComponentTree.d.ts +19 -0
- package/dist/styles/utils/resolveComponentTree.d.ts.map +1 -0
- package/dist/templates/themes/index.d.ts +84 -0
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/themes/defaults.d.ts +20 -0
- package/dist/themes/defaults.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -5
package/dist/index.js
CHANGED
|
@@ -1953,24 +1953,175 @@ var formatDate = (date, formatString = "MMMM d, yyyy") => {
|
|
|
1953
1953
|
return format(date, formatString);
|
|
1954
1954
|
};
|
|
1955
1955
|
|
|
1956
|
+
// src/styles/utils/componentDefaults.ts
|
|
1957
|
+
import { mergeWithDefaults } from "@json-to-office/shared";
|
|
1958
|
+
import { mergeWithDefaults as mergeWithDefaults2 } from "@json-to-office/shared";
|
|
1959
|
+
function getComponentDefaults(theme) {
|
|
1960
|
+
return theme.componentDefaults || {};
|
|
1961
|
+
}
|
|
1962
|
+
function getHeadingDefaults(theme) {
|
|
1963
|
+
const defaults = getComponentDefaults(theme);
|
|
1964
|
+
return defaults?.heading || {};
|
|
1965
|
+
}
|
|
1966
|
+
function getHeadingDefaultsForLevel(theme, level) {
|
|
1967
|
+
const defaults = {};
|
|
1968
|
+
if (theme.styles) {
|
|
1969
|
+
const styleKey = `heading${level}`;
|
|
1970
|
+
const headingStyle = theme.styles[styleKey];
|
|
1971
|
+
if (headingStyle?.alignment) {
|
|
1972
|
+
defaults.alignment = headingStyle.alignment;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
return defaults;
|
|
1976
|
+
}
|
|
1977
|
+
function getTextDefaults(theme) {
|
|
1978
|
+
const defaults = getComponentDefaults(theme);
|
|
1979
|
+
return defaults?.paragraph || {};
|
|
1980
|
+
}
|
|
1981
|
+
function getImageDefaults(theme) {
|
|
1982
|
+
const defaults = getComponentDefaults(theme);
|
|
1983
|
+
return defaults?.image || {};
|
|
1984
|
+
}
|
|
1985
|
+
function getStatisticDefaults(theme) {
|
|
1986
|
+
const defaults = getComponentDefaults(theme);
|
|
1987
|
+
return defaults?.statistic || {};
|
|
1988
|
+
}
|
|
1989
|
+
function getTableDefaults(theme) {
|
|
1990
|
+
const defaults = getComponentDefaults(theme);
|
|
1991
|
+
return defaults?.table || {};
|
|
1992
|
+
}
|
|
1993
|
+
function getSectionDefaults(theme) {
|
|
1994
|
+
const defaults = getComponentDefaults(theme);
|
|
1995
|
+
return defaults?.section || {};
|
|
1996
|
+
}
|
|
1997
|
+
function getColumnsDefaults(theme) {
|
|
1998
|
+
const defaults = getComponentDefaults(theme);
|
|
1999
|
+
return defaults?.columns || {};
|
|
2000
|
+
}
|
|
2001
|
+
function getListDefaults(theme) {
|
|
2002
|
+
const defaults = getComponentDefaults(theme);
|
|
2003
|
+
return defaults?.list || {};
|
|
2004
|
+
}
|
|
2005
|
+
function resolveHeadingProps(props, theme) {
|
|
2006
|
+
const defaults = getHeadingDefaults(theme);
|
|
2007
|
+
return mergeWithDefaults(props, defaults);
|
|
2008
|
+
}
|
|
2009
|
+
function resolveParagraphProps(props, theme) {
|
|
2010
|
+
const defaults = getTextDefaults(theme);
|
|
2011
|
+
return mergeWithDefaults(props, defaults);
|
|
2012
|
+
}
|
|
2013
|
+
function resolveImageProps(props, theme) {
|
|
2014
|
+
const defaults = getImageDefaults(theme);
|
|
2015
|
+
return mergeWithDefaults(props, defaults);
|
|
2016
|
+
}
|
|
2017
|
+
function resolveStatisticProps(props, theme) {
|
|
2018
|
+
const defaults = getStatisticDefaults(theme);
|
|
2019
|
+
return mergeWithDefaults(props, defaults);
|
|
2020
|
+
}
|
|
2021
|
+
function resolveTableProps(props, theme) {
|
|
2022
|
+
const defaults = getTableDefaults(theme);
|
|
2023
|
+
return mergeWithDefaults(props, defaults);
|
|
2024
|
+
}
|
|
2025
|
+
function resolveSectionProps(props, theme) {
|
|
2026
|
+
const defaults = getSectionDefaults(theme);
|
|
2027
|
+
return mergeWithDefaults(props, defaults);
|
|
2028
|
+
}
|
|
2029
|
+
function resolveColumnsProps(props, theme) {
|
|
2030
|
+
const defaults = getColumnsDefaults(theme);
|
|
2031
|
+
return mergeWithDefaults(props, defaults);
|
|
2032
|
+
}
|
|
2033
|
+
function resolveListProps(props, theme) {
|
|
2034
|
+
const defaults = getListDefaults(theme);
|
|
2035
|
+
return mergeWithDefaults(props, defaults);
|
|
2036
|
+
}
|
|
2037
|
+
function resolveHighchartsProps(props, _theme) {
|
|
2038
|
+
return props;
|
|
2039
|
+
}
|
|
2040
|
+
function getCustomComponentDefaults(theme, componentName) {
|
|
2041
|
+
const defaults = getComponentDefaults(theme);
|
|
2042
|
+
return defaults?.[componentName] || {};
|
|
2043
|
+
}
|
|
2044
|
+
function resolveCustomComponentProps(props, theme, componentName) {
|
|
2045
|
+
const defaults = getCustomComponentDefaults(theme, componentName);
|
|
2046
|
+
return mergeWithDefaults(props, defaults);
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
// src/styles/utils/resolveComponentTree.ts
|
|
2050
|
+
function resolveHeadingWithLevelDefaults(props, theme) {
|
|
2051
|
+
const resolved = resolveHeadingProps(props, theme);
|
|
2052
|
+
const level = resolved.level || 1;
|
|
2053
|
+
const levelDefaults = getHeadingDefaultsForLevel(theme, level);
|
|
2054
|
+
return {
|
|
2055
|
+
...resolved,
|
|
2056
|
+
// Only apply level-specific defaults if no explicit alignment in original props
|
|
2057
|
+
...props.alignment ? {} : levelDefaults
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
var RESOLVER_MAP = {
|
|
2061
|
+
heading: resolveHeadingWithLevelDefaults,
|
|
2062
|
+
paragraph: resolveParagraphProps,
|
|
2063
|
+
image: resolveImageProps,
|
|
2064
|
+
statistic: resolveStatisticProps,
|
|
2065
|
+
table: resolveTableProps,
|
|
2066
|
+
section: resolveSectionProps,
|
|
2067
|
+
columns: resolveColumnsProps,
|
|
2068
|
+
list: resolveListProps,
|
|
2069
|
+
highcharts: resolveHighchartsProps
|
|
2070
|
+
};
|
|
2071
|
+
function resolveComponentDefaults(component, theme) {
|
|
2072
|
+
if (!component.props) return component;
|
|
2073
|
+
const resolver = RESOLVER_MAP[component.name];
|
|
2074
|
+
const resolvedProps = resolver ? resolver(component.props, theme) : resolveCustomComponentProps(
|
|
2075
|
+
component.props,
|
|
2076
|
+
theme,
|
|
2077
|
+
component.name
|
|
2078
|
+
);
|
|
2079
|
+
return { ...component, props: resolvedProps };
|
|
2080
|
+
}
|
|
2081
|
+
function resolveComponentTree(components, theme) {
|
|
2082
|
+
return components.map((component) => {
|
|
2083
|
+
const resolved = resolveComponentDefaults(component, theme);
|
|
2084
|
+
const children = resolved.children;
|
|
2085
|
+
if (children && children.length > 0) {
|
|
2086
|
+
return {
|
|
2087
|
+
...resolved,
|
|
2088
|
+
children: resolveComponentTree(children, theme)
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
return resolved;
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
|
|
1956
2095
|
// src/core/structure.ts
|
|
1957
2096
|
async function processDocument(document, theme, themeName) {
|
|
1958
2097
|
const metadata = createDocumentMetadata(document.props);
|
|
2098
|
+
const docDefaults = document.props.componentDefaults;
|
|
2099
|
+
const effectiveTheme = docDefaults ? {
|
|
2100
|
+
...theme,
|
|
2101
|
+
componentDefaults: mergeWithDefaults2(
|
|
2102
|
+
docDefaults,
|
|
2103
|
+
theme.componentDefaults || {}
|
|
2104
|
+
)
|
|
2105
|
+
} : theme;
|
|
1959
2106
|
const context = createRenderContext(
|
|
1960
2107
|
{
|
|
1961
2108
|
metadata,
|
|
1962
2109
|
sections: [],
|
|
1963
|
-
theme,
|
|
2110
|
+
theme: effectiveTheme,
|
|
1964
2111
|
themeName
|
|
1965
2112
|
},
|
|
1966
|
-
|
|
2113
|
+
effectiveTheme,
|
|
1967
2114
|
themeName
|
|
1968
2115
|
);
|
|
1969
|
-
const
|
|
2116
|
+
const resolvedChildren = resolveComponentTree(
|
|
2117
|
+
document.children || [],
|
|
2118
|
+
effectiveTheme
|
|
2119
|
+
);
|
|
2120
|
+
const sections = await extractSections(resolvedChildren, context);
|
|
1970
2121
|
return {
|
|
1971
2122
|
metadata,
|
|
1972
2123
|
sections,
|
|
1973
|
-
theme,
|
|
2124
|
+
theme: effectiveTheme,
|
|
1974
2125
|
themeName
|
|
1975
2126
|
};
|
|
1976
2127
|
}
|
|
@@ -2000,19 +2151,24 @@ async function extractSections(components, context) {
|
|
|
2000
2151
|
Math.max(component.props.level || 1, 1),
|
|
2001
2152
|
6
|
|
2002
2153
|
);
|
|
2003
|
-
sectionComponents.unshift(
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2154
|
+
sectionComponents.unshift(
|
|
2155
|
+
resolveComponentDefaults(
|
|
2156
|
+
{
|
|
2157
|
+
name: "heading",
|
|
2158
|
+
props: {
|
|
2159
|
+
text: component.props.title,
|
|
2160
|
+
level: headingLevel,
|
|
2161
|
+
pageBreak: shouldPageBreak,
|
|
2162
|
+
// Apply zero-spacing to prevent unwanted initial line
|
|
2163
|
+
spacing: {
|
|
2164
|
+
before: 0,
|
|
2165
|
+
after: 0
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
},
|
|
2169
|
+
context.fullTheme
|
|
2170
|
+
)
|
|
2171
|
+
);
|
|
2016
2172
|
}
|
|
2017
2173
|
sections.push({
|
|
2018
2174
|
title: component.props?.title,
|
|
@@ -2052,18 +2208,23 @@ async function flattenComponents(components, context) {
|
|
|
2052
2208
|
Math.max(component.props.level || 1, 1),
|
|
2053
2209
|
6
|
|
2054
2210
|
);
|
|
2055
|
-
flattened.push(
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2211
|
+
flattened.push(
|
|
2212
|
+
resolveComponentDefaults(
|
|
2213
|
+
{
|
|
2214
|
+
name: "heading",
|
|
2215
|
+
props: {
|
|
2216
|
+
text: component.props.title,
|
|
2217
|
+
level: headingLevel,
|
|
2218
|
+
// Apply zero-spacing to prevent unwanted initial line
|
|
2219
|
+
spacing: {
|
|
2220
|
+
before: 0,
|
|
2221
|
+
after: 0
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
},
|
|
2225
|
+
context.fullTheme
|
|
2226
|
+
)
|
|
2227
|
+
);
|
|
2067
2228
|
}
|
|
2068
2229
|
flattened.push(...await flattenComponents(component.children, context));
|
|
2069
2230
|
} else {
|
|
@@ -3853,93 +4014,6 @@ function getComponentCacheStats() {
|
|
|
3853
4014
|
return componentCache.getStats();
|
|
3854
4015
|
}
|
|
3855
4016
|
|
|
3856
|
-
// src/styles/utils/componentDefaults.ts
|
|
3857
|
-
function getComponentDefaults(theme) {
|
|
3858
|
-
return theme.componentDefaults || {};
|
|
3859
|
-
}
|
|
3860
|
-
function getHeadingDefaults(theme) {
|
|
3861
|
-
const defaults = getComponentDefaults(theme);
|
|
3862
|
-
return defaults?.heading || {};
|
|
3863
|
-
}
|
|
3864
|
-
function getHeadingDefaultsForLevel(theme, level) {
|
|
3865
|
-
const defaults = {};
|
|
3866
|
-
if (theme.styles) {
|
|
3867
|
-
const styleKey = `heading${level}`;
|
|
3868
|
-
const headingStyle = theme.styles[styleKey];
|
|
3869
|
-
if (headingStyle?.alignment) {
|
|
3870
|
-
defaults.alignment = headingStyle.alignment;
|
|
3871
|
-
}
|
|
3872
|
-
}
|
|
3873
|
-
return defaults;
|
|
3874
|
-
}
|
|
3875
|
-
function getTextDefaults(theme) {
|
|
3876
|
-
const defaults = getComponentDefaults(theme);
|
|
3877
|
-
return defaults?.paragraph || {};
|
|
3878
|
-
}
|
|
3879
|
-
function getImageDefaults(theme) {
|
|
3880
|
-
const defaults = getComponentDefaults(theme);
|
|
3881
|
-
return defaults?.image || {};
|
|
3882
|
-
}
|
|
3883
|
-
function getStatisticDefaults(theme) {
|
|
3884
|
-
const defaults = getComponentDefaults(theme);
|
|
3885
|
-
return defaults?.statistic || {};
|
|
3886
|
-
}
|
|
3887
|
-
function getColumnsDefaults(theme) {
|
|
3888
|
-
const defaults = getComponentDefaults(theme);
|
|
3889
|
-
return defaults?.columns || {};
|
|
3890
|
-
}
|
|
3891
|
-
function getListDefaults(theme) {
|
|
3892
|
-
const defaults = getComponentDefaults(theme);
|
|
3893
|
-
return defaults?.list || {};
|
|
3894
|
-
}
|
|
3895
|
-
function deepMerge(target, source) {
|
|
3896
|
-
const output = { ...target };
|
|
3897
|
-
if (isObject(target) && isObject(source)) {
|
|
3898
|
-
Object.keys(source).forEach((key) => {
|
|
3899
|
-
if (isObject(source[key])) {
|
|
3900
|
-
if (!(key in target)) {
|
|
3901
|
-
output[key] = source[key];
|
|
3902
|
-
} else {
|
|
3903
|
-
output[key] = deepMerge(target[key], source[key]);
|
|
3904
|
-
}
|
|
3905
|
-
} else {
|
|
3906
|
-
output[key] = source[key];
|
|
3907
|
-
}
|
|
3908
|
-
});
|
|
3909
|
-
}
|
|
3910
|
-
return output;
|
|
3911
|
-
}
|
|
3912
|
-
function isObject(item) {
|
|
3913
|
-
return item !== null && typeof item === "object" && !Array.isArray(item);
|
|
3914
|
-
}
|
|
3915
|
-
function mergeWithDefaults(userConfig, themeDefaults) {
|
|
3916
|
-
return deepMerge(themeDefaults, userConfig);
|
|
3917
|
-
}
|
|
3918
|
-
function resolveHeadingProps(props, theme) {
|
|
3919
|
-
const defaults = getHeadingDefaults(theme);
|
|
3920
|
-
return mergeWithDefaults(props, defaults);
|
|
3921
|
-
}
|
|
3922
|
-
function resolveParagraphProps(props, theme) {
|
|
3923
|
-
const defaults = getTextDefaults(theme);
|
|
3924
|
-
return mergeWithDefaults(props, defaults);
|
|
3925
|
-
}
|
|
3926
|
-
function resolveImageProps(props, theme) {
|
|
3927
|
-
const defaults = getImageDefaults(theme);
|
|
3928
|
-
return mergeWithDefaults(props, defaults);
|
|
3929
|
-
}
|
|
3930
|
-
function resolveStatisticProps(props, theme) {
|
|
3931
|
-
const defaults = getStatisticDefaults(theme);
|
|
3932
|
-
return mergeWithDefaults(props, defaults);
|
|
3933
|
-
}
|
|
3934
|
-
function resolveColumnsProps(props, theme) {
|
|
3935
|
-
const defaults = getColumnsDefaults(theme);
|
|
3936
|
-
return mergeWithDefaults(props, defaults);
|
|
3937
|
-
}
|
|
3938
|
-
function resolveListProps(props, theme) {
|
|
3939
|
-
const defaults = getListDefaults(theme);
|
|
3940
|
-
return mergeWithDefaults(props, defaults);
|
|
3941
|
-
}
|
|
3942
|
-
|
|
3943
4017
|
// src/core/content.ts
|
|
3944
4018
|
import {
|
|
3945
4019
|
Paragraph,
|
|
@@ -4033,9 +4107,22 @@ var globalBookmarkRegistry = new BookmarkRegistry();
|
|
|
4033
4107
|
|
|
4034
4108
|
// src/core/content.ts
|
|
4035
4109
|
init_styleHelpers();
|
|
4110
|
+
import { synthesizeFamilyName } from "@json-to-office/shared";
|
|
4036
4111
|
init_colorUtils();
|
|
4037
4112
|
init_styleHelpers();
|
|
4038
4113
|
init_widthUtils();
|
|
4114
|
+
function applyFontWeightAlias(opts) {
|
|
4115
|
+
if (!opts.fontFamily) {
|
|
4116
|
+
return { font: void 0, bold: opts.bold, italics: opts.italic };
|
|
4117
|
+
}
|
|
4118
|
+
const weight = opts.fontWeight ?? (opts.bold === true ? 700 : void 0);
|
|
4119
|
+
const synth = synthesizeFamilyName(
|
|
4120
|
+
opts.fontFamily,
|
|
4121
|
+
weight,
|
|
4122
|
+
opts.italic === true
|
|
4123
|
+
);
|
|
4124
|
+
return { font: synth.family, bold: synth.bold, italics: synth.italic };
|
|
4125
|
+
}
|
|
4039
4126
|
function createText(content, theme, themeName, options = {}) {
|
|
4040
4127
|
const normalizedContent = normalizeUnicodeText(content);
|
|
4041
4128
|
const style = options.style || "Normal";
|
|
@@ -4055,15 +4142,27 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4055
4142
|
if (options.columnBreak) {
|
|
4056
4143
|
children.push(new ColumnBreak());
|
|
4057
4144
|
}
|
|
4145
|
+
const hasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4146
|
+
const effectiveFamily = options.fontFamily ?? (hasWeightRequest ? resolveFontFamily(theme, "body") : void 0);
|
|
4147
|
+
const weighted = applyFontWeightAlias({
|
|
4148
|
+
fontFamily: effectiveFamily,
|
|
4149
|
+
bold: options.bold,
|
|
4150
|
+
italic: options.italic,
|
|
4151
|
+
fontWeight: options.fontWeight
|
|
4152
|
+
});
|
|
4058
4153
|
const baseTextStyle = {
|
|
4059
|
-
|
|
4154
|
+
// Only emit `font` when it came from the caller or from an alias —
|
|
4155
|
+
// emitting the theme body family on every run would be a behavior change.
|
|
4156
|
+
...(options.fontFamily || weighted.font && weighted.font !== effectiveFamily) && {
|
|
4157
|
+
font: weighted.font
|
|
4158
|
+
},
|
|
4060
4159
|
...options.fontSize && { size: options.fontSize * 2 },
|
|
4061
4160
|
// Convert points to half-points
|
|
4062
4161
|
...options.fontColor && {
|
|
4063
4162
|
color: resolveColor(options.fontColor, theme)
|
|
4064
4163
|
},
|
|
4065
|
-
...
|
|
4066
|
-
...
|
|
4164
|
+
...weighted.bold !== void 0 && { bold: weighted.bold },
|
|
4165
|
+
...weighted.italics !== void 0 && { italics: weighted.italics },
|
|
4067
4166
|
...options.underline !== void 0 && {
|
|
4068
4167
|
underline: options.underline ? { type: "single" } : void 0
|
|
4069
4168
|
}
|
|
@@ -4183,13 +4282,25 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4183
4282
|
children.push(new ColumnBreak());
|
|
4184
4283
|
}
|
|
4185
4284
|
const hasDecorators = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText);
|
|
4285
|
+
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4286
|
+
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
4287
|
+
const headingWeighted = applyFontWeightAlias({
|
|
4288
|
+
fontFamily: headingEffectiveFamily,
|
|
4289
|
+
bold: options.bold,
|
|
4290
|
+
italic: options.italic,
|
|
4291
|
+
fontWeight: options.fontWeight
|
|
4292
|
+
});
|
|
4186
4293
|
const baseTextStyle = {
|
|
4187
|
-
...options.fontFamily
|
|
4294
|
+
...(options.fontFamily || headingWeighted.font && headingWeighted.font !== headingEffectiveFamily) && {
|
|
4295
|
+
font: headingWeighted.font
|
|
4296
|
+
},
|
|
4188
4297
|
...options.fontSize && { size: options.fontSize * 2 },
|
|
4189
4298
|
// points to half-points
|
|
4190
4299
|
...options.fontColor && { color: resolveColor(options.fontColor, theme) },
|
|
4191
|
-
...
|
|
4192
|
-
...
|
|
4300
|
+
...headingWeighted.bold !== void 0 && { bold: headingWeighted.bold },
|
|
4301
|
+
...headingWeighted.italics !== void 0 && {
|
|
4302
|
+
italics: headingWeighted.italics
|
|
4303
|
+
},
|
|
4193
4304
|
...options.underline !== void 0 && {
|
|
4194
4305
|
underline: options.underline ? { type: "single" } : void 0
|
|
4195
4306
|
}
|
|
@@ -4701,12 +4812,18 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4701
4812
|
if (!cell) {
|
|
4702
4813
|
return cellChildren;
|
|
4703
4814
|
}
|
|
4815
|
+
const cellWeighted = applyFontWeightAlias({
|
|
4816
|
+
fontFamily: cellDefaults.font?.family || baseCellStyle.font,
|
|
4817
|
+
bold: cellDefaults.font?.bold ?? false,
|
|
4818
|
+
italic: cellDefaults.font?.italic ?? false,
|
|
4819
|
+
fontWeight: cellDefaults.font?.fontWeight
|
|
4820
|
+
});
|
|
4704
4821
|
const mergedStyle = {
|
|
4705
|
-
font:
|
|
4822
|
+
font: cellWeighted.font,
|
|
4706
4823
|
size: cellDefaults.font?.size ? cellDefaults.font.size * 2 : baseCellStyle.size,
|
|
4707
4824
|
// Convert to half-points
|
|
4708
|
-
bold:
|
|
4709
|
-
italics:
|
|
4825
|
+
bold: cellWeighted.bold ?? false,
|
|
4826
|
+
italics: cellWeighted.italics ?? false,
|
|
4710
4827
|
underline: cellDefaults.font?.underline ? { type: "single" } : void 0,
|
|
4711
4828
|
color: cellDefaults.color || baseCellStyle.color
|
|
4712
4829
|
};
|
|
@@ -4714,15 +4831,21 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4714
4831
|
if (isParagraphComponent(cell)) {
|
|
4715
4832
|
const textComp = cell;
|
|
4716
4833
|
const paragraphFont = textComp.props.font;
|
|
4834
|
+
const paraWeighted = applyFontWeightAlias({
|
|
4835
|
+
fontFamily: paragraphFont?.family ?? mergedStyle.font,
|
|
4836
|
+
bold: paragraphFont?.bold,
|
|
4837
|
+
italic: paragraphFont?.italic,
|
|
4838
|
+
fontWeight: paragraphFont?.fontWeight
|
|
4839
|
+
});
|
|
4717
4840
|
const paragraphStyle = {
|
|
4718
4841
|
...mergedStyle,
|
|
4719
|
-
...
|
|
4842
|
+
...paraWeighted.font && { font: paraWeighted.font },
|
|
4720
4843
|
...paragraphFont?.size && { size: paragraphFont.size * 2 },
|
|
4721
|
-
...
|
|
4722
|
-
bold:
|
|
4844
|
+
...paraWeighted.bold !== void 0 && {
|
|
4845
|
+
bold: paraWeighted.bold
|
|
4723
4846
|
},
|
|
4724
|
-
...
|
|
4725
|
-
italics:
|
|
4847
|
+
...paraWeighted.italics !== void 0 && {
|
|
4848
|
+
italics: paraWeighted.italics
|
|
4726
4849
|
},
|
|
4727
4850
|
...paragraphFont?.underline !== void 0 && {
|
|
4728
4851
|
underline: paragraphFont.underline ? { type: "single" } : void 0
|
|
@@ -5153,35 +5276,29 @@ function createFooterElement(children, _options) {
|
|
|
5153
5276
|
// src/components/heading.ts
|
|
5154
5277
|
function renderHeadingComponent(component, theme, themeName) {
|
|
5155
5278
|
if (!isHeadingComponent(component)) return [];
|
|
5156
|
-
const
|
|
5157
|
-
const
|
|
5158
|
-
const levelDefaults = getHeadingDefaultsForLevel(theme, level);
|
|
5159
|
-
const finalConfig = {
|
|
5160
|
-
...resolvedConfig,
|
|
5161
|
-
// Only apply level defaults if no explicit alignment was provided in the original props
|
|
5162
|
-
...component.props.alignment ? {} : levelDefaults
|
|
5163
|
-
};
|
|
5164
|
-
const bookmarkId = component.id || globalBookmarkRegistry.generateId(finalConfig.text, "heading");
|
|
5279
|
+
const config = component.props;
|
|
5280
|
+
const bookmarkId = component.id || globalBookmarkRegistry.generateId(config.text, "heading");
|
|
5165
5281
|
const header = createHeading(
|
|
5166
|
-
|
|
5167
|
-
|
|
5282
|
+
config.text,
|
|
5283
|
+
config.level || 1,
|
|
5168
5284
|
theme,
|
|
5169
5285
|
themeName,
|
|
5170
5286
|
{
|
|
5171
|
-
alignment:
|
|
5172
|
-
spacing:
|
|
5173
|
-
lineSpacing:
|
|
5174
|
-
columnBreak:
|
|
5287
|
+
alignment: config.alignment,
|
|
5288
|
+
spacing: config.spacing,
|
|
5289
|
+
lineSpacing: config.lineSpacing,
|
|
5290
|
+
columnBreak: config.columnBreak,
|
|
5175
5291
|
// Local font overrides
|
|
5176
|
-
fontFamily:
|
|
5177
|
-
fontSize:
|
|
5178
|
-
fontColor:
|
|
5179
|
-
bold:
|
|
5180
|
-
|
|
5181
|
-
|
|
5292
|
+
fontFamily: config.font?.family,
|
|
5293
|
+
fontSize: config.font?.size,
|
|
5294
|
+
fontColor: config.font?.color,
|
|
5295
|
+
bold: config.font?.bold,
|
|
5296
|
+
fontWeight: config.font?.fontWeight,
|
|
5297
|
+
italic: config.font?.italic,
|
|
5298
|
+
underline: config.font?.underline,
|
|
5182
5299
|
// Pagination control
|
|
5183
|
-
keepNext:
|
|
5184
|
-
keepLines:
|
|
5300
|
+
keepNext: config.keepNext,
|
|
5301
|
+
keepLines: config.keepLines,
|
|
5185
5302
|
// Bookmark ID for internal linking
|
|
5186
5303
|
bookmarkId
|
|
5187
5304
|
}
|
|
@@ -5226,7 +5343,7 @@ function parseMarkdownList(text) {
|
|
|
5226
5343
|
}
|
|
5227
5344
|
function renderParagraphComponent(component, theme, themeName) {
|
|
5228
5345
|
if (!isParagraphComponent(component)) return [];
|
|
5229
|
-
const resolvedConfig =
|
|
5346
|
+
const resolvedConfig = component.props;
|
|
5230
5347
|
const listData = parseMarkdownList(resolvedConfig.text);
|
|
5231
5348
|
if (listData) {
|
|
5232
5349
|
const reference = globalNumberingRegistry.generateReference("markdown-list");
|
|
@@ -5292,6 +5409,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
5292
5409
|
fontSize: resolvedConfig.font?.size,
|
|
5293
5410
|
fontColor: resolvedConfig.font?.color,
|
|
5294
5411
|
bold: resolvedConfig.font?.bold,
|
|
5412
|
+
fontWeight: resolvedConfig.font?.fontWeight,
|
|
5295
5413
|
italic: resolvedConfig.font?.italic,
|
|
5296
5414
|
underline: resolvedConfig.font?.underline,
|
|
5297
5415
|
// Pass outline level for TOC support
|
|
@@ -5411,7 +5529,7 @@ function fillMissingLevels(levels, maxLevel) {
|
|
|
5411
5529
|
}
|
|
5412
5530
|
function renderListComponent(component, theme, themeName) {
|
|
5413
5531
|
if (!isListComponent(component)) return [];
|
|
5414
|
-
const resolvedConfig =
|
|
5532
|
+
const resolvedConfig = component.props;
|
|
5415
5533
|
const maxLevel = getMaxLevelFromItems(resolvedConfig.items);
|
|
5416
5534
|
const reference = resolvedConfig.reference || globalNumberingRegistry.generateReference("list");
|
|
5417
5535
|
if (!globalNumberingRegistry.has(reference)) {
|
|
@@ -5442,7 +5560,7 @@ function renderListComponent(component, theme, themeName) {
|
|
|
5442
5560
|
// src/components/image.ts
|
|
5443
5561
|
async function renderImageComponent(component, theme, themeName) {
|
|
5444
5562
|
if (!isImageComponent(component)) return [];
|
|
5445
|
-
const resolvedConfig =
|
|
5563
|
+
const resolvedConfig = component.props;
|
|
5446
5564
|
const imageSource = resolvedConfig.base64 || resolvedConfig.path;
|
|
5447
5565
|
if (!imageSource) {
|
|
5448
5566
|
throw new Error(
|
|
@@ -5802,7 +5920,6 @@ async function renderColumnsComponent(component, theme, themeName, context) {
|
|
|
5802
5920
|
if (context.parent && isTextBoxComponent(context.parent)) {
|
|
5803
5921
|
return await renderColumnsAsTable(component, theme, themeName, context);
|
|
5804
5922
|
}
|
|
5805
|
-
resolveColumnsProps(component.props, theme);
|
|
5806
5923
|
const elements = [];
|
|
5807
5924
|
if (component.children) {
|
|
5808
5925
|
for (const child of component.children) {
|
|
@@ -5914,9 +6031,9 @@ async function renderColumnsAsTable(component, theme, themeName, context) {
|
|
|
5914
6031
|
}
|
|
5915
6032
|
|
|
5916
6033
|
// src/components/statistic.ts
|
|
5917
|
-
function renderStatisticComponent(component,
|
|
6034
|
+
function renderStatisticComponent(component, _theme) {
|
|
5918
6035
|
if (!isStatisticComponent(component)) return [];
|
|
5919
|
-
const resolvedConfig =
|
|
6036
|
+
const resolvedConfig = component.props;
|
|
5920
6037
|
return createStatistic(
|
|
5921
6038
|
{
|
|
5922
6039
|
number: resolvedConfig.number,
|
|
@@ -6564,6 +6681,69 @@ async function renderComponent(component, theme, themeName, context) {
|
|
|
6564
6681
|
);
|
|
6565
6682
|
}
|
|
6566
6683
|
|
|
6684
|
+
// src/core/fontResolution.ts
|
|
6685
|
+
import {
|
|
6686
|
+
collectFontNamesFromDocx,
|
|
6687
|
+
validateFontReferences,
|
|
6688
|
+
FontRegistry
|
|
6689
|
+
} from "@json-to-office/shared";
|
|
6690
|
+
import {
|
|
6691
|
+
loadFileFontSource,
|
|
6692
|
+
FontDiskCache,
|
|
6693
|
+
fetchVariableFontSource
|
|
6694
|
+
} from "@json-to-office/shared/fonts/node";
|
|
6695
|
+
async function resolveDocumentFonts(document, theme, fonts, warnings) {
|
|
6696
|
+
const emit = (code, message) => {
|
|
6697
|
+
if (warnings) {
|
|
6698
|
+
warnings.push({
|
|
6699
|
+
component: "fontRegistry",
|
|
6700
|
+
message,
|
|
6701
|
+
severity: "warning",
|
|
6702
|
+
context: { code }
|
|
6703
|
+
});
|
|
6704
|
+
} else {
|
|
6705
|
+
console.warn(`[json-to-docx] ${code}: ${message}`);
|
|
6706
|
+
}
|
|
6707
|
+
};
|
|
6708
|
+
const names = /* @__PURE__ */ new Set();
|
|
6709
|
+
for (const n of collectFontNamesFromDocx(document)) names.add(n);
|
|
6710
|
+
for (const n of collectFontNamesFromDocx(theme)) names.add(n);
|
|
6711
|
+
if (names.size === 0) return [];
|
|
6712
|
+
const validation = validateFontReferences({
|
|
6713
|
+
referencedNames: names,
|
|
6714
|
+
registeredEntries: fonts?.extraEntries
|
|
6715
|
+
});
|
|
6716
|
+
if (validation.warnings.length > 0) {
|
|
6717
|
+
if (fonts?.strict) {
|
|
6718
|
+
throw new Error(
|
|
6719
|
+
`Unresolved font references (strict mode):
|
|
6720
|
+
` + validation.warnings.map((w) => ` - ${w.message}`).join("\n")
|
|
6721
|
+
);
|
|
6722
|
+
}
|
|
6723
|
+
for (const w of validation.warnings) {
|
|
6724
|
+
emit(w.code, w.message);
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6727
|
+
if (!fonts?.onResolved) return [];
|
|
6728
|
+
const registry = new FontRegistry({
|
|
6729
|
+
opts: fonts,
|
|
6730
|
+
fileLoader: loadFileFontSource,
|
|
6731
|
+
variableLoader: fetchVariableFontSource,
|
|
6732
|
+
diskCache: fonts?.googleFonts?.cacheDir ? new FontDiskCache(fonts.googleFonts.cacheDir) : void 0
|
|
6733
|
+
});
|
|
6734
|
+
const resolved = await registry.resolveMany(names);
|
|
6735
|
+
for (const r of resolved) {
|
|
6736
|
+
for (const msg of r.warnings) {
|
|
6737
|
+
emit("FONT_UNRESOLVED", msg);
|
|
6738
|
+
}
|
|
6739
|
+
}
|
|
6740
|
+
fonts.onResolved(resolved);
|
|
6741
|
+
return resolved;
|
|
6742
|
+
}
|
|
6743
|
+
|
|
6744
|
+
// src/core/generator.ts
|
|
6745
|
+
import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
|
|
6746
|
+
|
|
6567
6747
|
// src/json/parser.ts
|
|
6568
6748
|
import {
|
|
6569
6749
|
JsonDocumentParser,
|
|
@@ -6723,33 +6903,32 @@ function isReportComponentDefinition(definition) {
|
|
|
6723
6903
|
const def = definition;
|
|
6724
6904
|
return def.name === "docx" && "props" in def;
|
|
6725
6905
|
}
|
|
6726
|
-
async function generateDocument(document) {
|
|
6906
|
+
async function generateDocument(document, options) {
|
|
6727
6907
|
if (!document || document.name !== "docx") {
|
|
6728
6908
|
throw new Error("Top-level component must be a docx component");
|
|
6729
6909
|
}
|
|
6730
6910
|
if ("$schema" in document) {
|
|
6731
|
-
return await generateDocumentFromJson(document);
|
|
6911
|
+
return await generateDocumentFromJson(document, options);
|
|
6732
6912
|
}
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
});
|
|
6741
|
-
return renderedDocument;
|
|
6913
|
+
return await generateDocumentWithCustomThemes(
|
|
6914
|
+
document,
|
|
6915
|
+
options?.customThemes,
|
|
6916
|
+
options?.services,
|
|
6917
|
+
options?.fonts,
|
|
6918
|
+
options?.warnings
|
|
6919
|
+
);
|
|
6742
6920
|
}
|
|
6743
|
-
async function generateFromConfig(props, components) {
|
|
6921
|
+
async function generateFromConfig(props, components, options) {
|
|
6744
6922
|
const reportComponent = {
|
|
6745
6923
|
name: "docx",
|
|
6746
6924
|
props,
|
|
6747
6925
|
children: components
|
|
6748
6926
|
};
|
|
6749
|
-
return await generateDocument(reportComponent);
|
|
6927
|
+
return await generateDocument(reportComponent, options);
|
|
6750
6928
|
}
|
|
6751
|
-
async function generateDocumentWithCustomThemes(
|
|
6752
|
-
|
|
6929
|
+
async function generateDocumentWithCustomThemes(documentIn, customThemes, services, fonts, warnings) {
|
|
6930
|
+
let document = documentIn;
|
|
6931
|
+
let themeName = document.props.theme || "minimal";
|
|
6753
6932
|
let theme;
|
|
6754
6933
|
if (customThemes) {
|
|
6755
6934
|
if (customThemes[themeName]) {
|
|
@@ -6768,6 +6947,23 @@ async function generateDocumentWithCustomThemes(document, customThemes, services
|
|
|
6768
6947
|
} else {
|
|
6769
6948
|
theme = getThemeWithFallback(themeName);
|
|
6770
6949
|
}
|
|
6950
|
+
const mode = applyExportMode({ doc: document, theme, fonts });
|
|
6951
|
+
document = mode.doc;
|
|
6952
|
+
theme = mode.theme;
|
|
6953
|
+
themeName = scopedThemeName(themeName, fonts?.mode);
|
|
6954
|
+
for (const w of mode.warnings) {
|
|
6955
|
+
if (warnings) {
|
|
6956
|
+
warnings.push({
|
|
6957
|
+
component: "fontRegistry",
|
|
6958
|
+
message: w.message,
|
|
6959
|
+
severity: "warning",
|
|
6960
|
+
context: { code: w.code }
|
|
6961
|
+
});
|
|
6962
|
+
} else {
|
|
6963
|
+
console.warn(`[json-to-docx] [${w.code}] ${w.message}`);
|
|
6964
|
+
}
|
|
6965
|
+
}
|
|
6966
|
+
await resolveDocumentFonts(document, theme, fonts, warnings);
|
|
6771
6967
|
const structure = await processDocument(document, theme, themeName);
|
|
6772
6968
|
const layout = applyLayout(structure.sections, theme, themeName);
|
|
6773
6969
|
const renderedDocument = await renderDocument(structure, layout, {
|
|
@@ -6791,7 +6987,9 @@ async function generateDocumentFromJson(jsonConfig, options) {
|
|
|
6791
6987
|
return await generateDocumentWithCustomThemes(
|
|
6792
6988
|
reportComponent,
|
|
6793
6989
|
options?.customThemes,
|
|
6794
|
-
options?.services
|
|
6990
|
+
options?.services,
|
|
6991
|
+
options?.fonts,
|
|
6992
|
+
options?.warnings
|
|
6795
6993
|
);
|
|
6796
6994
|
}
|
|
6797
6995
|
function validateJsonSchema(jsonConfig) {
|
|
@@ -7054,6 +7252,7 @@ async function runExample(example, options = {}) {
|
|
|
7054
7252
|
// src/plugin/createDocumentGenerator.ts
|
|
7055
7253
|
init_styles();
|
|
7056
7254
|
import { Packer as Packer2 } from "docx";
|
|
7255
|
+
import { applyExportMode as applyExportMode2, scopedThemeName as scopedThemeName2 } from "@json-to-office/shared";
|
|
7057
7256
|
|
|
7058
7257
|
// src/plugin/version-resolver.ts
|
|
7059
7258
|
import { resolveComponentVersion } from "@json-to-office/shared/plugin";
|
|
@@ -7422,7 +7621,8 @@ function createBuilderImpl(state) {
|
|
|
7422
7621
|
customThemes: state.customThemes,
|
|
7423
7622
|
debug: state.debug,
|
|
7424
7623
|
enableCache: state.enableCache,
|
|
7425
|
-
services: state.services
|
|
7624
|
+
services: state.services,
|
|
7625
|
+
fonts: state.fonts
|
|
7426
7626
|
};
|
|
7427
7627
|
return createBuilderImpl(
|
|
7428
7628
|
newState
|
|
@@ -7435,25 +7635,37 @@ function createBuilderImpl(state) {
|
|
|
7435
7635
|
internalDocument,
|
|
7436
7636
|
state.components
|
|
7437
7637
|
);
|
|
7438
|
-
const
|
|
7439
|
-
const docTheme = resolveDocumentTheme(
|
|
7638
|
+
const baseThemeName = internalDocument.props.theme || "minimal";
|
|
7639
|
+
const docTheme = resolveDocumentTheme(baseThemeName);
|
|
7440
7640
|
const warnings = [];
|
|
7641
|
+
const mode = applyExportMode2({
|
|
7642
|
+
doc: internalDocument,
|
|
7643
|
+
theme: docTheme,
|
|
7644
|
+
fonts: state.fonts
|
|
7645
|
+
});
|
|
7646
|
+
const modedTheme = mode.theme;
|
|
7647
|
+
const themeName = scopedThemeName2(baseThemeName, state.fonts?.mode);
|
|
7648
|
+
for (const w of mode.warnings) {
|
|
7649
|
+
warnings.push({
|
|
7650
|
+
component: "fontRegistry",
|
|
7651
|
+
message: w.message,
|
|
7652
|
+
severity: "warning",
|
|
7653
|
+
context: { code: w.code }
|
|
7654
|
+
});
|
|
7655
|
+
}
|
|
7441
7656
|
const processedComponents = await processDocumentComponents(
|
|
7442
|
-
|
|
7657
|
+
mode.doc.children || [],
|
|
7443
7658
|
warnings,
|
|
7444
|
-
|
|
7659
|
+
modedTheme
|
|
7445
7660
|
);
|
|
7446
7661
|
const processedDocument = {
|
|
7447
|
-
...
|
|
7662
|
+
...mode.doc,
|
|
7448
7663
|
children: processedComponents
|
|
7449
7664
|
};
|
|
7450
|
-
const [
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
themeName
|
|
7455
|
-
);
|
|
7456
|
-
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
7665
|
+
const [modedDoc] = normalizeDocument(processedDocument);
|
|
7666
|
+
await resolveDocumentFonts(modedDoc, modedTheme, state.fonts, warnings);
|
|
7667
|
+
const structure = await processDocument(modedDoc, modedTheme, themeName);
|
|
7668
|
+
const layout = applyLayout(structure.sections, modedTheme, themeName);
|
|
7457
7669
|
const generatedDocument = await renderDocument(structure, layout, {
|
|
7458
7670
|
services: state.services
|
|
7459
7671
|
});
|
|
@@ -7534,13 +7746,19 @@ function createBuilderImpl(state) {
|
|
|
7534
7746
|
const themeName = internalDocument.props.theme || "minimal";
|
|
7535
7747
|
const docTheme = resolveDocumentTheme(themeName);
|
|
7536
7748
|
const warnings = [];
|
|
7749
|
+
const mode = applyExportMode2({
|
|
7750
|
+
doc: internalDocument,
|
|
7751
|
+
theme: docTheme,
|
|
7752
|
+
fonts: state.fonts
|
|
7753
|
+
});
|
|
7754
|
+
const modedTheme = mode.theme;
|
|
7537
7755
|
const processedComponents = await processDocumentComponents(
|
|
7538
|
-
|
|
7756
|
+
mode.doc.children || [],
|
|
7539
7757
|
warnings,
|
|
7540
|
-
|
|
7758
|
+
modedTheme
|
|
7541
7759
|
);
|
|
7542
7760
|
const processedDocument = {
|
|
7543
|
-
...
|
|
7761
|
+
...mode.doc,
|
|
7544
7762
|
children: processedComponents
|
|
7545
7763
|
};
|
|
7546
7764
|
const [finalReportComponent] = normalizeDocument(processedDocument);
|
|
@@ -7572,7 +7790,8 @@ function createDocumentGenerator(options) {
|
|
|
7572
7790
|
customThemes: options.customThemes,
|
|
7573
7791
|
debug: options.debug ?? false,
|
|
7574
7792
|
enableCache: options.enableCache ?? false,
|
|
7575
|
-
services: options.services
|
|
7793
|
+
services: options.services,
|
|
7794
|
+
fonts: options.fonts
|
|
7576
7795
|
};
|
|
7577
7796
|
return createBuilderImpl(initialState);
|
|
7578
7797
|
}
|