@json-to-office/core-docx 0.17.3 → 0.19.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/image.d.ts.map +1 -1
- package/dist/components/paragraph.d.ts.map +1 -1
- package/dist/core/content.d.ts +3 -0
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/render.d.ts.map +1 -1
- package/dist/core/structure.d.ts +2 -0
- package/dist/core/structure.d.ts.map +1 -1
- package/dist/index.js +202 -60
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/eldermoor-census.component.d.ts +32 -0
- package/dist/plugin/example/eldermoor-census.component.d.ts.map +1 -0
- package/dist/plugin/example/index.js +202 -60
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/styles/themeToDocxAdapter.d.ts +1 -1
- package/dist/styles/themeToDocxAdapter.d.ts.map +1 -1
- package/dist/templates/themes/index.d.ts +32 -0
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/imageUtils.d.ts +13 -0
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/placeholderProcessor.d.ts +1 -1
- package/dist/utils/placeholderProcessor.d.ts.map +1 -1
- package/dist/utils/textParser.d.ts +25 -0
- package/dist/utils/textParser.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ComponentDefinition } from '@json-to-office/shared-docx';
|
|
2
|
+
/**
|
|
3
|
+
* @example
|
|
4
|
+
* ```json
|
|
5
|
+
* {
|
|
6
|
+
* "name": "eldermoor-census",
|
|
7
|
+
* "props": { "title": "Regno di Valebrook", "manaPct": "51,2%", "castles": "3.120" }
|
|
8
|
+
* }
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare const eldermoorCensusComponent: import("../createComponent").CustomComponent<ComponentDefinition, {
|
|
12
|
+
'1.0.0': import("../createComponent").ComponentVersion<ComponentDefinition, import("@sinclair/typebox").TObject<{
|
|
13
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
14
|
+
manaPct: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
15
|
+
faithfulSubjects: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
16
|
+
swornGuilds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
17
|
+
mappedTerritoriesPct: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
18
|
+
castles: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
19
|
+
outposts: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
20
|
+
watchtowers: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
21
|
+
sovereignTreasury: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
22
|
+
warChest: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
23
|
+
marketMint: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
24
|
+
royalServants: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
25
|
+
servantsLeft: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
26
|
+
servantsRight: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
27
|
+
width: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TString]>>;
|
|
28
|
+
alignment: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"left">, import("@sinclair/typebox").TLiteral<"center">, import("@sinclair/typebox").TLiteral<"right">]>>;
|
|
29
|
+
caption: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
30
|
+
}>>;
|
|
31
|
+
}, "eldermoor-census">;
|
|
32
|
+
//# sourceMappingURL=eldermoor-census.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eldermoor-census.component.d.ts","sourceRoot":"","sources":["../../../src/plugin/example/eldermoor-census.component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAgNvE;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;sBAwBnC,CAAC"}
|
|
@@ -2195,12 +2195,17 @@ function resolveComponentTree(components, theme) {
|
|
|
2195
2195
|
async function processDocument(document, theme, themeName) {
|
|
2196
2196
|
const metadata = createDocumentMetadata(document.props);
|
|
2197
2197
|
const docDefaults = document.props.componentDefaults;
|
|
2198
|
-
const
|
|
2198
|
+
const mergedComponentDefaults = docDefaults ? mergeWithDefaults2(docDefaults, theme.componentDefaults || {}) : void 0;
|
|
2199
|
+
const docNoProofWords = document.props.noProofWords;
|
|
2200
|
+
const mergedNoProofWords = docNoProofWords || theme.noProofWords ? Array.from(
|
|
2201
|
+
/* @__PURE__ */ new Set([...theme.noProofWords || [], ...docNoProofWords || []])
|
|
2202
|
+
) : void 0;
|
|
2203
|
+
const effectiveTheme = mergedComponentDefaults || mergedNoProofWords ? {
|
|
2199
2204
|
...theme,
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2205
|
+
...mergedComponentDefaults && {
|
|
2206
|
+
componentDefaults: mergedComponentDefaults
|
|
2207
|
+
},
|
|
2208
|
+
...mergedNoProofWords && { noProofWords: mergedNoProofWords }
|
|
2204
2209
|
} : theme;
|
|
2205
2210
|
const context = createRenderContext(
|
|
2206
2211
|
{
|
|
@@ -2222,7 +2227,8 @@ async function processDocument(document, theme, themeName) {
|
|
|
2222
2227
|
sections,
|
|
2223
2228
|
theme: effectiveTheme,
|
|
2224
2229
|
themeName,
|
|
2225
|
-
trackRevisions: document.props.trackRevisions
|
|
2230
|
+
trackRevisions: document.props.trackRevisions,
|
|
2231
|
+
language: document.props.language
|
|
2226
2232
|
};
|
|
2227
2233
|
}
|
|
2228
2234
|
function createDocumentMetadata(props) {
|
|
@@ -2849,6 +2855,16 @@ async function downloadImageFromUrl(url) {
|
|
|
2849
2855
|
throw new Error(`Failed to download image from ${url}: Unknown error`);
|
|
2850
2856
|
}
|
|
2851
2857
|
}
|
|
2858
|
+
function resolveImageSource(props) {
|
|
2859
|
+
const hasValue = (v) => typeof v === "string" && v.trim().length > 0;
|
|
2860
|
+
if (hasValue(props.svg)) {
|
|
2861
|
+
const encoded = Buffer.from(props.svg, "utf-8").toString("base64");
|
|
2862
|
+
return `data:image/svg+xml;base64,${encoded}`;
|
|
2863
|
+
}
|
|
2864
|
+
if (hasValue(props.base64)) return props.base64;
|
|
2865
|
+
if (hasValue(props.path)) return props.path;
|
|
2866
|
+
return void 0;
|
|
2867
|
+
}
|
|
2852
2868
|
async function getImageBuffer(imagePath) {
|
|
2853
2869
|
if (isBase64Image(imagePath)) {
|
|
2854
2870
|
return { buffer: decodeBase64Image(imagePath) };
|
|
@@ -3076,7 +3092,7 @@ function convertBorders(borders, theme) {
|
|
|
3076
3092
|
...right && { right }
|
|
3077
3093
|
} : void 0;
|
|
3078
3094
|
}
|
|
3079
|
-
function createWordStyles(themeNameOrObject = "minimal") {
|
|
3095
|
+
function createWordStyles(themeNameOrObject = "minimal", language) {
|
|
3080
3096
|
const theme = typeof themeNameOrObject === "string" ? getTheme(themeNameOrObject) || getTheme("minimal") : themeNameOrObject;
|
|
3081
3097
|
const paragraphStyles = [
|
|
3082
3098
|
// Normal body text style
|
|
@@ -3534,8 +3550,20 @@ function createWordStyles(themeNameOrObject = "minimal") {
|
|
|
3534
3550
|
});
|
|
3535
3551
|
}
|
|
3536
3552
|
return {
|
|
3537
|
-
paragraphStyles
|
|
3553
|
+
paragraphStyles,
|
|
3538
3554
|
// Cast needed due to docx typing
|
|
3555
|
+
// Document-default proofing language (w:docDefaults/w:rPrDefault). Runs that
|
|
3556
|
+
// don't set their own w:lang inherit this, so Word spell-checks the whole
|
|
3557
|
+
// document in the requested language unless a component overrides it.
|
|
3558
|
+
...language && {
|
|
3559
|
+
default: {
|
|
3560
|
+
document: {
|
|
3561
|
+
run: {
|
|
3562
|
+
language: { value: language }
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3539
3567
|
};
|
|
3540
3568
|
}
|
|
3541
3569
|
function getStyleIdForLevel(level) {
|
|
@@ -3657,6 +3685,37 @@ import {
|
|
|
3657
3685
|
|
|
3658
3686
|
// src/utils/textParser.ts
|
|
3659
3687
|
import { TextRun, ExternalHyperlink, InternalHyperlink } from "docx";
|
|
3688
|
+
function escapeRegExp(s) {
|
|
3689
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3690
|
+
}
|
|
3691
|
+
function buildNoProofWordsRegex(noProofWords) {
|
|
3692
|
+
const words = (noProofWords || []).filter((w) => w && w.trim().length > 0);
|
|
3693
|
+
if (words.length === 0) return null;
|
|
3694
|
+
const escaped = words.slice().sort((a, b) => b.length - a.length).map(escapeRegExp);
|
|
3695
|
+
return new RegExp(
|
|
3696
|
+
`(?<![\\p{L}\\p{N}])(?:${escaped.join("|")})(?![\\p{L}\\p{N}])`,
|
|
3697
|
+
"giu"
|
|
3698
|
+
);
|
|
3699
|
+
}
|
|
3700
|
+
function splitByNoProofWords(text, makeRun, noProofWords) {
|
|
3701
|
+
const regex = buildNoProofWordsRegex(noProofWords);
|
|
3702
|
+
if (!regex || !text) return [makeRun(text, false)];
|
|
3703
|
+
const runs = [];
|
|
3704
|
+
let lastIndex = 0;
|
|
3705
|
+
let match;
|
|
3706
|
+
while ((match = regex.exec(text)) !== null) {
|
|
3707
|
+
if (match.index > lastIndex) {
|
|
3708
|
+
runs.push(makeRun(text.slice(lastIndex, match.index), false));
|
|
3709
|
+
}
|
|
3710
|
+
runs.push(makeRun(match[0], true));
|
|
3711
|
+
lastIndex = match.index + match[0].length;
|
|
3712
|
+
if (regex.lastIndex === match.index) regex.lastIndex++;
|
|
3713
|
+
}
|
|
3714
|
+
if (lastIndex < text.length) {
|
|
3715
|
+
runs.push(makeRun(text.slice(lastIndex), false));
|
|
3716
|
+
}
|
|
3717
|
+
return runs.length > 0 ? runs : [makeRun(text, false)];
|
|
3718
|
+
}
|
|
3660
3719
|
function parseTextWithDecorators(text, baseStyle = {}, options = {}) {
|
|
3661
3720
|
if (!text) {
|
|
3662
3721
|
return [new TextRun({ text: "", ...baseStyle })];
|
|
@@ -3667,7 +3726,8 @@ function parseTextWithDecorators(text, baseStyle = {}, options = {}) {
|
|
|
3667
3726
|
return processTextWithPlaceholders(
|
|
3668
3727
|
normalizedText,
|
|
3669
3728
|
baseStyle,
|
|
3670
|
-
options.placeholderContext || {}
|
|
3729
|
+
options.placeholderContext || {},
|
|
3730
|
+
options.noProofWords
|
|
3671
3731
|
);
|
|
3672
3732
|
}
|
|
3673
3733
|
if (options.enableHyperlinks) {
|
|
@@ -3738,20 +3798,38 @@ function createTextRunsWithNewlines(text, baseStyle, options, overrideStyle) {
|
|
|
3738
3798
|
bold: overrideStyle?.bold ?? baseStyle.bold,
|
|
3739
3799
|
italics: overrideStyle?.italics ?? baseStyle.italics
|
|
3740
3800
|
};
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3801
|
+
const commonProps = {
|
|
3802
|
+
...baseStyle.font && { font: baseStyle.font },
|
|
3803
|
+
...baseStyle.size && { size: baseStyle.size },
|
|
3804
|
+
...baseStyle.color && {
|
|
3805
|
+
color: runStyle.bold && options.boldColor ? options.boldColor : baseStyle.color
|
|
3806
|
+
},
|
|
3807
|
+
...runStyle.bold !== void 0 && { bold: runStyle.bold },
|
|
3808
|
+
...runStyle.italics !== void 0 && { italics: runStyle.italics },
|
|
3809
|
+
...baseStyle.underline && { underline: baseStyle.underline },
|
|
3810
|
+
...baseStyle.language && { language: baseStyle.language }
|
|
3811
|
+
};
|
|
3812
|
+
const wholeRunNoProof = baseStyle.noProof === true;
|
|
3813
|
+
const wordsForLine = wholeRunNoProof ? void 0 : options.noProofWords;
|
|
3814
|
+
let firstSegment = true;
|
|
3815
|
+
const lineRuns = splitByNoProofWords(
|
|
3816
|
+
line,
|
|
3817
|
+
(segment, matched) => {
|
|
3818
|
+
const segNoProof = matched || wholeRunNoProof;
|
|
3819
|
+
const run = new TextRun({
|
|
3820
|
+
text: segment,
|
|
3821
|
+
...commonProps,
|
|
3822
|
+
...(matched || baseStyle.noProof !== void 0) && {
|
|
3823
|
+
noProof: segNoProof
|
|
3824
|
+
},
|
|
3825
|
+
...needsLineBreak && firstSegment && { break: 1 }
|
|
3826
|
+
});
|
|
3827
|
+
firstSegment = false;
|
|
3828
|
+
return run;
|
|
3829
|
+
},
|
|
3830
|
+
wordsForLine
|
|
3754
3831
|
);
|
|
3832
|
+
runs.push(...lineRuns);
|
|
3755
3833
|
}
|
|
3756
3834
|
}
|
|
3757
3835
|
return runs;
|
|
@@ -3856,7 +3934,7 @@ var PlaceholderRegistry = class {
|
|
|
3856
3934
|
this.handlers.clear();
|
|
3857
3935
|
}
|
|
3858
3936
|
};
|
|
3859
|
-
function processTextWithPlaceholders(text, baseStyle = {}, context = {}) {
|
|
3937
|
+
function processTextWithPlaceholders(text, baseStyle = {}, context = {}, noProofWords) {
|
|
3860
3938
|
const normalizedText = normalizeUnicodeText(text);
|
|
3861
3939
|
const combinedRegex = /(\*\*\*|___)([\s\S]*?)\1|(\*\*|__)([\s\S]*?)\3|(\*|_)([\s\S]*?)\5|\{([^}]+)\}/g;
|
|
3862
3940
|
const result = [];
|
|
@@ -3866,7 +3944,9 @@ function processTextWithPlaceholders(text, baseStyle = {}, context = {}) {
|
|
|
3866
3944
|
if (match.index > lastIndex) {
|
|
3867
3945
|
const beforeText = normalizedText.substring(lastIndex, match.index);
|
|
3868
3946
|
if (beforeText) {
|
|
3869
|
-
result.push(
|
|
3947
|
+
result.push(
|
|
3948
|
+
...createTextRunsWithNewlines2(beforeText, baseStyle, noProofWords)
|
|
3949
|
+
);
|
|
3870
3950
|
}
|
|
3871
3951
|
}
|
|
3872
3952
|
if (match[7]) {
|
|
@@ -3880,11 +3960,17 @@ function processTextWithPlaceholders(text, baseStyle = {}, context = {}) {
|
|
|
3880
3960
|
result.push(placeholderResult);
|
|
3881
3961
|
} else if (typeof placeholderResult === "string") {
|
|
3882
3962
|
result.push(
|
|
3883
|
-
...createTextRunsWithNewlines2(
|
|
3963
|
+
...createTextRunsWithNewlines2(
|
|
3964
|
+
placeholderResult,
|
|
3965
|
+
baseStyle,
|
|
3966
|
+
noProofWords
|
|
3967
|
+
)
|
|
3884
3968
|
);
|
|
3885
3969
|
}
|
|
3886
3970
|
} else {
|
|
3887
|
-
result.push(
|
|
3971
|
+
result.push(
|
|
3972
|
+
...createTextRunsWithNewlines2(match[0], baseStyle, noProofWords)
|
|
3973
|
+
);
|
|
3888
3974
|
}
|
|
3889
3975
|
} else {
|
|
3890
3976
|
let decoratedText;
|
|
@@ -3919,33 +4005,54 @@ function processTextWithPlaceholders(text, baseStyle = {}, context = {}) {
|
|
|
3919
4005
|
if (lastIndex < normalizedText.length) {
|
|
3920
4006
|
const remainingText = normalizedText.substring(lastIndex);
|
|
3921
4007
|
if (remainingText) {
|
|
3922
|
-
result.push(
|
|
4008
|
+
result.push(
|
|
4009
|
+
...createTextRunsWithNewlines2(remainingText, baseStyle, noProofWords)
|
|
4010
|
+
);
|
|
3923
4011
|
}
|
|
3924
4012
|
}
|
|
3925
4013
|
if (result.length === 0 && normalizedText) {
|
|
3926
|
-
result.push(
|
|
4014
|
+
result.push(
|
|
4015
|
+
...createTextRunsWithNewlines2(normalizedText, baseStyle, noProofWords)
|
|
4016
|
+
);
|
|
3927
4017
|
}
|
|
3928
4018
|
return result;
|
|
3929
4019
|
}
|
|
3930
|
-
function createTextRunsWithNewlines2(text, baseStyle) {
|
|
4020
|
+
function createTextRunsWithNewlines2(text, baseStyle, noProofWords) {
|
|
3931
4021
|
const runs = [];
|
|
3932
4022
|
const lines = text.split("\n");
|
|
3933
4023
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
3934
4024
|
const line = lines[lineIndex];
|
|
3935
4025
|
const needsLineBreak = lineIndex > 0;
|
|
3936
4026
|
if (line || needsLineBreak) {
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
4027
|
+
const commonProps = {
|
|
4028
|
+
font: baseStyle.font,
|
|
4029
|
+
size: baseStyle.size,
|
|
4030
|
+
color: baseStyle.color,
|
|
4031
|
+
bold: baseStyle.bold,
|
|
4032
|
+
italics: baseStyle.italics,
|
|
4033
|
+
underline: baseStyle.underline,
|
|
4034
|
+
...baseStyle.language && { language: baseStyle.language }
|
|
4035
|
+
};
|
|
4036
|
+
const wholeRunNoProof = baseStyle.noProof === true;
|
|
4037
|
+
const wordsForLine = wholeRunNoProof ? void 0 : noProofWords;
|
|
4038
|
+
let firstSegment = true;
|
|
4039
|
+
const lineRuns = splitByNoProofWords(
|
|
4040
|
+
line,
|
|
4041
|
+
(segment, matched) => {
|
|
4042
|
+
const run = new TextRun2({
|
|
4043
|
+
text: segment,
|
|
4044
|
+
...commonProps,
|
|
4045
|
+
...(matched || baseStyle.noProof !== void 0) && {
|
|
4046
|
+
noProof: matched || wholeRunNoProof
|
|
4047
|
+
},
|
|
4048
|
+
break: needsLineBreak && firstSegment ? 1 : void 0
|
|
4049
|
+
});
|
|
4050
|
+
firstSegment = false;
|
|
4051
|
+
return run;
|
|
4052
|
+
},
|
|
4053
|
+
wordsForLine
|
|
3948
4054
|
);
|
|
4055
|
+
runs.push(...lineRuns);
|
|
3949
4056
|
}
|
|
3950
4057
|
}
|
|
3951
4058
|
return runs;
|
|
@@ -4290,6 +4397,11 @@ function applyFontWeightAlias(opts) {
|
|
|
4290
4397
|
);
|
|
4291
4398
|
return { font: synth.family, bold: synth.bold, italics: synth.italic };
|
|
4292
4399
|
}
|
|
4400
|
+
function resolveNoProofWords(theme, optionWords) {
|
|
4401
|
+
const themeWords = theme.noProofWords;
|
|
4402
|
+
const merged = [...themeWords || [], ...optionWords || []];
|
|
4403
|
+
return merged.length > 0 ? Array.from(new Set(merged)) : void 0;
|
|
4404
|
+
}
|
|
4293
4405
|
function createText(content, theme, themeName, options = {}) {
|
|
4294
4406
|
const normalizedContent = normalizeUnicodeText(content);
|
|
4295
4407
|
const style = options.style || "Normal";
|
|
@@ -4332,7 +4444,11 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4332
4444
|
...weighted.italics !== void 0 && { italics: weighted.italics },
|
|
4333
4445
|
...options.underline !== void 0 && {
|
|
4334
4446
|
underline: options.underline ? { type: "single" } : void 0
|
|
4335
|
-
}
|
|
4447
|
+
},
|
|
4448
|
+
// Proofing: per-run language and/or no-proof. Omitting language lets the
|
|
4449
|
+
// run inherit the document default set on docDefaults.
|
|
4450
|
+
...options.language && { language: { value: options.language } },
|
|
4451
|
+
...options.noProof !== void 0 && { noProof: options.noProof }
|
|
4336
4452
|
};
|
|
4337
4453
|
if (options.revision) {
|
|
4338
4454
|
const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);
|
|
@@ -4354,7 +4470,8 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4354
4470
|
} else {
|
|
4355
4471
|
const textRuns = parseTextWithDecorators(normalizedContent, baseTextStyle, {
|
|
4356
4472
|
boldColor: options.boldColor,
|
|
4357
|
-
enableHyperlinks: true
|
|
4473
|
+
enableHyperlinks: true,
|
|
4474
|
+
noProofWords: resolveNoProofWords(theme, options.noProofWords)
|
|
4358
4475
|
});
|
|
4359
4476
|
if (options.bookmarkId) {
|
|
4360
4477
|
globalBookmarkRegistry.register(
|
|
@@ -4489,8 +4606,21 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4489
4606
|
},
|
|
4490
4607
|
...options.underline !== void 0 && {
|
|
4491
4608
|
underline: options.underline ? { type: "single" } : void 0
|
|
4492
|
-
}
|
|
4609
|
+
},
|
|
4610
|
+
// Proofing: per-run language and/or no-proof (see createText).
|
|
4611
|
+
...options.language && { language: { value: options.language } },
|
|
4612
|
+
...options.noProof !== void 0 && { noProof: options.noProof }
|
|
4493
4613
|
};
|
|
4614
|
+
const headingNoProofWords = resolveNoProofWords(theme, options.noProofWords);
|
|
4615
|
+
const makeHeadingRuns = (value) => splitByNoProofWords(
|
|
4616
|
+
value,
|
|
4617
|
+
(segment, matched) => new TextRun4({
|
|
4618
|
+
text: segment,
|
|
4619
|
+
...baseTextStyle,
|
|
4620
|
+
...matched && { noProof: true }
|
|
4621
|
+
}),
|
|
4622
|
+
headingNoProofWords
|
|
4623
|
+
);
|
|
4494
4624
|
if (options.revision) {
|
|
4495
4625
|
const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);
|
|
4496
4626
|
if (options.bookmarkId) {
|
|
@@ -4518,13 +4648,12 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4518
4648
|
if (hasDecorators) {
|
|
4519
4649
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4520
4650
|
boldColor: options.boldColor,
|
|
4521
|
-
enableHyperlinks: true
|
|
4651
|
+
enableHyperlinks: true,
|
|
4652
|
+
noProofWords: headingNoProofWords
|
|
4522
4653
|
});
|
|
4523
4654
|
headingTextChildren.push(...textRuns);
|
|
4524
4655
|
} else {
|
|
4525
|
-
headingTextChildren.push(
|
|
4526
|
-
new TextRun4({ text: normalizedText, ...baseTextStyle })
|
|
4527
|
-
);
|
|
4656
|
+
headingTextChildren.push(...makeHeadingRuns(normalizedText));
|
|
4528
4657
|
}
|
|
4529
4658
|
children.push(
|
|
4530
4659
|
new Bookmark({
|
|
@@ -4536,11 +4665,12 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4536
4665
|
if (hasDecorators) {
|
|
4537
4666
|
const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {
|
|
4538
4667
|
boldColor: options.boldColor,
|
|
4539
|
-
enableHyperlinks: true
|
|
4668
|
+
enableHyperlinks: true,
|
|
4669
|
+
noProofWords: headingNoProofWords
|
|
4540
4670
|
});
|
|
4541
4671
|
children.push(...textRuns);
|
|
4542
4672
|
} else {
|
|
4543
|
-
children.push(
|
|
4673
|
+
children.push(...makeHeadingRuns(normalizedText));
|
|
4544
4674
|
}
|
|
4545
4675
|
}
|
|
4546
4676
|
return new Paragraph({
|
|
@@ -5066,10 +5196,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5066
5196
|
} else if (isImageComponent(cell)) {
|
|
5067
5197
|
const imageComp = cell;
|
|
5068
5198
|
try {
|
|
5069
|
-
const imageSource = imageComp.props
|
|
5199
|
+
const imageSource = resolveImageSource(imageComp.props);
|
|
5070
5200
|
if (!imageSource) {
|
|
5071
5201
|
throw new Error(
|
|
5072
|
-
'Image component requires
|
|
5202
|
+
'Image component requires one of "path", "base64", or "svg" property'
|
|
5073
5203
|
);
|
|
5074
5204
|
}
|
|
5075
5205
|
const imageResult = await getImageBuffer(imageSource);
|
|
@@ -5095,7 +5225,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5095
5225
|
});
|
|
5096
5226
|
cellChildren = [imageRun];
|
|
5097
5227
|
} catch (error) {
|
|
5098
|
-
const imageSource = imageComp.props.base64 || imageComp.props.path || "unknown";
|
|
5228
|
+
const imageSource = imageComp.props.svg?.trim() ? "inline-svg" : imageComp.props.base64 || imageComp.props.path || "unknown";
|
|
5099
5229
|
cellChildren = [
|
|
5100
5230
|
new TextRun4({
|
|
5101
5231
|
text: `[IMAGE: ${imageSource.substring(0, 50)}${imageSource.length > 50 ? "..." : ""}]`,
|
|
@@ -5503,6 +5633,10 @@ function renderHeadingComponent(component, theme, themeName) {
|
|
|
5503
5633
|
fontWeight: config.font?.fontWeight,
|
|
5504
5634
|
italic: config.font?.italic,
|
|
5505
5635
|
underline: config.font?.underline,
|
|
5636
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
5637
|
+
language: config.language,
|
|
5638
|
+
noProof: config.noProof,
|
|
5639
|
+
noProofWords: config.noProofWords,
|
|
5506
5640
|
// Pagination control
|
|
5507
5641
|
keepNext: config.keepNext,
|
|
5508
5642
|
keepLines: config.keepLines,
|
|
@@ -5621,6 +5755,10 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
5621
5755
|
fontWeight: resolvedConfig.font?.fontWeight,
|
|
5622
5756
|
italic: resolvedConfig.font?.italic,
|
|
5623
5757
|
underline: resolvedConfig.font?.underline,
|
|
5758
|
+
// Proofing: local language override + no-proof toggle + known-words list
|
|
5759
|
+
language: resolvedConfig.language,
|
|
5760
|
+
noProof: resolvedConfig.noProof,
|
|
5761
|
+
noProofWords: resolvedConfig.noProofWords,
|
|
5624
5762
|
// Pass outline level for TOC support
|
|
5625
5763
|
outlineLevel,
|
|
5626
5764
|
// Pass floating positioning properties
|
|
@@ -5772,10 +5910,10 @@ function renderListComponent(component, theme, themeName) {
|
|
|
5772
5910
|
async function renderImageComponent(component, theme, themeName) {
|
|
5773
5911
|
if (!isImageComponent(component)) return [];
|
|
5774
5912
|
const resolvedConfig = component.props;
|
|
5775
|
-
const imageSource = resolvedConfig
|
|
5913
|
+
const imageSource = resolveImageSource(resolvedConfig);
|
|
5776
5914
|
if (!imageSource) {
|
|
5777
5915
|
throw new Error(
|
|
5778
|
-
'Image component requires
|
|
5916
|
+
'Image component requires one of "path", "base64", or "svg" property'
|
|
5779
5917
|
);
|
|
5780
5918
|
}
|
|
5781
5919
|
return await createImage(imageSource, theme, themeName, {
|
|
@@ -6457,7 +6595,10 @@ async function generateChart(config, servicesConfig) {
|
|
|
6457
6595
|
infile: config.options,
|
|
6458
6596
|
type: "png",
|
|
6459
6597
|
b64: true,
|
|
6460
|
-
scale: config.scale
|
|
6598
|
+
scale: config.scale,
|
|
6599
|
+
// Forward resources verbatim only when present so the payload stays
|
|
6600
|
+
// byte-identical to before for callers that omit it.
|
|
6601
|
+
...config.resources ? { resources: config.resources } : {}
|
|
6461
6602
|
};
|
|
6462
6603
|
const response = await postJsonToService({
|
|
6463
6604
|
url: serverUrl,
|
|
@@ -6744,7 +6885,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6744
6885
|
}
|
|
6745
6886
|
const numberingConfigs = globalNumberingRegistry2.getAll();
|
|
6746
6887
|
return new Document({
|
|
6747
|
-
styles: createWordStyles(structure.theme),
|
|
6888
|
+
styles: createWordStyles(structure.theme, structure.language),
|
|
6748
6889
|
sections,
|
|
6749
6890
|
features: {
|
|
6750
6891
|
updateFields: true,
|
|
@@ -6795,13 +6936,13 @@ async function renderHeaderFooterComponents(components, theme, themeName, contex
|
|
|
6795
6936
|
);
|
|
6796
6937
|
} else if (isImageComponent(component)) {
|
|
6797
6938
|
const imageComp = component;
|
|
6798
|
-
let imageSource = imageComp.props
|
|
6939
|
+
let imageSource = resolveImageSource(imageComp.props);
|
|
6799
6940
|
if (!imageSource) {
|
|
6800
6941
|
elements.push(
|
|
6801
6942
|
new Paragraph7({
|
|
6802
6943
|
children: [
|
|
6803
6944
|
new TextRun6({
|
|
6804
|
-
text: "[IMAGE: Missing path or
|
|
6945
|
+
text: "[IMAGE: Missing path, base64, or svg property]",
|
|
6805
6946
|
font: getThemeFonts(theme).body.family,
|
|
6806
6947
|
size: 20,
|
|
6807
6948
|
bold: true,
|
|
@@ -6875,15 +7016,16 @@ async function renderHeaderFooterComponents(components, theme, themeName, contex
|
|
|
6875
7016
|
})
|
|
6876
7017
|
);
|
|
6877
7018
|
} catch (error) {
|
|
7019
|
+
const sourcePreview = imageSource.substring(0, 50);
|
|
6878
7020
|
console.error(
|
|
6879
|
-
`[Header/Footer Image Error] Failed to render image: ${
|
|
7021
|
+
`[Header/Footer Image Error] Failed to render image: ${sourcePreview}...`,
|
|
6880
7022
|
error instanceof Error ? error.message : error
|
|
6881
7023
|
);
|
|
6882
7024
|
elements.push(
|
|
6883
7025
|
new Paragraph7({
|
|
6884
7026
|
children: [
|
|
6885
7027
|
new TextRun6({
|
|
6886
|
-
text: `[IMAGE: ${
|
|
7028
|
+
text: `[IMAGE: ${sourcePreview}]`,
|
|
6887
7029
|
font: getThemeFonts(theme).body.family,
|
|
6888
7030
|
size: 20,
|
|
6889
7031
|
color: getThemeColors(theme).secondary,
|