@json-to-office/core-docx 0.1.0 → 0.2.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/table.d.ts.map +1 -1
- package/dist/core/content.d.ts +2 -1
- package/dist/core/content.d.ts.map +1 -1
- package/dist/index.js +79 -137
- package/dist/index.js.map +1 -1
- package/dist/plugin/createComponent.d.ts +8 -106
- package/dist/plugin/createComponent.d.ts.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 +87 -136
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/plugin/validation.d.ts +6 -22
- package/dist/plugin/validation.d.ts.map +1 -1
- package/dist/plugin/version-resolver.d.ts +1 -9
- package/dist/plugin/version-resolver.d.ts.map +1 -1
- package/dist/templates/themes/index.d.ts +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/widthUtils.d.ts +0 -1
- package/dist/utils/widthUtils.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1,113 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TSchema } from '@sinclair/typebox';
|
|
2
2
|
import type { ComponentDefinition } from '@json-to-office/shared-docx';
|
|
3
|
-
import type { AddWarningFunction } from '@json-to-office/shared-docx';
|
|
4
3
|
import type { ThemeConfig } from '../styles';
|
|
4
|
+
import type { RenderContext as SharedRenderContext, RenderFunction as SharedRenderFunction, ComponentVersion as SharedComponentVersion, ComponentVersionMap as SharedComponentVersionMap, CustomComponent as SharedCustomComponent } from '@json-to-office/shared/plugin';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
export interface RenderContext<T> {
|
|
9
|
-
/** The validated props for this component */
|
|
10
|
-
props: T;
|
|
11
|
-
/** The resolved theme configuration */
|
|
12
|
-
theme: ThemeConfig;
|
|
13
|
-
/** Function to add warnings during processing */
|
|
14
|
-
addWarning: AddWarningFunction;
|
|
15
|
-
/** For container components: processed nested children */
|
|
16
|
-
children?: unknown[];
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Render function that transforms custom component props into standard components.
|
|
20
|
-
*/
|
|
21
|
-
export type RenderFunction<TProps, TComponentDefinition = ComponentDefinition> = (context: RenderContext<TProps>) => Promise<TComponentDefinition[]>;
|
|
22
|
-
/**
|
|
23
|
-
* A single version entry within a versioned component.
|
|
24
|
-
* Each version is self-contained with its own schema, render, and metadata.
|
|
25
|
-
*/
|
|
26
|
-
export interface ComponentVersion<TComponentDefinition = ComponentDefinition, TPropsSchema extends TSchema = TSchema> {
|
|
27
|
-
/** TypeBox schema for props validation */
|
|
28
|
-
propsSchema: TPropsSchema;
|
|
29
|
-
/** Async render function to transform props into standard components */
|
|
30
|
-
render: RenderFunction<Static<TPropsSchema>, TComponentDefinition>;
|
|
31
|
-
/** Whether this version supports nested children */
|
|
32
|
-
hasChildren?: boolean;
|
|
33
|
-
/** Optional description for this version */
|
|
34
|
-
description?: string;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Map of semver version strings to their version definitions.
|
|
38
|
-
*/
|
|
39
|
-
export type ComponentVersionMap<TComponentDefinition = ComponentDefinition> = Record<string, ComponentVersion<TComponentDefinition, any>>;
|
|
40
|
-
/**
|
|
41
|
-
* Custom component definition with multiple semver-keyed versions.
|
|
42
|
-
* Each version is self-contained with its own schema + render.
|
|
43
|
-
*
|
|
44
|
-
* @typeParam TComponentDefinition - The component definition type for render return
|
|
45
|
-
* @typeParam TVersions - The versions map type
|
|
46
|
-
* @typeParam TName - The literal string type for the component name
|
|
47
|
-
*/
|
|
48
|
-
export interface CustomComponent<TComponentDefinition = ComponentDefinition, TVersions extends ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>, TName extends string = string> {
|
|
49
|
-
/** Unique name for the component type */
|
|
50
|
-
name: TName;
|
|
51
|
-
/** Map of semver version strings to version definitions */
|
|
52
|
-
versions: TVersions;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Create a single version entry with full type inference for props.
|
|
56
|
-
*
|
|
57
|
-
* Wrapping each version with `createVersion` lets TypeScript infer the
|
|
58
|
-
* props type from `propsSchema` and propagate it to the `render` function,
|
|
59
|
-
* so `props` is fully typed instead of `any`.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```typescript
|
|
63
|
-
* createVersion({
|
|
64
|
-
* propsSchema: Type.Object({ city: Type.String() }),
|
|
65
|
-
* render: async ({ props }) => {
|
|
66
|
-
* // props.city is inferred as string
|
|
67
|
-
* return [{ name: 'paragraph', props: { text: props.city } }];
|
|
68
|
-
* },
|
|
69
|
-
* })
|
|
70
|
-
* ```
|
|
6
|
+
* DOCX render context with ThemeConfig baked in
|
|
71
7
|
*/
|
|
8
|
+
export type RenderContext<T> = SharedRenderContext<T, ThemeConfig>;
|
|
9
|
+
export type RenderFunction<TProps, TComponentDefinition = ComponentDefinition> = SharedRenderFunction<TProps, TComponentDefinition, ThemeConfig>;
|
|
10
|
+
export type ComponentVersion<TComponentDefinition = ComponentDefinition, TPropsSchema extends TSchema = TSchema> = SharedComponentVersion<TComponentDefinition, TPropsSchema, ThemeConfig>;
|
|
11
|
+
export type ComponentVersionMap<TComponentDefinition = ComponentDefinition> = SharedComponentVersionMap<TComponentDefinition, ThemeConfig>;
|
|
12
|
+
export type CustomComponent<TComponentDefinition = ComponentDefinition, TVersions extends ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>, TName extends string = string> = SharedCustomComponent<TComponentDefinition, TVersions, TName>;
|
|
72
13
|
export declare function createVersion<TPropsSchema extends TSchema, TComponentDefinition = ComponentDefinition>(version: ComponentVersion<TComponentDefinition, TPropsSchema>): ComponentVersion<TComponentDefinition, TPropsSchema>;
|
|
73
|
-
/**
|
|
74
|
-
* Create a custom component with multiple semver-keyed versions.
|
|
75
|
-
*
|
|
76
|
-
* Use {@link createVersion} for each version entry to get full type inference
|
|
77
|
-
* for `props` in render functions.
|
|
78
|
-
*
|
|
79
|
-
* @example Basic single-version usage
|
|
80
|
-
* ```typescript
|
|
81
|
-
* const weatherComponent = createComponent({
|
|
82
|
-
* name: 'weather' as const,
|
|
83
|
-
* versions: {
|
|
84
|
-
* '1.0.0': createVersion({
|
|
85
|
-
* propsSchema: Type.Object({ city: Type.String() }),
|
|
86
|
-
* render: async ({ props }) => [{
|
|
87
|
-
* name: 'paragraph',
|
|
88
|
-
* props: { text: `Weather in ${props.city}` }
|
|
89
|
-
* }]
|
|
90
|
-
* })
|
|
91
|
-
* }
|
|
92
|
-
* });
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
|
-
* @example Multi-version with breaking changes
|
|
96
|
-
* ```typescript
|
|
97
|
-
* const weatherComponent = createComponent({
|
|
98
|
-
* name: 'weather' as const,
|
|
99
|
-
* versions: {
|
|
100
|
-
* '1.0.0': createVersion({
|
|
101
|
-
* propsSchema: WeatherV1PropsSchema,
|
|
102
|
-
* render: async ({ props }) => [...],
|
|
103
|
-
* }),
|
|
104
|
-
* '2.0.0': createVersion({
|
|
105
|
-
* propsSchema: WeatherV2PropsSchema,
|
|
106
|
-
* render: async ({ props }) => [...],
|
|
107
|
-
* }),
|
|
108
|
-
* },
|
|
109
|
-
* });
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
14
|
export declare function createComponent<TComponentDefinition = ComponentDefinition, TVersions extends ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>, TName extends string = string>(component: CustomComponent<TComponentDefinition, TVersions, TName>): CustomComponent<TComponentDefinition, TVersions, TName>;
|
|
113
15
|
//# sourceMappingURL=createComponent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../../src/plugin/createComponent.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../../src/plugin/createComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAK7C,OAAO,KAAK,EACV,aAAa,IAAI,mBAAmB,EACpC,cAAc,IAAI,oBAAoB,EACtC,gBAAgB,IAAI,sBAAsB,EAC1C,mBAAmB,IAAI,yBAAyB,EAChD,eAAe,IAAI,qBAAqB,EACzC,MAAM,+BAA+B,CAAC;AAIvC;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;AAEnE,MAAM,MAAM,cAAc,CACxB,MAAM,EACN,oBAAoB,GAAG,mBAAmB,IACxC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,EAAE,WAAW,CAAC,CAAC;AAEpE,MAAM,MAAM,gBAAgB,CAC1B,oBAAoB,GAAG,mBAAmB,EAC1C,YAAY,SAAS,OAAO,GAAG,OAAO,IACpC,sBAAsB,CAAC,oBAAoB,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,MAAM,mBAAmB,CAAC,oBAAoB,GAAG,mBAAmB,IACxE,yBAAyB,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;AAE/D,MAAM,MAAM,eAAe,CACzB,oBAAoB,GAAG,mBAAmB,EAC1C,SAAS,SACP,mBAAmB,CAAC,oBAAoB,CAAC,GAAG,mBAAmB,CAAC,oBAAoB,CAAC,EACvF,KAAK,SAAS,MAAM,GAAG,MAAM,IAC3B,qBAAqB,CAAC,oBAAoB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAIlE,wBAAgB,aAAa,CAC3B,YAAY,SAAS,OAAO,EAC5B,oBAAoB,GAAG,mBAAmB,EAE1C,OAAO,EAAE,gBAAgB,CAAC,oBAAoB,EAAE,YAAY,CAAC,GAC5D,gBAAgB,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAEtD;AAED,wBAAgB,eAAe,CAC7B,oBAAoB,GAAG,mBAAmB,EAC1C,SAAS,SACP,mBAAmB,CAAC,oBAAoB,CAAC,GAAG,mBAAmB,CAAC,oBAAoB,CAAC,EACvF,KAAK,SAAS,MAAM,GAAG,MAAM,EAE7B,SAAS,EAAE,eAAe,CAAC,oBAAoB,EAAE,SAAS,EAAE,KAAK,CAAC,GACjE,eAAe,CAAC,oBAAoB,EAAE,SAAS,EAAE,KAAK,CAAC,CAEzD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ThemeConfig } from '../styles';
|
|
2
2
|
import type { DocumentGeneratorBuilder } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Options for creating a document generator
|
|
@@ -6,6 +6,8 @@ import type { DocumentGeneratorBuilder } from './types';
|
|
|
6
6
|
export interface DocumentGeneratorOptions {
|
|
7
7
|
/** Theme configuration */
|
|
8
8
|
theme: ThemeConfig;
|
|
9
|
+
/** Custom themes keyed by name, resolved per-document via document.props.theme */
|
|
10
|
+
customThemes?: Record<string, ThemeConfig>;
|
|
9
11
|
/** Enable caching for better performance */
|
|
10
12
|
enableCache?: boolean;
|
|
11
13
|
/** Enable debug logging */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDocumentGenerator.d.ts","sourceRoot":"","sources":["../../src/plugin/createDocumentGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
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,EAEV,wBAAwB,EAKzB,MAAM,SAAS,CAAC;AAcjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,0BAA0B;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,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;CACjB;AA2bD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAAC,SAAS,EAAE,CAAC,CAWvC"}
|
|
@@ -678,7 +678,7 @@ function loadThemesFromJson() {
|
|
|
678
678
|
_themesCache = themes2;
|
|
679
679
|
return themes2;
|
|
680
680
|
}
|
|
681
|
-
var _themesCache, themes, getTheme, minimalTheme, corporateTheme, modernTheme;
|
|
681
|
+
var _themesCache, themes, getTheme, getThemeWithFallback, minimalTheme, corporateTheme, modernTheme;
|
|
682
682
|
var init_themes = __esm({
|
|
683
683
|
"src/templates/themes/index.ts"() {
|
|
684
684
|
"use strict";
|
|
@@ -691,6 +691,15 @@ var init_themes = __esm({
|
|
|
691
691
|
getTheme = (themeName) => {
|
|
692
692
|
return themes[themeName];
|
|
693
693
|
};
|
|
694
|
+
getThemeWithFallback = (themeName, fallbackTheme = "minimal") => {
|
|
695
|
+
const theme = getTheme(themeName) || getTheme(fallbackTheme);
|
|
696
|
+
if (!theme) {
|
|
697
|
+
throw new Error(
|
|
698
|
+
`Failed to load theme: ${themeName}. Fallback theme '${fallbackTheme}' also not found.`
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
return theme;
|
|
702
|
+
};
|
|
694
703
|
minimalTheme = themes["minimal"];
|
|
695
704
|
corporateTheme = themes["corporate"];
|
|
696
705
|
modernTheme = themes["modern"];
|
|
@@ -1333,7 +1342,6 @@ var init_styles = __esm({
|
|
|
1333
1342
|
// src/utils/widthUtils.ts
|
|
1334
1343
|
var widthUtils_exports = {};
|
|
1335
1344
|
__export(widthUtils_exports, {
|
|
1336
|
-
__widthUtils: () => __widthUtils,
|
|
1337
1345
|
getAvailableHeightTwips: () => getAvailableHeightTwips,
|
|
1338
1346
|
getAvailableWidthTwips: () => getAvailableWidthTwips,
|
|
1339
1347
|
getPageHeightTwips: () => getPageHeightTwips,
|
|
@@ -1378,13 +1386,11 @@ function relativeLengthToTwips(value, availableWidthTwips) {
|
|
|
1378
1386
|
if (fraction === void 0) return 0;
|
|
1379
1387
|
return Math.round(availableWidthTwips * fraction);
|
|
1380
1388
|
}
|
|
1381
|
-
var __widthUtils;
|
|
1382
1389
|
var init_widthUtils = __esm({
|
|
1383
1390
|
"src/utils/widthUtils.ts"() {
|
|
1384
1391
|
"use strict";
|
|
1385
1392
|
init_styles();
|
|
1386
1393
|
init_styleHelpers();
|
|
1387
|
-
__widthUtils = true;
|
|
1388
1394
|
}
|
|
1389
1395
|
});
|
|
1390
1396
|
|
|
@@ -2036,62 +2042,29 @@ var init_numberingConfig = __esm({
|
|
|
2036
2042
|
import { Packer as Packer2 } from "docx";
|
|
2037
2043
|
|
|
2038
2044
|
// src/plugin/createDocumentGenerator.ts
|
|
2045
|
+
init_styles();
|
|
2039
2046
|
import { Packer } from "docx";
|
|
2040
2047
|
|
|
2041
2048
|
// src/plugin/version-resolver.ts
|
|
2042
|
-
import {
|
|
2043
|
-
function resolveComponentVersion(componentName, versions, requestedVersion) {
|
|
2044
|
-
const versionKeys = Object.keys(versions);
|
|
2045
|
-
if (requestedVersion) {
|
|
2046
|
-
const entry = versions[requestedVersion];
|
|
2047
|
-
if (!entry) {
|
|
2048
|
-
throw new Error(
|
|
2049
|
-
`Component "${componentName}" does not have version "${requestedVersion}". Available versions: ${versionKeys.join(", ")}`
|
|
2050
|
-
);
|
|
2051
|
-
}
|
|
2052
|
-
return entry;
|
|
2053
|
-
}
|
|
2054
|
-
const latest = latestVersion(versionKeys);
|
|
2055
|
-
return versions[latest];
|
|
2056
|
-
}
|
|
2049
|
+
import { resolveComponentVersion } from "@json-to-office/shared/plugin";
|
|
2057
2050
|
|
|
2058
2051
|
// src/plugin/validation.ts
|
|
2059
2052
|
import {
|
|
2060
2053
|
validateCustomComponentProps,
|
|
2054
|
+
ComponentValidationError
|
|
2055
|
+
} from "@json-to-office/shared/plugin";
|
|
2056
|
+
import {
|
|
2061
2057
|
validateDocument as validateDocumentUnified
|
|
2062
2058
|
} from "@json-to-office/shared-docx/validation/unified";
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
`Cannot register component "${componentName}": a component with this name is already registered. Component names must be unique within a document generator.`
|
|
2069
|
-
);
|
|
2070
|
-
this.name = "DuplicateComponentError";
|
|
2071
|
-
this.componentName = componentName;
|
|
2072
|
-
if (Error.captureStackTrace) {
|
|
2073
|
-
Error.captureStackTrace(this, _DuplicateComponentError);
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
};
|
|
2077
|
-
var ComponentValidationError = class extends Error {
|
|
2078
|
-
errors;
|
|
2079
|
-
props;
|
|
2080
|
-
constructor(errors, props) {
|
|
2081
|
-
const propsStr = props !== void 0 ? `
|
|
2082
|
-
Props: ${JSON.stringify(props, null, 2)}` : "";
|
|
2083
|
-
const message = `Document validation failed:
|
|
2084
|
-
${errors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}${propsStr}`;
|
|
2085
|
-
super(message);
|
|
2086
|
-
this.name = "ComponentValidationError";
|
|
2087
|
-
this.errors = errors;
|
|
2088
|
-
this.props = props;
|
|
2089
|
-
}
|
|
2090
|
-
};
|
|
2091
|
-
function validateComponentProps(schema, props) {
|
|
2059
|
+
import {
|
|
2060
|
+
DuplicateComponentError,
|
|
2061
|
+
ComponentValidationError as ComponentValidationError2
|
|
2062
|
+
} from "@json-to-office/shared/plugin";
|
|
2063
|
+
function validateComponentProps(schema, props, componentName) {
|
|
2092
2064
|
return validateCustomComponentProps(schema.propsSchema, props, {
|
|
2093
2065
|
clean: true,
|
|
2094
|
-
applyDefaults: true
|
|
2066
|
+
applyDefaults: true,
|
|
2067
|
+
componentName
|
|
2095
2068
|
});
|
|
2096
2069
|
}
|
|
2097
2070
|
function validateDocument(document, customComponents) {
|
|
@@ -2118,7 +2091,8 @@ function validateDocument(document, customComponents) {
|
|
|
2118
2091
|
);
|
|
2119
2092
|
const validation = validateComponentProps(
|
|
2120
2093
|
versionEntry,
|
|
2121
|
-
componentData.props
|
|
2094
|
+
componentData.props,
|
|
2095
|
+
customComponent.name
|
|
2122
2096
|
);
|
|
2123
2097
|
if (!validation.valid && validation.errors) {
|
|
2124
2098
|
const indexedErrors = validation.errors.map(
|
|
@@ -2153,7 +2127,7 @@ var cleanComponentProps = getValidatedProps;
|
|
|
2153
2127
|
|
|
2154
2128
|
// src/plugin/schema.ts
|
|
2155
2129
|
import { Type } from "@sinclair/typebox";
|
|
2156
|
-
import { latestVersion
|
|
2130
|
+
import { latestVersion } from "@json-to-office/shared-docx";
|
|
2157
2131
|
import {
|
|
2158
2132
|
ReportPropsSchema,
|
|
2159
2133
|
SectionPropsSchema,
|
|
@@ -5070,15 +5044,21 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5070
5044
|
let columnWidths;
|
|
5071
5045
|
let tableWidth;
|
|
5072
5046
|
if (hasExplicitWidths) {
|
|
5073
|
-
const
|
|
5047
|
+
const widthUtils = await Promise.resolve().then(() => (init_widthUtils(), widthUtils_exports));
|
|
5048
|
+
const { getAvailableWidthTwips: getAvailableWidthTwips2, relativeLengthToTwips: relativeLengthToTwips2 } = widthUtils;
|
|
5074
5049
|
const availableTableWidth = getAvailableWidthTwips2(theme, themeName);
|
|
5075
5050
|
const columnsWithExplicitWidthTwips = columns.map(
|
|
5076
|
-
(col) => col.width !== void 0 ?
|
|
5051
|
+
(col) => col.width !== void 0 ? relativeLengthToTwips2(col.width, availableTableWidth) : void 0
|
|
5077
5052
|
);
|
|
5078
5053
|
const totalExplicitWidth = columnsWithExplicitWidthTwips.reduce(
|
|
5079
5054
|
(sum, w) => sum + (w || 0),
|
|
5080
5055
|
0
|
|
5081
5056
|
);
|
|
5057
|
+
if (totalExplicitWidth > availableTableWidth) {
|
|
5058
|
+
console.warn(
|
|
5059
|
+
`[json-to-office] Column widths total (${totalExplicitWidth} twips) exceeds available table width (${availableTableWidth} twips). Table may overflow.`
|
|
5060
|
+
);
|
|
5061
|
+
}
|
|
5082
5062
|
const columnsWithoutWidth = columns.filter(
|
|
5083
5063
|
(col) => col.width === void 0
|
|
5084
5064
|
).length;
|
|
@@ -6182,42 +6162,15 @@ async function renderHighchartsComponent(component, theme, _themeName) {
|
|
|
6182
6162
|
import { Type as Type2 } from "@sinclair/typebox";
|
|
6183
6163
|
|
|
6184
6164
|
// src/plugin/createComponent.ts
|
|
6185
|
-
import {
|
|
6165
|
+
import {
|
|
6166
|
+
createVersion as sharedCreateVersion,
|
|
6167
|
+
createComponent as sharedCreateComponent
|
|
6168
|
+
} from "@json-to-office/shared/plugin";
|
|
6186
6169
|
function createVersion(version) {
|
|
6187
|
-
return version;
|
|
6170
|
+
return sharedCreateVersion(version);
|
|
6188
6171
|
}
|
|
6189
6172
|
function createComponent(component) {
|
|
6190
|
-
|
|
6191
|
-
throw new Error("Component name is required");
|
|
6192
|
-
}
|
|
6193
|
-
if (!component.versions || typeof component.versions !== "object") {
|
|
6194
|
-
throw new Error(`Component "${component.name}" requires a versions map`);
|
|
6195
|
-
}
|
|
6196
|
-
const versionKeys = Object.keys(component.versions);
|
|
6197
|
-
if (versionKeys.length === 0) {
|
|
6198
|
-
throw new Error(
|
|
6199
|
-
`Component "${component.name}" must have at least one version`
|
|
6200
|
-
);
|
|
6201
|
-
}
|
|
6202
|
-
for (const key of versionKeys) {
|
|
6203
|
-
if (!isValidSemver(key)) {
|
|
6204
|
-
throw new Error(
|
|
6205
|
-
`Component "${component.name}": invalid semver key "${key}". Expected format: major.minor.patch`
|
|
6206
|
-
);
|
|
6207
|
-
}
|
|
6208
|
-
const entry = component.versions[key];
|
|
6209
|
-
if (!entry.propsSchema) {
|
|
6210
|
-
throw new Error(
|
|
6211
|
-
`Component "${component.name}" version "${key}" requires a propsSchema`
|
|
6212
|
-
);
|
|
6213
|
-
}
|
|
6214
|
-
if (!entry.render || typeof entry.render !== "function") {
|
|
6215
|
-
throw new Error(
|
|
6216
|
-
`Component "${component.name}" version "${key}" requires a render function`
|
|
6217
|
-
);
|
|
6218
|
-
}
|
|
6219
|
-
}
|
|
6220
|
-
return component;
|
|
6173
|
+
return sharedCreateComponent(component);
|
|
6221
6174
|
}
|
|
6222
6175
|
|
|
6223
6176
|
// src/components/text-space-after.ts
|
|
@@ -6691,45 +6644,29 @@ function normalizeDocument(document) {
|
|
|
6691
6644
|
return [normalized];
|
|
6692
6645
|
}
|
|
6693
6646
|
|
|
6694
|
-
// src/styles/theme-resolver.ts
|
|
6695
|
-
init_themes();
|
|
6696
|
-
function resolveTheme2(theme) {
|
|
6697
|
-
if (typeof theme === "string") {
|
|
6698
|
-
const resolvedTheme = getTheme(theme);
|
|
6699
|
-
if (resolvedTheme) {
|
|
6700
|
-
return resolvedTheme;
|
|
6701
|
-
}
|
|
6702
|
-
return getTheme("minimal");
|
|
6703
|
-
}
|
|
6704
|
-
if (theme) {
|
|
6705
|
-
return theme;
|
|
6706
|
-
}
|
|
6707
|
-
return getTheme("minimal");
|
|
6708
|
-
}
|
|
6709
|
-
|
|
6710
|
-
// src/styles/theme-validator.ts
|
|
6711
|
-
import { validateTheme as validateThemeUnified } from "@json-to-office/shared-docx/validation/unified";
|
|
6712
|
-
function validateTheme(theme) {
|
|
6713
|
-
if (!theme) {
|
|
6714
|
-
return void 0;
|
|
6715
|
-
}
|
|
6716
|
-
if (typeof theme === "string") {
|
|
6717
|
-
return theme;
|
|
6718
|
-
}
|
|
6719
|
-
const result = validateThemeUnified(theme);
|
|
6720
|
-
if (!result.valid) {
|
|
6721
|
-
const errorSummary = result.errors?.map((e) => e.message).join(", ") || "Invalid theme";
|
|
6722
|
-
throw new Error(`Invalid theme: ${errorSummary}`);
|
|
6723
|
-
}
|
|
6724
|
-
return result.data;
|
|
6725
|
-
}
|
|
6726
|
-
|
|
6727
6647
|
// src/plugin/createDocumentGenerator.ts
|
|
6728
6648
|
function createBuilderImpl(state) {
|
|
6729
|
-
const validatedTheme = validateTheme(state.theme);
|
|
6730
|
-
const fullTheme = resolveTheme2(validatedTheme);
|
|
6731
6649
|
const componentMap = new Map(state.components.map((c) => [c.name, c]));
|
|
6732
|
-
|
|
6650
|
+
function resolveDocumentTheme(themeName) {
|
|
6651
|
+
if (state.customThemes) {
|
|
6652
|
+
if (state.customThemes[themeName]) {
|
|
6653
|
+
return state.customThemes[themeName];
|
|
6654
|
+
}
|
|
6655
|
+
const key = Object.keys(state.customThemes).find(
|
|
6656
|
+
(k) => k.toLowerCase() === themeName.toLowerCase()
|
|
6657
|
+
);
|
|
6658
|
+
if (key) {
|
|
6659
|
+
return state.customThemes[key];
|
|
6660
|
+
}
|
|
6661
|
+
}
|
|
6662
|
+
return getThemeWithFallback(themeName);
|
|
6663
|
+
}
|
|
6664
|
+
async function processDocumentComponents(components, warningsCollector, resolvedTheme, depth = 0) {
|
|
6665
|
+
if (depth > 20) {
|
|
6666
|
+
throw new Error(
|
|
6667
|
+
"Maximum component nesting depth exceeded (20). Check for circular component references."
|
|
6668
|
+
);
|
|
6669
|
+
}
|
|
6733
6670
|
const processedComponents = [];
|
|
6734
6671
|
for (const componentData of components) {
|
|
6735
6672
|
const componentName = componentData?.name;
|
|
@@ -6759,7 +6696,9 @@ function createBuilderImpl(state) {
|
|
|
6759
6696
|
if (componentWithName.children && Array.isArray(componentWithName.children)) {
|
|
6760
6697
|
nestedChildren = await processDocumentComponents(
|
|
6761
6698
|
componentWithName.children,
|
|
6762
|
-
warningsCollector
|
|
6699
|
+
warningsCollector,
|
|
6700
|
+
resolvedTheme,
|
|
6701
|
+
depth + 1
|
|
6763
6702
|
);
|
|
6764
6703
|
}
|
|
6765
6704
|
const versionLabel = componentWithName.version ? `${customComponent.name}@${componentWithName.version}` : customComponent.name;
|
|
@@ -6773,14 +6712,16 @@ function createBuilderImpl(state) {
|
|
|
6773
6712
|
};
|
|
6774
6713
|
const result = await versionEntry.render({
|
|
6775
6714
|
props: cleanedProps,
|
|
6776
|
-
theme:
|
|
6715
|
+
theme: resolvedTheme,
|
|
6777
6716
|
addWarning,
|
|
6778
6717
|
children: nestedChildren
|
|
6779
6718
|
});
|
|
6780
6719
|
const resultComponents = Array.isArray(result) ? result : [result];
|
|
6781
6720
|
const processedResult = await processDocumentComponents(
|
|
6782
6721
|
resultComponents,
|
|
6783
|
-
warningsCollector
|
|
6722
|
+
warningsCollector,
|
|
6723
|
+
resolvedTheme,
|
|
6724
|
+
depth + 1
|
|
6784
6725
|
);
|
|
6785
6726
|
processedComponents.push(...processedResult);
|
|
6786
6727
|
if (state.debug) {
|
|
@@ -6790,7 +6731,7 @@ function createBuilderImpl(state) {
|
|
|
6790
6731
|
);
|
|
6791
6732
|
}
|
|
6792
6733
|
} catch (error) {
|
|
6793
|
-
if (error instanceof
|
|
6734
|
+
if (error instanceof ComponentValidationError2) {
|
|
6794
6735
|
throw error;
|
|
6795
6736
|
}
|
|
6796
6737
|
throw new Error(
|
|
@@ -6801,7 +6742,9 @@ function createBuilderImpl(state) {
|
|
|
6801
6742
|
if ("children" in componentData && Array.isArray(componentData.children)) {
|
|
6802
6743
|
const processedNested = await processDocumentComponents(
|
|
6803
6744
|
componentData.children,
|
|
6804
|
-
warningsCollector
|
|
6745
|
+
warningsCollector,
|
|
6746
|
+
resolvedTheme,
|
|
6747
|
+
depth + 1
|
|
6805
6748
|
);
|
|
6806
6749
|
processedComponents.push({
|
|
6807
6750
|
...componentData,
|
|
@@ -6815,18 +6758,19 @@ function createBuilderImpl(state) {
|
|
|
6815
6758
|
return processedComponents;
|
|
6816
6759
|
}
|
|
6817
6760
|
function addComponent(component) {
|
|
6818
|
-
if (state.componentNames.has(component.name)) {
|
|
6819
|
-
throw new DuplicateComponentError(component.name);
|
|
6820
|
-
}
|
|
6821
6761
|
if (!component.name) {
|
|
6822
6762
|
throw new Error("Component name is required");
|
|
6823
6763
|
}
|
|
6764
|
+
if (state.componentNames.has(component.name)) {
|
|
6765
|
+
throw new DuplicateComponentError(component.name);
|
|
6766
|
+
}
|
|
6824
6767
|
const newComponentNames = new Set(state.componentNames);
|
|
6825
6768
|
newComponentNames.add(component.name);
|
|
6826
6769
|
const newState = {
|
|
6827
6770
|
components: [...state.components, component],
|
|
6828
6771
|
componentNames: newComponentNames,
|
|
6829
6772
|
theme: state.theme,
|
|
6773
|
+
customThemes: state.customThemes,
|
|
6830
6774
|
debug: state.debug,
|
|
6831
6775
|
enableCache: state.enableCache
|
|
6832
6776
|
};
|
|
@@ -6841,10 +6785,13 @@ function createBuilderImpl(state) {
|
|
|
6841
6785
|
internalDocument,
|
|
6842
6786
|
state.components
|
|
6843
6787
|
);
|
|
6788
|
+
const themeName = internalDocument.props.theme || "minimal";
|
|
6789
|
+
const docTheme = resolveDocumentTheme(themeName);
|
|
6844
6790
|
const warnings = [];
|
|
6845
6791
|
const processedComponents = await processDocumentComponents(
|
|
6846
6792
|
internalDocument.children || [],
|
|
6847
|
-
warnings
|
|
6793
|
+
warnings,
|
|
6794
|
+
docTheme
|
|
6848
6795
|
);
|
|
6849
6796
|
const processedDocument = {
|
|
6850
6797
|
...internalDocument,
|
|
@@ -6853,10 +6800,10 @@ function createBuilderImpl(state) {
|
|
|
6853
6800
|
const [finalReportComponent] = normalizeDocument(processedDocument);
|
|
6854
6801
|
const structure = await processDocument(
|
|
6855
6802
|
finalReportComponent,
|
|
6856
|
-
|
|
6857
|
-
|
|
6803
|
+
docTheme,
|
|
6804
|
+
themeName
|
|
6858
6805
|
);
|
|
6859
|
-
const layout = applyLayout(structure.sections,
|
|
6806
|
+
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
6860
6807
|
const generatedDocument = await renderDocument(structure, layout);
|
|
6861
6808
|
return {
|
|
6862
6809
|
document: generatedDocument,
|
|
@@ -6892,7 +6839,7 @@ function createBuilderImpl(state) {
|
|
|
6892
6839
|
);
|
|
6893
6840
|
return { valid: true };
|
|
6894
6841
|
} catch (error) {
|
|
6895
|
-
if (error instanceof
|
|
6842
|
+
if (error instanceof ComponentValidationError2) {
|
|
6896
6843
|
return {
|
|
6897
6844
|
valid: false,
|
|
6898
6845
|
errors: error.errors.map((e) => ({
|
|
@@ -6932,10 +6879,13 @@ function createBuilderImpl(state) {
|
|
|
6932
6879
|
internalDocument,
|
|
6933
6880
|
state.components
|
|
6934
6881
|
);
|
|
6882
|
+
const themeName = internalDocument.props.theme || "minimal";
|
|
6883
|
+
const docTheme = resolveDocumentTheme(themeName);
|
|
6935
6884
|
const warnings = [];
|
|
6936
6885
|
const processedComponents = await processDocumentComponents(
|
|
6937
6886
|
internalDocument.children || [],
|
|
6938
|
-
warnings
|
|
6887
|
+
warnings,
|
|
6888
|
+
docTheme
|
|
6939
6889
|
);
|
|
6940
6890
|
const processedDocument = {
|
|
6941
6891
|
...internalDocument,
|
|
@@ -6967,6 +6917,7 @@ function createDocumentGenerator(options) {
|
|
|
6967
6917
|
components: [],
|
|
6968
6918
|
componentNames: /* @__PURE__ */ new Set(),
|
|
6969
6919
|
theme: options.theme,
|
|
6920
|
+
customThemes: options.customThemes,
|
|
6970
6921
|
debug: options.debug ?? false,
|
|
6971
6922
|
enableCache: options.enableCache ?? false
|
|
6972
6923
|
};
|