@json-to-office/core-docx 7.2.0 → 7.3.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/index.js +1539 -471
- package/dist/index.js.map +1 -1
- package/dist/ir/chartValues.d.ts +16 -0
- package/dist/ir/chartValues.d.ts.map +1 -0
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/ir/features.d.ts.map +1 -1
- package/dist/ir/theme.d.ts +43 -0
- package/dist/ir/theme.d.ts.map +1 -0
- package/dist/ir/types.d.ts +39 -3
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/validation.d.ts +2 -1
- package/dist/ir/validation.d.ts.map +1 -1
- package/dist/plugin/example/index.js +1536 -468
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/renderers/chartText.d.ts +43 -0
- package/dist/renderers/chartText.d.ts.map +1 -0
- package/dist/renderers/docxjs/charts.d.ts +45 -0
- package/dist/renderers/docxjs/charts.d.ts.map +1 -0
- package/dist/renderers/docxjs/docxSubpath.d.ts +34 -0
- package/dist/renderers/docxjs/docxSubpath.d.ts.map +1 -0
- package/dist/renderers/docxjs/drawingGroup.d.ts +79 -0
- package/dist/renderers/docxjs/drawingGroup.d.ts.map +1 -0
- package/dist/renderers/docxjs/drawingGroupRepair.d.ts +36 -0
- package/dist/renderers/docxjs/drawingGroupRepair.d.ts.map +1 -0
- package/dist/renderers/docxjs/emit.d.ts +10 -2
- package/dist/renderers/docxjs/emit.d.ts.map +1 -1
- package/dist/renderers/docxjs/index.d.ts +2 -1
- package/dist/renderers/docxjs/index.d.ts.map +1 -1
- package/dist/renderers/docxjs/presetShapes.d.ts +233 -0
- package/dist/renderers/docxjs/presetShapes.d.ts.map +1 -0
- package/dist/renderers/office-open/chartLook.d.ts +45 -0
- package/dist/renderers/office-open/chartLook.d.ts.map +1 -0
- package/dist/renderers/office-open/chartParts.d.ts +29 -15
- package/dist/renderers/office-open/chartParts.d.ts.map +1 -1
- package/dist/renderers/office-open/emit.d.ts +25 -39
- package/dist/renderers/office-open/emit.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts +16 -4
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/renderers/office-open/themePart.d.ts +28 -0
- package/dist/renderers/office-open/themePart.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/chartWorkbook.d.ts +2 -1
- package/dist/utils/chartWorkbook.d.ts.map +1 -1
- package/dist/utils/fixFloatingImageIds.d.ts +17 -9
- package/dist/utils/fixFloatingImageIds.d.ts.map +1 -1
- package/dist/utils/packageDocument.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/renderers/office-open/cellTocs.d.ts +0 -26
- package/dist/renderers/office-open/cellTocs.d.ts.map +0 -1
|
@@ -2751,7 +2751,7 @@ var init_imageUtils = __esm({
|
|
|
2751
2751
|
});
|
|
2752
2752
|
|
|
2753
2753
|
// src/ir/types.ts
|
|
2754
|
-
var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION, DOCX_IR_BORDER_STYLES;
|
|
2754
|
+
var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION, NOT_XML_CHAR, DOCX_IR_BORDER_STYLES;
|
|
2755
2755
|
var init_types = __esm({
|
|
2756
2756
|
"src/ir/types.ts"() {
|
|
2757
2757
|
"use strict";
|
|
@@ -2760,6 +2760,7 @@ var init_types = __esm({
|
|
|
2760
2760
|
EMU_PER_INCH = 914400;
|
|
2761
2761
|
EMU_PER_TWIP = EMU_PER_INCH / TWIPS_PER_INCH;
|
|
2762
2762
|
DOCX_IR_SCHEMA_VERSION = 1;
|
|
2763
|
+
NOT_XML_CHAR = /[^\t\n\r\u0020-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/u;
|
|
2763
2764
|
DOCX_IR_BORDER_STYLES = [
|
|
2764
2765
|
"single",
|
|
2765
2766
|
"dashDotStroked",
|
|
@@ -2846,6 +2847,226 @@ var init_units = __esm({
|
|
|
2846
2847
|
}
|
|
2847
2848
|
});
|
|
2848
2849
|
|
|
2850
|
+
// src/ir/chartValues.ts
|
|
2851
|
+
function isNumericLabel(label) {
|
|
2852
|
+
return NUMERIC_LABEL.test(label.trim());
|
|
2853
|
+
}
|
|
2854
|
+
function scatterX(labels, index) {
|
|
2855
|
+
const label = labels[index];
|
|
2856
|
+
return label !== void 0 && isNumericLabel(label) ? Number(label) : index + 1;
|
|
2857
|
+
}
|
|
2858
|
+
var NUMERIC_LABEL;
|
|
2859
|
+
var init_chartValues = __esm({
|
|
2860
|
+
"src/ir/chartValues.ts"() {
|
|
2861
|
+
"use strict";
|
|
2862
|
+
NUMERIC_LABEL = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
|
|
2863
|
+
}
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
// src/renderers/chartText.ts
|
|
2867
|
+
function chartTextRoles(font) {
|
|
2868
|
+
const { bold, ...rest } = font;
|
|
2869
|
+
const text = rest;
|
|
2870
|
+
return {
|
|
2871
|
+
text,
|
|
2872
|
+
axisTitle: { ...text, bold },
|
|
2873
|
+
title: {
|
|
2874
|
+
...text,
|
|
2875
|
+
fontSize: Math.round(text.fontSize * CHART_TITLE_SCALE),
|
|
2876
|
+
bold: true
|
|
2877
|
+
}
|
|
2878
|
+
};
|
|
2879
|
+
}
|
|
2880
|
+
var CHART_TITLE_SCALE;
|
|
2881
|
+
var init_chartText = __esm({
|
|
2882
|
+
"src/renderers/chartText.ts"() {
|
|
2883
|
+
"use strict";
|
|
2884
|
+
CHART_TITLE_SCALE = 1.4;
|
|
2885
|
+
}
|
|
2886
|
+
});
|
|
2887
|
+
|
|
2888
|
+
// src/renderers/docxjs/docxSubpath.ts
|
|
2889
|
+
function docxSubpath(specifier, component, importer) {
|
|
2890
|
+
let module;
|
|
2891
|
+
let failure;
|
|
2892
|
+
let loading;
|
|
2893
|
+
return {
|
|
2894
|
+
specifier,
|
|
2895
|
+
load() {
|
|
2896
|
+
loading ??= importer().then(
|
|
2897
|
+
(loadedModule) => {
|
|
2898
|
+
module = loadedModule;
|
|
2899
|
+
},
|
|
2900
|
+
(reason) => {
|
|
2901
|
+
failure = { reason };
|
|
2902
|
+
}
|
|
2903
|
+
);
|
|
2904
|
+
return loading;
|
|
2905
|
+
},
|
|
2906
|
+
loaded: () => module !== void 0,
|
|
2907
|
+
get() {
|
|
2908
|
+
if (module !== void 0) return module;
|
|
2909
|
+
if (failure !== void 0) {
|
|
2910
|
+
const { reason } = failure;
|
|
2911
|
+
const detail = reason instanceof Error ? reason.message : String(reason);
|
|
2912
|
+
throw new Error(
|
|
2913
|
+
`The docx \`${component}\` component needs docx 9.8.0 or later: the \`${specifier}\` entry could not be loaded (${detail})`
|
|
2914
|
+
);
|
|
2915
|
+
}
|
|
2916
|
+
throw new Error(
|
|
2917
|
+
`${specifier} is not loaded: await its load() before buildDocument() (render() does)`
|
|
2918
|
+
);
|
|
2919
|
+
}
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
var init_docxSubpath = __esm({
|
|
2923
|
+
"src/renderers/docxjs/docxSubpath.ts"() {
|
|
2924
|
+
"use strict";
|
|
2925
|
+
}
|
|
2926
|
+
});
|
|
2927
|
+
|
|
2928
|
+
// src/renderers/docxjs/charts.ts
|
|
2929
|
+
import { assertNever } from "@json-to-office/shared/rendering";
|
|
2930
|
+
function loadDocxCharts() {
|
|
2931
|
+
return charts.load();
|
|
2932
|
+
}
|
|
2933
|
+
function chartFont(role) {
|
|
2934
|
+
return {
|
|
2935
|
+
name: role.fontFamily,
|
|
2936
|
+
size: role.fontSize,
|
|
2937
|
+
color: role.color,
|
|
2938
|
+
bold: role.bold ?? false
|
|
2939
|
+
};
|
|
2940
|
+
}
|
|
2941
|
+
function chartRunOptions(chart, floating) {
|
|
2942
|
+
const roles = chartTextRoles(chart.textFont);
|
|
2943
|
+
const text = chartFont(roles.text);
|
|
2944
|
+
const axisTitle = chartFont(roles.axisTitle);
|
|
2945
|
+
const palette = chart.colors;
|
|
2946
|
+
const colorAt = (index) => palette.length > 0 ? palette[index % palette.length] : void 0;
|
|
2947
|
+
const withColor = (index) => {
|
|
2948
|
+
const color = colorAt(index);
|
|
2949
|
+
return color ? { color } : {};
|
|
2950
|
+
};
|
|
2951
|
+
const seriesName = (index) => chart.series[index].name ?? `Series ${index + 1}`;
|
|
2952
|
+
const categories = chart.series[0]?.labels ?? [];
|
|
2953
|
+
const axis = (title) => ({
|
|
2954
|
+
...title ? { title: { text: title, font: axisTitle } } : {},
|
|
2955
|
+
font: text
|
|
2956
|
+
});
|
|
2957
|
+
const common = {
|
|
2958
|
+
...chart.title && chart.showTitle !== false ? { title: { text: chart.title, font: chartFont(roles.title) } } : {},
|
|
2959
|
+
legend: chart.showLegend === false ? false : {
|
|
2960
|
+
position: LEGEND_POSITION[chart.legendPosition ?? "b"],
|
|
2961
|
+
font: text
|
|
2962
|
+
},
|
|
2963
|
+
font: { name: roles.text.fontFamily, color: roles.text.color },
|
|
2964
|
+
// Office-open's chart space is unfilled and unbordered; `ChartRun`'s
|
|
2965
|
+
// default is Word's white fill and grey border.
|
|
2966
|
+
chartArea: { fill: "none", border: "none" },
|
|
2967
|
+
transformation: {
|
|
2968
|
+
width: emuToPixels(chart.widthEmu),
|
|
2969
|
+
height: emuToPixels(chart.heightEmu)
|
|
2970
|
+
},
|
|
2971
|
+
// Without an authored description `ChartRun` describes the chart from
|
|
2972
|
+
// its data, which is deterministic; the name stays empty, as it is on
|
|
2973
|
+
// every other drawing this renderer writes.
|
|
2974
|
+
...chart.altText ? { altText: { name: "", description: chart.altText } } : {},
|
|
2975
|
+
...floating ? { floating } : {}
|
|
2976
|
+
};
|
|
2977
|
+
switch (chart.chartType) {
|
|
2978
|
+
case "column":
|
|
2979
|
+
case "bar":
|
|
2980
|
+
case "area":
|
|
2981
|
+
case "line":
|
|
2982
|
+
return {
|
|
2983
|
+
...common,
|
|
2984
|
+
type: chart.chartType,
|
|
2985
|
+
categories,
|
|
2986
|
+
...chart.chartType === "line" ? { markers: true } : {},
|
|
2987
|
+
series: chart.series.map((entry, index) => ({
|
|
2988
|
+
name: seriesName(index),
|
|
2989
|
+
values: entry.values,
|
|
2990
|
+
...withColor(index)
|
|
2991
|
+
})),
|
|
2992
|
+
categoryAxis: axis(chart.categoryAxisTitle),
|
|
2993
|
+
valueAxis: axis(chart.valueAxisTitle)
|
|
2994
|
+
};
|
|
2995
|
+
case "pie":
|
|
2996
|
+
case "doughnut":
|
|
2997
|
+
return {
|
|
2998
|
+
...common,
|
|
2999
|
+
type: chart.chartType,
|
|
3000
|
+
categories,
|
|
3001
|
+
series: chart.series.map((entry, index) => ({
|
|
3002
|
+
name: seriesName(index),
|
|
3003
|
+
values: entry.values,
|
|
3004
|
+
...palette.length > 0 ? { colors: entry.values.map((_, point) => colorAt(point)) } : {}
|
|
3005
|
+
}))
|
|
3006
|
+
};
|
|
3007
|
+
case "radar":
|
|
3008
|
+
return {
|
|
3009
|
+
...common,
|
|
3010
|
+
type: "radar",
|
|
3011
|
+
categories,
|
|
3012
|
+
markers: true,
|
|
3013
|
+
series: chart.series.map((entry, index) => ({
|
|
3014
|
+
name: seriesName(index),
|
|
3015
|
+
values: entry.values,
|
|
3016
|
+
...withColor(index)
|
|
3017
|
+
})),
|
|
3018
|
+
categoryAxis: axis(chart.categoryAxisTitle),
|
|
3019
|
+
valueAxis: axis(chart.valueAxisTitle)
|
|
3020
|
+
};
|
|
3021
|
+
case "scatter":
|
|
3022
|
+
return {
|
|
3023
|
+
...common,
|
|
3024
|
+
type: "scatter",
|
|
3025
|
+
markers: true,
|
|
3026
|
+
lines: "straight",
|
|
3027
|
+
series: chart.series.map((entry, index) => ({
|
|
3028
|
+
name: seriesName(index),
|
|
3029
|
+
points: entry.values.map((y, point) => ({
|
|
3030
|
+
x: scatterX(entry.labels, point),
|
|
3031
|
+
y
|
|
3032
|
+
})),
|
|
3033
|
+
...withColor(index)
|
|
3034
|
+
})),
|
|
3035
|
+
xAxis: { ...axis(chart.categoryAxisTitle), gridlines: false },
|
|
3036
|
+
yAxis: axis(chart.valueAxisTitle)
|
|
3037
|
+
};
|
|
3038
|
+
case "bubble":
|
|
3039
|
+
throw new Error(
|
|
3040
|
+
"the docxjs renderer has no emitter for a bubble chart; the compiler should have refused it"
|
|
3041
|
+
);
|
|
3042
|
+
default:
|
|
3043
|
+
return assertNever(chart.chartType, "DocxIrChartType");
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
function emitChart(chart, floating) {
|
|
3047
|
+
return new (charts.get()).ChartRun(
|
|
3048
|
+
chartRunOptions(chart, floating)
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
var charts, LEGEND_POSITION;
|
|
3052
|
+
var init_charts = __esm({
|
|
3053
|
+
"src/renderers/docxjs/charts.ts"() {
|
|
3054
|
+
"use strict";
|
|
3055
|
+
init_chartValues();
|
|
3056
|
+
init_units();
|
|
3057
|
+
init_chartText();
|
|
3058
|
+
init_docxSubpath();
|
|
3059
|
+
charts = docxSubpath("docx/charts", "chart", () => import("docx/charts"));
|
|
3060
|
+
LEGEND_POSITION = {
|
|
3061
|
+
b: "bottom",
|
|
3062
|
+
l: "left",
|
|
3063
|
+
r: "right",
|
|
3064
|
+
t: "top",
|
|
3065
|
+
tr: "topRight"
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
});
|
|
3069
|
+
|
|
2849
3070
|
// src/renderers/docxjs/emit.ts
|
|
2850
3071
|
import {
|
|
2851
3072
|
AlignmentType,
|
|
@@ -2881,7 +3102,7 @@ import {
|
|
|
2881
3102
|
WidthType,
|
|
2882
3103
|
WpsShapeRun
|
|
2883
3104
|
} from "docx";
|
|
2884
|
-
import { assertNever } from "@json-to-office/shared/rendering";
|
|
3105
|
+
import { assertNever as assertNever2 } from "@json-to-office/shared/rendering";
|
|
2885
3106
|
function complexField(instruction, formatting, leading, cachedText) {
|
|
2886
3107
|
const options = runOptions(formatting);
|
|
2887
3108
|
const fieldChar = (type, extra = {}) => new TextRun({
|
|
@@ -2918,7 +3139,12 @@ function runOptions(formatting) {
|
|
|
2918
3139
|
if (formatting.bold !== void 0) options.bold = formatting.bold;
|
|
2919
3140
|
if (formatting.italic !== void 0) options.italics = formatting.italic;
|
|
2920
3141
|
if (formatting.underline !== void 0) {
|
|
2921
|
-
options.underline = formatting.underline ? {
|
|
3142
|
+
options.underline = formatting.underline ? {
|
|
3143
|
+
type: formatting.underline.type,
|
|
3144
|
+
// A native visual's text is the one place a run states its own
|
|
3145
|
+
// underline colour.
|
|
3146
|
+
...formatting.underline.color ? { color: formatting.underline.color.hex } : {}
|
|
3147
|
+
} : void 0;
|
|
2922
3148
|
}
|
|
2923
3149
|
if (formatting.strike !== void 0) options.strike = formatting.strike;
|
|
2924
3150
|
if (formatting.allCaps !== void 0) options.allCaps = formatting.allCaps;
|
|
@@ -3044,21 +3270,36 @@ function inlineChildren(children, resources = /* @__PURE__ */ new Map()) {
|
|
|
3044
3270
|
case "shape":
|
|
3045
3271
|
out.push(emitShape(child, resources));
|
|
3046
3272
|
break;
|
|
3047
|
-
case "drawingGroup":
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3273
|
+
case "drawingGroup": {
|
|
3274
|
+
const build = resources.drawingGroup;
|
|
3275
|
+
if (!build) {
|
|
3276
|
+
throw new Error(
|
|
3277
|
+
"the docxjs renderer was handed a drawing group without loading docx/shapes; render() loads it whenever the IR holds one"
|
|
3278
|
+
);
|
|
3279
|
+
}
|
|
3280
|
+
const pending = breakOption();
|
|
3281
|
+
if (pending.break) out.push(new TextRun(pending));
|
|
3282
|
+
out.push(build(child, resources));
|
|
3283
|
+
break;
|
|
3284
|
+
}
|
|
3285
|
+
case "chart": {
|
|
3286
|
+
const pending = breakOption();
|
|
3287
|
+
if (pending.break) out.push(new TextRun(pending));
|
|
3288
|
+
out.push(
|
|
3289
|
+
emitChart(
|
|
3290
|
+
child,
|
|
3291
|
+
child.floating ? floatingOptions(child.floating) : void 0
|
|
3292
|
+
)
|
|
3054
3293
|
);
|
|
3294
|
+
break;
|
|
3295
|
+
}
|
|
3055
3296
|
case "noteReference":
|
|
3056
3297
|
out.push(
|
|
3057
3298
|
child.noteKind === "endnote" ? new EndnoteReferenceRun(child.id) : new FootnoteReferenceRun(child.id)
|
|
3058
3299
|
);
|
|
3059
3300
|
break;
|
|
3060
3301
|
default:
|
|
3061
|
-
|
|
3302
|
+
assertNever2(child, "DocxIrInline");
|
|
3062
3303
|
}
|
|
3063
3304
|
}
|
|
3064
3305
|
return out;
|
|
@@ -3263,7 +3504,7 @@ function emitBlock(block2, resources = /* @__PURE__ */ new Map()) {
|
|
|
3263
3504
|
case "toc":
|
|
3264
3505
|
return emitToc(block2);
|
|
3265
3506
|
default:
|
|
3266
|
-
return
|
|
3507
|
+
return assertNever2(block2, "DocxIrBlock");
|
|
3267
3508
|
}
|
|
3268
3509
|
}
|
|
3269
3510
|
function emitToc(block2) {
|
|
@@ -3407,6 +3648,7 @@ var ALIGNMENT2, PAGE_FIELDS, isSequenceField, WRAP_TYPE, ThemedTableOfContents,
|
|
|
3407
3648
|
var init_emit = __esm({
|
|
3408
3649
|
"src/renderers/docxjs/emit.ts"() {
|
|
3409
3650
|
"use strict";
|
|
3651
|
+
init_charts();
|
|
3410
3652
|
ALIGNMENT2 = {
|
|
3411
3653
|
left: AlignmentType.LEFT,
|
|
3412
3654
|
center: AlignmentType.CENTER,
|
|
@@ -3705,10 +3947,13 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3705
3947
|
const rename = new Map(
|
|
3706
3948
|
ordered.map((id, index) => [id, `rId${highest + 1 + index}`])
|
|
3707
3949
|
);
|
|
3708
|
-
const rewrite = (xml) => xml.replace(
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3950
|
+
const rewrite = (xml) => xml.replace(
|
|
3951
|
+
/(\s[\w:.-]+=)"([^"]*)"/g,
|
|
3952
|
+
(whole, prefix, value) => {
|
|
3953
|
+
const replacement = rename.get(value);
|
|
3954
|
+
return replacement === void 0 ? whole : `${prefix}"${replacement}"`;
|
|
3955
|
+
}
|
|
3956
|
+
);
|
|
3712
3957
|
updates.push({ name: relsName, xml: rewrite(relsXml) });
|
|
3713
3958
|
if (partEntry) {
|
|
3714
3959
|
updates.push({ name: partName, xml: rewrite(partXml) });
|
|
@@ -3719,17 +3964,62 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3719
3964
|
if (entry) zip.updateFile(entry, Buffer.from(update.xml, "utf8"));
|
|
3720
3965
|
}
|
|
3721
3966
|
}
|
|
3967
|
+
function canonicalizeEmbeddedPackages(zip, generatedAt, depth = 1) {
|
|
3968
|
+
const names = zip.getEntries().map((entry) => entry.entryName).filter((name) => EMBEDDED_OFFICE_PACKAGE.test(name));
|
|
3969
|
+
let changed = false;
|
|
3970
|
+
for (const name of names) {
|
|
3971
|
+
const entry = zip.getEntry(name);
|
|
3972
|
+
if (!entry) continue;
|
|
3973
|
+
let nested;
|
|
3974
|
+
try {
|
|
3975
|
+
nested = new AdmZip(entry.getData());
|
|
3976
|
+
nested.getEntries();
|
|
3977
|
+
} catch {
|
|
3978
|
+
continue;
|
|
3979
|
+
}
|
|
3980
|
+
if (canonicalizeNestedPackage(nested, generatedAt, depth)) {
|
|
3981
|
+
zip.updateFile(entry, nested.toBuffer());
|
|
3982
|
+
changed = true;
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
return changed;
|
|
3986
|
+
}
|
|
3987
|
+
function canonicalizeNestedPackage(zip, generatedAt, depth) {
|
|
3988
|
+
let changed = false;
|
|
3989
|
+
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
3990
|
+
if (coreProperties3) {
|
|
3991
|
+
const xml = coreProperties3.getData().toString("utf8");
|
|
3992
|
+
const normalized = xml.replace(
|
|
3993
|
+
CORE_TIMESTAMP,
|
|
3994
|
+
`$1${generatedAt.toISOString()}$2`
|
|
3995
|
+
);
|
|
3996
|
+
if (normalized !== xml) {
|
|
3997
|
+
zip.updateFile(coreProperties3, Buffer.from(normalized, "utf8"));
|
|
3998
|
+
changed = true;
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
if (depth < MAX_EMBEDDED_DEPTH && canonicalizeEmbeddedPackages(zip, generatedAt, depth + 1)) {
|
|
4002
|
+
changed = true;
|
|
4003
|
+
}
|
|
4004
|
+
const zipTimestamp = toDosTime(generatedAt);
|
|
4005
|
+
for (const entry of zip.getEntries()) {
|
|
4006
|
+
const header = entry.header;
|
|
4007
|
+
if (header.timeval !== zipTimestamp) {
|
|
4008
|
+
header.timeval = zipTimestamp;
|
|
4009
|
+
changed = true;
|
|
4010
|
+
}
|
|
4011
|
+
}
|
|
4012
|
+
return changed;
|
|
4013
|
+
}
|
|
3722
4014
|
function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
|
|
3723
4015
|
const zip = new AdmZip(buffer);
|
|
3724
4016
|
normalizeTextCase(zip);
|
|
3725
4017
|
canonicalizeRelationshipIds(zip);
|
|
4018
|
+
canonicalizeEmbeddedPackages(zip, generatedAt);
|
|
3726
4019
|
const isoTimestamp = generatedAt.toISOString();
|
|
3727
4020
|
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
3728
4021
|
if (coreProperties3) {
|
|
3729
|
-
const normalized = coreProperties3.getData().toString("utf8").replace(
|
|
3730
|
-
/(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g,
|
|
3731
|
-
`$1${isoTimestamp}$2`
|
|
3732
|
-
);
|
|
4022
|
+
const normalized = coreProperties3.getData().toString("utf8").replace(CORE_TIMESTAMP, `$1${isoTimestamp}$2`);
|
|
3733
4023
|
zip.updateFile(coreProperties3, Buffer.from(normalized, "utf8"));
|
|
3734
4024
|
}
|
|
3735
4025
|
const zipTimestamp = toDosTime(generatedAt);
|
|
@@ -3742,35 +4032,567 @@ function normalizeDocxCaseBuffer(buffer) {
|
|
|
3742
4032
|
const zip = new AdmZip(buffer);
|
|
3743
4033
|
return normalizeTextCase(zip) ? zip.toBuffer() : buffer;
|
|
3744
4034
|
}
|
|
3745
|
-
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID;
|
|
4035
|
+
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID, CORE_TIMESTAMP, EMBEDDED_OFFICE_PACKAGE, MAX_EMBEDDED_DEPTH;
|
|
3746
4036
|
var init_packageDocument = __esm({
|
|
3747
4037
|
"src/utils/packageDocument.ts"() {
|
|
3748
4038
|
"use strict";
|
|
3749
4039
|
init_normalizeTextCase();
|
|
3750
4040
|
DEFAULT_GENERATION_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
|
|
3751
4041
|
STABLE_RELATIONSHIP_ID = /^rId\d+$/;
|
|
4042
|
+
CORE_TIMESTAMP = /(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g;
|
|
4043
|
+
EMBEDDED_OFFICE_PACKAGE = /\.(?:docx|pptx|xlsx|xlsm)$/i;
|
|
4044
|
+
MAX_EMBEDDED_DEPTH = 3;
|
|
3752
4045
|
}
|
|
3753
4046
|
});
|
|
3754
4047
|
|
|
3755
4048
|
// src/utils/fixFloatingImageIds.ts
|
|
3756
4049
|
import AdmZip2 from "adm-zip";
|
|
4050
|
+
function compareDrawingParts(a, b) {
|
|
4051
|
+
const ma = DRAWING_PART.exec(a);
|
|
4052
|
+
const mb = DRAWING_PART.exec(b);
|
|
4053
|
+
const rank = RANK.indexOf(ma[1]) - RANK.indexOf(mb[1]);
|
|
4054
|
+
return rank !== 0 ? rank : Number(ma[2] || 0) - Number(mb[2] || 0);
|
|
4055
|
+
}
|
|
3757
4056
|
function fixFloatingImageIdsInBuffer(buffer) {
|
|
3758
4057
|
const zip = new AdmZip2(buffer);
|
|
3759
|
-
|
|
3760
|
-
if (!documentEntry) {
|
|
4058
|
+
if (!zip.getEntry("word/document.xml")) {
|
|
3761
4059
|
throw new Error("document.xml not found in DOCX");
|
|
3762
4060
|
}
|
|
4061
|
+
const parts = zip.getEntries().filter((entry) => DRAWING_PART.test(entry.entryName)).sort((a, b) => compareDrawingParts(a.entryName, b.entryName));
|
|
3763
4062
|
let idCounter = 1;
|
|
3764
|
-
const
|
|
3765
|
-
const
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
4063
|
+
for (const entry of parts) {
|
|
4064
|
+
const xml = entry.getData().toString("utf8");
|
|
4065
|
+
const renumbered = xml.replace(
|
|
4066
|
+
/(<wp:docPr\b[^>]*?\s)id="\d+"/g,
|
|
4067
|
+
(_match, prefix) => `${prefix}id="${idCounter++}"`
|
|
4068
|
+
);
|
|
4069
|
+
zip.updateFile(entry, Buffer.from(renumbered, "utf8"));
|
|
4070
|
+
}
|
|
3769
4071
|
return zip.toBuffer();
|
|
3770
4072
|
}
|
|
4073
|
+
var DRAWING_PART, RANK;
|
|
3771
4074
|
var init_fixFloatingImageIds = __esm({
|
|
3772
4075
|
"src/utils/fixFloatingImageIds.ts"() {
|
|
3773
4076
|
"use strict";
|
|
4077
|
+
DRAWING_PART = /^word\/(document|header|footer|footnotes|endnotes|comments)(\d*)\.xml$/;
|
|
4078
|
+
RANK = [
|
|
4079
|
+
"document",
|
|
4080
|
+
"header",
|
|
4081
|
+
"footer",
|
|
4082
|
+
"footnotes",
|
|
4083
|
+
"endnotes",
|
|
4084
|
+
"comments"
|
|
4085
|
+
];
|
|
4086
|
+
}
|
|
4087
|
+
});
|
|
4088
|
+
|
|
4089
|
+
// src/renderers/docxjs/presetShapes.ts
|
|
4090
|
+
function docxPresetShape(geometry) {
|
|
4091
|
+
const name = Object.hasOwn(OOXML_PRESET_TO_DOCX, geometry) ? OOXML_PRESET_TO_DOCX[geometry] : void 0;
|
|
4092
|
+
if (!name) {
|
|
4093
|
+
throw new Error(
|
|
4094
|
+
`the docxjs renderer has no preset for the OOXML geometry "${geometry}"`
|
|
4095
|
+
);
|
|
4096
|
+
}
|
|
4097
|
+
return name;
|
|
4098
|
+
}
|
|
4099
|
+
function docxLineDash(dash) {
|
|
4100
|
+
const name = Object.hasOwn(OOXML_DASH_TO_DOCX, dash) ? OOXML_DASH_TO_DOCX[dash] : void 0;
|
|
4101
|
+
if (!name) {
|
|
4102
|
+
throw new Error(
|
|
4103
|
+
`the docxjs renderer has no line dash for the OOXML value "${dash}"`
|
|
4104
|
+
);
|
|
4105
|
+
}
|
|
4106
|
+
return name;
|
|
4107
|
+
}
|
|
4108
|
+
var OOXML_PRESET_TO_DOCX, OOXML_DASH_TO_DOCX;
|
|
4109
|
+
var init_presetShapes = __esm({
|
|
4110
|
+
"src/renderers/docxjs/presetShapes.ts"() {
|
|
4111
|
+
"use strict";
|
|
4112
|
+
OOXML_PRESET_TO_DOCX = {
|
|
4113
|
+
line: "line",
|
|
4114
|
+
lineInv: "inverseLine",
|
|
4115
|
+
straightConnector1: "straightConnector",
|
|
4116
|
+
bentConnector2: "elbowConnectorOneBend",
|
|
4117
|
+
bentConnector3: "elbowConnector",
|
|
4118
|
+
bentConnector4: "elbowConnectorThreeBends",
|
|
4119
|
+
bentConnector5: "elbowConnectorFourBends",
|
|
4120
|
+
curvedConnector2: "curvedConnectorOneBend",
|
|
4121
|
+
curvedConnector3: "curvedConnector",
|
|
4122
|
+
curvedConnector4: "curvedConnectorThreeBends",
|
|
4123
|
+
curvedConnector5: "curvedConnectorFourBends",
|
|
4124
|
+
triangle: "triangle",
|
|
4125
|
+
rtTriangle: "rightTriangle",
|
|
4126
|
+
diamond: "diamond",
|
|
4127
|
+
parallelogram: "parallelogram",
|
|
4128
|
+
trapezoid: "trapezoid",
|
|
4129
|
+
nonIsoscelesTrapezoid: "nonIsoscelesTrapezoid",
|
|
4130
|
+
pentagon: "pentagon",
|
|
4131
|
+
hexagon: "hexagon",
|
|
4132
|
+
heptagon: "heptagon",
|
|
4133
|
+
octagon: "octagon",
|
|
4134
|
+
decagon: "decagon",
|
|
4135
|
+
dodecagon: "dodecagon",
|
|
4136
|
+
ellipse: "ellipse",
|
|
4137
|
+
teardrop: "teardrop",
|
|
4138
|
+
pieWedge: "pieWedge",
|
|
4139
|
+
pie: "pie",
|
|
4140
|
+
blockArc: "blockArc",
|
|
4141
|
+
donut: "donut",
|
|
4142
|
+
noSmoking: "noSymbol",
|
|
4143
|
+
chord: "chord",
|
|
4144
|
+
arc: "arc",
|
|
4145
|
+
frame: "frame",
|
|
4146
|
+
halfFrame: "halfFrame",
|
|
4147
|
+
corner: "lShape",
|
|
4148
|
+
diagStripe: "diagonalStripe",
|
|
4149
|
+
plus: "cross",
|
|
4150
|
+
plaque: "plaque",
|
|
4151
|
+
can: "cylinder",
|
|
4152
|
+
cube: "cube",
|
|
4153
|
+
bevel: "beveledRectangle",
|
|
4154
|
+
foldedCorner: "foldedCorner",
|
|
4155
|
+
smileyFace: "smileyFace",
|
|
4156
|
+
heart: "heart",
|
|
4157
|
+
lightningBolt: "lightningBolt",
|
|
4158
|
+
sun: "sun",
|
|
4159
|
+
moon: "moon",
|
|
4160
|
+
cloud: "cloud",
|
|
4161
|
+
leftBracket: "leftBracket",
|
|
4162
|
+
rightBracket: "rightBracket",
|
|
4163
|
+
leftBrace: "leftBrace",
|
|
4164
|
+
rightBrace: "rightBrace",
|
|
4165
|
+
bracketPair: "bracketPair",
|
|
4166
|
+
bracePair: "bracePair",
|
|
4167
|
+
rect: "rectangle",
|
|
4168
|
+
roundRect: "roundedRectangle",
|
|
4169
|
+
round1Rect: "roundedCornerRectangle",
|
|
4170
|
+
round2SameRect: "topRoundedCornersRectangle",
|
|
4171
|
+
round2DiagRect: "diagonalRoundedCornersRectangle",
|
|
4172
|
+
snip1Rect: "snippedCornerRectangle",
|
|
4173
|
+
snip2SameRect: "topSnippedCornersRectangle",
|
|
4174
|
+
snip2DiagRect: "diagonalSnippedCornersRectangle",
|
|
4175
|
+
snipRoundRect: "roundedAndSnippedCornersRectangle",
|
|
4176
|
+
rightArrow: "rightArrow",
|
|
4177
|
+
leftArrow: "leftArrow",
|
|
4178
|
+
upArrow: "upArrow",
|
|
4179
|
+
downArrow: "downArrow",
|
|
4180
|
+
leftRightArrow: "leftRightArrow",
|
|
4181
|
+
upDownArrow: "upDownArrow",
|
|
4182
|
+
quadArrow: "quadArrow",
|
|
4183
|
+
leftRightUpArrow: "leftRightUpArrow",
|
|
4184
|
+
bentArrow: "bentArrow",
|
|
4185
|
+
uturnArrow: "uTurnArrow",
|
|
4186
|
+
leftUpArrow: "leftUpArrow",
|
|
4187
|
+
bentUpArrow: "bentUpArrow",
|
|
4188
|
+
curvedRightArrow: "curvedRightArrow",
|
|
4189
|
+
curvedLeftArrow: "curvedLeftArrow",
|
|
4190
|
+
curvedUpArrow: "curvedUpArrow",
|
|
4191
|
+
curvedDownArrow: "curvedDownArrow",
|
|
4192
|
+
stripedRightArrow: "stripedRightArrow",
|
|
4193
|
+
notchedRightArrow: "notchedRightArrow",
|
|
4194
|
+
homePlate: "pentagonArrow",
|
|
4195
|
+
chevron: "chevron",
|
|
4196
|
+
rightArrowCallout: "rightArrowCallout",
|
|
4197
|
+
downArrowCallout: "downArrowCallout",
|
|
4198
|
+
leftArrowCallout: "leftArrowCallout",
|
|
4199
|
+
upArrowCallout: "upArrowCallout",
|
|
4200
|
+
leftRightArrowCallout: "leftRightArrowCallout",
|
|
4201
|
+
upDownArrowCallout: "upDownArrowCallout",
|
|
4202
|
+
quadArrowCallout: "quadArrowCallout",
|
|
4203
|
+
circularArrow: "circularArrow",
|
|
4204
|
+
leftCircularArrow: "leftCircularArrow",
|
|
4205
|
+
leftRightCircularArrow: "leftRightCircularArrow",
|
|
4206
|
+
swooshArrow: "swooshArrow",
|
|
4207
|
+
mathPlus: "mathPlus",
|
|
4208
|
+
mathMinus: "mathMinus",
|
|
4209
|
+
mathMultiply: "mathMultiply",
|
|
4210
|
+
mathDivide: "mathDivide",
|
|
4211
|
+
mathEqual: "mathEqual",
|
|
4212
|
+
mathNotEqual: "mathNotEqual",
|
|
4213
|
+
flowChartProcess: "flowChartProcess",
|
|
4214
|
+
flowChartAlternateProcess: "flowChartAlternateProcess",
|
|
4215
|
+
flowChartDecision: "flowChartDecision",
|
|
4216
|
+
flowChartInputOutput: "flowChartInputOutput",
|
|
4217
|
+
flowChartPredefinedProcess: "flowChartPredefinedProcess",
|
|
4218
|
+
flowChartInternalStorage: "flowChartInternalStorage",
|
|
4219
|
+
flowChartDocument: "flowChartDocument",
|
|
4220
|
+
flowChartMultidocument: "flowChartMultidocument",
|
|
4221
|
+
flowChartTerminator: "flowChartTerminator",
|
|
4222
|
+
flowChartPreparation: "flowChartPreparation",
|
|
4223
|
+
flowChartManualInput: "flowChartManualInput",
|
|
4224
|
+
flowChartManualOperation: "flowChartManualOperation",
|
|
4225
|
+
flowChartConnector: "flowChartConnector",
|
|
4226
|
+
flowChartOffpageConnector: "flowChartOffpageConnector",
|
|
4227
|
+
flowChartPunchedCard: "flowChartPunchedCard",
|
|
4228
|
+
flowChartPunchedTape: "flowChartPunchedTape",
|
|
4229
|
+
flowChartSummingJunction: "flowChartSummingJunction",
|
|
4230
|
+
flowChartOr: "flowChartOr",
|
|
4231
|
+
flowChartCollate: "flowChartCollate",
|
|
4232
|
+
flowChartSort: "flowChartSort",
|
|
4233
|
+
flowChartExtract: "flowChartExtract",
|
|
4234
|
+
flowChartMerge: "flowChartMerge",
|
|
4235
|
+
flowChartOfflineStorage: "flowChartOfflineStorage",
|
|
4236
|
+
flowChartOnlineStorage: "flowChartOnlineStorage",
|
|
4237
|
+
flowChartDelay: "flowChartDelay",
|
|
4238
|
+
flowChartMagneticTape: "flowChartMagneticTape",
|
|
4239
|
+
flowChartMagneticDisk: "flowChartMagneticDisk",
|
|
4240
|
+
flowChartMagneticDrum: "flowChartMagneticDrum",
|
|
4241
|
+
flowChartDisplay: "flowChartDisplay",
|
|
4242
|
+
irregularSeal1: "explosion12",
|
|
4243
|
+
irregularSeal2: "explosion14",
|
|
4244
|
+
star4: "star4",
|
|
4245
|
+
star5: "star5",
|
|
4246
|
+
star6: "star6",
|
|
4247
|
+
star7: "star7",
|
|
4248
|
+
star8: "star8",
|
|
4249
|
+
star10: "star10",
|
|
4250
|
+
star12: "star12",
|
|
4251
|
+
star16: "star16",
|
|
4252
|
+
star24: "star24",
|
|
4253
|
+
star32: "star32",
|
|
4254
|
+
ribbon2: "ribbonUp",
|
|
4255
|
+
ribbon: "ribbonDown",
|
|
4256
|
+
ellipseRibbon2: "curvedRibbonUp",
|
|
4257
|
+
ellipseRibbon: "curvedRibbonDown",
|
|
4258
|
+
leftRightRibbon: "leftRightRibbon",
|
|
4259
|
+
verticalScroll: "verticalScroll",
|
|
4260
|
+
horizontalScroll: "horizontalScroll",
|
|
4261
|
+
wave: "wave",
|
|
4262
|
+
doubleWave: "doubleWave",
|
|
4263
|
+
wedgeRectCallout: "rectangularCallout",
|
|
4264
|
+
wedgeRoundRectCallout: "roundedRectangularCallout",
|
|
4265
|
+
wedgeEllipseCallout: "ellipticalCallout",
|
|
4266
|
+
cloudCallout: "cloudCallout",
|
|
4267
|
+
borderCallout1: "lineCallout",
|
|
4268
|
+
borderCallout2: "bentLineCallout",
|
|
4269
|
+
borderCallout3: "doubleBentLineCallout",
|
|
4270
|
+
accentCallout1: "lineCalloutWithAccentBar",
|
|
4271
|
+
accentCallout2: "bentLineCalloutWithAccentBar",
|
|
4272
|
+
accentCallout3: "doubleBentLineCalloutWithAccentBar",
|
|
4273
|
+
callout1: "lineCalloutWithNoBorder",
|
|
4274
|
+
callout2: "bentLineCalloutWithNoBorder",
|
|
4275
|
+
callout3: "doubleBentLineCalloutWithNoBorder",
|
|
4276
|
+
accentBorderCallout1: "lineCalloutWithBorderAndAccentBar",
|
|
4277
|
+
accentBorderCallout2: "bentLineCalloutWithBorderAndAccentBar",
|
|
4278
|
+
accentBorderCallout3: "doubleBentLineCalloutWithBorderAndAccentBar",
|
|
4279
|
+
actionButtonBlank: "actionButtonBlank",
|
|
4280
|
+
actionButtonHome: "actionButtonHome",
|
|
4281
|
+
actionButtonHelp: "actionButtonHelp",
|
|
4282
|
+
actionButtonInformation: "actionButtonInformation",
|
|
4283
|
+
actionButtonForwardNext: "actionButtonForwardNext",
|
|
4284
|
+
actionButtonBackPrevious: "actionButtonBackPrevious",
|
|
4285
|
+
actionButtonEnd: "actionButtonEnd",
|
|
4286
|
+
actionButtonBeginning: "actionButtonBeginning",
|
|
4287
|
+
actionButtonReturn: "actionButtonReturn",
|
|
4288
|
+
actionButtonDocument: "actionButtonDocument",
|
|
4289
|
+
actionButtonSound: "actionButtonSound",
|
|
4290
|
+
actionButtonMovie: "actionButtonMovie",
|
|
4291
|
+
gear6: "gear6",
|
|
4292
|
+
gear9: "gear9",
|
|
4293
|
+
funnel: "funnel",
|
|
4294
|
+
cornerTabs: "cornerTabs",
|
|
4295
|
+
squareTabs: "squareTabs",
|
|
4296
|
+
plaqueTabs: "plaqueTabs",
|
|
4297
|
+
chartX: "chartX",
|
|
4298
|
+
chartStar: "chartStar",
|
|
4299
|
+
chartPlus: "chartPlus"
|
|
4300
|
+
};
|
|
4301
|
+
OOXML_DASH_TO_DOCX = {
|
|
4302
|
+
solid: "solid",
|
|
4303
|
+
dot: "dot",
|
|
4304
|
+
dash: "dash",
|
|
4305
|
+
lgDash: "longDash",
|
|
4306
|
+
dashDot: "dashDot",
|
|
4307
|
+
lgDashDot: "longDashDot",
|
|
4308
|
+
lgDashDotDot: "longDashDotDot",
|
|
4309
|
+
sysDash: "shortDash",
|
|
4310
|
+
sysDot: "shortDot",
|
|
4311
|
+
sysDashDot: "shortDashDot",
|
|
4312
|
+
sysDashDotDot: "shortDashDotDot"
|
|
4313
|
+
};
|
|
4314
|
+
}
|
|
4315
|
+
});
|
|
4316
|
+
|
|
4317
|
+
// src/renderers/docxjs/drawingGroup.ts
|
|
4318
|
+
function chooseMarkers(ir) {
|
|
4319
|
+
const strings = [];
|
|
4320
|
+
collectStrings(ir, strings, /* @__PURE__ */ new WeakSet());
|
|
4321
|
+
const unused = (base) => {
|
|
4322
|
+
for (let n = 0; ; n += 1) {
|
|
4323
|
+
const candidate = n === 0 ? base : `${base}-${n}`;
|
|
4324
|
+
if (!strings.some((value) => value.includes(candidate))) return candidate;
|
|
4325
|
+
}
|
|
4326
|
+
};
|
|
4327
|
+
return {
|
|
4328
|
+
noAltText: unused(DEFAULT_MARKERS.noAltText),
|
|
4329
|
+
textBox: unused(DEFAULT_MARKERS.textBox)
|
|
4330
|
+
};
|
|
4331
|
+
}
|
|
4332
|
+
function collectStrings(node, out, seen) {
|
|
4333
|
+
if (typeof node === "string") {
|
|
4334
|
+
out.push(node);
|
|
4335
|
+
return;
|
|
4336
|
+
}
|
|
4337
|
+
if (!node || typeof node !== "object") return;
|
|
4338
|
+
if (node instanceof ArrayBuffer || ArrayBuffer.isView(node)) return;
|
|
4339
|
+
if (seen.has(node)) return;
|
|
4340
|
+
seen.add(node);
|
|
4341
|
+
if (node instanceof Map) {
|
|
4342
|
+
for (const [key, value] of node) {
|
|
4343
|
+
collectStrings(key, out, seen);
|
|
4344
|
+
collectStrings(value, out, seen);
|
|
4345
|
+
}
|
|
4346
|
+
return;
|
|
4347
|
+
}
|
|
4348
|
+
if (node instanceof Set) {
|
|
4349
|
+
for (const value of node) collectStrings(value, out, seen);
|
|
4350
|
+
return;
|
|
4351
|
+
}
|
|
4352
|
+
for (const value of Object.values(node)) collectStrings(value, out, seen);
|
|
4353
|
+
}
|
|
4354
|
+
function createDrawingGroupFactory(shapes2, pictures, markers) {
|
|
4355
|
+
return (group, resources) => new shapes2.ShapeGroupRun(
|
|
4356
|
+
drawingGroupOptions(group, resources, pictures, markers)
|
|
4357
|
+
);
|
|
4358
|
+
}
|
|
4359
|
+
function drawingGroupOptions(group, resources, pictures, markers = DEFAULT_MARKERS) {
|
|
4360
|
+
const canvasWidth = group.canvasWidthEmu;
|
|
4361
|
+
const canvasHeight = group.canvasHeightEmu;
|
|
4362
|
+
const near = (value, edge) => Math.abs(value - edge) <= OVERFLOW_TOLERANCE_EMU;
|
|
4363
|
+
const bounds = unrotatedBounds(group.children);
|
|
4364
|
+
const fillsCanvas = bounds !== void 0 && near(bounds.left, 0) && near(bounds.top, 0) && near(bounds.right, canvasWidth) && near(bounds.bottom, canvasHeight);
|
|
4365
|
+
const union = {
|
|
4366
|
+
left: Math.min(0, bounds?.left ?? 0),
|
|
4367
|
+
top: Math.min(0, bounds?.top ?? 0),
|
|
4368
|
+
right: Math.max(canvasWidth, bounds?.right ?? 0),
|
|
4369
|
+
bottom: Math.max(canvasHeight, bounds?.bottom ?? 0)
|
|
4370
|
+
};
|
|
4371
|
+
const overflows = union.left < -OVERFLOW_TOLERANCE_EMU || union.top < -OVERFLOW_TOLERANCE_EMU || union.right > canvasWidth + OVERFLOW_TOLERANCE_EMU || union.bottom > canvasHeight + OVERFLOW_TOLERANCE_EMU;
|
|
4372
|
+
const widthEmu = overflows ? (union.right - union.left) * group.widthEmu / canvasWidth : group.widthEmu;
|
|
4373
|
+
const heightEmu = overflows ? (union.bottom - union.top) * group.heightEmu / canvasHeight : group.heightEmu;
|
|
4374
|
+
return {
|
|
4375
|
+
children: [
|
|
4376
|
+
...fillsCanvas ? [] : [canvasPad(canvasWidth, canvasHeight)],
|
|
4377
|
+
...group.children.map(
|
|
4378
|
+
(child, index) => groupChild(child, index, resources, pictures, markers)
|
|
4379
|
+
)
|
|
4380
|
+
],
|
|
4381
|
+
transformation: {
|
|
4382
|
+
width: emuToPixels(widthEmu),
|
|
4383
|
+
height: emuToPixels(heightEmu)
|
|
4384
|
+
},
|
|
4385
|
+
// `||`, not `??`: docx treats '' as no description too, and would then
|
|
4386
|
+
// describe the diagram from the child names.
|
|
4387
|
+
altText: { name: "", description: group.altText || markers.noAltText },
|
|
4388
|
+
...group.floating ? { floating: floatingOptions(group.floating) } : {}
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
function groupChild(child, index, resources, pictures, markers) {
|
|
4392
|
+
return child.kind === "picture" ? pictureChild(child, index, pictures) : shapeChild(child, index, resources, markers);
|
|
4393
|
+
}
|
|
4394
|
+
function canvasPad(canvasWidthEmu, canvasHeightEmu) {
|
|
4395
|
+
return {
|
|
4396
|
+
type: "rectangle",
|
|
4397
|
+
transformation: {
|
|
4398
|
+
offset: { left: 0, top: 0 },
|
|
4399
|
+
width: emuToPixels(canvasWidthEmu),
|
|
4400
|
+
height: emuToPixels(canvasHeightEmu)
|
|
4401
|
+
},
|
|
4402
|
+
fill: "none",
|
|
4403
|
+
line: "none",
|
|
4404
|
+
decorative: true,
|
|
4405
|
+
altText: { name: "Canvas" }
|
|
4406
|
+
};
|
|
4407
|
+
}
|
|
4408
|
+
function childTransformation(frame) {
|
|
4409
|
+
const rotation2 = frame.rotationDegrees;
|
|
4410
|
+
return {
|
|
4411
|
+
offset: { left: emuToPixels(frame.xEmu), top: emuToPixels(frame.yEmu) },
|
|
4412
|
+
width: emuToPixels(frame.widthEmu),
|
|
4413
|
+
height: emuToPixels(frame.heightEmu),
|
|
4414
|
+
...rotation2 !== void 0 && rotation2 % 360 !== 0 ? { rotation: rotation2 } : {},
|
|
4415
|
+
...frame.flipHorizontal || frame.flipVertical ? {
|
|
4416
|
+
flip: {
|
|
4417
|
+
...frame.flipHorizontal ? { horizontal: true } : {},
|
|
4418
|
+
...frame.flipVertical ? { vertical: true } : {}
|
|
4419
|
+
}
|
|
4420
|
+
} : {}
|
|
4421
|
+
};
|
|
4422
|
+
}
|
|
4423
|
+
function shapeChild(shape, index, resources, markers) {
|
|
4424
|
+
const paragraphs = shape.text?.paragraphs ?? [];
|
|
4425
|
+
return {
|
|
4426
|
+
type: docxPresetShape(shape.geometry),
|
|
4427
|
+
transformation: childTransformation(shape.frame),
|
|
4428
|
+
fill: shapeFill(shape.fill),
|
|
4429
|
+
line: shapeLine(shape.outline),
|
|
4430
|
+
altText: {
|
|
4431
|
+
name: shape.name ?? `Shape ${index + 1}`,
|
|
4432
|
+
...shape.isTextBox ? { title: markers.textBox } : {}
|
|
4433
|
+
},
|
|
4434
|
+
// Never `children: []`: docx would write an empty `w:txbxContent`, which
|
|
4435
|
+
// the schema does not allow.
|
|
4436
|
+
...paragraphs.length > 0 ? {
|
|
4437
|
+
children: paragraphs.map(
|
|
4438
|
+
(paragraph2) => emitParagraph(paragraph2, resources)
|
|
4439
|
+
)
|
|
4440
|
+
} : {},
|
|
4441
|
+
...shape.text ? { textOptions: textOptions(shape.text) } : {}
|
|
4442
|
+
};
|
|
4443
|
+
}
|
|
4444
|
+
function pictureChild(picture2, index, pictures) {
|
|
4445
|
+
const crop = picture2.crop;
|
|
4446
|
+
return {
|
|
4447
|
+
type: "picture",
|
|
4448
|
+
image: pictures(picture2.resourceId, {
|
|
4449
|
+
widthEmu: picture2.frame.widthEmu,
|
|
4450
|
+
heightEmu: picture2.frame.heightEmu
|
|
4451
|
+
}),
|
|
4452
|
+
transformation: childTransformation(picture2.frame),
|
|
4453
|
+
...crop ? {
|
|
4454
|
+
crop: {
|
|
4455
|
+
...crop.left !== void 0 ? { left: crop.left * 100 } : {},
|
|
4456
|
+
...crop.top !== void 0 ? { top: crop.top * 100 } : {},
|
|
4457
|
+
...crop.right !== void 0 ? { right: crop.right * 100 } : {},
|
|
4458
|
+
...crop.bottom !== void 0 ? { bottom: crop.bottom * 100 } : {}
|
|
4459
|
+
}
|
|
4460
|
+
} : {},
|
|
4461
|
+
altText: {
|
|
4462
|
+
name: picture2.name ?? `Picture ${index + 1}`,
|
|
4463
|
+
...picture2.altText ? { description: picture2.altText } : {}
|
|
4464
|
+
}
|
|
4465
|
+
};
|
|
4466
|
+
}
|
|
4467
|
+
function shapeFill(fill) {
|
|
4468
|
+
if (!fill || fill.kind === "none") return "none";
|
|
4469
|
+
return {
|
|
4470
|
+
type: "solid",
|
|
4471
|
+
color: fill.color.hex,
|
|
4472
|
+
...fill.transparencyPercent !== void 0 ? { transparency: clamp(fill.transparencyPercent, 0, 100) } : {}
|
|
4473
|
+
};
|
|
4474
|
+
}
|
|
4475
|
+
function shapeLine(outline) {
|
|
4476
|
+
if (!outline || !outline.color) return "none";
|
|
4477
|
+
return {
|
|
4478
|
+
color: outline.color.hex,
|
|
4479
|
+
// An omitted width is office-open's omitted `w`, a hairline, where docx's
|
|
4480
|
+
// own default would be 1pt.
|
|
4481
|
+
width: outline.widthEmu !== void 0 ? clamp(outline.widthEmu / EMU_PER_POINT, 0, MAX_POINTS) : 0,
|
|
4482
|
+
...outline.dash ? { dash: docxLineDash(outline.dash) } : {}
|
|
4483
|
+
};
|
|
4484
|
+
}
|
|
4485
|
+
function textOptions(text) {
|
|
4486
|
+
const insets = text.insetsEmu;
|
|
4487
|
+
const points = (emu) => clamp(emu / EMU_PER_POINT, 0, MAX_POINTS);
|
|
4488
|
+
const margins = insets ? {
|
|
4489
|
+
...insets.top !== void 0 ? { top: points(insets.top) } : {},
|
|
4490
|
+
...insets.right !== void 0 ? { right: points(insets.right) } : {},
|
|
4491
|
+
...insets.bottom !== void 0 ? { bottom: points(insets.bottom) } : {},
|
|
4492
|
+
...insets.left !== void 0 ? { left: points(insets.left) } : {}
|
|
4493
|
+
} : void 0;
|
|
4494
|
+
return {
|
|
4495
|
+
verticalAlignment: VERTICAL_ALIGNMENT[text.anchor ?? "top"],
|
|
4496
|
+
...margins && Object.keys(margins).length > 0 ? { margins } : {}
|
|
4497
|
+
};
|
|
4498
|
+
}
|
|
4499
|
+
function unrotatedBounds(children) {
|
|
4500
|
+
if (children.length === 0) return void 0;
|
|
4501
|
+
let left = Infinity;
|
|
4502
|
+
let top = Infinity;
|
|
4503
|
+
let right = -Infinity;
|
|
4504
|
+
let bottom = -Infinity;
|
|
4505
|
+
for (const { frame } of children) {
|
|
4506
|
+
left = Math.min(left, frame.xEmu);
|
|
4507
|
+
top = Math.min(top, frame.yEmu);
|
|
4508
|
+
right = Math.max(right, frame.xEmu + frame.widthEmu);
|
|
4509
|
+
bottom = Math.max(bottom, frame.yEmu + frame.heightEmu);
|
|
4510
|
+
}
|
|
4511
|
+
return { left, top, right, bottom };
|
|
4512
|
+
}
|
|
4513
|
+
function clamp(value, low, high) {
|
|
4514
|
+
return Math.min(high, Math.max(low, value));
|
|
4515
|
+
}
|
|
4516
|
+
var DEFAULT_MARKERS, EMU_PER_POINT, MAX_POINTS, OVERFLOW_TOLERANCE_EMU, VERTICAL_ALIGNMENT;
|
|
4517
|
+
var init_drawingGroup = __esm({
|
|
4518
|
+
"src/renderers/docxjs/drawingGroup.ts"() {
|
|
4519
|
+
"use strict";
|
|
4520
|
+
init_units();
|
|
4521
|
+
init_emit();
|
|
4522
|
+
init_presetShapes();
|
|
4523
|
+
DEFAULT_MARKERS = {
|
|
4524
|
+
noAltText: "jto:no-alt-text",
|
|
4525
|
+
textBox: "jto:text-box"
|
|
4526
|
+
};
|
|
4527
|
+
EMU_PER_POINT = 12700;
|
|
4528
|
+
MAX_POINTS = 1584;
|
|
4529
|
+
OVERFLOW_TOLERANCE_EMU = 2;
|
|
4530
|
+
VERTICAL_ALIGNMENT = {
|
|
4531
|
+
top: "top",
|
|
4532
|
+
middle: "center",
|
|
4533
|
+
bottom: "bottom"
|
|
4534
|
+
};
|
|
4535
|
+
}
|
|
4536
|
+
});
|
|
4537
|
+
|
|
4538
|
+
// src/renderers/docxjs/drawingGroupRepair.ts
|
|
4539
|
+
import AdmZip3 from "adm-zip";
|
|
4540
|
+
function repairDrawingGroupsInBuffer(buffer, markers) {
|
|
4541
|
+
const textBox = new RegExp(
|
|
4542
|
+
`(<wps:cNvPr\\b[^>]*?) title="${escapeRegExp2(markers.textBox)}"(\\s*/>)<wps:cNvSpPr/>`,
|
|
4543
|
+
"g"
|
|
4544
|
+
);
|
|
4545
|
+
const noAltText = new RegExp(
|
|
4546
|
+
`(<wp:docPr\\b[^>]*?) descr="${escapeRegExp2(markers.noAltText)}"`,
|
|
4547
|
+
"g"
|
|
4548
|
+
);
|
|
4549
|
+
const zip = new AdmZip3(buffer);
|
|
4550
|
+
const parts = zip.getEntries().filter((entry) => DRAWING_PART.test(entry.entryName)).sort((a, b) => compareDrawingParts(a.entryName, b.entryName));
|
|
4551
|
+
const texts = new Map(
|
|
4552
|
+
parts.map((entry) => [entry, entry.getData().toString("utf8")])
|
|
4553
|
+
);
|
|
4554
|
+
let highest = 0;
|
|
4555
|
+
for (const xml of texts.values()) {
|
|
4556
|
+
for (const match of xml.matchAll(DOC_PR_ID)) {
|
|
4557
|
+
highest = Math.max(highest, Number(match[1]));
|
|
4558
|
+
}
|
|
4559
|
+
for (const match of xml.replace(GROUP, "").matchAll(CNVPR_ID)) {
|
|
4560
|
+
highest = Math.max(highest, Number(match[1]));
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
let next = highest + 1;
|
|
4564
|
+
for (const [entry, xml] of texts) {
|
|
4565
|
+
if (!xml.includes("<wpg:wgp")) continue;
|
|
4566
|
+
const repaired = xml.replace(
|
|
4567
|
+
GROUP,
|
|
4568
|
+
(span) => span.replace(CHILD_ID, (_match, head) => `${head}id="${next++}"`).replace(
|
|
4569
|
+
ROTATION,
|
|
4570
|
+
(_match, head, value) => `${head}rot="${Math.round(Number(value))}"`
|
|
4571
|
+
).replace(textBox, '$1$2<wps:cNvSpPr txBox="1"/>')
|
|
4572
|
+
).replace(noAltText, "$1");
|
|
4573
|
+
texts.set(entry, repaired);
|
|
4574
|
+
zip.updateFile(entry, Buffer.from(repaired, "utf8"));
|
|
4575
|
+
}
|
|
4576
|
+
for (const [entry, xml] of texts) {
|
|
4577
|
+
if (xml.includes(markers.noAltText) || xml.includes(markers.textBox)) {
|
|
4578
|
+
throw new Error(
|
|
4579
|
+
`the drawing-group repair left a marker in ${entry.entryName}`
|
|
4580
|
+
);
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
return zip.toBuffer();
|
|
4584
|
+
}
|
|
4585
|
+
var GROUP, DOC_PR_ID, CNVPR_ID, CHILD_ID, ROTATION, escapeRegExp2;
|
|
4586
|
+
var init_drawingGroupRepair = __esm({
|
|
4587
|
+
"src/renderers/docxjs/drawingGroupRepair.ts"() {
|
|
4588
|
+
"use strict";
|
|
4589
|
+
init_fixFloatingImageIds();
|
|
4590
|
+
GROUP = /<wpg:wgp\b[^>]*>[\s\S]*?<\/wpg:wgp>/g;
|
|
4591
|
+
DOC_PR_ID = /<wp:docPr\b[^>]*?\sid="(\d+)"/g;
|
|
4592
|
+
CNVPR_ID = /<(?:wps|pic|wpg):cNvPr\b[^>]*?\sid="(\d+)"/g;
|
|
4593
|
+
CHILD_ID = /(<(?:wps|pic|wpg):cNvPr\b[^>]*?\s)id="\d+"/g;
|
|
4594
|
+
ROTATION = /(<a:xfrm\b[^>]*?\s)rot="([^"]*)"/g;
|
|
4595
|
+
escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3774
4596
|
}
|
|
3775
4597
|
});
|
|
3776
4598
|
|
|
@@ -3799,18 +4621,32 @@ function createDocxJsRenderer() {
|
|
|
3799
4621
|
format: "docx",
|
|
3800
4622
|
capabilities: DOCXJS_CAPABILITIES,
|
|
3801
4623
|
async render(ir, renderOptions) {
|
|
3802
|
-
|
|
4624
|
+
await loadDocxCharts();
|
|
4625
|
+
const prepared = await prepareImages(
|
|
3803
4626
|
ir,
|
|
3804
4627
|
renderOptions?.svgRasterFallback
|
|
3805
4628
|
);
|
|
4629
|
+
const markers = prepared.drawingGroups > 0 ? chooseMarkers(ir) : void 0;
|
|
4630
|
+
let resources = prepared.images;
|
|
4631
|
+
if (markers) {
|
|
4632
|
+
await shapes.load();
|
|
4633
|
+
resources = Object.assign(prepared.images, {
|
|
4634
|
+
drawingGroup: createDrawingGroupFactory(
|
|
4635
|
+
shapes.get(),
|
|
4636
|
+
prepared.pictureSource,
|
|
4637
|
+
markers
|
|
4638
|
+
)
|
|
4639
|
+
});
|
|
4640
|
+
}
|
|
3806
4641
|
const document = buildDocument(ir, resources);
|
|
3807
4642
|
const packed = await Packer.toBuffer(document);
|
|
3808
4643
|
const fixed = fixFloatingImageIdsInBuffer(packed);
|
|
4644
|
+
const repaired = markers ? repairDrawingGroupsInBuffer(fixed, markers) : fixed;
|
|
3809
4645
|
if (renderOptions?.deterministic === false)
|
|
3810
|
-
return new Uint8Array(normalizeDocxCaseBuffer(
|
|
4646
|
+
return new Uint8Array(normalizeDocxCaseBuffer(repaired));
|
|
3811
4647
|
return new Uint8Array(
|
|
3812
4648
|
canonicalizeDocxBuffer(
|
|
3813
|
-
|
|
4649
|
+
repaired,
|
|
3814
4650
|
resolveGenerationDate({
|
|
3815
4651
|
deterministic: renderOptions?.deterministic,
|
|
3816
4652
|
generatedAt: renderOptions?.generatedAt
|
|
@@ -3823,6 +4659,7 @@ function createDocxJsRenderer() {
|
|
|
3823
4659
|
function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
3824
4660
|
return new Document({
|
|
3825
4661
|
styles: emitStyles(ir.styles),
|
|
4662
|
+
...ir.theme ? { theme: themeOptions(ir.theme) } : {},
|
|
3826
4663
|
sections: ir.sections.map(
|
|
3827
4664
|
(section2, index) => sectionOptions(section2, resources, index === ir.sections.length - 1)
|
|
3828
4665
|
),
|
|
@@ -3854,6 +4691,21 @@ function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
|
3854
4691
|
} : {}
|
|
3855
4692
|
});
|
|
3856
4693
|
}
|
|
4694
|
+
function themeOptions(theme) {
|
|
4695
|
+
const colors = {};
|
|
4696
|
+
for (const [slot, color] of Object.entries(theme.colors)) {
|
|
4697
|
+
if (color) colors[slot] = color.hex;
|
|
4698
|
+
}
|
|
4699
|
+
const fonts = {
|
|
4700
|
+
...theme.headingFont ? { headings: theme.headingFont } : {},
|
|
4701
|
+
...theme.bodyFont ? { body: theme.bodyFont } : {}
|
|
4702
|
+
};
|
|
4703
|
+
return {
|
|
4704
|
+
name: theme.name,
|
|
4705
|
+
...Object.keys(colors).length > 0 ? { colors } : {},
|
|
4706
|
+
...Object.keys(fonts).length > 0 ? { fonts } : {}
|
|
4707
|
+
};
|
|
4708
|
+
}
|
|
3857
4709
|
function noteBodies(notes, resources) {
|
|
3858
4710
|
const bodies = {};
|
|
3859
4711
|
for (const note of notes) {
|
|
@@ -3891,7 +4743,7 @@ function numberingConfig(numbering) {
|
|
|
3891
4743
|
};
|
|
3892
4744
|
}
|
|
3893
4745
|
async function prepareImages(ir, svgRasterFallback) {
|
|
3894
|
-
const placements = collectImagePlacements(ir);
|
|
4746
|
+
const { placements, drawingGroups } = collectImagePlacements(ir);
|
|
3895
4747
|
const jobs = [];
|
|
3896
4748
|
for (const resource of ir.resources) {
|
|
3897
4749
|
if (resource.kind !== "image" || resource.mediaType !== "svg") continue;
|
|
@@ -3939,16 +4791,55 @@ async function prepareImages(ir, svgRasterFallback) {
|
|
|
3939
4791
|
});
|
|
3940
4792
|
});
|
|
3941
4793
|
}
|
|
3942
|
-
|
|
4794
|
+
const pictureSource = (resourceId, placement) => {
|
|
4795
|
+
const resource = ir.resources.find(
|
|
4796
|
+
(candidate) => candidate.kind === "image" && candidate.id === resourceId
|
|
4797
|
+
);
|
|
4798
|
+
if (!resource) {
|
|
4799
|
+
throw new Error(`no image was prepared for resource "${resourceId}"`);
|
|
4800
|
+
}
|
|
4801
|
+
const data = Buffer.from(resource.bytes);
|
|
4802
|
+
if (resource.mediaType !== "svg") {
|
|
4803
|
+
return {
|
|
4804
|
+
type: resource.mediaType,
|
|
4805
|
+
data
|
|
4806
|
+
};
|
|
4807
|
+
}
|
|
4808
|
+
const size = `${emuToPixels(placement.widthEmu)}x${emuToPixels(placement.heightEmu)}`;
|
|
4809
|
+
return {
|
|
4810
|
+
type: "svg",
|
|
4811
|
+
data,
|
|
4812
|
+
fallback: {
|
|
4813
|
+
type: "png",
|
|
4814
|
+
data: rasters.get(`${resourceId}:${size}`) ?? data
|
|
4815
|
+
}
|
|
4816
|
+
};
|
|
4817
|
+
};
|
|
4818
|
+
return { images: resources, pictureSource, drawingGroups };
|
|
3943
4819
|
}
|
|
3944
4820
|
function collectImagePlacements(ir) {
|
|
3945
4821
|
const placements = /* @__PURE__ */ new Map();
|
|
4822
|
+
let drawingGroups = 0;
|
|
4823
|
+
const record = (resourceId, widthEmu, heightEmu) => {
|
|
4824
|
+
const key = `${emuToPixels(widthEmu)}x${emuToPixels(heightEmu)}`;
|
|
4825
|
+
const sizes = placements.get(resourceId) ?? /* @__PURE__ */ new Set();
|
|
4826
|
+
sizes.add(key);
|
|
4827
|
+
placements.set(resourceId, sizes);
|
|
4828
|
+
};
|
|
3946
4829
|
const visitInline = (inline) => {
|
|
3947
4830
|
if (inline.kind === "image") {
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
4831
|
+
record(inline.resourceId, inline.widthEmu, inline.heightEmu);
|
|
4832
|
+
return;
|
|
4833
|
+
}
|
|
4834
|
+
if (inline.kind === "drawingGroup") {
|
|
4835
|
+
drawingGroups += 1;
|
|
4836
|
+
for (const child of inline.children) {
|
|
4837
|
+
if (child.kind === "picture") {
|
|
4838
|
+
record(child.resourceId, child.frame.widthEmu, child.frame.heightEmu);
|
|
4839
|
+
} else {
|
|
4840
|
+
child.text?.paragraphs.forEach(visitBlock);
|
|
4841
|
+
}
|
|
4842
|
+
}
|
|
3952
4843
|
return;
|
|
3953
4844
|
}
|
|
3954
4845
|
if (inline.kind === "hyperlink" || inline.kind === "revision") {
|
|
@@ -3979,7 +4870,7 @@ function collectImagePlacements(ir) {
|
|
|
3979
4870
|
for (const note of [...ir.footnotes, ...ir.endnotes]) {
|
|
3980
4871
|
note.children.forEach(visitBlock);
|
|
3981
4872
|
}
|
|
3982
|
-
return placements;
|
|
4873
|
+
return { placements, drawingGroups };
|
|
3983
4874
|
}
|
|
3984
4875
|
function sectionOptions(section2, resources, closesDocument = false) {
|
|
3985
4876
|
const { page, columns } = section2.properties;
|
|
@@ -4092,17 +4983,26 @@ function coreProperties(ir) {
|
|
|
4092
4983
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
4093
4984
|
};
|
|
4094
4985
|
}
|
|
4095
|
-
var DOCXJS_RENDERER_ID, DOCXJS_CAPABILITIES;
|
|
4986
|
+
var DOCXJS_RENDERER_ID, shapes, DOCXJS_CAPABILITIES;
|
|
4096
4987
|
var init_docxjs = __esm({
|
|
4097
4988
|
"src/renderers/docxjs/index.ts"() {
|
|
4098
4989
|
"use strict";
|
|
4099
4990
|
init_styles2();
|
|
4991
|
+
init_charts();
|
|
4100
4992
|
init_imageUtils();
|
|
4101
4993
|
init_packageDocument();
|
|
4102
4994
|
init_fixFloatingImageIds();
|
|
4103
4995
|
init_emit();
|
|
4996
|
+
init_docxSubpath();
|
|
4997
|
+
init_drawingGroup();
|
|
4998
|
+
init_drawingGroupRepair();
|
|
4104
4999
|
init_units();
|
|
4105
5000
|
DOCXJS_RENDERER_ID = "docxjs";
|
|
5001
|
+
shapes = docxSubpath(
|
|
5002
|
+
"docx/shapes",
|
|
5003
|
+
"visual",
|
|
5004
|
+
() => import("docx/shapes")
|
|
5005
|
+
);
|
|
4106
5006
|
DOCXJS_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
4107
5007
|
"paragraphs",
|
|
4108
5008
|
"styles",
|
|
@@ -4115,8 +5015,10 @@ var init_docxjs = __esm({
|
|
|
4115
5015
|
"images",
|
|
4116
5016
|
"floating-images",
|
|
4117
5017
|
"svg-images",
|
|
5018
|
+
"charts",
|
|
4118
5019
|
"text-frames",
|
|
4119
5020
|
"text-boxes",
|
|
5021
|
+
"drawing-groups",
|
|
4120
5022
|
"toc",
|
|
4121
5023
|
"cached-toc",
|
|
4122
5024
|
"fields",
|
|
@@ -4137,183 +5039,331 @@ var init_docxjs = __esm({
|
|
|
4137
5039
|
}
|
|
4138
5040
|
});
|
|
4139
5041
|
|
|
4140
|
-
// src/
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
zip.addFile(name, Buffer.from(content, "utf8"));
|
|
5042
|
+
// src/renderers/office-open/chartLook.ts
|
|
5043
|
+
function seriesLook(chartType) {
|
|
5044
|
+
switch (chartType) {
|
|
5045
|
+
case "line":
|
|
5046
|
+
case "scatter":
|
|
5047
|
+
return { marker: MARKER, smooth: false };
|
|
5048
|
+
case "radar":
|
|
5049
|
+
return { marker: MARKER };
|
|
5050
|
+
case "column":
|
|
5051
|
+
case "bar":
|
|
5052
|
+
return { invertIfNegative: false };
|
|
5053
|
+
default:
|
|
5054
|
+
return {};
|
|
4154
5055
|
}
|
|
4155
|
-
|
|
4156
|
-
|
|
5056
|
+
}
|
|
5057
|
+
function axesLook(chartType) {
|
|
5058
|
+
switch (chartType) {
|
|
5059
|
+
case "column":
|
|
5060
|
+
case "bar":
|
|
5061
|
+
case "line":
|
|
5062
|
+
case "area": {
|
|
5063
|
+
const horizontal = chartType === "bar";
|
|
5064
|
+
return {
|
|
5065
|
+
categoryAxis: {
|
|
5066
|
+
position: horizontal ? "l" : "b",
|
|
5067
|
+
...NO_TICKS,
|
|
5068
|
+
line: AXIS_LINE
|
|
5069
|
+
},
|
|
5070
|
+
valueAxis: {
|
|
5071
|
+
position: horizontal ? "b" : "l",
|
|
5072
|
+
gridLine: GRIDLINES,
|
|
5073
|
+
...NO_TICKS,
|
|
5074
|
+
lineVisible: false,
|
|
5075
|
+
crossBetween: chartType === "area" ? "midCat" : "between"
|
|
5076
|
+
}
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
5079
|
+
case "radar":
|
|
5080
|
+
return {
|
|
5081
|
+
categoryAxis: {
|
|
5082
|
+
position: "b",
|
|
5083
|
+
gridLine: GRIDLINES,
|
|
5084
|
+
...NO_TICKS,
|
|
5085
|
+
majorTickMark: "cross",
|
|
5086
|
+
line: AXIS_LINE
|
|
5087
|
+
},
|
|
5088
|
+
valueAxis: {
|
|
5089
|
+
position: "l",
|
|
5090
|
+
gridLine: GRIDLINES,
|
|
5091
|
+
...NO_TICKS,
|
|
5092
|
+
majorTickMark: "cross",
|
|
5093
|
+
line: AXIS_LINE,
|
|
5094
|
+
crossBetween: "between"
|
|
5095
|
+
}
|
|
5096
|
+
};
|
|
5097
|
+
case "scatter": {
|
|
5098
|
+
const line = { ...AXIS_LINE, color: SCATTER_AXIS_TINT };
|
|
5099
|
+
return {
|
|
5100
|
+
categoryAxis: {
|
|
5101
|
+
position: "b",
|
|
5102
|
+
...NO_TICKS,
|
|
5103
|
+
line,
|
|
5104
|
+
crossBetween: "midCat"
|
|
5105
|
+
},
|
|
5106
|
+
valueAxis: {
|
|
5107
|
+
position: "l",
|
|
5108
|
+
gridLine: GRIDLINES,
|
|
5109
|
+
...NO_TICKS,
|
|
5110
|
+
line,
|
|
5111
|
+
crossBetween: "midCat"
|
|
5112
|
+
}
|
|
5113
|
+
};
|
|
5114
|
+
}
|
|
5115
|
+
default:
|
|
5116
|
+
return {};
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
function plotLook(chart) {
|
|
5120
|
+
const common = {
|
|
5121
|
+
...axesLook(chart.chartType),
|
|
5122
|
+
autoTitleDeleted: !(chart.title && chart.showTitle !== false),
|
|
5123
|
+
plotAreaUnfilled: true
|
|
5124
|
+
};
|
|
5125
|
+
switch (chart.chartType) {
|
|
5126
|
+
case "column":
|
|
5127
|
+
return { ...common, dataBorder: "none", gapWidth: 219, overlap: -27 };
|
|
5128
|
+
case "bar":
|
|
5129
|
+
return { ...common, dataBorder: "none", gapWidth: 182, overlap: 0 };
|
|
5130
|
+
case "area":
|
|
5131
|
+
return { ...common, dataBorder: "none" };
|
|
5132
|
+
case "line":
|
|
5133
|
+
return { ...common, ...LINE_SERIES, lineMarkers: true };
|
|
5134
|
+
case "radar":
|
|
5135
|
+
return { ...common, ...LINE_SERIES, radarStyle: "marker" };
|
|
5136
|
+
case "scatter": {
|
|
5137
|
+
const labels = chart.series[0]?.labels ?? [];
|
|
5138
|
+
return {
|
|
5139
|
+
...common,
|
|
5140
|
+
...LINE_SERIES,
|
|
5141
|
+
lineWidthPoints: 1.5,
|
|
5142
|
+
scatterStyle: "lineMarker",
|
|
5143
|
+
scatterXValues: labels.map((_, index) => scatterX(labels, index))
|
|
5144
|
+
};
|
|
5145
|
+
}
|
|
5146
|
+
case "pie":
|
|
5147
|
+
case "doughnut":
|
|
5148
|
+
return {
|
|
5149
|
+
...common,
|
|
5150
|
+
dataBorder: { widthPoints: 1.5, color: { scheme: "lt1" } },
|
|
5151
|
+
firstSliceAngle: 0,
|
|
5152
|
+
...chart.chartType === "doughnut" ? { holeSize: 50 } : {}
|
|
5153
|
+
};
|
|
5154
|
+
default:
|
|
5155
|
+
return common;
|
|
4157
5156
|
}
|
|
4158
|
-
return new Uint8Array(zip.toBuffer());
|
|
4159
5157
|
}
|
|
4160
|
-
var
|
|
4161
|
-
var
|
|
4162
|
-
"src/
|
|
5158
|
+
var TEXT_1_TINT, SCATTER_AXIS_TINT, HAIRLINE_POINTS, GRIDLINES, AXIS_LINE, NO_TICKS, LINE_SERIES, MARKER;
|
|
5159
|
+
var init_chartLook = __esm({
|
|
5160
|
+
"src/renderers/office-open/chartLook.ts"() {
|
|
4163
5161
|
"use strict";
|
|
4164
|
-
|
|
4165
|
-
|
|
5162
|
+
init_chartValues();
|
|
5163
|
+
TEXT_1_TINT = { scheme: "tx1", lumMod: 15e3, lumOff: 85e3 };
|
|
5164
|
+
SCATTER_AXIS_TINT = {
|
|
5165
|
+
scheme: "tx1",
|
|
5166
|
+
lumMod: 25e3,
|
|
5167
|
+
lumOff: 75e3
|
|
5168
|
+
};
|
|
5169
|
+
HAIRLINE_POINTS = 0.75;
|
|
5170
|
+
GRIDLINES = {
|
|
5171
|
+
size: HAIRLINE_POINTS,
|
|
5172
|
+
color: TEXT_1_TINT
|
|
5173
|
+
};
|
|
5174
|
+
AXIS_LINE = {
|
|
5175
|
+
widthPoints: HAIRLINE_POINTS,
|
|
5176
|
+
color: TEXT_1_TINT
|
|
5177
|
+
};
|
|
5178
|
+
NO_TICKS = {
|
|
5179
|
+
majorTickMark: "none",
|
|
5180
|
+
minorTickMark: "none",
|
|
5181
|
+
tickLabelPosition: "nextTo"
|
|
5182
|
+
};
|
|
5183
|
+
LINE_SERIES = {
|
|
5184
|
+
lineWidthPoints: 2.25,
|
|
5185
|
+
lineCap: "rnd",
|
|
5186
|
+
lineJoin: "round",
|
|
5187
|
+
markerLineWidthPoints: HAIRLINE_POINTS
|
|
5188
|
+
};
|
|
5189
|
+
MARKER = { symbol: "circle", size: 5 };
|
|
4166
5190
|
}
|
|
4167
5191
|
});
|
|
4168
5192
|
|
|
4169
5193
|
// src/renderers/office-open/chartParts.ts
|
|
4170
5194
|
import {
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
matchChartParts,
|
|
4174
|
-
spliceChartXml
|
|
5195
|
+
finishChartXml,
|
|
5196
|
+
matchChartParts
|
|
4175
5197
|
} from "@json-to-office/shared/rendering";
|
|
4176
|
-
function
|
|
4177
|
-
const
|
|
4178
|
-
const textFont =
|
|
4179
|
-
const axisTitleFont =
|
|
4180
|
-
const chartTitleFont =
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
5198
|
+
function chartInput(chart) {
|
|
5199
|
+
const roles = chartTextRoles(chart.textFont);
|
|
5200
|
+
const textFont = roles.text;
|
|
5201
|
+
const axisTitleFont = roles.axisTitle;
|
|
5202
|
+
const chartTitleFont = roles.title;
|
|
5203
|
+
const look = plotLook(chart);
|
|
5204
|
+
const categoryAxis = {
|
|
5205
|
+
...look.categoryAxis,
|
|
5206
|
+
...chart.categoryAxisTitle ? { title: chart.categoryAxisTitle, titleFont: axisTitleFont } : {}
|
|
5207
|
+
};
|
|
5208
|
+
const valueAxis = {
|
|
5209
|
+
...look.valueAxis,
|
|
5210
|
+
...chart.valueAxisTitle ? { title: chart.valueAxisTitle, titleFont: axisTitleFont } : {}
|
|
4184
5211
|
};
|
|
4185
5212
|
return {
|
|
5213
|
+
...look,
|
|
4186
5214
|
chartType: chart.chartType,
|
|
4187
5215
|
series: chart.series,
|
|
4188
5216
|
colors: chart.colors,
|
|
5217
|
+
...chart.title && chart.showTitle !== false ? { title: chart.title } : {},
|
|
4189
5218
|
textFont,
|
|
4190
5219
|
titleFont: chartTitleFont,
|
|
4191
5220
|
...chart.legendPosition ? { legendPosition: chart.legendPosition } : {},
|
|
4192
|
-
...
|
|
4193
|
-
|
|
4194
|
-
title: chart.categoryAxisTitle,
|
|
4195
|
-
titleFont: axisTitleFont
|
|
4196
|
-
}
|
|
4197
|
-
} : {},
|
|
4198
|
-
...chart.valueAxisTitle ? {
|
|
4199
|
-
valueAxis: { title: chart.valueAxisTitle, titleFont: axisTitleFont }
|
|
4200
|
-
} : {}
|
|
5221
|
+
...Object.keys(categoryAxis).length > 0 ? { categoryAxis } : {},
|
|
5222
|
+
...Object.keys(valueAxis).length > 0 ? { valueAxis } : {}
|
|
4201
5223
|
};
|
|
4202
5224
|
}
|
|
4203
|
-
function
|
|
4204
|
-
|
|
4205
|
-
if (!entry) return;
|
|
4206
|
-
const xml = entry.getData().toString("utf8");
|
|
4207
|
-
if (xml.includes(`Extension="xlsx"`)) return;
|
|
4208
|
-
zip.updateFile(
|
|
4209
|
-
entry,
|
|
4210
|
-
Buffer.from(
|
|
4211
|
-
xml.replace(
|
|
4212
|
-
'<Default Extension="xml"',
|
|
4213
|
-
`<Default Extension="xlsx" ContentType="${CHART_WORKBOOK_CONTENT_TYPE}"/><Default Extension="xml"`
|
|
4214
|
-
),
|
|
4215
|
-
"utf8"
|
|
4216
|
-
)
|
|
4217
|
-
);
|
|
4218
|
-
}
|
|
4219
|
-
function spliceChartParts(zip, charts) {
|
|
4220
|
-
if (charts.length === 0) return;
|
|
5225
|
+
function finishChartParts(zip, charts2) {
|
|
5226
|
+
if (charts2.length === 0) return;
|
|
4221
5227
|
const parts = zip.getEntries().map((entry) => entry.entryName).map((name) => name.match(/^word\/charts\/chart(\d+)\.xml$/)).filter((match) => match !== null).map(
|
|
4222
5228
|
(match) => [
|
|
4223
5229
|
Number(match[1]),
|
|
4224
5230
|
zip.getEntry(match[0]).getData().toString("utf8")
|
|
4225
5231
|
]
|
|
4226
5232
|
);
|
|
4227
|
-
|
|
4228
|
-
|
|
5233
|
+
const inputs = charts2.map(chartInput);
|
|
5234
|
+
for (const { ordinal, xml, chart } of matchChartParts(parts, inputs)) {
|
|
5235
|
+
const finished = finishChartXml(xml, chart);
|
|
5236
|
+
if (finished === xml) continue;
|
|
4229
5237
|
zip.updateFile(
|
|
4230
5238
|
zip.getEntry(`word/charts/chart${ordinal}.xml`),
|
|
4231
|
-
Buffer.from(
|
|
4232
|
-
);
|
|
4233
|
-
zip.addFile(
|
|
4234
|
-
`word/embeddings/${workbookName}`,
|
|
4235
|
-
Buffer.from(buildChartWorkbook(chart.series))
|
|
4236
|
-
);
|
|
4237
|
-
zip.addFile(
|
|
4238
|
-
`word/charts/_rels/chart${ordinal}.xml.rels`,
|
|
4239
|
-
Buffer.from(chartWorkbookRelsXml(workbookName), "utf8")
|
|
5239
|
+
Buffer.from(finished, "utf8")
|
|
4240
5240
|
);
|
|
4241
5241
|
}
|
|
4242
|
-
declareWorkbookContentType(zip);
|
|
4243
5242
|
}
|
|
4244
|
-
var CHART_TITLE_SCALE;
|
|
4245
5243
|
var init_chartParts = __esm({
|
|
4246
5244
|
"src/renderers/office-open/chartParts.ts"() {
|
|
4247
5245
|
"use strict";
|
|
4248
|
-
|
|
4249
|
-
|
|
5246
|
+
init_chartText();
|
|
5247
|
+
init_chartLook();
|
|
4250
5248
|
}
|
|
4251
5249
|
});
|
|
4252
5250
|
|
|
4253
|
-
// src/renderers/office-open/
|
|
4254
|
-
function
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
for (const entry of zip.getEntries()) {
|
|
4258
|
-
if (!TABLE_PARTS.test(entry.entryName)) continue;
|
|
4259
|
-
const original = entry.getData().toString("utf8");
|
|
4260
|
-
let xml = original;
|
|
4261
|
-
for (const toc of tocs) {
|
|
4262
|
-
const start = markerParagraph(xml, toc.start);
|
|
4263
|
-
if (!start) continue;
|
|
4264
|
-
const end = markerParagraph(xml, toc.end);
|
|
4265
|
-
if (spliced.has(toc) || !end || end.from < start.to) {
|
|
4266
|
-
throw new Error(
|
|
4267
|
-
`the office-open renderer lost track of a table of contents in a table cell (${entry.entryName})`
|
|
4268
|
-
);
|
|
4269
|
-
}
|
|
4270
|
-
xml = xml.slice(0, start.from) + stringifyTableOfContents(
|
|
4271
|
-
toc.alias,
|
|
4272
|
-
toc.options,
|
|
4273
|
-
xml.slice(start.to, end.from)
|
|
4274
|
-
) + xml.slice(end.to);
|
|
4275
|
-
spliced.add(toc);
|
|
4276
|
-
}
|
|
4277
|
-
if (xml !== original) zip.updateFile(entry, Buffer.from(xml, "utf8"));
|
|
4278
|
-
}
|
|
4279
|
-
if (spliced.size !== tocs.length) {
|
|
5251
|
+
// src/renderers/office-open/themePart.ts
|
|
5252
|
+
function replaceOnce(xml, pattern, replacer, what) {
|
|
5253
|
+
const count = [...xml.matchAll(pattern)].length;
|
|
5254
|
+
if (count !== 1) {
|
|
4280
5255
|
throw new Error(
|
|
4281
|
-
`
|
|
5256
|
+
`office-open's theme part has ${count} ${what}, expected one`
|
|
4282
5257
|
);
|
|
4283
5258
|
}
|
|
5259
|
+
return xml.replace(pattern, replacer);
|
|
5260
|
+
}
|
|
5261
|
+
function spliceTheme(zip, theme) {
|
|
5262
|
+
const entry = zip.getEntry(THEME_PART);
|
|
5263
|
+
if (!entry) throw new Error(`office-open wrote no ${THEME_PART}`);
|
|
5264
|
+
let xml = entry.getData().toString("utf8");
|
|
5265
|
+
const name = esc(theme.name);
|
|
5266
|
+
xml = renamed(xml, "theme", name);
|
|
5267
|
+
const colors = Object.entries(theme.colors);
|
|
5268
|
+
if (colors.some(([, color]) => color)) {
|
|
5269
|
+
xml = renamed(xml, "clrScheme", name);
|
|
5270
|
+
for (const [slot, color] of colors) {
|
|
5271
|
+
if (!color) continue;
|
|
5272
|
+
const element = SCHEME_ELEMENT[slot];
|
|
5273
|
+
xml = replaceOnce(
|
|
5274
|
+
xml,
|
|
5275
|
+
new RegExp(`<a:${element}>[\\s\\S]*?</a:${element}>`, "g"),
|
|
5276
|
+
() => `<a:${element}><a:srgbClr val="${color.hex}"/></a:${element}>`,
|
|
5277
|
+
`a:${element}`
|
|
5278
|
+
);
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
if (theme.headingFont || theme.bodyFont) {
|
|
5282
|
+
xml = renamed(xml, "fontScheme", name);
|
|
5283
|
+
for (const [collection, key, officeFace] of OFFICE_FACES) {
|
|
5284
|
+
const family = theme[key];
|
|
5285
|
+
if (family === void 0 || family === officeFace) continue;
|
|
5286
|
+
xml = replaceOnce(
|
|
5287
|
+
xml,
|
|
5288
|
+
new RegExp(`(<a:${collection}>)<a:latin\\b[^>]*/>`, "g"),
|
|
5289
|
+
(_match, open) => `${open}<a:latin typeface="${esc(family)}"/>`,
|
|
5290
|
+
`a:${collection} a:latin`
|
|
5291
|
+
);
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
zip.updateFile(THEME_PART, Buffer.from(xml, "utf8"));
|
|
4284
5295
|
}
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
xml
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
5296
|
+
var THEME_PART, SCHEME_ELEMENT, OFFICE_FACES, esc, renamed;
|
|
5297
|
+
var init_themePart = __esm({
|
|
5298
|
+
"src/renderers/office-open/themePart.ts"() {
|
|
5299
|
+
"use strict";
|
|
5300
|
+
THEME_PART = "word/theme/theme1.xml";
|
|
5301
|
+
SCHEME_ELEMENT = {
|
|
5302
|
+
dark1: "dk1",
|
|
5303
|
+
light1: "lt1",
|
|
5304
|
+
dark2: "dk2",
|
|
5305
|
+
light2: "lt2",
|
|
5306
|
+
accent1: "accent1",
|
|
5307
|
+
accent2: "accent2",
|
|
5308
|
+
accent3: "accent3",
|
|
5309
|
+
accent4: "accent4",
|
|
5310
|
+
accent5: "accent5",
|
|
5311
|
+
accent6: "accent6",
|
|
5312
|
+
hyperlink: "hlink",
|
|
5313
|
+
followedHyperlink: "folHlink"
|
|
5314
|
+
};
|
|
5315
|
+
OFFICE_FACES = [
|
|
5316
|
+
["majorFont", "headingFont", "Calibri Light"],
|
|
5317
|
+
["minorFont", "bodyFont", "Calibri"]
|
|
5318
|
+
];
|
|
5319
|
+
esc = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
5320
|
+
renamed = (xml, element, name) => replaceOnce(
|
|
5321
|
+
xml,
|
|
5322
|
+
new RegExp(`(<a:${element}\\b[^>]*?\\bname=")[^"]*(")`, "g"),
|
|
5323
|
+
(_match, open, close) => `${open}${name}${close}`,
|
|
5324
|
+
`a:${element} name`
|
|
4296
5325
|
);
|
|
4297
5326
|
}
|
|
4298
|
-
|
|
5327
|
+
});
|
|
5328
|
+
|
|
5329
|
+
// src/utils/chartWorkbook.ts
|
|
5330
|
+
import AdmZip4 from "adm-zip";
|
|
5331
|
+
import { chartWorkbookParts } from "@json-to-office/shared/rendering";
|
|
5332
|
+
import {
|
|
5333
|
+
CHART_WORKBOOK_SHEET_NAME,
|
|
5334
|
+
categoryReference,
|
|
5335
|
+
columnLetter,
|
|
5336
|
+
seriesNameReference,
|
|
5337
|
+
seriesValueReference
|
|
5338
|
+
} from "@json-to-office/shared/rendering";
|
|
5339
|
+
function buildChartWorkbook(series, options = {}) {
|
|
5340
|
+
const zip = new AdmZip4();
|
|
5341
|
+
for (const [name, content] of chartWorkbookParts(series, options)) {
|
|
5342
|
+
zip.addFile(name, Buffer.from(content, "utf8"));
|
|
5343
|
+
}
|
|
5344
|
+
for (const entry of zip.getEntries()) {
|
|
5345
|
+
entry.header.timeval = WORKBOOK_TIMESTAMP;
|
|
5346
|
+
}
|
|
5347
|
+
return new Uint8Array(zip.toBuffer());
|
|
4299
5348
|
}
|
|
4300
|
-
var
|
|
4301
|
-
var
|
|
4302
|
-
"src/
|
|
5349
|
+
var WORKBOOK_TIMESTAMP;
|
|
5350
|
+
var init_chartWorkbook = __esm({
|
|
5351
|
+
"src/utils/chartWorkbook.ts"() {
|
|
4303
5352
|
"use strict";
|
|
4304
|
-
|
|
5353
|
+
init_packageDocument();
|
|
5354
|
+
WORKBOOK_TIMESTAMP = toDosTime(DEFAULT_GENERATION_DATE);
|
|
4305
5355
|
}
|
|
4306
5356
|
});
|
|
4307
5357
|
|
|
4308
5358
|
// src/renderers/office-open/emit.ts
|
|
4309
|
-
import { assertNever as
|
|
5359
|
+
import { assertNever as assertNever3 } from "@json-to-office/shared/rendering";
|
|
5360
|
+
import { chartLook, withSeriesLook } from "@json-to-office/shared/rendering";
|
|
4310
5361
|
function emptyContext() {
|
|
4311
5362
|
let next = 1;
|
|
4312
5363
|
return {
|
|
4313
5364
|
pictures: /* @__PURE__ */ new Map(),
|
|
4314
5365
|
nextDrawingId: () => next++,
|
|
4315
|
-
charts: []
|
|
4316
|
-
cellTocs: []
|
|
5366
|
+
charts: []
|
|
4317
5367
|
};
|
|
4318
5368
|
}
|
|
4319
5369
|
function simpleField(instruction, cachedText) {
|
|
@@ -4354,18 +5404,19 @@ function runProperties2(formatting) {
|
|
|
4354
5404
|
if (formatting.doubleStrike !== void 0) {
|
|
4355
5405
|
out.doubleStrike = formatting.doubleStrike;
|
|
4356
5406
|
}
|
|
4357
|
-
if (formatting.superScript) out.
|
|
4358
|
-
if (formatting.subScript) out.
|
|
5407
|
+
if (formatting.superScript) out.verticalAlign = "superscript";
|
|
5408
|
+
if (formatting.subScript) out.verticalAlign = "subscript";
|
|
4359
5409
|
if (formatting.smallCaps !== void 0) out.smallCaps = formatting.smallCaps;
|
|
4360
5410
|
if (formatting.allCaps !== void 0) out.allCaps = formatting.allCaps;
|
|
4361
|
-
if (formatting.highlight !== void 0)
|
|
5411
|
+
if (formatting.highlight !== void 0) {
|
|
5412
|
+
out.highlight = formatting.highlight;
|
|
5413
|
+
}
|
|
4362
5414
|
if (formatting.shading) out.shading = shading(formatting.shading);
|
|
4363
5415
|
if (formatting.scalePercent !== void 0)
|
|
4364
5416
|
out.scale = formatting.scalePercent;
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
out.characterSpacing = twentieths === 0 && stated !== 0 ? "0pt" : twentieths;
|
|
5417
|
+
const stated = formatting.characterSpacingTwentieths;
|
|
5418
|
+
if (stated !== void 0 && stated !== 0) {
|
|
5419
|
+
out.characterSpacing = twips(stated);
|
|
4369
5420
|
}
|
|
4370
5421
|
if (formatting.language) out.language = { value: formatting.language };
|
|
4371
5422
|
if (formatting.noProof !== void 0) out.noProof = formatting.noProof;
|
|
@@ -4395,7 +5446,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4395
5446
|
switch (child.kind) {
|
|
4396
5447
|
case "lineBreak":
|
|
4397
5448
|
pendingBreaks += 1;
|
|
4398
|
-
if (child.clear && child.clear !== "none")
|
|
5449
|
+
if (child.clear && child.clear !== "none") {
|
|
5450
|
+
pendingClear = child.clear;
|
|
5451
|
+
}
|
|
4399
5452
|
break;
|
|
4400
5453
|
case "text":
|
|
4401
5454
|
out.push({
|
|
@@ -4433,7 +5486,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4433
5486
|
case "drawingGroup": {
|
|
4434
5487
|
const pending = breakOption();
|
|
4435
5488
|
if (pending.break) out.push(pending);
|
|
4436
|
-
out.push({ wpgGroup:
|
|
5489
|
+
out.push({ wpgGroup: drawingGroupOptions2(child, ctx) });
|
|
4437
5490
|
break;
|
|
4438
5491
|
}
|
|
4439
5492
|
case "hyperlink":
|
|
@@ -4463,8 +5516,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4463
5516
|
out.push({ wpsShape: shapeOptions(child, ctx) });
|
|
4464
5517
|
break;
|
|
4465
5518
|
case "chart":
|
|
4466
|
-
|
|
4467
|
-
|
|
5519
|
+
out.push({
|
|
5520
|
+
chart: chartOptions(child, ctx, ctx.charts?.push(child) ?? 1)
|
|
5521
|
+
});
|
|
4468
5522
|
break;
|
|
4469
5523
|
case "noteReference":
|
|
4470
5524
|
out.push(
|
|
@@ -4472,7 +5526,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4472
5526
|
);
|
|
4473
5527
|
break;
|
|
4474
5528
|
default:
|
|
4475
|
-
|
|
5529
|
+
assertNever3(child, "DocxIrInline");
|
|
4476
5530
|
}
|
|
4477
5531
|
}
|
|
4478
5532
|
return out;
|
|
@@ -4513,8 +5567,11 @@ function floatingOptions2(floating) {
|
|
|
4513
5567
|
...floating.vertical ? { verticalPosition: position(floating.vertical) } : {},
|
|
4514
5568
|
...floating.wrap ? {
|
|
4515
5569
|
wrap: {
|
|
4516
|
-
|
|
4517
|
-
|
|
5570
|
+
// Named, as OOXML names them; 0.11 took docx.js's numbers.
|
|
5571
|
+
type: floating.wrap.type,
|
|
5572
|
+
...floating.wrap.side ? {
|
|
5573
|
+
side: floating.wrap.side
|
|
5574
|
+
} : {}
|
|
4518
5575
|
}
|
|
4519
5576
|
} : {},
|
|
4520
5577
|
...floating.margins ? {
|
|
@@ -4541,66 +5598,92 @@ function imageMedia(ctx, resourceId, placement) {
|
|
|
4541
5598
|
}
|
|
4542
5599
|
function pictureOptions(image, ctx) {
|
|
4543
5600
|
const media = imageMedia(ctx, image.resourceId, image);
|
|
4544
|
-
|
|
4545
|
-
type:
|
|
5601
|
+
const source = media.type === "svg" ? {
|
|
5602
|
+
type: "svg",
|
|
4546
5603
|
data: media.data,
|
|
4547
|
-
//
|
|
4548
|
-
//
|
|
4549
|
-
|
|
5604
|
+
// The SVG slot always carries a raster: `prepareImages` falls back
|
|
5605
|
+
// to the vector bytes when none could be made.
|
|
5606
|
+
fallback: media.fallback ?? {
|
|
5607
|
+
type: "png",
|
|
5608
|
+
data: media.data
|
|
5609
|
+
}
|
|
5610
|
+
} : { type: media.type, data: media.data };
|
|
5611
|
+
return {
|
|
5612
|
+
...source,
|
|
4550
5613
|
// Raw numbers are EMUs in @office-open/docx. Passing pixels here makes a
|
|
4551
5614
|
// normal image only a few hundred EMUs wide, effectively a dot.
|
|
4552
5615
|
transformation: { width: image.widthEmu, height: image.heightEmu },
|
|
4553
5616
|
// The id is stated rather than left to the backend's process-global
|
|
4554
|
-
// counter. `name` stays empty, which is what
|
|
4555
|
-
|
|
4556
|
-
altText: { id: String(ctx.nextDrawingId()) },
|
|
5617
|
+
// counter. `name` stays empty, which is what the backend falls back to.
|
|
5618
|
+
altText: { id: String(ctx.nextDrawingId()), name: "" },
|
|
4557
5619
|
...image.floating ? { floating: floatingOptions2(image.floating) } : {}
|
|
4558
5620
|
// No `description` or `title`: no DOCX this pipeline has produced carries
|
|
4559
5621
|
// `wp:docPr` alt text, and the compiler warns so the gap is visible rather
|
|
4560
5622
|
// than silent.
|
|
4561
5623
|
};
|
|
4562
5624
|
}
|
|
4563
|
-
function
|
|
5625
|
+
function drawingGroupOptions2(group, ctx) {
|
|
4564
5626
|
const id = ctx.nextDrawingId();
|
|
4565
5627
|
return {
|
|
4566
5628
|
altText: {
|
|
4567
5629
|
id: String(id),
|
|
5630
|
+
name: "",
|
|
4568
5631
|
...group.altText ? { description: group.altText } : {}
|
|
4569
5632
|
},
|
|
4570
5633
|
transformation: { width: group.widthEmu, height: group.heightEmu },
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
5634
|
+
childOffsetX: 0,
|
|
5635
|
+
childOffsetY: 0,
|
|
5636
|
+
childExtentWidth: group.canvasWidthEmu,
|
|
5637
|
+
childExtentHeight: group.canvasHeightEmu,
|
|
5638
|
+
children: group.children.map((child) => groupChild2(child, ctx)),
|
|
4574
5639
|
...group.floating ? { floating: floatingOptions2(group.floating) } : {}
|
|
4575
5640
|
};
|
|
4576
5641
|
}
|
|
4577
|
-
function chartOptions(chart, ctx) {
|
|
5642
|
+
function chartOptions(chart, ctx, ordinal) {
|
|
4578
5643
|
const id = ctx.nextDrawingId();
|
|
5644
|
+
const input = chartInput(chart);
|
|
5645
|
+
const look = chartLook(input);
|
|
4579
5646
|
return {
|
|
4580
5647
|
type: chart.chartType,
|
|
4581
5648
|
categories: chart.series[0]?.labels ?? [],
|
|
4582
|
-
series: chart.series.map(
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
5649
|
+
series: chart.series.map(
|
|
5650
|
+
(entry, index) => withSeriesLook(
|
|
5651
|
+
{
|
|
5652
|
+
name: entry.name ?? `Series ${index + 1}`,
|
|
5653
|
+
values: entry.values,
|
|
5654
|
+
...seriesLook(chart.chartType)
|
|
5655
|
+
},
|
|
5656
|
+
look.series[index]
|
|
5657
|
+
)
|
|
5658
|
+
),
|
|
5659
|
+
...look.chart,
|
|
4587
5660
|
...chart.showLegend !== void 0 ? { showLegend: chart.showLegend } : {},
|
|
5661
|
+
externalData: {
|
|
5662
|
+
...look.chart.externalData,
|
|
5663
|
+
fileName: `chart${ordinal}.xlsx`,
|
|
5664
|
+
// A scatter chart's column A holds the x values its `c:xVal` caches.
|
|
5665
|
+
data: buildChartWorkbook(
|
|
5666
|
+
chart.series,
|
|
5667
|
+
input.scatterXValues ? { categoryValues: input.scatterXValues } : {}
|
|
5668
|
+
)
|
|
5669
|
+
},
|
|
4588
5670
|
transformation: { width: chart.widthEmu, height: chart.heightEmu },
|
|
4589
5671
|
altText: {
|
|
4590
5672
|
id: String(id),
|
|
5673
|
+
name: "",
|
|
4591
5674
|
...chart.altText ? { description: chart.altText } : {}
|
|
4592
5675
|
},
|
|
4593
5676
|
...chart.floating ? { floating: floatingOptions2(chart.floating) } : {}
|
|
4594
5677
|
};
|
|
4595
5678
|
}
|
|
4596
|
-
function
|
|
5679
|
+
function groupChild2(child, ctx) {
|
|
4597
5680
|
return child.kind === "shape" ? groupShape(child, ctx) : groupPicture(child, ctx);
|
|
4598
5681
|
}
|
|
4599
5682
|
function groupShape(shape, ctx) {
|
|
4600
5683
|
const id = ctx.nextDrawingId();
|
|
4601
5684
|
return {
|
|
4602
5685
|
type: "wps",
|
|
4603
|
-
transformation:
|
|
5686
|
+
transformation: childTransformation2(shape.frame),
|
|
4604
5687
|
data: {
|
|
4605
5688
|
nonVisualProperties: {
|
|
4606
5689
|
id,
|
|
@@ -4609,7 +5692,7 @@ function groupShape(shape, ctx) {
|
|
|
4609
5692
|
// to hold text, and it changes how the object behaves on selection.
|
|
4610
5693
|
...shape.isTextBox ? { textBox: "1" } : {}
|
|
4611
5694
|
},
|
|
4612
|
-
|
|
5695
|
+
geometry: shape.geometry,
|
|
4613
5696
|
...shape.fill ? { fill: drawingFill(shape.fill) } : {},
|
|
4614
5697
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
4615
5698
|
children: (shape.text?.paragraphs ?? []).map(
|
|
@@ -4635,7 +5718,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4635
5718
|
fileName: media.fallbackFileName
|
|
4636
5719
|
}
|
|
4637
5720
|
} : {},
|
|
4638
|
-
transformation:
|
|
5721
|
+
transformation: childTransformation2(picture2.frame),
|
|
4639
5722
|
nonVisualProperties: {
|
|
4640
5723
|
id,
|
|
4641
5724
|
...picture2.name ? { name: picture2.name } : {},
|
|
@@ -4644,11 +5727,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4644
5727
|
...picture2.crop ? { sourceRectangle: sourceRectangle(picture2.crop) } : {}
|
|
4645
5728
|
};
|
|
4646
5729
|
}
|
|
4647
|
-
function
|
|
4648
|
-
const flip = {
|
|
4649
|
-
...frame.flipHorizontal ? { horizontal: true } : {},
|
|
4650
|
-
...frame.flipVertical ? { vertical: true } : {}
|
|
4651
|
-
};
|
|
5730
|
+
function childTransformation2(frame) {
|
|
4652
5731
|
return {
|
|
4653
5732
|
offset: {
|
|
4654
5733
|
emus: { x: frame.xEmu, y: frame.yEmu },
|
|
@@ -4664,7 +5743,8 @@ function childTransformation(frame) {
|
|
|
4664
5743
|
},
|
|
4665
5744
|
// Degrees: the backend multiplies by 60000 on the way into `@rot`.
|
|
4666
5745
|
...frame.rotationDegrees !== void 0 ? { rotation: frame.rotationDegrees } : {},
|
|
4667
|
-
...
|
|
5746
|
+
...frame.flipHorizontal ? { flipHorizontal: true } : {},
|
|
5747
|
+
...frame.flipVertical ? { flipVertical: true } : {}
|
|
4668
5748
|
};
|
|
4669
5749
|
}
|
|
4670
5750
|
function drawingFill(fill) {
|
|
@@ -4672,7 +5752,6 @@ function drawingFill(fill) {
|
|
|
4672
5752
|
return {
|
|
4673
5753
|
type: "solid",
|
|
4674
5754
|
color: {
|
|
4675
|
-
type: "rgb",
|
|
4676
5755
|
value: fill.color.hex,
|
|
4677
5756
|
// Transparency becomes an alpha transform on the colour. DrawingML
|
|
4678
5757
|
// states *opacity*, so the value is the complement of what the author
|
|
@@ -4714,7 +5793,7 @@ function sourceRectangle(crop) {
|
|
|
4714
5793
|
function shapeOptions(shape, ctx) {
|
|
4715
5794
|
const id = String(ctx.nextDrawingId());
|
|
4716
5795
|
return {
|
|
4717
|
-
altText: { id },
|
|
5796
|
+
altText: { id, name: "" },
|
|
4718
5797
|
children: shape.children.map((child) => paragraph(child, ctx)),
|
|
4719
5798
|
// Raw transformation numbers are EMUs in @office-open/docx, while the IR
|
|
4720
5799
|
// deliberately stores native shape dimensions in pixels.
|
|
@@ -4725,7 +5804,7 @@ function shapeOptions(shape, ctx) {
|
|
|
4725
5804
|
...shape.fill ? {
|
|
4726
5805
|
fill: {
|
|
4727
5806
|
type: "solid",
|
|
4728
|
-
color: {
|
|
5807
|
+
color: { value: shape.fill.hex }
|
|
4729
5808
|
}
|
|
4730
5809
|
} : {},
|
|
4731
5810
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
@@ -4830,13 +5909,19 @@ function frameOptions2(frame) {
|
|
|
4830
5909
|
...frame.anchorLock !== void 0 ? { anchorLock: frame.anchorLock } : {},
|
|
4831
5910
|
...frame.rule ? { rule: frame.rule } : {}
|
|
4832
5911
|
};
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
5912
|
+
if (frame.xTwips !== void 0 || frame.yTwips !== void 0) {
|
|
5913
|
+
return {
|
|
5914
|
+
type: "absolute",
|
|
5915
|
+
position: { x: frame.xTwips ?? 0, y: frame.yTwips ?? 0 },
|
|
5916
|
+
...base
|
|
5917
|
+
};
|
|
5918
|
+
}
|
|
5919
|
+
return {
|
|
4838
5920
|
type: "alignment",
|
|
4839
|
-
alignment: {
|
|
5921
|
+
alignment: {
|
|
5922
|
+
x: frame.xAlign,
|
|
5923
|
+
y: frame.yAlign
|
|
5924
|
+
},
|
|
4840
5925
|
...base
|
|
4841
5926
|
};
|
|
4842
5927
|
}
|
|
@@ -4857,7 +5942,7 @@ function block(value, ctx = emptyContext()) {
|
|
|
4857
5942
|
case "toc":
|
|
4858
5943
|
return { toc: tableOfContents(value) };
|
|
4859
5944
|
default:
|
|
4860
|
-
return
|
|
5945
|
+
return assertNever3(value, "DocxIrBlock");
|
|
4861
5946
|
}
|
|
4862
5947
|
}
|
|
4863
5948
|
function tocEntry(entry) {
|
|
@@ -4876,6 +5961,7 @@ function tableOfContents(value) {
|
|
|
4876
5961
|
headingStyleRange: `${value.headingRange.from}-${value.headingRange.to}`
|
|
4877
5962
|
} : {},
|
|
4878
5963
|
...value.styleLevels?.length ? {
|
|
5964
|
+
// `StyleLevel` is a class the backend only reads the two fields of.
|
|
4879
5965
|
stylesWithLevels: value.styleLevels.map((style) => ({
|
|
4880
5966
|
styleName: style.styleName,
|
|
4881
5967
|
level: style.level
|
|
@@ -4897,14 +5983,16 @@ function table(value, ctx) {
|
|
|
4897
5983
|
// unstated columns comes out fractional, and the XML would carry it
|
|
4898
5984
|
// verbatim; floored here, as the docxjs backend floors it.
|
|
4899
5985
|
size: value.width.kind === "auto" ? 0 : value.width.kind === "twips" ? twips(value.width.value) : value.width.value,
|
|
4900
|
-
type: value.width.kind === "twips" ? "
|
|
5986
|
+
type: value.width.kind === "twips" ? "twips" : value.width.kind === "percent" ? "percent" : "auto"
|
|
4901
5987
|
},
|
|
4902
5988
|
layout: value.layout,
|
|
4903
5989
|
// An empty grid is a table with nothing to say about its columns, which is
|
|
4904
5990
|
// not the same as one whose columns are all zero wide. The compiler hands
|
|
4905
5991
|
// over every grid in twips; floored for the same reason as the width.
|
|
4906
5992
|
...value.columnGrid.values.length > 0 ? { columnWidths: value.columnGrid.values.map(twips) } : {},
|
|
4907
|
-
...value.alignment ? {
|
|
5993
|
+
...value.alignment ? {
|
|
5994
|
+
alignment: alignment(value.alignment)
|
|
5995
|
+
} : {},
|
|
4908
5996
|
...value.borders ? { borders: borders2(value.borders) } : {},
|
|
4909
5997
|
...value.cellMargins ? { margins: cellMargins(value.cellMargins) } : {},
|
|
4910
5998
|
...value.floating ? { float: tableFloat2(value.floating) } : {}
|
|
@@ -4949,52 +6037,29 @@ function tableRow(row, ctx) {
|
|
|
4949
6037
|
}
|
|
4950
6038
|
function tableCell(cell, ctx) {
|
|
4951
6039
|
const children = cellChildren2(cell, ctx);
|
|
4952
|
-
if (cell.children[cell.children.length - 1]?.kind
|
|
6040
|
+
if (cell.children[cell.children.length - 1]?.kind === "toc")
|
|
4953
6041
|
children.push({ paragraph: { children: [] } });
|
|
4954
6042
|
return {
|
|
4955
6043
|
children,
|
|
4956
|
-
...cell.widthTwips !== void 0 ? { width: { size: twips(cell.widthTwips), type: "
|
|
4957
|
-
...cell.verticalAlign ? {
|
|
6044
|
+
...cell.widthTwips !== void 0 ? { width: { size: twips(cell.widthTwips), type: "twips" } } : {},
|
|
6045
|
+
...cell.verticalAlign ? {
|
|
6046
|
+
verticalAlign: cell.verticalAlign
|
|
6047
|
+
} : {},
|
|
4958
6048
|
...cell.shading ? { shading: shading(cell.shading) } : {},
|
|
4959
6049
|
...cell.margins ? { margins: cellMargins(cell.margins) } : {},
|
|
4960
6050
|
...cell.borders ? { borders: borders2(cell.borders) } : {},
|
|
4961
6051
|
...cell.columnSpan !== void 0 ? { columnSpan: cell.columnSpan } : {},
|
|
4962
6052
|
...cell.rowSpan !== void 0 ? { verticalMerge: cell.rowSpan } : {},
|
|
4963
|
-
...cell.textDirection ? {
|
|
6053
|
+
...cell.textDirection ? {
|
|
6054
|
+
textDirection: cell.textDirection
|
|
6055
|
+
} : {}
|
|
4964
6056
|
};
|
|
4965
6057
|
}
|
|
4966
6058
|
function cellChildren2(cell, ctx) {
|
|
4967
|
-
|
|
4968
|
-
for (const child of cell.children) {
|
|
4969
|
-
if (child.kind !== "toc") {
|
|
4970
|
-
children.push(block(child, ctx));
|
|
4971
|
-
continue;
|
|
4972
|
-
}
|
|
4973
|
-
const { alias, entries, ...options } = tableOfContents(child);
|
|
4974
|
-
const index = ctx.cellTocs.length;
|
|
4975
|
-
const toc = {
|
|
4976
|
-
start: cellTocMarker(index, "start"),
|
|
4977
|
-
end: cellTocMarker(index, "end"),
|
|
4978
|
-
alias: String(alias),
|
|
4979
|
-
options
|
|
4980
|
-
};
|
|
4981
|
-
ctx.cellTocs.push(toc);
|
|
4982
|
-
children.push(
|
|
4983
|
-
markerParagraph2(toc.start),
|
|
4984
|
-
...entries ?? [],
|
|
4985
|
-
markerParagraph2(toc.end)
|
|
4986
|
-
);
|
|
4987
|
-
}
|
|
4988
|
-
return children;
|
|
4989
|
-
}
|
|
4990
|
-
function cellTocMarker(index, edge) {
|
|
4991
|
-
return `\uE000jto-cell-toc-${index}-${edge}\uE000`;
|
|
4992
|
-
}
|
|
4993
|
-
function markerParagraph2(text) {
|
|
4994
|
-
return { paragraph: { children: [{ text }] } };
|
|
6059
|
+
return cell.children.map((child) => block(child, ctx));
|
|
4995
6060
|
}
|
|
4996
6061
|
function cellMargins(margins) {
|
|
4997
|
-
const side = (value) => value === void 0 ? void 0 : { size: twips(value), type: "
|
|
6062
|
+
const side = (value) => value === void 0 ? void 0 : { size: twips(value), type: "twips" };
|
|
4998
6063
|
const out = {};
|
|
4999
6064
|
for (const [name, value] of [
|
|
5000
6065
|
["top", margins.topTwips],
|
|
@@ -5037,39 +6102,43 @@ function section(value, ctx, closesDocument = false) {
|
|
|
5037
6102
|
properties: {
|
|
5038
6103
|
...value.properties.type ? { type: value.properties.type } : {},
|
|
5039
6104
|
...value.properties.titlePage !== void 0 ? { titlePage: value.properties.titlePage } : {},
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
...page.code !== void 0 ? { code: page.code } : {}
|
|
5047
|
-
},
|
|
5048
|
-
margin: {
|
|
5049
|
-
top: twips(page.margins.topTwips),
|
|
5050
|
-
right: twips(page.margins.rightTwips),
|
|
5051
|
-
bottom: twips(page.margins.bottomTwips),
|
|
5052
|
-
left: twips(page.margins.leftTwips),
|
|
5053
|
-
...page.margins.headerTwips !== void 0 ? { header: twips(page.margins.headerTwips) } : {},
|
|
5054
|
-
...page.margins.footerTwips !== void 0 ? { footer: twips(page.margins.footerTwips) } : {},
|
|
5055
|
-
...page.margins.gutterTwips !== void 0 ? { gutter: twips(page.margins.gutterTwips) } : {}
|
|
5056
|
-
},
|
|
5057
|
-
...value.properties.pageNumbers ? {
|
|
5058
|
-
pageNumbers: {
|
|
5059
|
-
...value.properties.pageNumbers.start !== void 0 ? { start: value.properties.pageNumbers.start } : {},
|
|
5060
|
-
...value.properties.pageNumbers.formatType ? { formatType: value.properties.pageNumbers.formatType } : {}
|
|
5061
|
-
}
|
|
5062
|
-
} : {},
|
|
5063
|
-
...value.properties.borders ? {
|
|
5064
|
-
borders: {
|
|
5065
|
-
...value.properties.borders.display ? { display: value.properties.borders.display } : {},
|
|
5066
|
-
...value.properties.borders.offsetFrom ? { offsetFrom: value.properties.borders.offsetFrom } : {},
|
|
5067
|
-
...value.properties.borders.borders ? borders2(value.properties.borders.borders) : {}
|
|
5068
|
-
}
|
|
5069
|
-
} : {}
|
|
6105
|
+
// Orientation is implied by the width/height pair, which is how this
|
|
6106
|
+
// pipeline has always expressed it; stating it as well changes `w:pgSz`.
|
|
6107
|
+
pageSize: {
|
|
6108
|
+
width: twips(page.widthTwips),
|
|
6109
|
+
height: twips(page.heightTwips),
|
|
6110
|
+
...page.code !== void 0 ? { code: page.code } : {}
|
|
5070
6111
|
},
|
|
6112
|
+
pageMargin: {
|
|
6113
|
+
top: twips(page.margins.topTwips),
|
|
6114
|
+
right: twips(page.margins.rightTwips),
|
|
6115
|
+
bottom: twips(page.margins.bottomTwips),
|
|
6116
|
+
left: twips(page.margins.leftTwips),
|
|
6117
|
+
...page.margins.headerTwips !== void 0 ? { header: twips(page.margins.headerTwips) } : {},
|
|
6118
|
+
...page.margins.footerTwips !== void 0 ? { footer: twips(page.margins.footerTwips) } : {},
|
|
6119
|
+
...page.margins.gutterTwips !== void 0 ? { gutter: twips(page.margins.gutterTwips) } : {}
|
|
6120
|
+
},
|
|
6121
|
+
...value.properties.pageNumbers ? {
|
|
6122
|
+
pageNumberType: {
|
|
6123
|
+
...value.properties.pageNumbers.start !== void 0 ? { start: value.properties.pageNumbers.start } : {},
|
|
6124
|
+
...value.properties.pageNumbers.formatType ? {
|
|
6125
|
+
format: value.properties.pageNumbers.formatType
|
|
6126
|
+
} : {}
|
|
6127
|
+
}
|
|
6128
|
+
} : {},
|
|
6129
|
+
...value.properties.borders ? {
|
|
6130
|
+
pageBorders: {
|
|
6131
|
+
...value.properties.borders.display ? {
|
|
6132
|
+
display: value.properties.borders.display
|
|
6133
|
+
} : {},
|
|
6134
|
+
...value.properties.borders.offsetFrom ? {
|
|
6135
|
+
offsetFrom: value.properties.borders.offsetFrom
|
|
6136
|
+
} : {},
|
|
6137
|
+
...value.properties.borders.borders ? borders2(value.properties.borders.borders) : {}
|
|
6138
|
+
}
|
|
6139
|
+
} : {},
|
|
5071
6140
|
...columns ? {
|
|
5072
|
-
|
|
6141
|
+
columns: {
|
|
5073
6142
|
count: columns.count,
|
|
5074
6143
|
...columns.spaceTwips !== void 0 ? { space: twips(columns.spaceTwips) } : {},
|
|
5075
6144
|
...columns.separator !== void 0 ? { separate: columns.separator } : {},
|
|
@@ -5113,6 +6182,8 @@ function sectionChildren2(value, ctx, closesDocument = false) {
|
|
|
5113
6182
|
spacing: { before: 0, after: 0, line: 20, lineRule: "exact" }
|
|
5114
6183
|
}
|
|
5115
6184
|
});
|
|
6185
|
+
if (!closesDocument && !bookmark?.closes && last?.kind === "toc")
|
|
6186
|
+
blocks.push({ paragraph: { children: [] } });
|
|
5116
6187
|
if (!bookmark) return blocks;
|
|
5117
6188
|
return [
|
|
5118
6189
|
...bookmark.opens ? [{ bookmarkStart: { id: bookmark.id, name: bookmark.name } }] : [],
|
|
@@ -5123,15 +6194,19 @@ function sectionChildren2(value, ctx, closesDocument = false) {
|
|
|
5123
6194
|
function numberingConfig2(numbering) {
|
|
5124
6195
|
return {
|
|
5125
6196
|
reference: numbering.reference,
|
|
5126
|
-
levels: numbering.levels.map(
|
|
5127
|
-
level
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
6197
|
+
levels: numbering.levels.map(
|
|
6198
|
+
(level) => ({
|
|
6199
|
+
level: level.level,
|
|
6200
|
+
format: level.format,
|
|
6201
|
+
text: level.text,
|
|
6202
|
+
...level.alignment ? { alignment: alignment(level.alignment) } : {},
|
|
6203
|
+
...level.suffix ? { suffix: level.suffix } : {},
|
|
6204
|
+
// Always stated. docx.js writes `w:start w:val="1"` for a level that
|
|
6205
|
+
// names none, and so did this backend until 0.14, which writes no
|
|
6206
|
+
// `w:start` at all when it is not given one; Word and LibreOffice then
|
|
6207
|
+
// count every such list from 0.
|
|
6208
|
+
start: level.start ?? 1,
|
|
6209
|
+
...level.paragraphStyleId ? { paragraphStyle: level.paragraphStyleId } : {},
|
|
5135
6210
|
...level.indent ? {
|
|
5136
6211
|
paragraph: {
|
|
5137
6212
|
indent: {
|
|
@@ -5141,25 +6216,22 @@ function numberingConfig2(numbering) {
|
|
|
5141
6216
|
}
|
|
5142
6217
|
} : {},
|
|
5143
6218
|
...level.run ? { run: runProperties2(level.run) } : {}
|
|
5144
|
-
}
|
|
5145
|
-
|
|
6219
|
+
})
|
|
6220
|
+
)
|
|
5146
6221
|
};
|
|
5147
6222
|
}
|
|
5148
|
-
var
|
|
6223
|
+
var BODY_ANCHOR;
|
|
5149
6224
|
var init_emit2 = __esm({
|
|
5150
6225
|
"src/renderers/office-open/emit.ts"() {
|
|
5151
6226
|
"use strict";
|
|
5152
6227
|
init_units();
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
tight: 2,
|
|
5157
|
-
topAndBottom: 3
|
|
5158
|
-
};
|
|
6228
|
+
init_chartWorkbook();
|
|
6229
|
+
init_chartLook();
|
|
6230
|
+
init_chartParts();
|
|
5159
6231
|
BODY_ANCHOR = {
|
|
5160
|
-
top: "
|
|
5161
|
-
middle: "
|
|
5162
|
-
bottom: "
|
|
6232
|
+
top: "top",
|
|
6233
|
+
middle: "center",
|
|
6234
|
+
bottom: "bottom"
|
|
5163
6235
|
};
|
|
5164
6236
|
}
|
|
5165
6237
|
});
|
|
@@ -5219,37 +6291,49 @@ var init_styles3 = __esm({
|
|
|
5219
6291
|
var office_open_exports = {};
|
|
5220
6292
|
__export(office_open_exports, {
|
|
5221
6293
|
OFFICE_OPEN_DOCX_RENDERER_ID: () => OFFICE_OPEN_DOCX_RENDERER_ID,
|
|
6294
|
+
OFFICE_OPEN_VERSION: () => OFFICE_OPEN_VERSION,
|
|
5222
6295
|
buildDocumentOptions: () => buildDocumentOptions,
|
|
5223
6296
|
createOfficeOpenDocxRenderer: () => createOfficeOpenDocxRenderer
|
|
5224
6297
|
});
|
|
5225
|
-
import
|
|
6298
|
+
import AdmZip5 from "adm-zip";
|
|
6299
|
+
import {
|
|
6300
|
+
assertBackendVersion,
|
|
6301
|
+
installedPackageVersion
|
|
6302
|
+
} from "@json-to-office/shared/rendering/node";
|
|
6303
|
+
function installedBackendVersion() {
|
|
6304
|
+
let resolved;
|
|
6305
|
+
try {
|
|
6306
|
+
resolved = import.meta.resolve?.(OFFICE_OPEN_DOCX);
|
|
6307
|
+
} catch {
|
|
6308
|
+
resolved = void 0;
|
|
6309
|
+
}
|
|
6310
|
+
return installedPackageVersion(OFFICE_OPEN_DOCX, import.meta.url, resolved);
|
|
6311
|
+
}
|
|
5226
6312
|
async function createOfficeOpenDocxRenderer() {
|
|
5227
6313
|
const backend = await import(
|
|
5228
6314
|
/* @vite-ignore */
|
|
5229
6315
|
OFFICE_OPEN_DOCX
|
|
5230
6316
|
);
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
);
|
|
5239
|
-
|
|
6317
|
+
assertBackendVersion(
|
|
6318
|
+
OFFICE_OPEN_DOCX,
|
|
6319
|
+
OFFICE_OPEN_VERSION,
|
|
6320
|
+
installedBackendVersion()
|
|
6321
|
+
);
|
|
6322
|
+
if (typeof backend.generateDocument !== "function") {
|
|
6323
|
+
throw new Error(
|
|
6324
|
+
`${OFFICE_OPEN_DOCX} does not export generateDocument(); the installed version is not compatible with this adapter.`
|
|
6325
|
+
);
|
|
5240
6326
|
}
|
|
5241
6327
|
return {
|
|
5242
6328
|
id: OFFICE_OPEN_DOCX_RENDERER_ID,
|
|
5243
6329
|
format: "docx",
|
|
5244
6330
|
capabilities: OFFICE_OPEN_CAPABILITIES,
|
|
5245
6331
|
async render(ir, options) {
|
|
5246
|
-
const
|
|
5247
|
-
const cellTocs = [];
|
|
6332
|
+
const charts2 = [];
|
|
5248
6333
|
const document = await buildDocumentOptions(
|
|
5249
6334
|
ir,
|
|
5250
|
-
|
|
5251
|
-
options?.svgRasterFallback
|
|
5252
|
-
cellTocs
|
|
6335
|
+
charts2,
|
|
6336
|
+
options?.svgRasterFallback
|
|
5253
6337
|
);
|
|
5254
6338
|
const bytes = await backend.generateDocument(document, {
|
|
5255
6339
|
type: "uint8array"
|
|
@@ -5257,10 +6341,10 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5257
6341
|
let raw = Buffer.from(
|
|
5258
6342
|
bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)
|
|
5259
6343
|
);
|
|
5260
|
-
if (
|
|
5261
|
-
const zip = new
|
|
5262
|
-
|
|
5263
|
-
|
|
6344
|
+
if (ir.theme || charts2.length > 0) {
|
|
6345
|
+
const zip = new AdmZip5(raw);
|
|
6346
|
+
if (ir.theme) spliceTheme(zip, ir.theme);
|
|
6347
|
+
finishChartParts(zip, charts2);
|
|
5264
6348
|
raw = zip.toBuffer();
|
|
5265
6349
|
}
|
|
5266
6350
|
if (options?.deterministic === false)
|
|
@@ -5277,13 +6361,12 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5277
6361
|
}
|
|
5278
6362
|
};
|
|
5279
6363
|
}
|
|
5280
|
-
async function buildDocumentOptions(ir,
|
|
6364
|
+
async function buildDocumentOptions(ir, charts2 = [], svgRasterFallback) {
|
|
5281
6365
|
let nextDrawingId = 1;
|
|
5282
6366
|
const ctx = {
|
|
5283
6367
|
pictures: await prepareImages2(ir, svgRasterFallback),
|
|
5284
6368
|
nextDrawingId: () => nextDrawingId++,
|
|
5285
|
-
charts
|
|
5286
|
-
cellTocs
|
|
6369
|
+
charts: charts2
|
|
5287
6370
|
};
|
|
5288
6371
|
return {
|
|
5289
6372
|
styles: emitStyles2(ir.styles),
|
|
@@ -5291,16 +6374,20 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback, cellTocs
|
|
|
5291
6374
|
(value, index) => section(value, ctx, index === ir.sections.length - 1)
|
|
5292
6375
|
),
|
|
5293
6376
|
...coreProperties2(ir),
|
|
5294
|
-
|
|
6377
|
+
settings: {
|
|
5295
6378
|
updateFields: ir.settings.updateFields,
|
|
5296
6379
|
...ir.settings.trackRevisions ? { trackRevisions: true } : {}
|
|
5297
6380
|
},
|
|
5298
|
-
...ir.numbering.length > 0 ? {
|
|
6381
|
+
...ir.numbering.length > 0 ? {
|
|
6382
|
+
numbering: {
|
|
6383
|
+
abstractNumberings: ir.numbering.map(numberingConfig2)
|
|
6384
|
+
}
|
|
6385
|
+
} : {},
|
|
5299
6386
|
...ir.footnotes.length > 0 ? { footnotes: noteBodies2(ir.footnotes, ctx) } : {},
|
|
5300
6387
|
...ir.endnotes.length > 0 ? { endnotes: noteBodies2(ir.endnotes, ctx) } : {},
|
|
5301
6388
|
...ir.comments.length > 0 ? {
|
|
5302
|
-
comments:
|
|
5303
|
-
|
|
6389
|
+
comments: ir.comments.map(
|
|
6390
|
+
(comment) => ({
|
|
5304
6391
|
id: comment.id,
|
|
5305
6392
|
author: comment.author,
|
|
5306
6393
|
...comment.initials ? { initials: comment.initials } : {},
|
|
@@ -5308,29 +6395,25 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback, cellTocs
|
|
|
5308
6395
|
children: comment.children.map(
|
|
5309
6396
|
(child) => paragraphOf(child, ctx)
|
|
5310
6397
|
)
|
|
5311
|
-
})
|
|
5312
|
-
|
|
6398
|
+
})
|
|
6399
|
+
)
|
|
5313
6400
|
} : {}
|
|
5314
6401
|
};
|
|
5315
6402
|
}
|
|
5316
6403
|
function paragraphOf(value, ctx) {
|
|
5317
6404
|
const emitted = block(value, ctx);
|
|
5318
|
-
|
|
5319
|
-
if (!asParagraph) {
|
|
6405
|
+
if (!("paragraph" in emitted) || typeof emitted.paragraph === "string") {
|
|
5320
6406
|
throw new Error(
|
|
5321
6407
|
`the office-open renderer expected a paragraph, not a "${value.kind}"`
|
|
5322
6408
|
);
|
|
5323
6409
|
}
|
|
5324
|
-
return
|
|
6410
|
+
return emitted.paragraph;
|
|
5325
6411
|
}
|
|
5326
6412
|
function noteBodies2(notes, ctx) {
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
};
|
|
5332
|
-
}
|
|
5333
|
-
return bodies;
|
|
6413
|
+
return notes.map((note) => ({
|
|
6414
|
+
id: note.id,
|
|
6415
|
+
children: note.children.map((child) => paragraphOf(child, ctx))
|
|
6416
|
+
}));
|
|
5334
6417
|
}
|
|
5335
6418
|
async function prepareImages2(ir, svgRasterFallback) {
|
|
5336
6419
|
const placements = collectImagePlacements2(ir);
|
|
@@ -5353,23 +6436,16 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5353
6436
|
if (resource.kind !== "image") continue;
|
|
5354
6437
|
const type = resource.mediaType;
|
|
5355
6438
|
const data = Buffer.from(resource.bytes);
|
|
5356
|
-
const placementData = /* @__PURE__ */ new Map();
|
|
5357
|
-
[...placements.get(resource.id) ?? []].forEach((size, index) => {
|
|
5358
|
-
placementData.set(
|
|
5359
|
-
size,
|
|
5360
|
-
index === 0 ? data : distinguishImageBytes(data, type, size)
|
|
5361
|
-
);
|
|
5362
|
-
});
|
|
5363
6439
|
resources.set(resource.id, (placement) => {
|
|
5364
6440
|
const sizeKey = placementKey(placement);
|
|
5365
6441
|
const stem = `${resource.id}-${sizeKey}`;
|
|
5366
6442
|
return {
|
|
5367
6443
|
type,
|
|
5368
|
-
//
|
|
5369
|
-
//
|
|
5370
|
-
//
|
|
5371
|
-
//
|
|
5372
|
-
data
|
|
6444
|
+
// The same bytes at every size: the backend keeps each drawing's
|
|
6445
|
+
// extent on the drawing. 0.11 kept it on its deduplicated media
|
|
6446
|
+
// entry, and an image drawn at a second size took the first one's,
|
|
6447
|
+
// unless its bytes were told apart.
|
|
6448
|
+
data,
|
|
5373
6449
|
// Named after the resource and the size it is drawn at, so two
|
|
5374
6450
|
// placements of one image at one size share a single part and a third
|
|
5375
6451
|
// at another size gets its own.
|
|
@@ -5392,104 +6468,6 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5392
6468
|
function placementKey(placement) {
|
|
5393
6469
|
return `${emuToPixels(placement.widthEmu)}x${emuToPixels(placement.heightEmu)}`;
|
|
5394
6470
|
}
|
|
5395
|
-
function distinguishImageBytes(data, mediaType, placement) {
|
|
5396
|
-
const marker = Buffer.from(`json-to-office:${placement}`, "utf8");
|
|
5397
|
-
switch (mediaType) {
|
|
5398
|
-
case "png":
|
|
5399
|
-
return addPngTextChunk(data, marker);
|
|
5400
|
-
case "jpg":
|
|
5401
|
-
return addJpegComment(data, marker);
|
|
5402
|
-
case "gif":
|
|
5403
|
-
return addGifComment(data, marker);
|
|
5404
|
-
case "svg":
|
|
5405
|
-
return Buffer.concat([
|
|
5406
|
-
data,
|
|
5407
|
-
Buffer.from(`
|
|
5408
|
-
<!-- ${marker.toString("utf8")} -->`, "utf8")
|
|
5409
|
-
]);
|
|
5410
|
-
case "bmp": {
|
|
5411
|
-
const marked = Buffer.concat([data, marker]);
|
|
5412
|
-
if (marked.length >= 14 && marked.subarray(0, 2).toString("ascii") === "BM") {
|
|
5413
|
-
marked.writeUInt32LE(marked.length, 2);
|
|
5414
|
-
}
|
|
5415
|
-
return marked;
|
|
5416
|
-
}
|
|
5417
|
-
default:
|
|
5418
|
-
return Buffer.concat([data, marker]);
|
|
5419
|
-
}
|
|
5420
|
-
}
|
|
5421
|
-
function addPngTextChunk(data, marker) {
|
|
5422
|
-
const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
5423
|
-
if (data.length < 8 || !data.subarray(0, 8).equals(signature)) {
|
|
5424
|
-
return Buffer.concat([data, marker]);
|
|
5425
|
-
}
|
|
5426
|
-
let offset = 8;
|
|
5427
|
-
while (offset + 12 <= data.length) {
|
|
5428
|
-
const payloadLength = data.readUInt32BE(offset);
|
|
5429
|
-
const chunkEnd = offset + 12 + payloadLength;
|
|
5430
|
-
if (chunkEnd > data.length) break;
|
|
5431
|
-
if (data.subarray(offset + 4, offset + 8).toString("ascii") === "IEND") {
|
|
5432
|
-
const payload = Buffer.concat([
|
|
5433
|
-
Buffer.from("json-to-office\0", "latin1"),
|
|
5434
|
-
marker
|
|
5435
|
-
]);
|
|
5436
|
-
const chunk = Buffer.alloc(12 + payload.length);
|
|
5437
|
-
chunk.writeUInt32BE(payload.length, 0);
|
|
5438
|
-
chunk.write("tEXt", 4, 4, "ascii");
|
|
5439
|
-
payload.copy(chunk, 8);
|
|
5440
|
-
chunk.writeUInt32BE(
|
|
5441
|
-
crc32(chunk.subarray(4, 8 + payload.length)),
|
|
5442
|
-
8 + payload.length
|
|
5443
|
-
);
|
|
5444
|
-
return Buffer.concat([
|
|
5445
|
-
data.subarray(0, offset),
|
|
5446
|
-
chunk,
|
|
5447
|
-
data.subarray(offset)
|
|
5448
|
-
]);
|
|
5449
|
-
}
|
|
5450
|
-
offset = chunkEnd;
|
|
5451
|
-
}
|
|
5452
|
-
throw new Error(
|
|
5453
|
-
"Cannot mark a PNG that has no intact IEND chunk; its bytes were not checked to decode before rendering"
|
|
5454
|
-
);
|
|
5455
|
-
}
|
|
5456
|
-
function addJpegComment(data, marker) {
|
|
5457
|
-
if (data.length < 2 || data[0] !== 255 || data[1] !== 216) {
|
|
5458
|
-
return Buffer.concat([data, marker]);
|
|
5459
|
-
}
|
|
5460
|
-
const comment = Buffer.alloc(4 + marker.length);
|
|
5461
|
-
comment[0] = 255;
|
|
5462
|
-
comment[1] = 254;
|
|
5463
|
-
comment.writeUInt16BE(marker.length + 2, 2);
|
|
5464
|
-
marker.copy(comment, 4);
|
|
5465
|
-
return Buffer.concat([data.subarray(0, 2), comment, data.subarray(2)]);
|
|
5466
|
-
}
|
|
5467
|
-
function addGifComment(data, marker) {
|
|
5468
|
-
const trailer = data.lastIndexOf(59);
|
|
5469
|
-
if (trailer < 0 || marker.length > 255) {
|
|
5470
|
-
return Buffer.concat([data, marker]);
|
|
5471
|
-
}
|
|
5472
|
-
const comment = Buffer.concat([
|
|
5473
|
-
Buffer.from([33, 254, marker.length]),
|
|
5474
|
-
marker,
|
|
5475
|
-
Buffer.from([0])
|
|
5476
|
-
]);
|
|
5477
|
-
return Buffer.concat([
|
|
5478
|
-
data.subarray(0, trailer),
|
|
5479
|
-
comment,
|
|
5480
|
-
data.subarray(trailer)
|
|
5481
|
-
]);
|
|
5482
|
-
}
|
|
5483
|
-
function crc32(data) {
|
|
5484
|
-
let crc = 4294967295;
|
|
5485
|
-
for (const byte of data) {
|
|
5486
|
-
crc ^= byte;
|
|
5487
|
-
for (let bit = 0; bit < 8; bit += 1) {
|
|
5488
|
-
crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
5489
|
-
}
|
|
5490
|
-
}
|
|
5491
|
-
return (crc ^ 4294967295) >>> 0;
|
|
5492
|
-
}
|
|
5493
6471
|
function collectImagePlacements2(ir) {
|
|
5494
6472
|
const placements = /* @__PURE__ */ new Map();
|
|
5495
6473
|
const record = (resourceId, placement) => {
|
|
@@ -5557,18 +6535,19 @@ function coreProperties2(ir) {
|
|
|
5557
6535
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
5558
6536
|
};
|
|
5559
6537
|
}
|
|
5560
|
-
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX, OFFICE_OPEN_CAPABILITIES;
|
|
6538
|
+
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX, OFFICE_OPEN_VERSION, OFFICE_OPEN_CAPABILITIES;
|
|
5561
6539
|
var init_office_open = __esm({
|
|
5562
6540
|
"src/renderers/office-open/index.ts"() {
|
|
5563
6541
|
"use strict";
|
|
5564
6542
|
init_chartParts();
|
|
5565
|
-
|
|
6543
|
+
init_themePart();
|
|
5566
6544
|
init_imageUtils();
|
|
5567
6545
|
init_packageDocument();
|
|
5568
6546
|
init_emit2();
|
|
5569
6547
|
init_styles3();
|
|
5570
6548
|
OFFICE_OPEN_DOCX_RENDERER_ID = "office-open";
|
|
5571
6549
|
OFFICE_OPEN_DOCX = "@office-open/docx";
|
|
6550
|
+
OFFICE_OPEN_VERSION = "0.14.6";
|
|
5572
6551
|
OFFICE_OPEN_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
5573
6552
|
"paragraphs",
|
|
5574
6553
|
"styles",
|
|
@@ -9484,6 +10463,7 @@ function emptyToUndefined(formatting) {
|
|
|
9484
10463
|
}
|
|
9485
10464
|
|
|
9486
10465
|
// src/ir/compiler.ts
|
|
10466
|
+
init_chartValues();
|
|
9487
10467
|
init_types();
|
|
9488
10468
|
|
|
9489
10469
|
// src/ir/measure.ts
|
|
@@ -9516,6 +10496,49 @@ function tableWidthTwips(width, measureTwips) {
|
|
|
9516
10496
|
|
|
9517
10497
|
// src/ir/compiler.ts
|
|
9518
10498
|
init_units();
|
|
10499
|
+
|
|
10500
|
+
// src/ir/theme.ts
|
|
10501
|
+
init_colorUtils();
|
|
10502
|
+
init_styleHelpers();
|
|
10503
|
+
init_types();
|
|
10504
|
+
var THEME_COLOR_TOKENS = [
|
|
10505
|
+
["dark1", "text"],
|
|
10506
|
+
["light1", "background"],
|
|
10507
|
+
["dark2", "textSecondary"],
|
|
10508
|
+
["light2", "backgroundSecondary"],
|
|
10509
|
+
["accent1", "primary"],
|
|
10510
|
+
["accent2", "secondary"],
|
|
10511
|
+
["accent3", "accent"],
|
|
10512
|
+
["accent4", "accent4"],
|
|
10513
|
+
["accent5", "accent5"],
|
|
10514
|
+
["accent6", "accent6"]
|
|
10515
|
+
];
|
|
10516
|
+
var NOT_XML_CHARS = new RegExp(NOT_XML_CHAR.source, "gu");
|
|
10517
|
+
var xmlText = (value) => (value ?? "").replace(NOT_XML_CHARS, "").trim();
|
|
10518
|
+
function compileTheme(theme, themeName) {
|
|
10519
|
+
const colors = {};
|
|
10520
|
+
for (const [slot, token] of THEME_COLOR_TOKENS) {
|
|
10521
|
+
const hex = schemeHex(token, theme);
|
|
10522
|
+
if (hex) colors[slot] = { hex };
|
|
10523
|
+
}
|
|
10524
|
+
const headingFont = xmlText(resolveFontFamily(theme, "heading"));
|
|
10525
|
+
const bodyFont = xmlText(resolveFontFamily(theme, "body"));
|
|
10526
|
+
return {
|
|
10527
|
+
name: xmlText(theme.name) || xmlText(themeName) || "Office Theme",
|
|
10528
|
+
colors,
|
|
10529
|
+
...headingFont ? { headingFont } : {},
|
|
10530
|
+
...bodyFont ? { bodyFont } : {}
|
|
10531
|
+
};
|
|
10532
|
+
}
|
|
10533
|
+
function schemeHex(token, theme) {
|
|
10534
|
+
try {
|
|
10535
|
+
return resolveColor(token, theme);
|
|
10536
|
+
} catch {
|
|
10537
|
+
return void 0;
|
|
10538
|
+
}
|
|
10539
|
+
}
|
|
10540
|
+
|
|
10541
|
+
// src/ir/compiler.ts
|
|
9519
10542
|
var CONTENT_BOOKMARK_ID_BASE = 2e6;
|
|
9520
10543
|
var SINGLE_LINE_TWIPS = 240;
|
|
9521
10544
|
function compileDocument(structure, layout, warnings = [], images = /* @__PURE__ */ new Map(), options = {}) {
|
|
@@ -9581,6 +10604,7 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
9581
10604
|
trackRevisions: structure.trackRevisions === true,
|
|
9582
10605
|
...noProofWords(structure.theme) ? { noProofWords: noProofWords(structure.theme) } : {}
|
|
9583
10606
|
},
|
|
10607
|
+
theme: compileTheme(structure.theme, structure.themeName),
|
|
9584
10608
|
// The statistic styles are appended rather than built with the rest: a
|
|
9585
10609
|
// document that uses no statistic must keep the exact style set it had
|
|
9586
10610
|
// before the component had styles, or every recorded golden moves for a
|
|
@@ -10349,14 +11373,6 @@ function compileShape2(props, children, scope) {
|
|
|
10349
11373
|
);
|
|
10350
11374
|
}
|
|
10351
11375
|
const fill = style?.shading?.fill;
|
|
10352
|
-
const dropOutline = Boolean(fill) && Boolean(outline.outline);
|
|
10353
|
-
if (dropOutline) {
|
|
10354
|
-
warnOnce(
|
|
10355
|
-
ctx,
|
|
10356
|
-
"text-box",
|
|
10357
|
-
'[core-docx] text-box renderAs "shape" cannot carry a fill and a border at once (docx emits invalid shape properties); keeping the fill and dropping the border.'
|
|
10358
|
-
);
|
|
10359
|
-
}
|
|
10360
11376
|
ctx.features.require("text-boxes", path3);
|
|
10361
11377
|
if (props.floating) ctx.features.require("floating-images", path3);
|
|
10362
11378
|
const insets = shapeInsets(
|
|
@@ -10375,7 +11391,7 @@ function compileShape2(props, children, scope) {
|
|
|
10375
11391
|
heightPx: height.pixels,
|
|
10376
11392
|
children,
|
|
10377
11393
|
...fill ? { fill: irColor(resolveColor(fill, ctx.theme)) } : {},
|
|
10378
|
-
...outline.outline
|
|
11394
|
+
...outline.outline ? { outline: outline.outline } : {},
|
|
10379
11395
|
...insets ? { insetsEmu: insets } : {},
|
|
10380
11396
|
...props.floating ? { floating: compileFloating(props.floating, ctx, path3) } : {}
|
|
10381
11397
|
}
|
|
@@ -11598,6 +12614,7 @@ function compileImage2(component, scope) {
|
|
|
11598
12614
|
}
|
|
11599
12615
|
var DEFAULT_CHART_HEIGHT_INCHES = 3;
|
|
11600
12616
|
var MAX_CHART_TEXT_POINTS = 10;
|
|
12617
|
+
var MIN_CHART_TEXT_POINTS = 1;
|
|
11601
12618
|
function chartTextFont(theme) {
|
|
11602
12619
|
const bodySize = getThemeFonts(theme).body?.size;
|
|
11603
12620
|
let color = "000000";
|
|
@@ -11607,9 +12624,12 @@ function chartTextFont(theme) {
|
|
|
11607
12624
|
}
|
|
11608
12625
|
return {
|
|
11609
12626
|
fontFamily: resolveFontFamily(theme, "body"),
|
|
11610
|
-
fontSize: Math.
|
|
11611
|
-
|
|
11612
|
-
|
|
12627
|
+
fontSize: Math.max(
|
|
12628
|
+
MIN_CHART_TEXT_POINTS,
|
|
12629
|
+
Math.min(
|
|
12630
|
+
typeof bodySize === "number" && bodySize > 0 ? bodySize : 11,
|
|
12631
|
+
MAX_CHART_TEXT_POINTS
|
|
12632
|
+
)
|
|
11613
12633
|
),
|
|
11614
12634
|
bold: false,
|
|
11615
12635
|
color
|
|
@@ -11620,7 +12640,7 @@ function compileChart(component, scope) {
|
|
|
11620
12640
|
const props = component.props ?? {};
|
|
11621
12641
|
if (props.type === "bubble") {
|
|
11622
12642
|
throw new Error(
|
|
11623
|
-
`Chart at ${path3} is a bubble chart,
|
|
12643
|
+
`Chart at ${path3} is a bubble chart, but the docx \`chart\` component has no bubble sizes; use the pptx \`chart\` component on the pptxgenjs renderer.`
|
|
11624
12644
|
);
|
|
11625
12645
|
}
|
|
11626
12646
|
const rawSeries = Array.isArray(props.data) ? props.data : [];
|
|
@@ -11642,10 +12662,22 @@ function compileChart(component, scope) {
|
|
|
11642
12662
|
`Chart series "${label}" at ${path3} has ${labels.length} labels and ${values.length} values; they must be the same length.`
|
|
11643
12663
|
);
|
|
11644
12664
|
}
|
|
12665
|
+
if (labels.length === 0) {
|
|
12666
|
+
throw new Error(
|
|
12667
|
+
`Chart series "${label}" at ${path3} has no data points; give it at least one label and value.`
|
|
12668
|
+
);
|
|
12669
|
+
}
|
|
12670
|
+
const numbers = values.map((value) => Number(value));
|
|
12671
|
+
const bad = numbers.findIndex((value) => !Number.isFinite(value));
|
|
12672
|
+
if (bad !== -1) {
|
|
12673
|
+
throw new Error(
|
|
12674
|
+
`Chart series "${label}" at ${path3} has a value that is not a finite number (${JSON.stringify(values[bad])} at "${String(labels[bad])}").`
|
|
12675
|
+
);
|
|
12676
|
+
}
|
|
11645
12677
|
return {
|
|
11646
12678
|
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
11647
12679
|
labels: labels.map((value) => String(value)),
|
|
11648
|
-
values:
|
|
12680
|
+
values: numbers
|
|
11649
12681
|
};
|
|
11650
12682
|
});
|
|
11651
12683
|
const categories = series[0].labels;
|
|
@@ -11657,6 +12689,34 @@ function compileChart(component, scope) {
|
|
|
11657
12689
|
);
|
|
11658
12690
|
}
|
|
11659
12691
|
}
|
|
12692
|
+
if (props.type === "pie" && series.length > 1) {
|
|
12693
|
+
throw new Error(
|
|
12694
|
+
`Chart at ${path3} is a pie with ${series.length} series; a pie draws one series. Use a doughnut for one ring per series, or a column chart to compare them.`
|
|
12695
|
+
);
|
|
12696
|
+
}
|
|
12697
|
+
if (props.type === "pie" || props.type === "doughnut") {
|
|
12698
|
+
for (const [index, entry] of series.entries()) {
|
|
12699
|
+
const at = entry.values.findIndex((value) => value < 0);
|
|
12700
|
+
if (at === -1) continue;
|
|
12701
|
+
throw new Error(
|
|
12702
|
+
`Chart series "${entry.name ?? `series ${index}`}" at ${path3} has a negative value (${entry.values[at]} at "${entry.labels[at]}"); a ${props.type} chart draws each value as a share of the whole.`
|
|
12703
|
+
);
|
|
12704
|
+
}
|
|
12705
|
+
}
|
|
12706
|
+
if (props.type === "scatter" && series.some((entry) => entry.labels.some((label) => !isNumericLabel(label)))) {
|
|
12707
|
+
warnOnce(
|
|
12708
|
+
ctx,
|
|
12709
|
+
"chart",
|
|
12710
|
+
`Chart at ${path3} is a scatter chart whose labels are not all numbers; each label is its point's x, so these points are placed at 1, 2, 3\u2026 in order.`
|
|
12711
|
+
);
|
|
12712
|
+
}
|
|
12713
|
+
if ((props.type === "pie" || props.type === "doughnut") && (typeof props.catAxisTitle === "string" || typeof props.valAxisTitle === "string")) {
|
|
12714
|
+
warnOnce(
|
|
12715
|
+
ctx,
|
|
12716
|
+
"chart",
|
|
12717
|
+
`Chart at ${path3} is a ${props.type} chart, which has no axes; its axis titles are not drawn.`
|
|
12718
|
+
);
|
|
12719
|
+
}
|
|
11660
12720
|
const colors = Array.isArray(props.chartColors) ? props.chartColors.map(
|
|
11661
12721
|
(color) => resolveColor(String(color), ctx.theme)
|
|
11662
12722
|
) : chartPaletteValues(ctx.theme).flatMap((value) => {
|
|
@@ -11669,13 +12729,21 @@ function compileChart(component, scope) {
|
|
|
11669
12729
|
const contentWidthInches = scope.measureTwips / 1440;
|
|
11670
12730
|
const widthInches = typeof props.width === "number" ? props.width : contentWidthInches;
|
|
11671
12731
|
const heightInches = typeof props.height === "number" ? props.height : DEFAULT_CHART_HEIGHT_INCHES;
|
|
12732
|
+
const widthEmu = inchesToEmu(widthInches);
|
|
12733
|
+
const heightEmu = inchesToEmu(heightInches);
|
|
12734
|
+
if (!(widthEmu > 0 && heightEmu > 0)) {
|
|
12735
|
+
const inches = (value) => String(Number.isFinite(value) ? Math.round(value * 100) / 100 : value);
|
|
12736
|
+
throw new Error(
|
|
12737
|
+
`Chart at ${path3} has no room: it would be ${inches(widthInches)}\xD7${inches(heightInches)} in. Set \`width\`/\`height\`, or give it a container with space.`
|
|
12738
|
+
);
|
|
12739
|
+
}
|
|
11672
12740
|
const chart = {
|
|
11673
12741
|
kind: "chart",
|
|
11674
12742
|
chartType: props.type,
|
|
11675
12743
|
series,
|
|
11676
12744
|
colors,
|
|
11677
|
-
widthEmu
|
|
11678
|
-
heightEmu
|
|
12745
|
+
widthEmu,
|
|
12746
|
+
heightEmu,
|
|
11679
12747
|
...typeof props.title === "string" ? { title: props.title } : {},
|
|
11680
12748
|
...props.showTitle !== void 0 ? { showTitle: props.showTitle } : {},
|
|
11681
12749
|
...props.showLegend !== void 0 ? { showLegend: props.showLegend } : {},
|
|
@@ -11878,7 +12946,7 @@ function compileFrame(floating, ctx, path3) {
|
|
|
11878
12946
|
function compileFloating(floating, ctx, path3) {
|
|
11879
12947
|
if (floating.wrap?.type === "tight") {
|
|
11880
12948
|
throw new Error(
|
|
11881
|
-
"Image floating wrap.type 'tight' is not supported
|
|
12949
|
+
"Image floating wrap.type 'tight' is not supported. Use 'square', 'topAndBottom', or 'none'."
|
|
11882
12950
|
);
|
|
11883
12951
|
}
|
|
11884
12952
|
const hRelative = floating.horizontalPosition?.relative;
|