@json-to-office/core-docx 0.8.0 → 0.12.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/heading.d.ts.map +1 -1
- package/dist/components/highcharts.d.ts.map +1 -1
- package/dist/components/paragraph.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/index.js +202 -48
- 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 +165 -32
- package/dist/plugin/example/index.js.map +1 -1
- 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 +5 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ThemeConfig } from '../styles';
|
|
2
|
-
import type { ServicesConfig } from '@json-to-office/shared';
|
|
2
|
+
import type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';
|
|
3
3
|
import type { DocumentGeneratorBuilder } from './types';
|
|
4
4
|
/**
|
|
5
5
|
* Options for creating a document generator
|
|
@@ -15,6 +15,8 @@ export interface DocumentGeneratorOptions {
|
|
|
15
15
|
debug?: boolean;
|
|
16
16
|
/** External service configuration (e.g. Highcharts export server) */
|
|
17
17
|
services?: ServicesConfig;
|
|
18
|
+
/** Font resolution options — extraEntries, Google Fonts config, onResolved hook. */
|
|
19
|
+
fonts?: FontRuntimeOpts;
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* Create a document generator with chainable component registration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,KAAK,EAEV,wBAAwB,EAKzB,MAAM,SAAS,CAAC;AAcjB;;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;CACzB;AAseD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAavC"}
|
|
@@ -1813,6 +1813,67 @@ import { Packer as Packer2 } from "docx";
|
|
|
1813
1813
|
// src/plugin/createDocumentGenerator.ts
|
|
1814
1814
|
init_styles();
|
|
1815
1815
|
import { Packer } from "docx";
|
|
1816
|
+
import { applyExportMode, scopedThemeName } from "@json-to-office/shared";
|
|
1817
|
+
|
|
1818
|
+
// src/core/fontResolution.ts
|
|
1819
|
+
import {
|
|
1820
|
+
collectFontNamesFromDocx,
|
|
1821
|
+
validateFontReferences,
|
|
1822
|
+
FontRegistry
|
|
1823
|
+
} from "@json-to-office/shared";
|
|
1824
|
+
import {
|
|
1825
|
+
loadFileFontSource,
|
|
1826
|
+
FontDiskCache,
|
|
1827
|
+
fetchVariableFontSource
|
|
1828
|
+
} from "@json-to-office/shared/fonts/node";
|
|
1829
|
+
async function resolveDocumentFonts(document, theme, fonts, warnings) {
|
|
1830
|
+
const emit = (code, message) => {
|
|
1831
|
+
if (warnings) {
|
|
1832
|
+
warnings.push({
|
|
1833
|
+
component: "fontRegistry",
|
|
1834
|
+
message,
|
|
1835
|
+
severity: "warning",
|
|
1836
|
+
context: { code }
|
|
1837
|
+
});
|
|
1838
|
+
} else {
|
|
1839
|
+
console.warn(`[json-to-docx] ${code}: ${message}`);
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
const names = /* @__PURE__ */ new Set();
|
|
1843
|
+
for (const n of collectFontNamesFromDocx(document)) names.add(n);
|
|
1844
|
+
for (const n of collectFontNamesFromDocx(theme)) names.add(n);
|
|
1845
|
+
if (names.size === 0) return [];
|
|
1846
|
+
const validation = validateFontReferences({
|
|
1847
|
+
referencedNames: names,
|
|
1848
|
+
registeredEntries: fonts?.extraEntries
|
|
1849
|
+
});
|
|
1850
|
+
if (validation.warnings.length > 0) {
|
|
1851
|
+
if (fonts?.strict) {
|
|
1852
|
+
throw new Error(
|
|
1853
|
+
`Unresolved font references (strict mode):
|
|
1854
|
+
` + validation.warnings.map((w) => ` - ${w.message}`).join("\n")
|
|
1855
|
+
);
|
|
1856
|
+
}
|
|
1857
|
+
for (const w of validation.warnings) {
|
|
1858
|
+
emit(w.code, w.message);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
if (!fonts?.onResolved) return [];
|
|
1862
|
+
const registry = new FontRegistry({
|
|
1863
|
+
opts: fonts,
|
|
1864
|
+
fileLoader: loadFileFontSource,
|
|
1865
|
+
variableLoader: fetchVariableFontSource,
|
|
1866
|
+
diskCache: fonts?.googleFonts?.cacheDir ? new FontDiskCache(fonts.googleFonts.cacheDir) : void 0
|
|
1867
|
+
});
|
|
1868
|
+
const resolved = await registry.resolveMany(names);
|
|
1869
|
+
for (const r of resolved) {
|
|
1870
|
+
for (const msg of r.warnings) {
|
|
1871
|
+
emit("FONT_UNRESOLVED", msg);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
fonts.onResolved(resolved);
|
|
1875
|
+
return resolved;
|
|
1876
|
+
}
|
|
1816
1877
|
|
|
1817
1878
|
// src/plugin/version-resolver.ts
|
|
1818
1879
|
import { resolveComponentVersion } from "@json-to-office/shared/plugin";
|
|
@@ -4098,9 +4159,22 @@ var globalBookmarkRegistry = new BookmarkRegistry();
|
|
|
4098
4159
|
|
|
4099
4160
|
// src/core/content.ts
|
|
4100
4161
|
init_styleHelpers();
|
|
4162
|
+
import { synthesizeFamilyName } from "@json-to-office/shared";
|
|
4101
4163
|
init_colorUtils();
|
|
4102
4164
|
init_styleHelpers();
|
|
4103
4165
|
init_widthUtils();
|
|
4166
|
+
function applyFontWeightAlias(opts) {
|
|
4167
|
+
if (!opts.fontFamily) {
|
|
4168
|
+
return { font: void 0, bold: opts.bold, italics: opts.italic };
|
|
4169
|
+
}
|
|
4170
|
+
const weight = opts.fontWeight ?? (opts.bold === true ? 700 : void 0);
|
|
4171
|
+
const synth = synthesizeFamilyName(
|
|
4172
|
+
opts.fontFamily,
|
|
4173
|
+
weight,
|
|
4174
|
+
opts.italic === true
|
|
4175
|
+
);
|
|
4176
|
+
return { font: synth.family, bold: synth.bold, italics: synth.italic };
|
|
4177
|
+
}
|
|
4104
4178
|
function createText(content, theme, themeName, options = {}) {
|
|
4105
4179
|
const normalizedContent = normalizeUnicodeText(content);
|
|
4106
4180
|
const style = options.style || "Normal";
|
|
@@ -4120,15 +4194,27 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4120
4194
|
if (options.columnBreak) {
|
|
4121
4195
|
children.push(new ColumnBreak());
|
|
4122
4196
|
}
|
|
4197
|
+
const hasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4198
|
+
const effectiveFamily = options.fontFamily ?? (hasWeightRequest ? resolveFontFamily(theme, "body") : void 0);
|
|
4199
|
+
const weighted = applyFontWeightAlias({
|
|
4200
|
+
fontFamily: effectiveFamily,
|
|
4201
|
+
bold: options.bold,
|
|
4202
|
+
italic: options.italic,
|
|
4203
|
+
fontWeight: options.fontWeight
|
|
4204
|
+
});
|
|
4123
4205
|
const baseTextStyle = {
|
|
4124
|
-
|
|
4206
|
+
// Only emit `font` when it came from the caller or from an alias —
|
|
4207
|
+
// emitting the theme body family on every run would be a behavior change.
|
|
4208
|
+
...(options.fontFamily || weighted.font && weighted.font !== effectiveFamily) && {
|
|
4209
|
+
font: weighted.font
|
|
4210
|
+
},
|
|
4125
4211
|
...options.fontSize && { size: options.fontSize * 2 },
|
|
4126
4212
|
// Convert points to half-points
|
|
4127
4213
|
...options.fontColor && {
|
|
4128
4214
|
color: resolveColor(options.fontColor, theme)
|
|
4129
4215
|
},
|
|
4130
|
-
...
|
|
4131
|
-
...
|
|
4216
|
+
...weighted.bold !== void 0 && { bold: weighted.bold },
|
|
4217
|
+
...weighted.italics !== void 0 && { italics: weighted.italics },
|
|
4132
4218
|
...options.underline !== void 0 && {
|
|
4133
4219
|
underline: options.underline ? { type: "single" } : void 0
|
|
4134
4220
|
}
|
|
@@ -4248,13 +4334,25 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4248
4334
|
children.push(new ColumnBreak());
|
|
4249
4335
|
}
|
|
4250
4336
|
const hasDecorators = /(\*\*\*|___|(\*\*|__)|(\*|_))/.test(normalizedText);
|
|
4337
|
+
const headingHasWeightRequest = options.fontWeight != null || options.bold === true;
|
|
4338
|
+
const headingEffectiveFamily = options.fontFamily ?? (headingHasWeightRequest ? resolveFontFamily(theme, "heading") : void 0);
|
|
4339
|
+
const headingWeighted = applyFontWeightAlias({
|
|
4340
|
+
fontFamily: headingEffectiveFamily,
|
|
4341
|
+
bold: options.bold,
|
|
4342
|
+
italic: options.italic,
|
|
4343
|
+
fontWeight: options.fontWeight
|
|
4344
|
+
});
|
|
4251
4345
|
const baseTextStyle = {
|
|
4252
|
-
...options.fontFamily
|
|
4346
|
+
...(options.fontFamily || headingWeighted.font && headingWeighted.font !== headingEffectiveFamily) && {
|
|
4347
|
+
font: headingWeighted.font
|
|
4348
|
+
},
|
|
4253
4349
|
...options.fontSize && { size: options.fontSize * 2 },
|
|
4254
4350
|
// points to half-points
|
|
4255
4351
|
...options.fontColor && { color: resolveColor(options.fontColor, theme) },
|
|
4256
|
-
...
|
|
4257
|
-
...
|
|
4352
|
+
...headingWeighted.bold !== void 0 && { bold: headingWeighted.bold },
|
|
4353
|
+
...headingWeighted.italics !== void 0 && {
|
|
4354
|
+
italics: headingWeighted.italics
|
|
4355
|
+
},
|
|
4258
4356
|
...options.underline !== void 0 && {
|
|
4259
4357
|
underline: options.underline ? { type: "single" } : void 0
|
|
4260
4358
|
}
|
|
@@ -4766,12 +4864,18 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4766
4864
|
if (!cell) {
|
|
4767
4865
|
return cellChildren;
|
|
4768
4866
|
}
|
|
4867
|
+
const cellWeighted = applyFontWeightAlias({
|
|
4868
|
+
fontFamily: cellDefaults.font?.family || baseCellStyle.font,
|
|
4869
|
+
bold: cellDefaults.font?.bold ?? false,
|
|
4870
|
+
italic: cellDefaults.font?.italic ?? false,
|
|
4871
|
+
fontWeight: cellDefaults.font?.fontWeight
|
|
4872
|
+
});
|
|
4769
4873
|
const mergedStyle = {
|
|
4770
|
-
font:
|
|
4874
|
+
font: cellWeighted.font,
|
|
4771
4875
|
size: cellDefaults.font?.size ? cellDefaults.font.size * 2 : baseCellStyle.size,
|
|
4772
4876
|
// Convert to half-points
|
|
4773
|
-
bold:
|
|
4774
|
-
italics:
|
|
4877
|
+
bold: cellWeighted.bold ?? false,
|
|
4878
|
+
italics: cellWeighted.italics ?? false,
|
|
4775
4879
|
underline: cellDefaults.font?.underline ? { type: "single" } : void 0,
|
|
4776
4880
|
color: cellDefaults.color || baseCellStyle.color
|
|
4777
4881
|
};
|
|
@@ -4779,15 +4883,21 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4779
4883
|
if (isParagraphComponent(cell)) {
|
|
4780
4884
|
const textComp = cell;
|
|
4781
4885
|
const paragraphFont = textComp.props.font;
|
|
4886
|
+
const paraWeighted = applyFontWeightAlias({
|
|
4887
|
+
fontFamily: paragraphFont?.family ?? mergedStyle.font,
|
|
4888
|
+
bold: paragraphFont?.bold,
|
|
4889
|
+
italic: paragraphFont?.italic,
|
|
4890
|
+
fontWeight: paragraphFont?.fontWeight
|
|
4891
|
+
});
|
|
4782
4892
|
const paragraphStyle = {
|
|
4783
4893
|
...mergedStyle,
|
|
4784
|
-
...
|
|
4894
|
+
...paraWeighted.font && { font: paraWeighted.font },
|
|
4785
4895
|
...paragraphFont?.size && { size: paragraphFont.size * 2 },
|
|
4786
|
-
...
|
|
4787
|
-
bold:
|
|
4896
|
+
...paraWeighted.bold !== void 0 && {
|
|
4897
|
+
bold: paraWeighted.bold
|
|
4788
4898
|
},
|
|
4789
|
-
...
|
|
4790
|
-
italics:
|
|
4899
|
+
...paraWeighted.italics !== void 0 && {
|
|
4900
|
+
italics: paraWeighted.italics
|
|
4791
4901
|
},
|
|
4792
4902
|
...paragraphFont?.underline !== void 0 && {
|
|
4793
4903
|
underline: paragraphFont.underline ? { type: "single" } : void 0
|
|
@@ -5235,6 +5345,7 @@ function renderHeadingComponent(component, theme, themeName) {
|
|
|
5235
5345
|
fontSize: config.font?.size,
|
|
5236
5346
|
fontColor: config.font?.color,
|
|
5237
5347
|
bold: config.font?.bold,
|
|
5348
|
+
fontWeight: config.font?.fontWeight,
|
|
5238
5349
|
italic: config.font?.italic,
|
|
5239
5350
|
underline: config.font?.underline,
|
|
5240
5351
|
// Pagination control
|
|
@@ -5350,6 +5461,7 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
5350
5461
|
fontSize: resolvedConfig.font?.size,
|
|
5351
5462
|
fontColor: resolvedConfig.font?.color,
|
|
5352
5463
|
bold: resolvedConfig.font?.bold,
|
|
5464
|
+
fontWeight: resolvedConfig.font?.fontWeight,
|
|
5353
5465
|
italic: resolvedConfig.font?.italic,
|
|
5354
5466
|
underline: resolvedConfig.font?.underline,
|
|
5355
5467
|
// Pass outline level for TOC support
|
|
@@ -6148,9 +6260,10 @@ async function generateChart(config, servicesConfig) {
|
|
|
6148
6260
|
b64: true,
|
|
6149
6261
|
scale: config.scale
|
|
6150
6262
|
};
|
|
6263
|
+
const resolvedHeaders = typeof servicesConfig?.headers === "function" ? await servicesConfig.headers(requestBody) : servicesConfig?.headers;
|
|
6151
6264
|
const headers = {
|
|
6152
6265
|
"Content-Type": "application/json",
|
|
6153
|
-
...
|
|
6266
|
+
...resolvedHeaders
|
|
6154
6267
|
};
|
|
6155
6268
|
const response = await fetch(`${serverUrl}/export`, {
|
|
6156
6269
|
method: "POST",
|
|
@@ -6828,7 +6941,8 @@ function createBuilderImpl(state) {
|
|
|
6828
6941
|
customThemes: state.customThemes,
|
|
6829
6942
|
debug: state.debug,
|
|
6830
6943
|
enableCache: state.enableCache,
|
|
6831
|
-
services: state.services
|
|
6944
|
+
services: state.services,
|
|
6945
|
+
fonts: state.fonts
|
|
6832
6946
|
};
|
|
6833
6947
|
return createBuilderImpl(
|
|
6834
6948
|
newState
|
|
@@ -6841,25 +6955,37 @@ function createBuilderImpl(state) {
|
|
|
6841
6955
|
internalDocument,
|
|
6842
6956
|
state.components
|
|
6843
6957
|
);
|
|
6844
|
-
const
|
|
6845
|
-
const docTheme = resolveDocumentTheme(
|
|
6958
|
+
const baseThemeName = internalDocument.props.theme || "minimal";
|
|
6959
|
+
const docTheme = resolveDocumentTheme(baseThemeName);
|
|
6846
6960
|
const warnings = [];
|
|
6961
|
+
const mode = applyExportMode({
|
|
6962
|
+
doc: internalDocument,
|
|
6963
|
+
theme: docTheme,
|
|
6964
|
+
fonts: state.fonts
|
|
6965
|
+
});
|
|
6966
|
+
const modedTheme = mode.theme;
|
|
6967
|
+
const themeName = scopedThemeName(baseThemeName, state.fonts?.mode);
|
|
6968
|
+
for (const w of mode.warnings) {
|
|
6969
|
+
warnings.push({
|
|
6970
|
+
component: "fontRegistry",
|
|
6971
|
+
message: w.message,
|
|
6972
|
+
severity: "warning",
|
|
6973
|
+
context: { code: w.code }
|
|
6974
|
+
});
|
|
6975
|
+
}
|
|
6847
6976
|
const processedComponents = await processDocumentComponents(
|
|
6848
|
-
|
|
6977
|
+
mode.doc.children || [],
|
|
6849
6978
|
warnings,
|
|
6850
|
-
|
|
6979
|
+
modedTheme
|
|
6851
6980
|
);
|
|
6852
6981
|
const processedDocument = {
|
|
6853
|
-
...
|
|
6982
|
+
...mode.doc,
|
|
6854
6983
|
children: processedComponents
|
|
6855
6984
|
};
|
|
6856
|
-
const [
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
themeName
|
|
6861
|
-
);
|
|
6862
|
-
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
6985
|
+
const [modedDoc] = normalizeDocument(processedDocument);
|
|
6986
|
+
await resolveDocumentFonts(modedDoc, modedTheme, state.fonts, warnings);
|
|
6987
|
+
const structure = await processDocument(modedDoc, modedTheme, themeName);
|
|
6988
|
+
const layout = applyLayout(structure.sections, modedTheme, themeName);
|
|
6863
6989
|
const generatedDocument = await renderDocument(structure, layout, {
|
|
6864
6990
|
services: state.services
|
|
6865
6991
|
});
|
|
@@ -6940,13 +7066,19 @@ function createBuilderImpl(state) {
|
|
|
6940
7066
|
const themeName = internalDocument.props.theme || "minimal";
|
|
6941
7067
|
const docTheme = resolveDocumentTheme(themeName);
|
|
6942
7068
|
const warnings = [];
|
|
7069
|
+
const mode = applyExportMode({
|
|
7070
|
+
doc: internalDocument,
|
|
7071
|
+
theme: docTheme,
|
|
7072
|
+
fonts: state.fonts
|
|
7073
|
+
});
|
|
7074
|
+
const modedTheme = mode.theme;
|
|
6943
7075
|
const processedComponents = await processDocumentComponents(
|
|
6944
|
-
|
|
7076
|
+
mode.doc.children || [],
|
|
6945
7077
|
warnings,
|
|
6946
|
-
|
|
7078
|
+
modedTheme
|
|
6947
7079
|
);
|
|
6948
7080
|
const processedDocument = {
|
|
6949
|
-
...
|
|
7081
|
+
...mode.doc,
|
|
6950
7082
|
children: processedComponents
|
|
6951
7083
|
};
|
|
6952
7084
|
const [finalReportComponent] = normalizeDocument(processedDocument);
|
|
@@ -6978,7 +7110,8 @@ function createDocumentGenerator(options) {
|
|
|
6978
7110
|
customThemes: options.customThemes,
|
|
6979
7111
|
debug: options.debug ?? false,
|
|
6980
7112
|
enableCache: options.enableCache ?? false,
|
|
6981
|
-
services: options.services
|
|
7113
|
+
services: options.services,
|
|
7114
|
+
fonts: options.fonts
|
|
6982
7115
|
};
|
|
6983
7116
|
return createBuilderImpl(initialState);
|
|
6984
7117
|
}
|