@json-to-office/core-docx 0.8.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/heading.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 +200 -47
- 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 +163 -31
- 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 +4 -5
|
@@ -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
|
|
@@ -6828,7 +6940,8 @@ function createBuilderImpl(state) {
|
|
|
6828
6940
|
customThemes: state.customThemes,
|
|
6829
6941
|
debug: state.debug,
|
|
6830
6942
|
enableCache: state.enableCache,
|
|
6831
|
-
services: state.services
|
|
6943
|
+
services: state.services,
|
|
6944
|
+
fonts: state.fonts
|
|
6832
6945
|
};
|
|
6833
6946
|
return createBuilderImpl(
|
|
6834
6947
|
newState
|
|
@@ -6841,25 +6954,37 @@ function createBuilderImpl(state) {
|
|
|
6841
6954
|
internalDocument,
|
|
6842
6955
|
state.components
|
|
6843
6956
|
);
|
|
6844
|
-
const
|
|
6845
|
-
const docTheme = resolveDocumentTheme(
|
|
6957
|
+
const baseThemeName = internalDocument.props.theme || "minimal";
|
|
6958
|
+
const docTheme = resolveDocumentTheme(baseThemeName);
|
|
6846
6959
|
const warnings = [];
|
|
6960
|
+
const mode = applyExportMode({
|
|
6961
|
+
doc: internalDocument,
|
|
6962
|
+
theme: docTheme,
|
|
6963
|
+
fonts: state.fonts
|
|
6964
|
+
});
|
|
6965
|
+
const modedTheme = mode.theme;
|
|
6966
|
+
const themeName = scopedThemeName(baseThemeName, state.fonts?.mode);
|
|
6967
|
+
for (const w of mode.warnings) {
|
|
6968
|
+
warnings.push({
|
|
6969
|
+
component: "fontRegistry",
|
|
6970
|
+
message: w.message,
|
|
6971
|
+
severity: "warning",
|
|
6972
|
+
context: { code: w.code }
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6847
6975
|
const processedComponents = await processDocumentComponents(
|
|
6848
|
-
|
|
6976
|
+
mode.doc.children || [],
|
|
6849
6977
|
warnings,
|
|
6850
|
-
|
|
6978
|
+
modedTheme
|
|
6851
6979
|
);
|
|
6852
6980
|
const processedDocument = {
|
|
6853
|
-
...
|
|
6981
|
+
...mode.doc,
|
|
6854
6982
|
children: processedComponents
|
|
6855
6983
|
};
|
|
6856
|
-
const [
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
themeName
|
|
6861
|
-
);
|
|
6862
|
-
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
6984
|
+
const [modedDoc] = normalizeDocument(processedDocument);
|
|
6985
|
+
await resolveDocumentFonts(modedDoc, modedTheme, state.fonts, warnings);
|
|
6986
|
+
const structure = await processDocument(modedDoc, modedTheme, themeName);
|
|
6987
|
+
const layout = applyLayout(structure.sections, modedTheme, themeName);
|
|
6863
6988
|
const generatedDocument = await renderDocument(structure, layout, {
|
|
6864
6989
|
services: state.services
|
|
6865
6990
|
});
|
|
@@ -6940,13 +7065,19 @@ function createBuilderImpl(state) {
|
|
|
6940
7065
|
const themeName = internalDocument.props.theme || "minimal";
|
|
6941
7066
|
const docTheme = resolveDocumentTheme(themeName);
|
|
6942
7067
|
const warnings = [];
|
|
7068
|
+
const mode = applyExportMode({
|
|
7069
|
+
doc: internalDocument,
|
|
7070
|
+
theme: docTheme,
|
|
7071
|
+
fonts: state.fonts
|
|
7072
|
+
});
|
|
7073
|
+
const modedTheme = mode.theme;
|
|
6943
7074
|
const processedComponents = await processDocumentComponents(
|
|
6944
|
-
|
|
7075
|
+
mode.doc.children || [],
|
|
6945
7076
|
warnings,
|
|
6946
|
-
|
|
7077
|
+
modedTheme
|
|
6947
7078
|
);
|
|
6948
7079
|
const processedDocument = {
|
|
6949
|
-
...
|
|
7080
|
+
...mode.doc,
|
|
6950
7081
|
children: processedComponents
|
|
6951
7082
|
};
|
|
6952
7083
|
const [finalReportComponent] = normalizeDocument(processedDocument);
|
|
@@ -6978,7 +7109,8 @@ function createDocumentGenerator(options) {
|
|
|
6978
7109
|
customThemes: options.customThemes,
|
|
6979
7110
|
debug: options.debug ?? false,
|
|
6980
7111
|
enableCache: options.enableCache ?? false,
|
|
6981
|
-
services: options.services
|
|
7112
|
+
services: options.services,
|
|
7113
|
+
fonts: options.fonts
|
|
6982
7114
|
};
|
|
6983
7115
|
return createBuilderImpl(initialState);
|
|
6984
7116
|
}
|