@json-to-office/core-docx 7.1.2 → 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 +1647 -427
- 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 +45 -3
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/units.d.ts +12 -0
- package/dist/ir/units.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 +1644 -424
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/quality/text-inventory.d.ts +13 -3
- package/dist/quality/text-inventory.d.ts.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 -17
- package/dist/renderers/office-open/emit.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts +16 -3
- 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/styles/themeToStyles.d.ts.map +1 -1
- package/dist/styles/utils/styleHelpers.d.ts +3 -1
- package/dist/styles/utils/styleHelpers.d.ts.map +1 -1
- 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 +7 -7
package/dist/index.js
CHANGED
|
@@ -1810,15 +1810,15 @@ function convertLineSpacing(lineSpacing) {
|
|
|
1810
1810
|
lineRule2 = "auto";
|
|
1811
1811
|
break;
|
|
1812
1812
|
case "atLeast":
|
|
1813
|
-
line = value !== void 0 ? value
|
|
1813
|
+
line = value !== void 0 ? pointsToTwips(value) : void 0;
|
|
1814
1814
|
lineRule2 = "atLeast";
|
|
1815
1815
|
break;
|
|
1816
1816
|
case "exactly":
|
|
1817
|
-
line = value !== void 0 ? value
|
|
1817
|
+
line = value !== void 0 ? pointsToTwips(value) : void 0;
|
|
1818
1818
|
lineRule2 = "exact";
|
|
1819
1819
|
break;
|
|
1820
1820
|
case "multiple":
|
|
1821
|
-
line = value !== void 0 ? value * SINGLE_LINE_SPACING_TWIPS : void 0;
|
|
1821
|
+
line = value !== void 0 ? Math.round(value * SINGLE_LINE_SPACING_TWIPS) : void 0;
|
|
1822
1822
|
lineRule2 = "auto";
|
|
1823
1823
|
break;
|
|
1824
1824
|
default:
|
|
@@ -2779,7 +2779,7 @@ var init_imageUtils = __esm({
|
|
|
2779
2779
|
});
|
|
2780
2780
|
|
|
2781
2781
|
// src/ir/types.ts
|
|
2782
|
-
var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION, DOCX_IR_BORDER_STYLES;
|
|
2782
|
+
var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION, NOT_XML_CHAR, DOCX_IR_BORDER_STYLES;
|
|
2783
2783
|
var init_types = __esm({
|
|
2784
2784
|
"src/ir/types.ts"() {
|
|
2785
2785
|
"use strict";
|
|
@@ -2788,6 +2788,7 @@ var init_types = __esm({
|
|
|
2788
2788
|
EMU_PER_INCH = 914400;
|
|
2789
2789
|
EMU_PER_TWIP = EMU_PER_INCH / TWIPS_PER_INCH;
|
|
2790
2790
|
DOCX_IR_SCHEMA_VERSION = 1;
|
|
2791
|
+
NOT_XML_CHAR = /[^\t\n\r\u0020-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/u;
|
|
2791
2792
|
DOCX_IR_BORDER_STYLES = [
|
|
2792
2793
|
"single",
|
|
2793
2794
|
"dashDotStroked",
|
|
@@ -2825,6 +2826,9 @@ import { createHash as createHash2 } from "crypto";
|
|
|
2825
2826
|
function pointsToTwips2(points) {
|
|
2826
2827
|
return Math.round(points * TWIPS_PER_POINT2);
|
|
2827
2828
|
}
|
|
2829
|
+
function wholeTwips(twips2) {
|
|
2830
|
+
return Math.round(twips2);
|
|
2831
|
+
}
|
|
2828
2832
|
function pointsToHalfPoints(points) {
|
|
2829
2833
|
return Math.round(points * 2);
|
|
2830
2834
|
}
|
|
@@ -2840,8 +2844,8 @@ function inchesToEmu(inches) {
|
|
|
2840
2844
|
function pointsToEmu(points) {
|
|
2841
2845
|
return Math.round(points * EMU_PER_INCH / 72);
|
|
2842
2846
|
}
|
|
2843
|
-
function twipsToEmu(
|
|
2844
|
-
return Math.round(
|
|
2847
|
+
function twipsToEmu(twips2) {
|
|
2848
|
+
return Math.round(twips2 * EMU_PER_TWIP);
|
|
2845
2849
|
}
|
|
2846
2850
|
function pixelsToEmu(pixels) {
|
|
2847
2851
|
return Math.round(pixels * 9525);
|
|
@@ -2849,8 +2853,8 @@ function pixelsToEmu(pixels) {
|
|
|
2849
2853
|
function emuToPixels(emu) {
|
|
2850
2854
|
return emu / 9525;
|
|
2851
2855
|
}
|
|
2852
|
-
function twipsToPixels(
|
|
2853
|
-
return
|
|
2856
|
+
function twipsToPixels(twips2) {
|
|
2857
|
+
return twips2 / TWIPS_PER_INCH * 96;
|
|
2854
2858
|
}
|
|
2855
2859
|
function irColor(hex) {
|
|
2856
2860
|
return { hex: hex.startsWith("#") ? hex.slice(1) : hex };
|
|
@@ -2871,6 +2875,226 @@ var init_units = __esm({
|
|
|
2871
2875
|
}
|
|
2872
2876
|
});
|
|
2873
2877
|
|
|
2878
|
+
// src/ir/chartValues.ts
|
|
2879
|
+
function isNumericLabel(label) {
|
|
2880
|
+
return NUMERIC_LABEL.test(label.trim());
|
|
2881
|
+
}
|
|
2882
|
+
function scatterX(labels, index) {
|
|
2883
|
+
const label = labels[index];
|
|
2884
|
+
return label !== void 0 && isNumericLabel(label) ? Number(label) : index + 1;
|
|
2885
|
+
}
|
|
2886
|
+
var NUMERIC_LABEL;
|
|
2887
|
+
var init_chartValues = __esm({
|
|
2888
|
+
"src/ir/chartValues.ts"() {
|
|
2889
|
+
"use strict";
|
|
2890
|
+
NUMERIC_LABEL = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
|
|
2891
|
+
}
|
|
2892
|
+
});
|
|
2893
|
+
|
|
2894
|
+
// src/renderers/chartText.ts
|
|
2895
|
+
function chartTextRoles(font) {
|
|
2896
|
+
const { bold, ...rest } = font;
|
|
2897
|
+
const text = rest;
|
|
2898
|
+
return {
|
|
2899
|
+
text,
|
|
2900
|
+
axisTitle: { ...text, bold },
|
|
2901
|
+
title: {
|
|
2902
|
+
...text,
|
|
2903
|
+
fontSize: Math.round(text.fontSize * CHART_TITLE_SCALE),
|
|
2904
|
+
bold: true
|
|
2905
|
+
}
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2908
|
+
var CHART_TITLE_SCALE;
|
|
2909
|
+
var init_chartText = __esm({
|
|
2910
|
+
"src/renderers/chartText.ts"() {
|
|
2911
|
+
"use strict";
|
|
2912
|
+
CHART_TITLE_SCALE = 1.4;
|
|
2913
|
+
}
|
|
2914
|
+
});
|
|
2915
|
+
|
|
2916
|
+
// src/renderers/docxjs/docxSubpath.ts
|
|
2917
|
+
function docxSubpath(specifier, component, importer) {
|
|
2918
|
+
let module;
|
|
2919
|
+
let failure;
|
|
2920
|
+
let loading;
|
|
2921
|
+
return {
|
|
2922
|
+
specifier,
|
|
2923
|
+
load() {
|
|
2924
|
+
loading ??= importer().then(
|
|
2925
|
+
(loadedModule) => {
|
|
2926
|
+
module = loadedModule;
|
|
2927
|
+
},
|
|
2928
|
+
(reason) => {
|
|
2929
|
+
failure = { reason };
|
|
2930
|
+
}
|
|
2931
|
+
);
|
|
2932
|
+
return loading;
|
|
2933
|
+
},
|
|
2934
|
+
loaded: () => module !== void 0,
|
|
2935
|
+
get() {
|
|
2936
|
+
if (module !== void 0) return module;
|
|
2937
|
+
if (failure !== void 0) {
|
|
2938
|
+
const { reason } = failure;
|
|
2939
|
+
const detail = reason instanceof Error ? reason.message : String(reason);
|
|
2940
|
+
throw new Error(
|
|
2941
|
+
`The docx \`${component}\` component needs docx 9.8.0 or later: the \`${specifier}\` entry could not be loaded (${detail})`
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
throw new Error(
|
|
2945
|
+
`${specifier} is not loaded: await its load() before buildDocument() (render() does)`
|
|
2946
|
+
);
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
var init_docxSubpath = __esm({
|
|
2951
|
+
"src/renderers/docxjs/docxSubpath.ts"() {
|
|
2952
|
+
"use strict";
|
|
2953
|
+
}
|
|
2954
|
+
});
|
|
2955
|
+
|
|
2956
|
+
// src/renderers/docxjs/charts.ts
|
|
2957
|
+
import { assertNever } from "@json-to-office/shared/rendering";
|
|
2958
|
+
function loadDocxCharts() {
|
|
2959
|
+
return charts.load();
|
|
2960
|
+
}
|
|
2961
|
+
function chartFont(role) {
|
|
2962
|
+
return {
|
|
2963
|
+
name: role.fontFamily,
|
|
2964
|
+
size: role.fontSize,
|
|
2965
|
+
color: role.color,
|
|
2966
|
+
bold: role.bold ?? false
|
|
2967
|
+
};
|
|
2968
|
+
}
|
|
2969
|
+
function chartRunOptions(chart, floating) {
|
|
2970
|
+
const roles = chartTextRoles(chart.textFont);
|
|
2971
|
+
const text = chartFont(roles.text);
|
|
2972
|
+
const axisTitle = chartFont(roles.axisTitle);
|
|
2973
|
+
const palette = chart.colors;
|
|
2974
|
+
const colorAt = (index) => palette.length > 0 ? palette[index % palette.length] : void 0;
|
|
2975
|
+
const withColor = (index) => {
|
|
2976
|
+
const color = colorAt(index);
|
|
2977
|
+
return color ? { color } : {};
|
|
2978
|
+
};
|
|
2979
|
+
const seriesName = (index) => chart.series[index].name ?? `Series ${index + 1}`;
|
|
2980
|
+
const categories = chart.series[0]?.labels ?? [];
|
|
2981
|
+
const axis = (title) => ({
|
|
2982
|
+
...title ? { title: { text: title, font: axisTitle } } : {},
|
|
2983
|
+
font: text
|
|
2984
|
+
});
|
|
2985
|
+
const common = {
|
|
2986
|
+
...chart.title && chart.showTitle !== false ? { title: { text: chart.title, font: chartFont(roles.title) } } : {},
|
|
2987
|
+
legend: chart.showLegend === false ? false : {
|
|
2988
|
+
position: LEGEND_POSITION[chart.legendPosition ?? "b"],
|
|
2989
|
+
font: text
|
|
2990
|
+
},
|
|
2991
|
+
font: { name: roles.text.fontFamily, color: roles.text.color },
|
|
2992
|
+
// Office-open's chart space is unfilled and unbordered; `ChartRun`'s
|
|
2993
|
+
// default is Word's white fill and grey border.
|
|
2994
|
+
chartArea: { fill: "none", border: "none" },
|
|
2995
|
+
transformation: {
|
|
2996
|
+
width: emuToPixels(chart.widthEmu),
|
|
2997
|
+
height: emuToPixels(chart.heightEmu)
|
|
2998
|
+
},
|
|
2999
|
+
// Without an authored description `ChartRun` describes the chart from
|
|
3000
|
+
// its data, which is deterministic; the name stays empty, as it is on
|
|
3001
|
+
// every other drawing this renderer writes.
|
|
3002
|
+
...chart.altText ? { altText: { name: "", description: chart.altText } } : {},
|
|
3003
|
+
...floating ? { floating } : {}
|
|
3004
|
+
};
|
|
3005
|
+
switch (chart.chartType) {
|
|
3006
|
+
case "column":
|
|
3007
|
+
case "bar":
|
|
3008
|
+
case "area":
|
|
3009
|
+
case "line":
|
|
3010
|
+
return {
|
|
3011
|
+
...common,
|
|
3012
|
+
type: chart.chartType,
|
|
3013
|
+
categories,
|
|
3014
|
+
...chart.chartType === "line" ? { markers: true } : {},
|
|
3015
|
+
series: chart.series.map((entry, index) => ({
|
|
3016
|
+
name: seriesName(index),
|
|
3017
|
+
values: entry.values,
|
|
3018
|
+
...withColor(index)
|
|
3019
|
+
})),
|
|
3020
|
+
categoryAxis: axis(chart.categoryAxisTitle),
|
|
3021
|
+
valueAxis: axis(chart.valueAxisTitle)
|
|
3022
|
+
};
|
|
3023
|
+
case "pie":
|
|
3024
|
+
case "doughnut":
|
|
3025
|
+
return {
|
|
3026
|
+
...common,
|
|
3027
|
+
type: chart.chartType,
|
|
3028
|
+
categories,
|
|
3029
|
+
series: chart.series.map((entry, index) => ({
|
|
3030
|
+
name: seriesName(index),
|
|
3031
|
+
values: entry.values,
|
|
3032
|
+
...palette.length > 0 ? { colors: entry.values.map((_, point) => colorAt(point)) } : {}
|
|
3033
|
+
}))
|
|
3034
|
+
};
|
|
3035
|
+
case "radar":
|
|
3036
|
+
return {
|
|
3037
|
+
...common,
|
|
3038
|
+
type: "radar",
|
|
3039
|
+
categories,
|
|
3040
|
+
markers: true,
|
|
3041
|
+
series: chart.series.map((entry, index) => ({
|
|
3042
|
+
name: seriesName(index),
|
|
3043
|
+
values: entry.values,
|
|
3044
|
+
...withColor(index)
|
|
3045
|
+
})),
|
|
3046
|
+
categoryAxis: axis(chart.categoryAxisTitle),
|
|
3047
|
+
valueAxis: axis(chart.valueAxisTitle)
|
|
3048
|
+
};
|
|
3049
|
+
case "scatter":
|
|
3050
|
+
return {
|
|
3051
|
+
...common,
|
|
3052
|
+
type: "scatter",
|
|
3053
|
+
markers: true,
|
|
3054
|
+
lines: "straight",
|
|
3055
|
+
series: chart.series.map((entry, index) => ({
|
|
3056
|
+
name: seriesName(index),
|
|
3057
|
+
points: entry.values.map((y, point) => ({
|
|
3058
|
+
x: scatterX(entry.labels, point),
|
|
3059
|
+
y
|
|
3060
|
+
})),
|
|
3061
|
+
...withColor(index)
|
|
3062
|
+
})),
|
|
3063
|
+
xAxis: { ...axis(chart.categoryAxisTitle), gridlines: false },
|
|
3064
|
+
yAxis: axis(chart.valueAxisTitle)
|
|
3065
|
+
};
|
|
3066
|
+
case "bubble":
|
|
3067
|
+
throw new Error(
|
|
3068
|
+
"the docxjs renderer has no emitter for a bubble chart; the compiler should have refused it"
|
|
3069
|
+
);
|
|
3070
|
+
default:
|
|
3071
|
+
return assertNever(chart.chartType, "DocxIrChartType");
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
function emitChart(chart, floating) {
|
|
3075
|
+
return new (charts.get()).ChartRun(
|
|
3076
|
+
chartRunOptions(chart, floating)
|
|
3077
|
+
);
|
|
3078
|
+
}
|
|
3079
|
+
var charts, LEGEND_POSITION;
|
|
3080
|
+
var init_charts = __esm({
|
|
3081
|
+
"src/renderers/docxjs/charts.ts"() {
|
|
3082
|
+
"use strict";
|
|
3083
|
+
init_chartValues();
|
|
3084
|
+
init_units();
|
|
3085
|
+
init_chartText();
|
|
3086
|
+
init_docxSubpath();
|
|
3087
|
+
charts = docxSubpath("docx/charts", "chart", () => import("docx/charts"));
|
|
3088
|
+
LEGEND_POSITION = {
|
|
3089
|
+
b: "bottom",
|
|
3090
|
+
l: "left",
|
|
3091
|
+
r: "right",
|
|
3092
|
+
t: "top",
|
|
3093
|
+
tr: "topRight"
|
|
3094
|
+
};
|
|
3095
|
+
}
|
|
3096
|
+
});
|
|
3097
|
+
|
|
2874
3098
|
// src/renderers/docxjs/emit.ts
|
|
2875
3099
|
import {
|
|
2876
3100
|
AlignmentType,
|
|
@@ -2906,7 +3130,7 @@ import {
|
|
|
2906
3130
|
WidthType,
|
|
2907
3131
|
WpsShapeRun
|
|
2908
3132
|
} from "docx";
|
|
2909
|
-
import { assertNever } from "@json-to-office/shared/rendering";
|
|
3133
|
+
import { assertNever as assertNever2 } from "@json-to-office/shared/rendering";
|
|
2910
3134
|
function complexField(instruction, formatting, leading, cachedText) {
|
|
2911
3135
|
const options = runOptions(formatting);
|
|
2912
3136
|
const fieldChar = (type, extra = {}) => new TextRun({
|
|
@@ -2943,7 +3167,12 @@ function runOptions(formatting) {
|
|
|
2943
3167
|
if (formatting.bold !== void 0) options.bold = formatting.bold;
|
|
2944
3168
|
if (formatting.italic !== void 0) options.italics = formatting.italic;
|
|
2945
3169
|
if (formatting.underline !== void 0) {
|
|
2946
|
-
options.underline = formatting.underline ? {
|
|
3170
|
+
options.underline = formatting.underline ? {
|
|
3171
|
+
type: formatting.underline.type,
|
|
3172
|
+
// A native visual's text is the one place a run states its own
|
|
3173
|
+
// underline colour.
|
|
3174
|
+
...formatting.underline.color ? { color: formatting.underline.color.hex } : {}
|
|
3175
|
+
} : void 0;
|
|
2947
3176
|
}
|
|
2948
3177
|
if (formatting.strike !== void 0) options.strike = formatting.strike;
|
|
2949
3178
|
if (formatting.allCaps !== void 0) options.allCaps = formatting.allCaps;
|
|
@@ -3069,21 +3298,36 @@ function inlineChildren(children, resources = /* @__PURE__ */ new Map()) {
|
|
|
3069
3298
|
case "shape":
|
|
3070
3299
|
out.push(emitShape(child, resources));
|
|
3071
3300
|
break;
|
|
3072
|
-
case "drawingGroup":
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3301
|
+
case "drawingGroup": {
|
|
3302
|
+
const build = resources.drawingGroup;
|
|
3303
|
+
if (!build) {
|
|
3304
|
+
throw new Error(
|
|
3305
|
+
"the docxjs renderer was handed a drawing group without loading docx/shapes; render() loads it whenever the IR holds one"
|
|
3306
|
+
);
|
|
3307
|
+
}
|
|
3308
|
+
const pending = breakOption();
|
|
3309
|
+
if (pending.break) out.push(new TextRun(pending));
|
|
3310
|
+
out.push(build(child, resources));
|
|
3311
|
+
break;
|
|
3312
|
+
}
|
|
3313
|
+
case "chart": {
|
|
3314
|
+
const pending = breakOption();
|
|
3315
|
+
if (pending.break) out.push(new TextRun(pending));
|
|
3316
|
+
out.push(
|
|
3317
|
+
emitChart(
|
|
3318
|
+
child,
|
|
3319
|
+
child.floating ? floatingOptions(child.floating) : void 0
|
|
3320
|
+
)
|
|
3079
3321
|
);
|
|
3322
|
+
break;
|
|
3323
|
+
}
|
|
3080
3324
|
case "noteReference":
|
|
3081
3325
|
out.push(
|
|
3082
3326
|
child.noteKind === "endnote" ? new EndnoteReferenceRun(child.id) : new FootnoteReferenceRun(child.id)
|
|
3083
3327
|
);
|
|
3084
3328
|
break;
|
|
3085
3329
|
default:
|
|
3086
|
-
|
|
3330
|
+
assertNever2(child, "DocxIrInline");
|
|
3087
3331
|
}
|
|
3088
3332
|
}
|
|
3089
3333
|
return out;
|
|
@@ -3288,7 +3532,7 @@ function emitBlock(block2, resources = /* @__PURE__ */ new Map()) {
|
|
|
3288
3532
|
case "toc":
|
|
3289
3533
|
return emitToc(block2);
|
|
3290
3534
|
default:
|
|
3291
|
-
return
|
|
3535
|
+
return assertNever2(block2, "DocxIrBlock");
|
|
3292
3536
|
}
|
|
3293
3537
|
}
|
|
3294
3538
|
function emitToc(block2) {
|
|
@@ -3432,6 +3676,7 @@ var ALIGNMENT2, PAGE_FIELDS, isSequenceField, WRAP_TYPE, ThemedTableOfContents,
|
|
|
3432
3676
|
var init_emit = __esm({
|
|
3433
3677
|
"src/renderers/docxjs/emit.ts"() {
|
|
3434
3678
|
"use strict";
|
|
3679
|
+
init_charts();
|
|
3435
3680
|
ALIGNMENT2 = {
|
|
3436
3681
|
left: AlignmentType.LEFT,
|
|
3437
3682
|
center: AlignmentType.CENTER,
|
|
@@ -3730,10 +3975,13 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3730
3975
|
const rename = new Map(
|
|
3731
3976
|
ordered.map((id, index) => [id, `rId${highest + 1 + index}`])
|
|
3732
3977
|
);
|
|
3733
|
-
const rewrite = (xml) => xml.replace(
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3978
|
+
const rewrite = (xml) => xml.replace(
|
|
3979
|
+
/(\s[\w:.-]+=)"([^"]*)"/g,
|
|
3980
|
+
(whole, prefix, value) => {
|
|
3981
|
+
const replacement = rename.get(value);
|
|
3982
|
+
return replacement === void 0 ? whole : `${prefix}"${replacement}"`;
|
|
3983
|
+
}
|
|
3984
|
+
);
|
|
3737
3985
|
updates.push({ name: relsName, xml: rewrite(relsXml) });
|
|
3738
3986
|
if (partEntry) {
|
|
3739
3987
|
updates.push({ name: partName, xml: rewrite(partXml) });
|
|
@@ -3744,17 +3992,62 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3744
3992
|
if (entry) zip.updateFile(entry, Buffer.from(update.xml, "utf8"));
|
|
3745
3993
|
}
|
|
3746
3994
|
}
|
|
3995
|
+
function canonicalizeEmbeddedPackages(zip, generatedAt, depth = 1) {
|
|
3996
|
+
const names = zip.getEntries().map((entry) => entry.entryName).filter((name) => EMBEDDED_OFFICE_PACKAGE.test(name));
|
|
3997
|
+
let changed = false;
|
|
3998
|
+
for (const name of names) {
|
|
3999
|
+
const entry = zip.getEntry(name);
|
|
4000
|
+
if (!entry) continue;
|
|
4001
|
+
let nested;
|
|
4002
|
+
try {
|
|
4003
|
+
nested = new AdmZip(entry.getData());
|
|
4004
|
+
nested.getEntries();
|
|
4005
|
+
} catch {
|
|
4006
|
+
continue;
|
|
4007
|
+
}
|
|
4008
|
+
if (canonicalizeNestedPackage(nested, generatedAt, depth)) {
|
|
4009
|
+
zip.updateFile(entry, nested.toBuffer());
|
|
4010
|
+
changed = true;
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
return changed;
|
|
4014
|
+
}
|
|
4015
|
+
function canonicalizeNestedPackage(zip, generatedAt, depth) {
|
|
4016
|
+
let changed = false;
|
|
4017
|
+
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
4018
|
+
if (coreProperties3) {
|
|
4019
|
+
const xml = coreProperties3.getData().toString("utf8");
|
|
4020
|
+
const normalized = xml.replace(
|
|
4021
|
+
CORE_TIMESTAMP,
|
|
4022
|
+
`$1${generatedAt.toISOString()}$2`
|
|
4023
|
+
);
|
|
4024
|
+
if (normalized !== xml) {
|
|
4025
|
+
zip.updateFile(coreProperties3, Buffer.from(normalized, "utf8"));
|
|
4026
|
+
changed = true;
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
if (depth < MAX_EMBEDDED_DEPTH && canonicalizeEmbeddedPackages(zip, generatedAt, depth + 1)) {
|
|
4030
|
+
changed = true;
|
|
4031
|
+
}
|
|
4032
|
+
const zipTimestamp = toDosTime(generatedAt);
|
|
4033
|
+
for (const entry of zip.getEntries()) {
|
|
4034
|
+
const header = entry.header;
|
|
4035
|
+
if (header.timeval !== zipTimestamp) {
|
|
4036
|
+
header.timeval = zipTimestamp;
|
|
4037
|
+
changed = true;
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
return changed;
|
|
4041
|
+
}
|
|
3747
4042
|
function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
|
|
3748
4043
|
const zip = new AdmZip(buffer);
|
|
3749
4044
|
normalizeTextCase(zip);
|
|
3750
4045
|
canonicalizeRelationshipIds(zip);
|
|
4046
|
+
canonicalizeEmbeddedPackages(zip, generatedAt);
|
|
3751
4047
|
const isoTimestamp = generatedAt.toISOString();
|
|
3752
4048
|
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
3753
4049
|
if (coreProperties3) {
|
|
3754
|
-
const normalized = coreProperties3.getData().toString("utf8").replace(
|
|
3755
|
-
/(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g,
|
|
3756
|
-
`$1${isoTimestamp}$2`
|
|
3757
|
-
);
|
|
4050
|
+
const normalized = coreProperties3.getData().toString("utf8").replace(CORE_TIMESTAMP, `$1${isoTimestamp}$2`);
|
|
3758
4051
|
zip.updateFile(coreProperties3, Buffer.from(normalized, "utf8"));
|
|
3759
4052
|
}
|
|
3760
4053
|
const zipTimestamp = toDosTime(generatedAt);
|
|
@@ -3767,35 +4060,567 @@ function normalizeDocxCaseBuffer(buffer) {
|
|
|
3767
4060
|
const zip = new AdmZip(buffer);
|
|
3768
4061
|
return normalizeTextCase(zip) ? zip.toBuffer() : buffer;
|
|
3769
4062
|
}
|
|
3770
|
-
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID;
|
|
4063
|
+
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID, CORE_TIMESTAMP, EMBEDDED_OFFICE_PACKAGE, MAX_EMBEDDED_DEPTH;
|
|
3771
4064
|
var init_packageDocument = __esm({
|
|
3772
4065
|
"src/utils/packageDocument.ts"() {
|
|
3773
4066
|
"use strict";
|
|
3774
4067
|
init_normalizeTextCase();
|
|
3775
4068
|
DEFAULT_GENERATION_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
|
|
3776
4069
|
STABLE_RELATIONSHIP_ID = /^rId\d+$/;
|
|
4070
|
+
CORE_TIMESTAMP = /(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g;
|
|
4071
|
+
EMBEDDED_OFFICE_PACKAGE = /\.(?:docx|pptx|xlsx|xlsm)$/i;
|
|
4072
|
+
MAX_EMBEDDED_DEPTH = 3;
|
|
3777
4073
|
}
|
|
3778
4074
|
});
|
|
3779
4075
|
|
|
3780
4076
|
// src/utils/fixFloatingImageIds.ts
|
|
3781
4077
|
import AdmZip2 from "adm-zip";
|
|
4078
|
+
function compareDrawingParts(a, b) {
|
|
4079
|
+
const ma = DRAWING_PART.exec(a);
|
|
4080
|
+
const mb = DRAWING_PART.exec(b);
|
|
4081
|
+
const rank = RANK.indexOf(ma[1]) - RANK.indexOf(mb[1]);
|
|
4082
|
+
return rank !== 0 ? rank : Number(ma[2] || 0) - Number(mb[2] || 0);
|
|
4083
|
+
}
|
|
3782
4084
|
function fixFloatingImageIdsInBuffer(buffer) {
|
|
3783
4085
|
const zip = new AdmZip2(buffer);
|
|
3784
|
-
|
|
3785
|
-
if (!documentEntry) {
|
|
4086
|
+
if (!zip.getEntry("word/document.xml")) {
|
|
3786
4087
|
throw new Error("document.xml not found in DOCX");
|
|
3787
4088
|
}
|
|
4089
|
+
const parts = zip.getEntries().filter((entry) => DRAWING_PART.test(entry.entryName)).sort((a, b) => compareDrawingParts(a.entryName, b.entryName));
|
|
3788
4090
|
let idCounter = 1;
|
|
3789
|
-
const
|
|
3790
|
-
const
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
4091
|
+
for (const entry of parts) {
|
|
4092
|
+
const xml = entry.getData().toString("utf8");
|
|
4093
|
+
const renumbered = xml.replace(
|
|
4094
|
+
/(<wp:docPr\b[^>]*?\s)id="\d+"/g,
|
|
4095
|
+
(_match, prefix) => `${prefix}id="${idCounter++}"`
|
|
4096
|
+
);
|
|
4097
|
+
zip.updateFile(entry, Buffer.from(renumbered, "utf8"));
|
|
4098
|
+
}
|
|
3794
4099
|
return zip.toBuffer();
|
|
3795
4100
|
}
|
|
4101
|
+
var DRAWING_PART, RANK;
|
|
3796
4102
|
var init_fixFloatingImageIds = __esm({
|
|
3797
4103
|
"src/utils/fixFloatingImageIds.ts"() {
|
|
3798
4104
|
"use strict";
|
|
4105
|
+
DRAWING_PART = /^word\/(document|header|footer|footnotes|endnotes|comments)(\d*)\.xml$/;
|
|
4106
|
+
RANK = [
|
|
4107
|
+
"document",
|
|
4108
|
+
"header",
|
|
4109
|
+
"footer",
|
|
4110
|
+
"footnotes",
|
|
4111
|
+
"endnotes",
|
|
4112
|
+
"comments"
|
|
4113
|
+
];
|
|
4114
|
+
}
|
|
4115
|
+
});
|
|
4116
|
+
|
|
4117
|
+
// src/renderers/docxjs/presetShapes.ts
|
|
4118
|
+
function docxPresetShape(geometry) {
|
|
4119
|
+
const name = Object.hasOwn(OOXML_PRESET_TO_DOCX, geometry) ? OOXML_PRESET_TO_DOCX[geometry] : void 0;
|
|
4120
|
+
if (!name) {
|
|
4121
|
+
throw new Error(
|
|
4122
|
+
`the docxjs renderer has no preset for the OOXML geometry "${geometry}"`
|
|
4123
|
+
);
|
|
4124
|
+
}
|
|
4125
|
+
return name;
|
|
4126
|
+
}
|
|
4127
|
+
function docxLineDash(dash) {
|
|
4128
|
+
const name = Object.hasOwn(OOXML_DASH_TO_DOCX, dash) ? OOXML_DASH_TO_DOCX[dash] : void 0;
|
|
4129
|
+
if (!name) {
|
|
4130
|
+
throw new Error(
|
|
4131
|
+
`the docxjs renderer has no line dash for the OOXML value "${dash}"`
|
|
4132
|
+
);
|
|
4133
|
+
}
|
|
4134
|
+
return name;
|
|
4135
|
+
}
|
|
4136
|
+
var OOXML_PRESET_TO_DOCX, OOXML_DASH_TO_DOCX;
|
|
4137
|
+
var init_presetShapes = __esm({
|
|
4138
|
+
"src/renderers/docxjs/presetShapes.ts"() {
|
|
4139
|
+
"use strict";
|
|
4140
|
+
OOXML_PRESET_TO_DOCX = {
|
|
4141
|
+
line: "line",
|
|
4142
|
+
lineInv: "inverseLine",
|
|
4143
|
+
straightConnector1: "straightConnector",
|
|
4144
|
+
bentConnector2: "elbowConnectorOneBend",
|
|
4145
|
+
bentConnector3: "elbowConnector",
|
|
4146
|
+
bentConnector4: "elbowConnectorThreeBends",
|
|
4147
|
+
bentConnector5: "elbowConnectorFourBends",
|
|
4148
|
+
curvedConnector2: "curvedConnectorOneBend",
|
|
4149
|
+
curvedConnector3: "curvedConnector",
|
|
4150
|
+
curvedConnector4: "curvedConnectorThreeBends",
|
|
4151
|
+
curvedConnector5: "curvedConnectorFourBends",
|
|
4152
|
+
triangle: "triangle",
|
|
4153
|
+
rtTriangle: "rightTriangle",
|
|
4154
|
+
diamond: "diamond",
|
|
4155
|
+
parallelogram: "parallelogram",
|
|
4156
|
+
trapezoid: "trapezoid",
|
|
4157
|
+
nonIsoscelesTrapezoid: "nonIsoscelesTrapezoid",
|
|
4158
|
+
pentagon: "pentagon",
|
|
4159
|
+
hexagon: "hexagon",
|
|
4160
|
+
heptagon: "heptagon",
|
|
4161
|
+
octagon: "octagon",
|
|
4162
|
+
decagon: "decagon",
|
|
4163
|
+
dodecagon: "dodecagon",
|
|
4164
|
+
ellipse: "ellipse",
|
|
4165
|
+
teardrop: "teardrop",
|
|
4166
|
+
pieWedge: "pieWedge",
|
|
4167
|
+
pie: "pie",
|
|
4168
|
+
blockArc: "blockArc",
|
|
4169
|
+
donut: "donut",
|
|
4170
|
+
noSmoking: "noSymbol",
|
|
4171
|
+
chord: "chord",
|
|
4172
|
+
arc: "arc",
|
|
4173
|
+
frame: "frame",
|
|
4174
|
+
halfFrame: "halfFrame",
|
|
4175
|
+
corner: "lShape",
|
|
4176
|
+
diagStripe: "diagonalStripe",
|
|
4177
|
+
plus: "cross",
|
|
4178
|
+
plaque: "plaque",
|
|
4179
|
+
can: "cylinder",
|
|
4180
|
+
cube: "cube",
|
|
4181
|
+
bevel: "beveledRectangle",
|
|
4182
|
+
foldedCorner: "foldedCorner",
|
|
4183
|
+
smileyFace: "smileyFace",
|
|
4184
|
+
heart: "heart",
|
|
4185
|
+
lightningBolt: "lightningBolt",
|
|
4186
|
+
sun: "sun",
|
|
4187
|
+
moon: "moon",
|
|
4188
|
+
cloud: "cloud",
|
|
4189
|
+
leftBracket: "leftBracket",
|
|
4190
|
+
rightBracket: "rightBracket",
|
|
4191
|
+
leftBrace: "leftBrace",
|
|
4192
|
+
rightBrace: "rightBrace",
|
|
4193
|
+
bracketPair: "bracketPair",
|
|
4194
|
+
bracePair: "bracePair",
|
|
4195
|
+
rect: "rectangle",
|
|
4196
|
+
roundRect: "roundedRectangle",
|
|
4197
|
+
round1Rect: "roundedCornerRectangle",
|
|
4198
|
+
round2SameRect: "topRoundedCornersRectangle",
|
|
4199
|
+
round2DiagRect: "diagonalRoundedCornersRectangle",
|
|
4200
|
+
snip1Rect: "snippedCornerRectangle",
|
|
4201
|
+
snip2SameRect: "topSnippedCornersRectangle",
|
|
4202
|
+
snip2DiagRect: "diagonalSnippedCornersRectangle",
|
|
4203
|
+
snipRoundRect: "roundedAndSnippedCornersRectangle",
|
|
4204
|
+
rightArrow: "rightArrow",
|
|
4205
|
+
leftArrow: "leftArrow",
|
|
4206
|
+
upArrow: "upArrow",
|
|
4207
|
+
downArrow: "downArrow",
|
|
4208
|
+
leftRightArrow: "leftRightArrow",
|
|
4209
|
+
upDownArrow: "upDownArrow",
|
|
4210
|
+
quadArrow: "quadArrow",
|
|
4211
|
+
leftRightUpArrow: "leftRightUpArrow",
|
|
4212
|
+
bentArrow: "bentArrow",
|
|
4213
|
+
uturnArrow: "uTurnArrow",
|
|
4214
|
+
leftUpArrow: "leftUpArrow",
|
|
4215
|
+
bentUpArrow: "bentUpArrow",
|
|
4216
|
+
curvedRightArrow: "curvedRightArrow",
|
|
4217
|
+
curvedLeftArrow: "curvedLeftArrow",
|
|
4218
|
+
curvedUpArrow: "curvedUpArrow",
|
|
4219
|
+
curvedDownArrow: "curvedDownArrow",
|
|
4220
|
+
stripedRightArrow: "stripedRightArrow",
|
|
4221
|
+
notchedRightArrow: "notchedRightArrow",
|
|
4222
|
+
homePlate: "pentagonArrow",
|
|
4223
|
+
chevron: "chevron",
|
|
4224
|
+
rightArrowCallout: "rightArrowCallout",
|
|
4225
|
+
downArrowCallout: "downArrowCallout",
|
|
4226
|
+
leftArrowCallout: "leftArrowCallout",
|
|
4227
|
+
upArrowCallout: "upArrowCallout",
|
|
4228
|
+
leftRightArrowCallout: "leftRightArrowCallout",
|
|
4229
|
+
upDownArrowCallout: "upDownArrowCallout",
|
|
4230
|
+
quadArrowCallout: "quadArrowCallout",
|
|
4231
|
+
circularArrow: "circularArrow",
|
|
4232
|
+
leftCircularArrow: "leftCircularArrow",
|
|
4233
|
+
leftRightCircularArrow: "leftRightCircularArrow",
|
|
4234
|
+
swooshArrow: "swooshArrow",
|
|
4235
|
+
mathPlus: "mathPlus",
|
|
4236
|
+
mathMinus: "mathMinus",
|
|
4237
|
+
mathMultiply: "mathMultiply",
|
|
4238
|
+
mathDivide: "mathDivide",
|
|
4239
|
+
mathEqual: "mathEqual",
|
|
4240
|
+
mathNotEqual: "mathNotEqual",
|
|
4241
|
+
flowChartProcess: "flowChartProcess",
|
|
4242
|
+
flowChartAlternateProcess: "flowChartAlternateProcess",
|
|
4243
|
+
flowChartDecision: "flowChartDecision",
|
|
4244
|
+
flowChartInputOutput: "flowChartInputOutput",
|
|
4245
|
+
flowChartPredefinedProcess: "flowChartPredefinedProcess",
|
|
4246
|
+
flowChartInternalStorage: "flowChartInternalStorage",
|
|
4247
|
+
flowChartDocument: "flowChartDocument",
|
|
4248
|
+
flowChartMultidocument: "flowChartMultidocument",
|
|
4249
|
+
flowChartTerminator: "flowChartTerminator",
|
|
4250
|
+
flowChartPreparation: "flowChartPreparation",
|
|
4251
|
+
flowChartManualInput: "flowChartManualInput",
|
|
4252
|
+
flowChartManualOperation: "flowChartManualOperation",
|
|
4253
|
+
flowChartConnector: "flowChartConnector",
|
|
4254
|
+
flowChartOffpageConnector: "flowChartOffpageConnector",
|
|
4255
|
+
flowChartPunchedCard: "flowChartPunchedCard",
|
|
4256
|
+
flowChartPunchedTape: "flowChartPunchedTape",
|
|
4257
|
+
flowChartSummingJunction: "flowChartSummingJunction",
|
|
4258
|
+
flowChartOr: "flowChartOr",
|
|
4259
|
+
flowChartCollate: "flowChartCollate",
|
|
4260
|
+
flowChartSort: "flowChartSort",
|
|
4261
|
+
flowChartExtract: "flowChartExtract",
|
|
4262
|
+
flowChartMerge: "flowChartMerge",
|
|
4263
|
+
flowChartOfflineStorage: "flowChartOfflineStorage",
|
|
4264
|
+
flowChartOnlineStorage: "flowChartOnlineStorage",
|
|
4265
|
+
flowChartDelay: "flowChartDelay",
|
|
4266
|
+
flowChartMagneticTape: "flowChartMagneticTape",
|
|
4267
|
+
flowChartMagneticDisk: "flowChartMagneticDisk",
|
|
4268
|
+
flowChartMagneticDrum: "flowChartMagneticDrum",
|
|
4269
|
+
flowChartDisplay: "flowChartDisplay",
|
|
4270
|
+
irregularSeal1: "explosion12",
|
|
4271
|
+
irregularSeal2: "explosion14",
|
|
4272
|
+
star4: "star4",
|
|
4273
|
+
star5: "star5",
|
|
4274
|
+
star6: "star6",
|
|
4275
|
+
star7: "star7",
|
|
4276
|
+
star8: "star8",
|
|
4277
|
+
star10: "star10",
|
|
4278
|
+
star12: "star12",
|
|
4279
|
+
star16: "star16",
|
|
4280
|
+
star24: "star24",
|
|
4281
|
+
star32: "star32",
|
|
4282
|
+
ribbon2: "ribbonUp",
|
|
4283
|
+
ribbon: "ribbonDown",
|
|
4284
|
+
ellipseRibbon2: "curvedRibbonUp",
|
|
4285
|
+
ellipseRibbon: "curvedRibbonDown",
|
|
4286
|
+
leftRightRibbon: "leftRightRibbon",
|
|
4287
|
+
verticalScroll: "verticalScroll",
|
|
4288
|
+
horizontalScroll: "horizontalScroll",
|
|
4289
|
+
wave: "wave",
|
|
4290
|
+
doubleWave: "doubleWave",
|
|
4291
|
+
wedgeRectCallout: "rectangularCallout",
|
|
4292
|
+
wedgeRoundRectCallout: "roundedRectangularCallout",
|
|
4293
|
+
wedgeEllipseCallout: "ellipticalCallout",
|
|
4294
|
+
cloudCallout: "cloudCallout",
|
|
4295
|
+
borderCallout1: "lineCallout",
|
|
4296
|
+
borderCallout2: "bentLineCallout",
|
|
4297
|
+
borderCallout3: "doubleBentLineCallout",
|
|
4298
|
+
accentCallout1: "lineCalloutWithAccentBar",
|
|
4299
|
+
accentCallout2: "bentLineCalloutWithAccentBar",
|
|
4300
|
+
accentCallout3: "doubleBentLineCalloutWithAccentBar",
|
|
4301
|
+
callout1: "lineCalloutWithNoBorder",
|
|
4302
|
+
callout2: "bentLineCalloutWithNoBorder",
|
|
4303
|
+
callout3: "doubleBentLineCalloutWithNoBorder",
|
|
4304
|
+
accentBorderCallout1: "lineCalloutWithBorderAndAccentBar",
|
|
4305
|
+
accentBorderCallout2: "bentLineCalloutWithBorderAndAccentBar",
|
|
4306
|
+
accentBorderCallout3: "doubleBentLineCalloutWithBorderAndAccentBar",
|
|
4307
|
+
actionButtonBlank: "actionButtonBlank",
|
|
4308
|
+
actionButtonHome: "actionButtonHome",
|
|
4309
|
+
actionButtonHelp: "actionButtonHelp",
|
|
4310
|
+
actionButtonInformation: "actionButtonInformation",
|
|
4311
|
+
actionButtonForwardNext: "actionButtonForwardNext",
|
|
4312
|
+
actionButtonBackPrevious: "actionButtonBackPrevious",
|
|
4313
|
+
actionButtonEnd: "actionButtonEnd",
|
|
4314
|
+
actionButtonBeginning: "actionButtonBeginning",
|
|
4315
|
+
actionButtonReturn: "actionButtonReturn",
|
|
4316
|
+
actionButtonDocument: "actionButtonDocument",
|
|
4317
|
+
actionButtonSound: "actionButtonSound",
|
|
4318
|
+
actionButtonMovie: "actionButtonMovie",
|
|
4319
|
+
gear6: "gear6",
|
|
4320
|
+
gear9: "gear9",
|
|
4321
|
+
funnel: "funnel",
|
|
4322
|
+
cornerTabs: "cornerTabs",
|
|
4323
|
+
squareTabs: "squareTabs",
|
|
4324
|
+
plaqueTabs: "plaqueTabs",
|
|
4325
|
+
chartX: "chartX",
|
|
4326
|
+
chartStar: "chartStar",
|
|
4327
|
+
chartPlus: "chartPlus"
|
|
4328
|
+
};
|
|
4329
|
+
OOXML_DASH_TO_DOCX = {
|
|
4330
|
+
solid: "solid",
|
|
4331
|
+
dot: "dot",
|
|
4332
|
+
dash: "dash",
|
|
4333
|
+
lgDash: "longDash",
|
|
4334
|
+
dashDot: "dashDot",
|
|
4335
|
+
lgDashDot: "longDashDot",
|
|
4336
|
+
lgDashDotDot: "longDashDotDot",
|
|
4337
|
+
sysDash: "shortDash",
|
|
4338
|
+
sysDot: "shortDot",
|
|
4339
|
+
sysDashDot: "shortDashDot",
|
|
4340
|
+
sysDashDotDot: "shortDashDotDot"
|
|
4341
|
+
};
|
|
4342
|
+
}
|
|
4343
|
+
});
|
|
4344
|
+
|
|
4345
|
+
// src/renderers/docxjs/drawingGroup.ts
|
|
4346
|
+
function chooseMarkers(ir) {
|
|
4347
|
+
const strings = [];
|
|
4348
|
+
collectStrings(ir, strings, /* @__PURE__ */ new WeakSet());
|
|
4349
|
+
const unused = (base) => {
|
|
4350
|
+
for (let n = 0; ; n += 1) {
|
|
4351
|
+
const candidate = n === 0 ? base : `${base}-${n}`;
|
|
4352
|
+
if (!strings.some((value) => value.includes(candidate))) return candidate;
|
|
4353
|
+
}
|
|
4354
|
+
};
|
|
4355
|
+
return {
|
|
4356
|
+
noAltText: unused(DEFAULT_MARKERS.noAltText),
|
|
4357
|
+
textBox: unused(DEFAULT_MARKERS.textBox)
|
|
4358
|
+
};
|
|
4359
|
+
}
|
|
4360
|
+
function collectStrings(node, out, seen) {
|
|
4361
|
+
if (typeof node === "string") {
|
|
4362
|
+
out.push(node);
|
|
4363
|
+
return;
|
|
4364
|
+
}
|
|
4365
|
+
if (!node || typeof node !== "object") return;
|
|
4366
|
+
if (node instanceof ArrayBuffer || ArrayBuffer.isView(node)) return;
|
|
4367
|
+
if (seen.has(node)) return;
|
|
4368
|
+
seen.add(node);
|
|
4369
|
+
if (node instanceof Map) {
|
|
4370
|
+
for (const [key, value] of node) {
|
|
4371
|
+
collectStrings(key, out, seen);
|
|
4372
|
+
collectStrings(value, out, seen);
|
|
4373
|
+
}
|
|
4374
|
+
return;
|
|
4375
|
+
}
|
|
4376
|
+
if (node instanceof Set) {
|
|
4377
|
+
for (const value of node) collectStrings(value, out, seen);
|
|
4378
|
+
return;
|
|
4379
|
+
}
|
|
4380
|
+
for (const value of Object.values(node)) collectStrings(value, out, seen);
|
|
4381
|
+
}
|
|
4382
|
+
function createDrawingGroupFactory(shapes2, pictures, markers) {
|
|
4383
|
+
return (group, resources) => new shapes2.ShapeGroupRun(
|
|
4384
|
+
drawingGroupOptions(group, resources, pictures, markers)
|
|
4385
|
+
);
|
|
4386
|
+
}
|
|
4387
|
+
function drawingGroupOptions(group, resources, pictures, markers = DEFAULT_MARKERS) {
|
|
4388
|
+
const canvasWidth = group.canvasWidthEmu;
|
|
4389
|
+
const canvasHeight = group.canvasHeightEmu;
|
|
4390
|
+
const near = (value, edge) => Math.abs(value - edge) <= OVERFLOW_TOLERANCE_EMU;
|
|
4391
|
+
const bounds = unrotatedBounds(group.children);
|
|
4392
|
+
const fillsCanvas = bounds !== void 0 && near(bounds.left, 0) && near(bounds.top, 0) && near(bounds.right, canvasWidth) && near(bounds.bottom, canvasHeight);
|
|
4393
|
+
const union = {
|
|
4394
|
+
left: Math.min(0, bounds?.left ?? 0),
|
|
4395
|
+
top: Math.min(0, bounds?.top ?? 0),
|
|
4396
|
+
right: Math.max(canvasWidth, bounds?.right ?? 0),
|
|
4397
|
+
bottom: Math.max(canvasHeight, bounds?.bottom ?? 0)
|
|
4398
|
+
};
|
|
4399
|
+
const overflows = union.left < -OVERFLOW_TOLERANCE_EMU || union.top < -OVERFLOW_TOLERANCE_EMU || union.right > canvasWidth + OVERFLOW_TOLERANCE_EMU || union.bottom > canvasHeight + OVERFLOW_TOLERANCE_EMU;
|
|
4400
|
+
const widthEmu = overflows ? (union.right - union.left) * group.widthEmu / canvasWidth : group.widthEmu;
|
|
4401
|
+
const heightEmu = overflows ? (union.bottom - union.top) * group.heightEmu / canvasHeight : group.heightEmu;
|
|
4402
|
+
return {
|
|
4403
|
+
children: [
|
|
4404
|
+
...fillsCanvas ? [] : [canvasPad(canvasWidth, canvasHeight)],
|
|
4405
|
+
...group.children.map(
|
|
4406
|
+
(child, index) => groupChild(child, index, resources, pictures, markers)
|
|
4407
|
+
)
|
|
4408
|
+
],
|
|
4409
|
+
transformation: {
|
|
4410
|
+
width: emuToPixels(widthEmu),
|
|
4411
|
+
height: emuToPixels(heightEmu)
|
|
4412
|
+
},
|
|
4413
|
+
// `||`, not `??`: docx treats '' as no description too, and would then
|
|
4414
|
+
// describe the diagram from the child names.
|
|
4415
|
+
altText: { name: "", description: group.altText || markers.noAltText },
|
|
4416
|
+
...group.floating ? { floating: floatingOptions(group.floating) } : {}
|
|
4417
|
+
};
|
|
4418
|
+
}
|
|
4419
|
+
function groupChild(child, index, resources, pictures, markers) {
|
|
4420
|
+
return child.kind === "picture" ? pictureChild(child, index, pictures) : shapeChild(child, index, resources, markers);
|
|
4421
|
+
}
|
|
4422
|
+
function canvasPad(canvasWidthEmu, canvasHeightEmu) {
|
|
4423
|
+
return {
|
|
4424
|
+
type: "rectangle",
|
|
4425
|
+
transformation: {
|
|
4426
|
+
offset: { left: 0, top: 0 },
|
|
4427
|
+
width: emuToPixels(canvasWidthEmu),
|
|
4428
|
+
height: emuToPixels(canvasHeightEmu)
|
|
4429
|
+
},
|
|
4430
|
+
fill: "none",
|
|
4431
|
+
line: "none",
|
|
4432
|
+
decorative: true,
|
|
4433
|
+
altText: { name: "Canvas" }
|
|
4434
|
+
};
|
|
4435
|
+
}
|
|
4436
|
+
function childTransformation(frame) {
|
|
4437
|
+
const rotation2 = frame.rotationDegrees;
|
|
4438
|
+
return {
|
|
4439
|
+
offset: { left: emuToPixels(frame.xEmu), top: emuToPixels(frame.yEmu) },
|
|
4440
|
+
width: emuToPixels(frame.widthEmu),
|
|
4441
|
+
height: emuToPixels(frame.heightEmu),
|
|
4442
|
+
...rotation2 !== void 0 && rotation2 % 360 !== 0 ? { rotation: rotation2 } : {},
|
|
4443
|
+
...frame.flipHorizontal || frame.flipVertical ? {
|
|
4444
|
+
flip: {
|
|
4445
|
+
...frame.flipHorizontal ? { horizontal: true } : {},
|
|
4446
|
+
...frame.flipVertical ? { vertical: true } : {}
|
|
4447
|
+
}
|
|
4448
|
+
} : {}
|
|
4449
|
+
};
|
|
4450
|
+
}
|
|
4451
|
+
function shapeChild(shape, index, resources, markers) {
|
|
4452
|
+
const paragraphs = shape.text?.paragraphs ?? [];
|
|
4453
|
+
return {
|
|
4454
|
+
type: docxPresetShape(shape.geometry),
|
|
4455
|
+
transformation: childTransformation(shape.frame),
|
|
4456
|
+
fill: shapeFill(shape.fill),
|
|
4457
|
+
line: shapeLine(shape.outline),
|
|
4458
|
+
altText: {
|
|
4459
|
+
name: shape.name ?? `Shape ${index + 1}`,
|
|
4460
|
+
...shape.isTextBox ? { title: markers.textBox } : {}
|
|
4461
|
+
},
|
|
4462
|
+
// Never `children: []`: docx would write an empty `w:txbxContent`, which
|
|
4463
|
+
// the schema does not allow.
|
|
4464
|
+
...paragraphs.length > 0 ? {
|
|
4465
|
+
children: paragraphs.map(
|
|
4466
|
+
(paragraph2) => emitParagraph(paragraph2, resources)
|
|
4467
|
+
)
|
|
4468
|
+
} : {},
|
|
4469
|
+
...shape.text ? { textOptions: textOptions(shape.text) } : {}
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
function pictureChild(picture2, index, pictures) {
|
|
4473
|
+
const crop = picture2.crop;
|
|
4474
|
+
return {
|
|
4475
|
+
type: "picture",
|
|
4476
|
+
image: pictures(picture2.resourceId, {
|
|
4477
|
+
widthEmu: picture2.frame.widthEmu,
|
|
4478
|
+
heightEmu: picture2.frame.heightEmu
|
|
4479
|
+
}),
|
|
4480
|
+
transformation: childTransformation(picture2.frame),
|
|
4481
|
+
...crop ? {
|
|
4482
|
+
crop: {
|
|
4483
|
+
...crop.left !== void 0 ? { left: crop.left * 100 } : {},
|
|
4484
|
+
...crop.top !== void 0 ? { top: crop.top * 100 } : {},
|
|
4485
|
+
...crop.right !== void 0 ? { right: crop.right * 100 } : {},
|
|
4486
|
+
...crop.bottom !== void 0 ? { bottom: crop.bottom * 100 } : {}
|
|
4487
|
+
}
|
|
4488
|
+
} : {},
|
|
4489
|
+
altText: {
|
|
4490
|
+
name: picture2.name ?? `Picture ${index + 1}`,
|
|
4491
|
+
...picture2.altText ? { description: picture2.altText } : {}
|
|
4492
|
+
}
|
|
4493
|
+
};
|
|
4494
|
+
}
|
|
4495
|
+
function shapeFill(fill) {
|
|
4496
|
+
if (!fill || fill.kind === "none") return "none";
|
|
4497
|
+
return {
|
|
4498
|
+
type: "solid",
|
|
4499
|
+
color: fill.color.hex,
|
|
4500
|
+
...fill.transparencyPercent !== void 0 ? { transparency: clamp(fill.transparencyPercent, 0, 100) } : {}
|
|
4501
|
+
};
|
|
4502
|
+
}
|
|
4503
|
+
function shapeLine(outline) {
|
|
4504
|
+
if (!outline || !outline.color) return "none";
|
|
4505
|
+
return {
|
|
4506
|
+
color: outline.color.hex,
|
|
4507
|
+
// An omitted width is office-open's omitted `w`, a hairline, where docx's
|
|
4508
|
+
// own default would be 1pt.
|
|
4509
|
+
width: outline.widthEmu !== void 0 ? clamp(outline.widthEmu / EMU_PER_POINT, 0, MAX_POINTS) : 0,
|
|
4510
|
+
...outline.dash ? { dash: docxLineDash(outline.dash) } : {}
|
|
4511
|
+
};
|
|
4512
|
+
}
|
|
4513
|
+
function textOptions(text) {
|
|
4514
|
+
const insets = text.insetsEmu;
|
|
4515
|
+
const points = (emu) => clamp(emu / EMU_PER_POINT, 0, MAX_POINTS);
|
|
4516
|
+
const margins = insets ? {
|
|
4517
|
+
...insets.top !== void 0 ? { top: points(insets.top) } : {},
|
|
4518
|
+
...insets.right !== void 0 ? { right: points(insets.right) } : {},
|
|
4519
|
+
...insets.bottom !== void 0 ? { bottom: points(insets.bottom) } : {},
|
|
4520
|
+
...insets.left !== void 0 ? { left: points(insets.left) } : {}
|
|
4521
|
+
} : void 0;
|
|
4522
|
+
return {
|
|
4523
|
+
verticalAlignment: VERTICAL_ALIGNMENT[text.anchor ?? "top"],
|
|
4524
|
+
...margins && Object.keys(margins).length > 0 ? { margins } : {}
|
|
4525
|
+
};
|
|
4526
|
+
}
|
|
4527
|
+
function unrotatedBounds(children) {
|
|
4528
|
+
if (children.length === 0) return void 0;
|
|
4529
|
+
let left = Infinity;
|
|
4530
|
+
let top = Infinity;
|
|
4531
|
+
let right = -Infinity;
|
|
4532
|
+
let bottom = -Infinity;
|
|
4533
|
+
for (const { frame } of children) {
|
|
4534
|
+
left = Math.min(left, frame.xEmu);
|
|
4535
|
+
top = Math.min(top, frame.yEmu);
|
|
4536
|
+
right = Math.max(right, frame.xEmu + frame.widthEmu);
|
|
4537
|
+
bottom = Math.max(bottom, frame.yEmu + frame.heightEmu);
|
|
4538
|
+
}
|
|
4539
|
+
return { left, top, right, bottom };
|
|
4540
|
+
}
|
|
4541
|
+
function clamp(value, low, high) {
|
|
4542
|
+
return Math.min(high, Math.max(low, value));
|
|
4543
|
+
}
|
|
4544
|
+
var DEFAULT_MARKERS, EMU_PER_POINT, MAX_POINTS, OVERFLOW_TOLERANCE_EMU, VERTICAL_ALIGNMENT;
|
|
4545
|
+
var init_drawingGroup = __esm({
|
|
4546
|
+
"src/renderers/docxjs/drawingGroup.ts"() {
|
|
4547
|
+
"use strict";
|
|
4548
|
+
init_units();
|
|
4549
|
+
init_emit();
|
|
4550
|
+
init_presetShapes();
|
|
4551
|
+
DEFAULT_MARKERS = {
|
|
4552
|
+
noAltText: "jto:no-alt-text",
|
|
4553
|
+
textBox: "jto:text-box"
|
|
4554
|
+
};
|
|
4555
|
+
EMU_PER_POINT = 12700;
|
|
4556
|
+
MAX_POINTS = 1584;
|
|
4557
|
+
OVERFLOW_TOLERANCE_EMU = 2;
|
|
4558
|
+
VERTICAL_ALIGNMENT = {
|
|
4559
|
+
top: "top",
|
|
4560
|
+
middle: "center",
|
|
4561
|
+
bottom: "bottom"
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4564
|
+
});
|
|
4565
|
+
|
|
4566
|
+
// src/renderers/docxjs/drawingGroupRepair.ts
|
|
4567
|
+
import AdmZip3 from "adm-zip";
|
|
4568
|
+
function repairDrawingGroupsInBuffer(buffer, markers) {
|
|
4569
|
+
const textBox = new RegExp(
|
|
4570
|
+
`(<wps:cNvPr\\b[^>]*?) title="${escapeRegExp2(markers.textBox)}"(\\s*/>)<wps:cNvSpPr/>`,
|
|
4571
|
+
"g"
|
|
4572
|
+
);
|
|
4573
|
+
const noAltText = new RegExp(
|
|
4574
|
+
`(<wp:docPr\\b[^>]*?) descr="${escapeRegExp2(markers.noAltText)}"`,
|
|
4575
|
+
"g"
|
|
4576
|
+
);
|
|
4577
|
+
const zip = new AdmZip3(buffer);
|
|
4578
|
+
const parts = zip.getEntries().filter((entry) => DRAWING_PART.test(entry.entryName)).sort((a, b) => compareDrawingParts(a.entryName, b.entryName));
|
|
4579
|
+
const texts = new Map(
|
|
4580
|
+
parts.map((entry) => [entry, entry.getData().toString("utf8")])
|
|
4581
|
+
);
|
|
4582
|
+
let highest = 0;
|
|
4583
|
+
for (const xml of texts.values()) {
|
|
4584
|
+
for (const match of xml.matchAll(DOC_PR_ID)) {
|
|
4585
|
+
highest = Math.max(highest, Number(match[1]));
|
|
4586
|
+
}
|
|
4587
|
+
for (const match of xml.replace(GROUP, "").matchAll(CNVPR_ID)) {
|
|
4588
|
+
highest = Math.max(highest, Number(match[1]));
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
let next = highest + 1;
|
|
4592
|
+
for (const [entry, xml] of texts) {
|
|
4593
|
+
if (!xml.includes("<wpg:wgp")) continue;
|
|
4594
|
+
const repaired = xml.replace(
|
|
4595
|
+
GROUP,
|
|
4596
|
+
(span) => span.replace(CHILD_ID, (_match, head) => `${head}id="${next++}"`).replace(
|
|
4597
|
+
ROTATION,
|
|
4598
|
+
(_match, head, value) => `${head}rot="${Math.round(Number(value))}"`
|
|
4599
|
+
).replace(textBox, '$1$2<wps:cNvSpPr txBox="1"/>')
|
|
4600
|
+
).replace(noAltText, "$1");
|
|
4601
|
+
texts.set(entry, repaired);
|
|
4602
|
+
zip.updateFile(entry, Buffer.from(repaired, "utf8"));
|
|
4603
|
+
}
|
|
4604
|
+
for (const [entry, xml] of texts) {
|
|
4605
|
+
if (xml.includes(markers.noAltText) || xml.includes(markers.textBox)) {
|
|
4606
|
+
throw new Error(
|
|
4607
|
+
`the drawing-group repair left a marker in ${entry.entryName}`
|
|
4608
|
+
);
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
return zip.toBuffer();
|
|
4612
|
+
}
|
|
4613
|
+
var GROUP, DOC_PR_ID, CNVPR_ID, CHILD_ID, ROTATION, escapeRegExp2;
|
|
4614
|
+
var init_drawingGroupRepair = __esm({
|
|
4615
|
+
"src/renderers/docxjs/drawingGroupRepair.ts"() {
|
|
4616
|
+
"use strict";
|
|
4617
|
+
init_fixFloatingImageIds();
|
|
4618
|
+
GROUP = /<wpg:wgp\b[^>]*>[\s\S]*?<\/wpg:wgp>/g;
|
|
4619
|
+
DOC_PR_ID = /<wp:docPr\b[^>]*?\sid="(\d+)"/g;
|
|
4620
|
+
CNVPR_ID = /<(?:wps|pic|wpg):cNvPr\b[^>]*?\sid="(\d+)"/g;
|
|
4621
|
+
CHILD_ID = /(<(?:wps|pic|wpg):cNvPr\b[^>]*?\s)id="\d+"/g;
|
|
4622
|
+
ROTATION = /(<a:xfrm\b[^>]*?\s)rot="([^"]*)"/g;
|
|
4623
|
+
escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3799
4624
|
}
|
|
3800
4625
|
});
|
|
3801
4626
|
|
|
@@ -3824,18 +4649,32 @@ function createDocxJsRenderer() {
|
|
|
3824
4649
|
format: "docx",
|
|
3825
4650
|
capabilities: DOCXJS_CAPABILITIES,
|
|
3826
4651
|
async render(ir, renderOptions) {
|
|
3827
|
-
|
|
4652
|
+
await loadDocxCharts();
|
|
4653
|
+
const prepared = await prepareImages(
|
|
3828
4654
|
ir,
|
|
3829
4655
|
renderOptions?.svgRasterFallback
|
|
3830
4656
|
);
|
|
4657
|
+
const markers = prepared.drawingGroups > 0 ? chooseMarkers(ir) : void 0;
|
|
4658
|
+
let resources = prepared.images;
|
|
4659
|
+
if (markers) {
|
|
4660
|
+
await shapes.load();
|
|
4661
|
+
resources = Object.assign(prepared.images, {
|
|
4662
|
+
drawingGroup: createDrawingGroupFactory(
|
|
4663
|
+
shapes.get(),
|
|
4664
|
+
prepared.pictureSource,
|
|
4665
|
+
markers
|
|
4666
|
+
)
|
|
4667
|
+
});
|
|
4668
|
+
}
|
|
3831
4669
|
const document = buildDocument(ir, resources);
|
|
3832
4670
|
const packed = await Packer.toBuffer(document);
|
|
3833
4671
|
const fixed = fixFloatingImageIdsInBuffer(packed);
|
|
4672
|
+
const repaired = markers ? repairDrawingGroupsInBuffer(fixed, markers) : fixed;
|
|
3834
4673
|
if (renderOptions?.deterministic === false)
|
|
3835
|
-
return new Uint8Array(normalizeDocxCaseBuffer(
|
|
4674
|
+
return new Uint8Array(normalizeDocxCaseBuffer(repaired));
|
|
3836
4675
|
return new Uint8Array(
|
|
3837
4676
|
canonicalizeDocxBuffer(
|
|
3838
|
-
|
|
4677
|
+
repaired,
|
|
3839
4678
|
resolveGenerationDate({
|
|
3840
4679
|
deterministic: renderOptions?.deterministic,
|
|
3841
4680
|
generatedAt: renderOptions?.generatedAt
|
|
@@ -3848,6 +4687,7 @@ function createDocxJsRenderer() {
|
|
|
3848
4687
|
function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
3849
4688
|
return new Document({
|
|
3850
4689
|
styles: emitStyles(ir.styles),
|
|
4690
|
+
...ir.theme ? { theme: themeOptions(ir.theme) } : {},
|
|
3851
4691
|
sections: ir.sections.map(
|
|
3852
4692
|
(section2, index) => sectionOptions(section2, resources, index === ir.sections.length - 1)
|
|
3853
4693
|
),
|
|
@@ -3879,6 +4719,21 @@ function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
|
3879
4719
|
} : {}
|
|
3880
4720
|
});
|
|
3881
4721
|
}
|
|
4722
|
+
function themeOptions(theme) {
|
|
4723
|
+
const colors = {};
|
|
4724
|
+
for (const [slot, color] of Object.entries(theme.colors)) {
|
|
4725
|
+
if (color) colors[slot] = color.hex;
|
|
4726
|
+
}
|
|
4727
|
+
const fonts = {
|
|
4728
|
+
...theme.headingFont ? { headings: theme.headingFont } : {},
|
|
4729
|
+
...theme.bodyFont ? { body: theme.bodyFont } : {}
|
|
4730
|
+
};
|
|
4731
|
+
return {
|
|
4732
|
+
name: theme.name,
|
|
4733
|
+
...Object.keys(colors).length > 0 ? { colors } : {},
|
|
4734
|
+
...Object.keys(fonts).length > 0 ? { fonts } : {}
|
|
4735
|
+
};
|
|
4736
|
+
}
|
|
3882
4737
|
function noteBodies(notes, resources) {
|
|
3883
4738
|
const bodies = {};
|
|
3884
4739
|
for (const note of notes) {
|
|
@@ -3916,7 +4771,7 @@ function numberingConfig(numbering) {
|
|
|
3916
4771
|
};
|
|
3917
4772
|
}
|
|
3918
4773
|
async function prepareImages(ir, svgRasterFallback) {
|
|
3919
|
-
const placements = collectImagePlacements(ir);
|
|
4774
|
+
const { placements, drawingGroups } = collectImagePlacements(ir);
|
|
3920
4775
|
const jobs = [];
|
|
3921
4776
|
for (const resource of ir.resources) {
|
|
3922
4777
|
if (resource.kind !== "image" || resource.mediaType !== "svg") continue;
|
|
@@ -3964,16 +4819,55 @@ async function prepareImages(ir, svgRasterFallback) {
|
|
|
3964
4819
|
});
|
|
3965
4820
|
});
|
|
3966
4821
|
}
|
|
3967
|
-
|
|
4822
|
+
const pictureSource = (resourceId, placement) => {
|
|
4823
|
+
const resource = ir.resources.find(
|
|
4824
|
+
(candidate) => candidate.kind === "image" && candidate.id === resourceId
|
|
4825
|
+
);
|
|
4826
|
+
if (!resource) {
|
|
4827
|
+
throw new Error(`no image was prepared for resource "${resourceId}"`);
|
|
4828
|
+
}
|
|
4829
|
+
const data = Buffer.from(resource.bytes);
|
|
4830
|
+
if (resource.mediaType !== "svg") {
|
|
4831
|
+
return {
|
|
4832
|
+
type: resource.mediaType,
|
|
4833
|
+
data
|
|
4834
|
+
};
|
|
4835
|
+
}
|
|
4836
|
+
const size = `${emuToPixels(placement.widthEmu)}x${emuToPixels(placement.heightEmu)}`;
|
|
4837
|
+
return {
|
|
4838
|
+
type: "svg",
|
|
4839
|
+
data,
|
|
4840
|
+
fallback: {
|
|
4841
|
+
type: "png",
|
|
4842
|
+
data: rasters.get(`${resourceId}:${size}`) ?? data
|
|
4843
|
+
}
|
|
4844
|
+
};
|
|
4845
|
+
};
|
|
4846
|
+
return { images: resources, pictureSource, drawingGroups };
|
|
3968
4847
|
}
|
|
3969
4848
|
function collectImagePlacements(ir) {
|
|
3970
4849
|
const placements = /* @__PURE__ */ new Map();
|
|
4850
|
+
let drawingGroups = 0;
|
|
4851
|
+
const record = (resourceId, widthEmu, heightEmu) => {
|
|
4852
|
+
const key = `${emuToPixels(widthEmu)}x${emuToPixels(heightEmu)}`;
|
|
4853
|
+
const sizes = placements.get(resourceId) ?? /* @__PURE__ */ new Set();
|
|
4854
|
+
sizes.add(key);
|
|
4855
|
+
placements.set(resourceId, sizes);
|
|
4856
|
+
};
|
|
3971
4857
|
const visitInline = (inline) => {
|
|
3972
4858
|
if (inline.kind === "image") {
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
4859
|
+
record(inline.resourceId, inline.widthEmu, inline.heightEmu);
|
|
4860
|
+
return;
|
|
4861
|
+
}
|
|
4862
|
+
if (inline.kind === "drawingGroup") {
|
|
4863
|
+
drawingGroups += 1;
|
|
4864
|
+
for (const child of inline.children) {
|
|
4865
|
+
if (child.kind === "picture") {
|
|
4866
|
+
record(child.resourceId, child.frame.widthEmu, child.frame.heightEmu);
|
|
4867
|
+
} else {
|
|
4868
|
+
child.text?.paragraphs.forEach(visitBlock);
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
3977
4871
|
return;
|
|
3978
4872
|
}
|
|
3979
4873
|
if (inline.kind === "hyperlink" || inline.kind === "revision") {
|
|
@@ -4004,7 +4898,7 @@ function collectImagePlacements(ir) {
|
|
|
4004
4898
|
for (const note of [...ir.footnotes, ...ir.endnotes]) {
|
|
4005
4899
|
note.children.forEach(visitBlock);
|
|
4006
4900
|
}
|
|
4007
|
-
return placements;
|
|
4901
|
+
return { placements, drawingGroups };
|
|
4008
4902
|
}
|
|
4009
4903
|
function sectionOptions(section2, resources, closesDocument = false) {
|
|
4010
4904
|
const { page, columns } = section2.properties;
|
|
@@ -4117,17 +5011,26 @@ function coreProperties(ir) {
|
|
|
4117
5011
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
4118
5012
|
};
|
|
4119
5013
|
}
|
|
4120
|
-
var DOCXJS_RENDERER_ID, DOCXJS_CAPABILITIES;
|
|
5014
|
+
var DOCXJS_RENDERER_ID, shapes, DOCXJS_CAPABILITIES;
|
|
4121
5015
|
var init_docxjs = __esm({
|
|
4122
5016
|
"src/renderers/docxjs/index.ts"() {
|
|
4123
5017
|
"use strict";
|
|
4124
5018
|
init_styles2();
|
|
5019
|
+
init_charts();
|
|
4125
5020
|
init_imageUtils();
|
|
4126
5021
|
init_packageDocument();
|
|
4127
5022
|
init_fixFloatingImageIds();
|
|
4128
5023
|
init_emit();
|
|
5024
|
+
init_docxSubpath();
|
|
5025
|
+
init_drawingGroup();
|
|
5026
|
+
init_drawingGroupRepair();
|
|
4129
5027
|
init_units();
|
|
4130
5028
|
DOCXJS_RENDERER_ID = "docxjs";
|
|
5029
|
+
shapes = docxSubpath(
|
|
5030
|
+
"docx/shapes",
|
|
5031
|
+
"visual",
|
|
5032
|
+
() => import("docx/shapes")
|
|
5033
|
+
);
|
|
4131
5034
|
DOCXJS_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
4132
5035
|
"paragraphs",
|
|
4133
5036
|
"styles",
|
|
@@ -4140,8 +5043,10 @@ var init_docxjs = __esm({
|
|
|
4140
5043
|
"images",
|
|
4141
5044
|
"floating-images",
|
|
4142
5045
|
"svg-images",
|
|
5046
|
+
"charts",
|
|
4143
5047
|
"text-frames",
|
|
4144
5048
|
"text-boxes",
|
|
5049
|
+
"drawing-groups",
|
|
4145
5050
|
"toc",
|
|
4146
5051
|
"cached-toc",
|
|
4147
5052
|
"fields",
|
|
@@ -4162,124 +5067,332 @@ var init_docxjs = __esm({
|
|
|
4162
5067
|
}
|
|
4163
5068
|
});
|
|
4164
5069
|
|
|
4165
|
-
// src/
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
zip.addFile(name, Buffer.from(content, "utf8"));
|
|
5070
|
+
// src/renderers/office-open/chartLook.ts
|
|
5071
|
+
function seriesLook(chartType) {
|
|
5072
|
+
switch (chartType) {
|
|
5073
|
+
case "line":
|
|
5074
|
+
case "scatter":
|
|
5075
|
+
return { marker: MARKER, smooth: false };
|
|
5076
|
+
case "radar":
|
|
5077
|
+
return { marker: MARKER };
|
|
5078
|
+
case "column":
|
|
5079
|
+
case "bar":
|
|
5080
|
+
return { invertIfNegative: false };
|
|
5081
|
+
default:
|
|
5082
|
+
return {};
|
|
4179
5083
|
}
|
|
4180
|
-
|
|
4181
|
-
|
|
5084
|
+
}
|
|
5085
|
+
function axesLook(chartType) {
|
|
5086
|
+
switch (chartType) {
|
|
5087
|
+
case "column":
|
|
5088
|
+
case "bar":
|
|
5089
|
+
case "line":
|
|
5090
|
+
case "area": {
|
|
5091
|
+
const horizontal = chartType === "bar";
|
|
5092
|
+
return {
|
|
5093
|
+
categoryAxis: {
|
|
5094
|
+
position: horizontal ? "l" : "b",
|
|
5095
|
+
...NO_TICKS,
|
|
5096
|
+
line: AXIS_LINE
|
|
5097
|
+
},
|
|
5098
|
+
valueAxis: {
|
|
5099
|
+
position: horizontal ? "b" : "l",
|
|
5100
|
+
gridLine: GRIDLINES,
|
|
5101
|
+
...NO_TICKS,
|
|
5102
|
+
lineVisible: false,
|
|
5103
|
+
crossBetween: chartType === "area" ? "midCat" : "between"
|
|
5104
|
+
}
|
|
5105
|
+
};
|
|
5106
|
+
}
|
|
5107
|
+
case "radar":
|
|
5108
|
+
return {
|
|
5109
|
+
categoryAxis: {
|
|
5110
|
+
position: "b",
|
|
5111
|
+
gridLine: GRIDLINES,
|
|
5112
|
+
...NO_TICKS,
|
|
5113
|
+
majorTickMark: "cross",
|
|
5114
|
+
line: AXIS_LINE
|
|
5115
|
+
},
|
|
5116
|
+
valueAxis: {
|
|
5117
|
+
position: "l",
|
|
5118
|
+
gridLine: GRIDLINES,
|
|
5119
|
+
...NO_TICKS,
|
|
5120
|
+
majorTickMark: "cross",
|
|
5121
|
+
line: AXIS_LINE,
|
|
5122
|
+
crossBetween: "between"
|
|
5123
|
+
}
|
|
5124
|
+
};
|
|
5125
|
+
case "scatter": {
|
|
5126
|
+
const line = { ...AXIS_LINE, color: SCATTER_AXIS_TINT };
|
|
5127
|
+
return {
|
|
5128
|
+
categoryAxis: {
|
|
5129
|
+
position: "b",
|
|
5130
|
+
...NO_TICKS,
|
|
5131
|
+
line,
|
|
5132
|
+
crossBetween: "midCat"
|
|
5133
|
+
},
|
|
5134
|
+
valueAxis: {
|
|
5135
|
+
position: "l",
|
|
5136
|
+
gridLine: GRIDLINES,
|
|
5137
|
+
...NO_TICKS,
|
|
5138
|
+
line,
|
|
5139
|
+
crossBetween: "midCat"
|
|
5140
|
+
}
|
|
5141
|
+
};
|
|
5142
|
+
}
|
|
5143
|
+
default:
|
|
5144
|
+
return {};
|
|
4182
5145
|
}
|
|
4183
|
-
return new Uint8Array(zip.toBuffer());
|
|
4184
5146
|
}
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
5147
|
+
function plotLook(chart) {
|
|
5148
|
+
const common = {
|
|
5149
|
+
...axesLook(chart.chartType),
|
|
5150
|
+
autoTitleDeleted: !(chart.title && chart.showTitle !== false),
|
|
5151
|
+
plotAreaUnfilled: true
|
|
5152
|
+
};
|
|
5153
|
+
switch (chart.chartType) {
|
|
5154
|
+
case "column":
|
|
5155
|
+
return { ...common, dataBorder: "none", gapWidth: 219, overlap: -27 };
|
|
5156
|
+
case "bar":
|
|
5157
|
+
return { ...common, dataBorder: "none", gapWidth: 182, overlap: 0 };
|
|
5158
|
+
case "area":
|
|
5159
|
+
return { ...common, dataBorder: "none" };
|
|
5160
|
+
case "line":
|
|
5161
|
+
return { ...common, ...LINE_SERIES, lineMarkers: true };
|
|
5162
|
+
case "radar":
|
|
5163
|
+
return { ...common, ...LINE_SERIES, radarStyle: "marker" };
|
|
5164
|
+
case "scatter": {
|
|
5165
|
+
const labels = chart.series[0]?.labels ?? [];
|
|
5166
|
+
return {
|
|
5167
|
+
...common,
|
|
5168
|
+
...LINE_SERIES,
|
|
5169
|
+
lineWidthPoints: 1.5,
|
|
5170
|
+
scatterStyle: "lineMarker",
|
|
5171
|
+
scatterXValues: labels.map((_, index) => scatterX(labels, index))
|
|
5172
|
+
};
|
|
5173
|
+
}
|
|
5174
|
+
case "pie":
|
|
5175
|
+
case "doughnut":
|
|
5176
|
+
return {
|
|
5177
|
+
...common,
|
|
5178
|
+
dataBorder: { widthPoints: 1.5, color: { scheme: "lt1" } },
|
|
5179
|
+
firstSliceAngle: 0,
|
|
5180
|
+
...chart.chartType === "doughnut" ? { holeSize: 50 } : {}
|
|
5181
|
+
};
|
|
5182
|
+
default:
|
|
5183
|
+
return common;
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
var TEXT_1_TINT, SCATTER_AXIS_TINT, HAIRLINE_POINTS, GRIDLINES, AXIS_LINE, NO_TICKS, LINE_SERIES, MARKER;
|
|
5187
|
+
var init_chartLook = __esm({
|
|
5188
|
+
"src/renderers/office-open/chartLook.ts"() {
|
|
4188
5189
|
"use strict";
|
|
4189
|
-
|
|
4190
|
-
|
|
5190
|
+
init_chartValues();
|
|
5191
|
+
TEXT_1_TINT = { scheme: "tx1", lumMod: 15e3, lumOff: 85e3 };
|
|
5192
|
+
SCATTER_AXIS_TINT = {
|
|
5193
|
+
scheme: "tx1",
|
|
5194
|
+
lumMod: 25e3,
|
|
5195
|
+
lumOff: 75e3
|
|
5196
|
+
};
|
|
5197
|
+
HAIRLINE_POINTS = 0.75;
|
|
5198
|
+
GRIDLINES = {
|
|
5199
|
+
size: HAIRLINE_POINTS,
|
|
5200
|
+
color: TEXT_1_TINT
|
|
5201
|
+
};
|
|
5202
|
+
AXIS_LINE = {
|
|
5203
|
+
widthPoints: HAIRLINE_POINTS,
|
|
5204
|
+
color: TEXT_1_TINT
|
|
5205
|
+
};
|
|
5206
|
+
NO_TICKS = {
|
|
5207
|
+
majorTickMark: "none",
|
|
5208
|
+
minorTickMark: "none",
|
|
5209
|
+
tickLabelPosition: "nextTo"
|
|
5210
|
+
};
|
|
5211
|
+
LINE_SERIES = {
|
|
5212
|
+
lineWidthPoints: 2.25,
|
|
5213
|
+
lineCap: "rnd",
|
|
5214
|
+
lineJoin: "round",
|
|
5215
|
+
markerLineWidthPoints: HAIRLINE_POINTS
|
|
5216
|
+
};
|
|
5217
|
+
MARKER = { symbol: "circle", size: 5 };
|
|
4191
5218
|
}
|
|
4192
5219
|
});
|
|
4193
5220
|
|
|
4194
5221
|
// src/renderers/office-open/chartParts.ts
|
|
4195
5222
|
import {
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
matchChartParts,
|
|
4199
|
-
spliceChartXml
|
|
5223
|
+
finishChartXml,
|
|
5224
|
+
matchChartParts
|
|
4200
5225
|
} from "@json-to-office/shared/rendering";
|
|
4201
|
-
function
|
|
4202
|
-
const
|
|
4203
|
-
const textFont =
|
|
4204
|
-
const axisTitleFont =
|
|
4205
|
-
const chartTitleFont =
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
5226
|
+
function chartInput(chart) {
|
|
5227
|
+
const roles = chartTextRoles(chart.textFont);
|
|
5228
|
+
const textFont = roles.text;
|
|
5229
|
+
const axisTitleFont = roles.axisTitle;
|
|
5230
|
+
const chartTitleFont = roles.title;
|
|
5231
|
+
const look = plotLook(chart);
|
|
5232
|
+
const categoryAxis = {
|
|
5233
|
+
...look.categoryAxis,
|
|
5234
|
+
...chart.categoryAxisTitle ? { title: chart.categoryAxisTitle, titleFont: axisTitleFont } : {}
|
|
5235
|
+
};
|
|
5236
|
+
const valueAxis = {
|
|
5237
|
+
...look.valueAxis,
|
|
5238
|
+
...chart.valueAxisTitle ? { title: chart.valueAxisTitle, titleFont: axisTitleFont } : {}
|
|
4209
5239
|
};
|
|
4210
5240
|
return {
|
|
5241
|
+
...look,
|
|
4211
5242
|
chartType: chart.chartType,
|
|
4212
5243
|
series: chart.series,
|
|
4213
5244
|
colors: chart.colors,
|
|
5245
|
+
...chart.title && chart.showTitle !== false ? { title: chart.title } : {},
|
|
4214
5246
|
textFont,
|
|
4215
5247
|
titleFont: chartTitleFont,
|
|
4216
5248
|
...chart.legendPosition ? { legendPosition: chart.legendPosition } : {},
|
|
4217
|
-
...
|
|
4218
|
-
|
|
4219
|
-
title: chart.categoryAxisTitle,
|
|
4220
|
-
titleFont: axisTitleFont
|
|
4221
|
-
}
|
|
4222
|
-
} : {},
|
|
4223
|
-
...chart.valueAxisTitle ? {
|
|
4224
|
-
valueAxis: { title: chart.valueAxisTitle, titleFont: axisTitleFont }
|
|
4225
|
-
} : {}
|
|
5249
|
+
...Object.keys(categoryAxis).length > 0 ? { categoryAxis } : {},
|
|
5250
|
+
...Object.keys(valueAxis).length > 0 ? { valueAxis } : {}
|
|
4226
5251
|
};
|
|
4227
5252
|
}
|
|
4228
|
-
function
|
|
4229
|
-
|
|
4230
|
-
if (!entry) return;
|
|
4231
|
-
const xml = entry.getData().toString("utf8");
|
|
4232
|
-
if (xml.includes(`Extension="xlsx"`)) return;
|
|
4233
|
-
zip.updateFile(
|
|
4234
|
-
entry,
|
|
4235
|
-
Buffer.from(
|
|
4236
|
-
xml.replace(
|
|
4237
|
-
'<Default Extension="xml"',
|
|
4238
|
-
`<Default Extension="xlsx" ContentType="${CHART_WORKBOOK_CONTENT_TYPE}"/><Default Extension="xml"`
|
|
4239
|
-
),
|
|
4240
|
-
"utf8"
|
|
4241
|
-
)
|
|
4242
|
-
);
|
|
4243
|
-
}
|
|
4244
|
-
function spliceChartParts(zip, charts) {
|
|
4245
|
-
if (charts.length === 0) return;
|
|
5253
|
+
function finishChartParts(zip, charts2) {
|
|
5254
|
+
if (charts2.length === 0) return;
|
|
4246
5255
|
const parts = zip.getEntries().map((entry) => entry.entryName).map((name) => name.match(/^word\/charts\/chart(\d+)\.xml$/)).filter((match) => match !== null).map(
|
|
4247
5256
|
(match) => [
|
|
4248
5257
|
Number(match[1]),
|
|
4249
5258
|
zip.getEntry(match[0]).getData().toString("utf8")
|
|
4250
5259
|
]
|
|
4251
5260
|
);
|
|
4252
|
-
|
|
4253
|
-
|
|
5261
|
+
const inputs = charts2.map(chartInput);
|
|
5262
|
+
for (const { ordinal, xml, chart } of matchChartParts(parts, inputs)) {
|
|
5263
|
+
const finished = finishChartXml(xml, chart);
|
|
5264
|
+
if (finished === xml) continue;
|
|
4254
5265
|
zip.updateFile(
|
|
4255
5266
|
zip.getEntry(`word/charts/chart${ordinal}.xml`),
|
|
4256
|
-
Buffer.from(
|
|
5267
|
+
Buffer.from(finished, "utf8")
|
|
4257
5268
|
);
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
var init_chartParts = __esm({
|
|
5272
|
+
"src/renderers/office-open/chartParts.ts"() {
|
|
5273
|
+
"use strict";
|
|
5274
|
+
init_chartText();
|
|
5275
|
+
init_chartLook();
|
|
5276
|
+
}
|
|
5277
|
+
});
|
|
5278
|
+
|
|
5279
|
+
// src/renderers/office-open/themePart.ts
|
|
5280
|
+
function replaceOnce(xml, pattern, replacer, what) {
|
|
5281
|
+
const count = [...xml.matchAll(pattern)].length;
|
|
5282
|
+
if (count !== 1) {
|
|
5283
|
+
throw new Error(
|
|
5284
|
+
`office-open's theme part has ${count} ${what}, expected one`
|
|
4261
5285
|
);
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
5286
|
+
}
|
|
5287
|
+
return xml.replace(pattern, replacer);
|
|
5288
|
+
}
|
|
5289
|
+
function spliceTheme(zip, theme) {
|
|
5290
|
+
const entry = zip.getEntry(THEME_PART);
|
|
5291
|
+
if (!entry) throw new Error(`office-open wrote no ${THEME_PART}`);
|
|
5292
|
+
let xml = entry.getData().toString("utf8");
|
|
5293
|
+
const name = esc(theme.name);
|
|
5294
|
+
xml = renamed(xml, "theme", name);
|
|
5295
|
+
const colors = Object.entries(theme.colors);
|
|
5296
|
+
if (colors.some(([, color]) => color)) {
|
|
5297
|
+
xml = renamed(xml, "clrScheme", name);
|
|
5298
|
+
for (const [slot, color] of colors) {
|
|
5299
|
+
if (!color) continue;
|
|
5300
|
+
const element = SCHEME_ELEMENT[slot];
|
|
5301
|
+
xml = replaceOnce(
|
|
5302
|
+
xml,
|
|
5303
|
+
new RegExp(`<a:${element}>[\\s\\S]*?</a:${element}>`, "g"),
|
|
5304
|
+
() => `<a:${element}><a:srgbClr val="${color.hex}"/></a:${element}>`,
|
|
5305
|
+
`a:${element}`
|
|
5306
|
+
);
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
if (theme.headingFont || theme.bodyFont) {
|
|
5310
|
+
xml = renamed(xml, "fontScheme", name);
|
|
5311
|
+
for (const [collection, key, officeFace] of OFFICE_FACES) {
|
|
5312
|
+
const family = theme[key];
|
|
5313
|
+
if (family === void 0 || family === officeFace) continue;
|
|
5314
|
+
xml = replaceOnce(
|
|
5315
|
+
xml,
|
|
5316
|
+
new RegExp(`(<a:${collection}>)<a:latin\\b[^>]*/>`, "g"),
|
|
5317
|
+
(_match, open) => `${open}<a:latin typeface="${esc(family)}"/>`,
|
|
5318
|
+
`a:${collection} a:latin`
|
|
5319
|
+
);
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
zip.updateFile(THEME_PART, Buffer.from(xml, "utf8"));
|
|
5323
|
+
}
|
|
5324
|
+
var THEME_PART, SCHEME_ELEMENT, OFFICE_FACES, esc, renamed;
|
|
5325
|
+
var init_themePart = __esm({
|
|
5326
|
+
"src/renderers/office-open/themePart.ts"() {
|
|
5327
|
+
"use strict";
|
|
5328
|
+
THEME_PART = "word/theme/theme1.xml";
|
|
5329
|
+
SCHEME_ELEMENT = {
|
|
5330
|
+
dark1: "dk1",
|
|
5331
|
+
light1: "lt1",
|
|
5332
|
+
dark2: "dk2",
|
|
5333
|
+
light2: "lt2",
|
|
5334
|
+
accent1: "accent1",
|
|
5335
|
+
accent2: "accent2",
|
|
5336
|
+
accent3: "accent3",
|
|
5337
|
+
accent4: "accent4",
|
|
5338
|
+
accent5: "accent5",
|
|
5339
|
+
accent6: "accent6",
|
|
5340
|
+
hyperlink: "hlink",
|
|
5341
|
+
followedHyperlink: "folHlink"
|
|
5342
|
+
};
|
|
5343
|
+
OFFICE_FACES = [
|
|
5344
|
+
["majorFont", "headingFont", "Calibri Light"],
|
|
5345
|
+
["minorFont", "bodyFont", "Calibri"]
|
|
5346
|
+
];
|
|
5347
|
+
esc = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
5348
|
+
renamed = (xml, element, name) => replaceOnce(
|
|
5349
|
+
xml,
|
|
5350
|
+
new RegExp(`(<a:${element}\\b[^>]*?\\bname=")[^"]*(")`, "g"),
|
|
5351
|
+
(_match, open, close) => `${open}${name}${close}`,
|
|
5352
|
+
`a:${element} name`
|
|
4265
5353
|
);
|
|
4266
5354
|
}
|
|
4267
|
-
|
|
5355
|
+
});
|
|
5356
|
+
|
|
5357
|
+
// src/utils/chartWorkbook.ts
|
|
5358
|
+
import AdmZip4 from "adm-zip";
|
|
5359
|
+
import { chartWorkbookParts } from "@json-to-office/shared/rendering";
|
|
5360
|
+
import {
|
|
5361
|
+
CHART_WORKBOOK_SHEET_NAME,
|
|
5362
|
+
categoryReference,
|
|
5363
|
+
columnLetter,
|
|
5364
|
+
seriesNameReference,
|
|
5365
|
+
seriesValueReference
|
|
5366
|
+
} from "@json-to-office/shared/rendering";
|
|
5367
|
+
function buildChartWorkbook(series, options = {}) {
|
|
5368
|
+
const zip = new AdmZip4();
|
|
5369
|
+
for (const [name, content] of chartWorkbookParts(series, options)) {
|
|
5370
|
+
zip.addFile(name, Buffer.from(content, "utf8"));
|
|
5371
|
+
}
|
|
5372
|
+
for (const entry of zip.getEntries()) {
|
|
5373
|
+
entry.header.timeval = WORKBOOK_TIMESTAMP;
|
|
5374
|
+
}
|
|
5375
|
+
return new Uint8Array(zip.toBuffer());
|
|
4268
5376
|
}
|
|
4269
|
-
var
|
|
4270
|
-
var
|
|
4271
|
-
"src/
|
|
5377
|
+
var WORKBOOK_TIMESTAMP;
|
|
5378
|
+
var init_chartWorkbook = __esm({
|
|
5379
|
+
"src/utils/chartWorkbook.ts"() {
|
|
4272
5380
|
"use strict";
|
|
4273
|
-
|
|
4274
|
-
|
|
5381
|
+
init_packageDocument();
|
|
5382
|
+
WORKBOOK_TIMESTAMP = toDosTime(DEFAULT_GENERATION_DATE);
|
|
4275
5383
|
}
|
|
4276
5384
|
});
|
|
4277
5385
|
|
|
4278
5386
|
// src/renderers/office-open/emit.ts
|
|
4279
|
-
import { assertNever as
|
|
5387
|
+
import { assertNever as assertNever3 } from "@json-to-office/shared/rendering";
|
|
5388
|
+
import { chartLook, withSeriesLook } from "@json-to-office/shared/rendering";
|
|
4280
5389
|
function emptyContext() {
|
|
4281
5390
|
let next = 1;
|
|
4282
|
-
return {
|
|
5391
|
+
return {
|
|
5392
|
+
pictures: /* @__PURE__ */ new Map(),
|
|
5393
|
+
nextDrawingId: () => next++,
|
|
5394
|
+
charts: []
|
|
5395
|
+
};
|
|
4283
5396
|
}
|
|
4284
5397
|
function simpleField(instruction, cachedText) {
|
|
4285
5398
|
return {
|
|
@@ -4289,6 +5402,9 @@ function simpleField(instruction, cachedText) {
|
|
|
4289
5402
|
}
|
|
4290
5403
|
};
|
|
4291
5404
|
}
|
|
5405
|
+
function twips(value) {
|
|
5406
|
+
return Math.floor(value);
|
|
5407
|
+
}
|
|
4292
5408
|
function runProperties2(formatting) {
|
|
4293
5409
|
if (!formatting) return {};
|
|
4294
5410
|
const out = {};
|
|
@@ -4316,16 +5432,19 @@ function runProperties2(formatting) {
|
|
|
4316
5432
|
if (formatting.doubleStrike !== void 0) {
|
|
4317
5433
|
out.doubleStrike = formatting.doubleStrike;
|
|
4318
5434
|
}
|
|
4319
|
-
if (formatting.superScript) out.
|
|
4320
|
-
if (formatting.subScript) out.
|
|
5435
|
+
if (formatting.superScript) out.verticalAlign = "superscript";
|
|
5436
|
+
if (formatting.subScript) out.verticalAlign = "subscript";
|
|
4321
5437
|
if (formatting.smallCaps !== void 0) out.smallCaps = formatting.smallCaps;
|
|
4322
5438
|
if (formatting.allCaps !== void 0) out.allCaps = formatting.allCaps;
|
|
4323
|
-
if (formatting.highlight !== void 0)
|
|
5439
|
+
if (formatting.highlight !== void 0) {
|
|
5440
|
+
out.highlight = formatting.highlight;
|
|
5441
|
+
}
|
|
4324
5442
|
if (formatting.shading) out.shading = shading(formatting.shading);
|
|
4325
5443
|
if (formatting.scalePercent !== void 0)
|
|
4326
5444
|
out.scale = formatting.scalePercent;
|
|
4327
|
-
|
|
4328
|
-
|
|
5445
|
+
const stated = formatting.characterSpacingTwentieths;
|
|
5446
|
+
if (stated !== void 0 && stated !== 0) {
|
|
5447
|
+
out.characterSpacing = twips(stated);
|
|
4329
5448
|
}
|
|
4330
5449
|
if (formatting.language) out.language = { value: formatting.language };
|
|
4331
5450
|
if (formatting.noProof !== void 0) out.noProof = formatting.noProof;
|
|
@@ -4355,7 +5474,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4355
5474
|
switch (child.kind) {
|
|
4356
5475
|
case "lineBreak":
|
|
4357
5476
|
pendingBreaks += 1;
|
|
4358
|
-
if (child.clear && child.clear !== "none")
|
|
5477
|
+
if (child.clear && child.clear !== "none") {
|
|
5478
|
+
pendingClear = child.clear;
|
|
5479
|
+
}
|
|
4359
5480
|
break;
|
|
4360
5481
|
case "text":
|
|
4361
5482
|
out.push({
|
|
@@ -4393,7 +5514,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4393
5514
|
case "drawingGroup": {
|
|
4394
5515
|
const pending = breakOption();
|
|
4395
5516
|
if (pending.break) out.push(pending);
|
|
4396
|
-
out.push({ wpgGroup:
|
|
5517
|
+
out.push({ wpgGroup: drawingGroupOptions2(child, ctx) });
|
|
4397
5518
|
break;
|
|
4398
5519
|
}
|
|
4399
5520
|
case "hyperlink":
|
|
@@ -4423,8 +5544,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4423
5544
|
out.push({ wpsShape: shapeOptions(child, ctx) });
|
|
4424
5545
|
break;
|
|
4425
5546
|
case "chart":
|
|
4426
|
-
|
|
4427
|
-
|
|
5547
|
+
out.push({
|
|
5548
|
+
chart: chartOptions(child, ctx, ctx.charts?.push(child) ?? 1)
|
|
5549
|
+
});
|
|
4428
5550
|
break;
|
|
4429
5551
|
case "noteReference":
|
|
4430
5552
|
out.push(
|
|
@@ -4432,7 +5554,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4432
5554
|
);
|
|
4433
5555
|
break;
|
|
4434
5556
|
default:
|
|
4435
|
-
|
|
5557
|
+
assertNever3(child, "DocxIrInline");
|
|
4436
5558
|
}
|
|
4437
5559
|
}
|
|
4438
5560
|
return out;
|
|
@@ -4473,8 +5595,11 @@ function floatingOptions2(floating) {
|
|
|
4473
5595
|
...floating.vertical ? { verticalPosition: position(floating.vertical) } : {},
|
|
4474
5596
|
...floating.wrap ? {
|
|
4475
5597
|
wrap: {
|
|
4476
|
-
|
|
4477
|
-
|
|
5598
|
+
// Named, as OOXML names them; 0.11 took docx.js's numbers.
|
|
5599
|
+
type: floating.wrap.type,
|
|
5600
|
+
...floating.wrap.side ? {
|
|
5601
|
+
side: floating.wrap.side
|
|
5602
|
+
} : {}
|
|
4478
5603
|
}
|
|
4479
5604
|
} : {},
|
|
4480
5605
|
...floating.margins ? {
|
|
@@ -4501,66 +5626,92 @@ function imageMedia(ctx, resourceId, placement) {
|
|
|
4501
5626
|
}
|
|
4502
5627
|
function pictureOptions(image, ctx) {
|
|
4503
5628
|
const media = imageMedia(ctx, image.resourceId, image);
|
|
4504
|
-
|
|
4505
|
-
type:
|
|
5629
|
+
const source = media.type === "svg" ? {
|
|
5630
|
+
type: "svg",
|
|
4506
5631
|
data: media.data,
|
|
4507
|
-
//
|
|
4508
|
-
//
|
|
4509
|
-
|
|
5632
|
+
// The SVG slot always carries a raster: `prepareImages` falls back
|
|
5633
|
+
// to the vector bytes when none could be made.
|
|
5634
|
+
fallback: media.fallback ?? {
|
|
5635
|
+
type: "png",
|
|
5636
|
+
data: media.data
|
|
5637
|
+
}
|
|
5638
|
+
} : { type: media.type, data: media.data };
|
|
5639
|
+
return {
|
|
5640
|
+
...source,
|
|
4510
5641
|
// Raw numbers are EMUs in @office-open/docx. Passing pixels here makes a
|
|
4511
5642
|
// normal image only a few hundred EMUs wide, effectively a dot.
|
|
4512
5643
|
transformation: { width: image.widthEmu, height: image.heightEmu },
|
|
4513
5644
|
// The id is stated rather than left to the backend's process-global
|
|
4514
|
-
// counter. `name` stays empty, which is what
|
|
4515
|
-
|
|
4516
|
-
altText: { id: String(ctx.nextDrawingId()) },
|
|
5645
|
+
// counter. `name` stays empty, which is what the backend falls back to.
|
|
5646
|
+
altText: { id: String(ctx.nextDrawingId()), name: "" },
|
|
4517
5647
|
...image.floating ? { floating: floatingOptions2(image.floating) } : {}
|
|
4518
5648
|
// No `description` or `title`: no DOCX this pipeline has produced carries
|
|
4519
5649
|
// `wp:docPr` alt text, and the compiler warns so the gap is visible rather
|
|
4520
5650
|
// than silent.
|
|
4521
5651
|
};
|
|
4522
5652
|
}
|
|
4523
|
-
function
|
|
5653
|
+
function drawingGroupOptions2(group, ctx) {
|
|
4524
5654
|
const id = ctx.nextDrawingId();
|
|
4525
5655
|
return {
|
|
4526
5656
|
altText: {
|
|
4527
5657
|
id: String(id),
|
|
5658
|
+
name: "",
|
|
4528
5659
|
...group.altText ? { description: group.altText } : {}
|
|
4529
5660
|
},
|
|
4530
5661
|
transformation: { width: group.widthEmu, height: group.heightEmu },
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
5662
|
+
childOffsetX: 0,
|
|
5663
|
+
childOffsetY: 0,
|
|
5664
|
+
childExtentWidth: group.canvasWidthEmu,
|
|
5665
|
+
childExtentHeight: group.canvasHeightEmu,
|
|
5666
|
+
children: group.children.map((child) => groupChild2(child, ctx)),
|
|
4534
5667
|
...group.floating ? { floating: floatingOptions2(group.floating) } : {}
|
|
4535
5668
|
};
|
|
4536
5669
|
}
|
|
4537
|
-
function chartOptions(chart, ctx) {
|
|
5670
|
+
function chartOptions(chart, ctx, ordinal) {
|
|
4538
5671
|
const id = ctx.nextDrawingId();
|
|
5672
|
+
const input = chartInput(chart);
|
|
5673
|
+
const look = chartLook(input);
|
|
4539
5674
|
return {
|
|
4540
5675
|
type: chart.chartType,
|
|
4541
5676
|
categories: chart.series[0]?.labels ?? [],
|
|
4542
|
-
series: chart.series.map(
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
5677
|
+
series: chart.series.map(
|
|
5678
|
+
(entry, index) => withSeriesLook(
|
|
5679
|
+
{
|
|
5680
|
+
name: entry.name ?? `Series ${index + 1}`,
|
|
5681
|
+
values: entry.values,
|
|
5682
|
+
...seriesLook(chart.chartType)
|
|
5683
|
+
},
|
|
5684
|
+
look.series[index]
|
|
5685
|
+
)
|
|
5686
|
+
),
|
|
5687
|
+
...look.chart,
|
|
4547
5688
|
...chart.showLegend !== void 0 ? { showLegend: chart.showLegend } : {},
|
|
5689
|
+
externalData: {
|
|
5690
|
+
...look.chart.externalData,
|
|
5691
|
+
fileName: `chart${ordinal}.xlsx`,
|
|
5692
|
+
// A scatter chart's column A holds the x values its `c:xVal` caches.
|
|
5693
|
+
data: buildChartWorkbook(
|
|
5694
|
+
chart.series,
|
|
5695
|
+
input.scatterXValues ? { categoryValues: input.scatterXValues } : {}
|
|
5696
|
+
)
|
|
5697
|
+
},
|
|
4548
5698
|
transformation: { width: chart.widthEmu, height: chart.heightEmu },
|
|
4549
5699
|
altText: {
|
|
4550
5700
|
id: String(id),
|
|
5701
|
+
name: "",
|
|
4551
5702
|
...chart.altText ? { description: chart.altText } : {}
|
|
4552
5703
|
},
|
|
4553
5704
|
...chart.floating ? { floating: floatingOptions2(chart.floating) } : {}
|
|
4554
5705
|
};
|
|
4555
5706
|
}
|
|
4556
|
-
function
|
|
5707
|
+
function groupChild2(child, ctx) {
|
|
4557
5708
|
return child.kind === "shape" ? groupShape(child, ctx) : groupPicture(child, ctx);
|
|
4558
5709
|
}
|
|
4559
5710
|
function groupShape(shape, ctx) {
|
|
4560
5711
|
const id = ctx.nextDrawingId();
|
|
4561
5712
|
return {
|
|
4562
5713
|
type: "wps",
|
|
4563
|
-
transformation:
|
|
5714
|
+
transformation: childTransformation2(shape.frame),
|
|
4564
5715
|
data: {
|
|
4565
5716
|
nonVisualProperties: {
|
|
4566
5717
|
id,
|
|
@@ -4569,7 +5720,7 @@ function groupShape(shape, ctx) {
|
|
|
4569
5720
|
// to hold text, and it changes how the object behaves on selection.
|
|
4570
5721
|
...shape.isTextBox ? { textBox: "1" } : {}
|
|
4571
5722
|
},
|
|
4572
|
-
|
|
5723
|
+
geometry: shape.geometry,
|
|
4573
5724
|
...shape.fill ? { fill: drawingFill(shape.fill) } : {},
|
|
4574
5725
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
4575
5726
|
children: (shape.text?.paragraphs ?? []).map(
|
|
@@ -4595,7 +5746,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4595
5746
|
fileName: media.fallbackFileName
|
|
4596
5747
|
}
|
|
4597
5748
|
} : {},
|
|
4598
|
-
transformation:
|
|
5749
|
+
transformation: childTransformation2(picture2.frame),
|
|
4599
5750
|
nonVisualProperties: {
|
|
4600
5751
|
id,
|
|
4601
5752
|
...picture2.name ? { name: picture2.name } : {},
|
|
@@ -4604,11 +5755,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4604
5755
|
...picture2.crop ? { sourceRectangle: sourceRectangle(picture2.crop) } : {}
|
|
4605
5756
|
};
|
|
4606
5757
|
}
|
|
4607
|
-
function
|
|
4608
|
-
const flip = {
|
|
4609
|
-
...frame.flipHorizontal ? { horizontal: true } : {},
|
|
4610
|
-
...frame.flipVertical ? { vertical: true } : {}
|
|
4611
|
-
};
|
|
5758
|
+
function childTransformation2(frame) {
|
|
4612
5759
|
return {
|
|
4613
5760
|
offset: {
|
|
4614
5761
|
emus: { x: frame.xEmu, y: frame.yEmu },
|
|
@@ -4624,7 +5771,8 @@ function childTransformation(frame) {
|
|
|
4624
5771
|
},
|
|
4625
5772
|
// Degrees: the backend multiplies by 60000 on the way into `@rot`.
|
|
4626
5773
|
...frame.rotationDegrees !== void 0 ? { rotation: frame.rotationDegrees } : {},
|
|
4627
|
-
...
|
|
5774
|
+
...frame.flipHorizontal ? { flipHorizontal: true } : {},
|
|
5775
|
+
...frame.flipVertical ? { flipVertical: true } : {}
|
|
4628
5776
|
};
|
|
4629
5777
|
}
|
|
4630
5778
|
function drawingFill(fill) {
|
|
@@ -4632,7 +5780,6 @@ function drawingFill(fill) {
|
|
|
4632
5780
|
return {
|
|
4633
5781
|
type: "solid",
|
|
4634
5782
|
color: {
|
|
4635
|
-
type: "rgb",
|
|
4636
5783
|
value: fill.color.hex,
|
|
4637
5784
|
// Transparency becomes an alpha transform on the colour. DrawingML
|
|
4638
5785
|
// states *opacity*, so the value is the complement of what the author
|
|
@@ -4674,7 +5821,7 @@ function sourceRectangle(crop) {
|
|
|
4674
5821
|
function shapeOptions(shape, ctx) {
|
|
4675
5822
|
const id = String(ctx.nextDrawingId());
|
|
4676
5823
|
return {
|
|
4677
|
-
altText: { id },
|
|
5824
|
+
altText: { id, name: "" },
|
|
4678
5825
|
children: shape.children.map((child) => paragraph(child, ctx)),
|
|
4679
5826
|
// Raw transformation numbers are EMUs in @office-open/docx, while the IR
|
|
4680
5827
|
// deliberately stores native shape dimensions in pixels.
|
|
@@ -4685,7 +5832,7 @@ function shapeOptions(shape, ctx) {
|
|
|
4685
5832
|
...shape.fill ? {
|
|
4686
5833
|
fill: {
|
|
4687
5834
|
type: "solid",
|
|
4688
|
-
color: {
|
|
5835
|
+
color: { value: shape.fill.hex }
|
|
4689
5836
|
}
|
|
4690
5837
|
} : {},
|
|
4691
5838
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
@@ -4716,16 +5863,16 @@ function paragraphProperties2(formatting) {
|
|
|
4716
5863
|
if (formatting.indent) {
|
|
4717
5864
|
const indent = {};
|
|
4718
5865
|
if (formatting.indent.leftTwips !== void 0) {
|
|
4719
|
-
indent.left = formatting.indent.leftTwips;
|
|
5866
|
+
indent.left = twips(formatting.indent.leftTwips);
|
|
4720
5867
|
}
|
|
4721
5868
|
if (formatting.indent.rightTwips !== void 0) {
|
|
4722
|
-
indent.right = formatting.indent.rightTwips;
|
|
5869
|
+
indent.right = twips(formatting.indent.rightTwips);
|
|
4723
5870
|
}
|
|
4724
5871
|
if (formatting.indent.firstLineTwips !== void 0) {
|
|
4725
|
-
indent.firstLine = formatting.indent.firstLineTwips;
|
|
5872
|
+
indent.firstLine = twips(formatting.indent.firstLineTwips);
|
|
4726
5873
|
}
|
|
4727
5874
|
if (formatting.indent.hangingTwips !== void 0) {
|
|
4728
|
-
indent.hanging = formatting.indent.hangingTwips;
|
|
5875
|
+
indent.hanging = twips(formatting.indent.hangingTwips);
|
|
4729
5876
|
}
|
|
4730
5877
|
out.indent = indent;
|
|
4731
5878
|
}
|
|
@@ -4790,13 +5937,19 @@ function frameOptions2(frame) {
|
|
|
4790
5937
|
...frame.anchorLock !== void 0 ? { anchorLock: frame.anchorLock } : {},
|
|
4791
5938
|
...frame.rule ? { rule: frame.rule } : {}
|
|
4792
5939
|
};
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
5940
|
+
if (frame.xTwips !== void 0 || frame.yTwips !== void 0) {
|
|
5941
|
+
return {
|
|
5942
|
+
type: "absolute",
|
|
5943
|
+
position: { x: frame.xTwips ?? 0, y: frame.yTwips ?? 0 },
|
|
5944
|
+
...base
|
|
5945
|
+
};
|
|
5946
|
+
}
|
|
5947
|
+
return {
|
|
4798
5948
|
type: "alignment",
|
|
4799
|
-
alignment: {
|
|
5949
|
+
alignment: {
|
|
5950
|
+
x: frame.xAlign,
|
|
5951
|
+
y: frame.yAlign
|
|
5952
|
+
},
|
|
4800
5953
|
...base
|
|
4801
5954
|
};
|
|
4802
5955
|
}
|
|
@@ -4817,7 +5970,7 @@ function block(value, ctx = emptyContext()) {
|
|
|
4817
5970
|
case "toc":
|
|
4818
5971
|
return { toc: tableOfContents(value) };
|
|
4819
5972
|
default:
|
|
4820
|
-
return
|
|
5973
|
+
return assertNever3(value, "DocxIrBlock");
|
|
4821
5974
|
}
|
|
4822
5975
|
}
|
|
4823
5976
|
function tocEntry(entry) {
|
|
@@ -4836,6 +5989,7 @@ function tableOfContents(value) {
|
|
|
4836
5989
|
headingStyleRange: `${value.headingRange.from}-${value.headingRange.to}`
|
|
4837
5990
|
} : {},
|
|
4838
5991
|
...value.styleLevels?.length ? {
|
|
5992
|
+
// `StyleLevel` is a class the backend only reads the two fields of.
|
|
4839
5993
|
stylesWithLevels: value.styleLevels.map((style) => ({
|
|
4840
5994
|
styleName: style.styleName,
|
|
4841
5995
|
level: style.level
|
|
@@ -4856,15 +6010,17 @@ function table(value, ctx) {
|
|
|
4856
6010
|
// `w:w` is an integer in OOXML. A grid that splits a remainder between
|
|
4857
6011
|
// unstated columns comes out fractional, and the XML would carry it
|
|
4858
6012
|
// verbatim; floored here, as the docxjs backend floors it.
|
|
4859
|
-
size: value.width.kind === "auto" ? 0 : value.width.kind === "twips" ?
|
|
4860
|
-
type: value.width.kind === "twips" ? "
|
|
6013
|
+
size: value.width.kind === "auto" ? 0 : value.width.kind === "twips" ? twips(value.width.value) : value.width.value,
|
|
6014
|
+
type: value.width.kind === "twips" ? "twips" : value.width.kind === "percent" ? "percent" : "auto"
|
|
4861
6015
|
},
|
|
4862
6016
|
layout: value.layout,
|
|
4863
6017
|
// An empty grid is a table with nothing to say about its columns, which is
|
|
4864
6018
|
// not the same as one whose columns are all zero wide. The compiler hands
|
|
4865
6019
|
// over every grid in twips; floored for the same reason as the width.
|
|
4866
|
-
...value.columnGrid.values.length > 0 ? { columnWidths: value.columnGrid.values.map(
|
|
4867
|
-
...value.alignment ? {
|
|
6020
|
+
...value.columnGrid.values.length > 0 ? { columnWidths: value.columnGrid.values.map(twips) } : {},
|
|
6021
|
+
...value.alignment ? {
|
|
6022
|
+
alignment: alignment(value.alignment)
|
|
6023
|
+
} : {},
|
|
4868
6024
|
...value.borders ? { borders: borders2(value.borders) } : {},
|
|
4869
6025
|
...value.cellMargins ? { margins: cellMargins(value.cellMargins) } : {},
|
|
4870
6026
|
...value.floating ? { float: tableFloat2(value.floating) } : {}
|
|
@@ -4874,14 +6030,22 @@ function tableFloat2(floating) {
|
|
|
4874
6030
|
return {
|
|
4875
6031
|
...floating.horizontalAnchor ? { horizontalAnchor: floating.horizontalAnchor } : {},
|
|
4876
6032
|
...floating.verticalAnchor ? { verticalAnchor: floating.verticalAnchor } : {},
|
|
4877
|
-
...floating.absoluteHorizontalPositionTwips !== void 0 ? {
|
|
6033
|
+
...floating.absoluteHorizontalPositionTwips !== void 0 ? {
|
|
6034
|
+
absoluteHorizontalPosition: twips(
|
|
6035
|
+
floating.absoluteHorizontalPositionTwips
|
|
6036
|
+
)
|
|
6037
|
+
} : {},
|
|
4878
6038
|
...floating.relativeHorizontalPosition ? { relativeHorizontalPosition: floating.relativeHorizontalPosition } : {},
|
|
4879
|
-
...floating.absoluteVerticalPositionTwips !== void 0 ? {
|
|
6039
|
+
...floating.absoluteVerticalPositionTwips !== void 0 ? {
|
|
6040
|
+
absoluteVerticalPosition: twips(
|
|
6041
|
+
floating.absoluteVerticalPositionTwips
|
|
6042
|
+
)
|
|
6043
|
+
} : {},
|
|
4880
6044
|
...floating.relativeVerticalPosition ? { relativeVerticalPosition: floating.relativeVerticalPosition } : {},
|
|
4881
|
-
...floating.topFromTextTwips !== void 0 ? { topFromText: floating.topFromTextTwips } : {},
|
|
4882
|
-
...floating.rightFromTextTwips !== void 0 ? { rightFromText: floating.rightFromTextTwips } : {},
|
|
4883
|
-
...floating.bottomFromTextTwips !== void 0 ? { bottomFromText: floating.bottomFromTextTwips } : {},
|
|
4884
|
-
...floating.leftFromTextTwips !== void 0 ? { leftFromText: floating.leftFromTextTwips } : {},
|
|
6045
|
+
...floating.topFromTextTwips !== void 0 ? { topFromText: twips(floating.topFromTextTwips) } : {},
|
|
6046
|
+
...floating.rightFromTextTwips !== void 0 ? { rightFromText: twips(floating.rightFromTextTwips) } : {},
|
|
6047
|
+
...floating.bottomFromTextTwips !== void 0 ? { bottomFromText: twips(floating.bottomFromTextTwips) } : {},
|
|
6048
|
+
...floating.leftFromTextTwips !== void 0 ? { leftFromText: twips(floating.leftFromTextTwips) } : {},
|
|
4885
6049
|
...floating.overlap ? { overlap: floating.overlap } : {}
|
|
4886
6050
|
};
|
|
4887
6051
|
}
|
|
@@ -4889,7 +6053,10 @@ function tableRow(row, ctx) {
|
|
|
4889
6053
|
return {
|
|
4890
6054
|
cells: row.cells.map((cell) => tableCell(cell, ctx)),
|
|
4891
6055
|
...row.heightTwips !== void 0 ? {
|
|
4892
|
-
height: {
|
|
6056
|
+
height: {
|
|
6057
|
+
value: twips(row.heightTwips),
|
|
6058
|
+
rule: row.heightRule ?? "atLeast"
|
|
6059
|
+
}
|
|
4893
6060
|
} : {},
|
|
4894
6061
|
...row.isHeader !== void 0 ? { tableHeader: row.isHeader } : {},
|
|
4895
6062
|
...row.cantSplit !== void 0 ? { cantSplit: row.cantSplit } : {},
|
|
@@ -4897,20 +6064,30 @@ function tableRow(row, ctx) {
|
|
|
4897
6064
|
};
|
|
4898
6065
|
}
|
|
4899
6066
|
function tableCell(cell, ctx) {
|
|
6067
|
+
const children = cellChildren2(cell, ctx);
|
|
6068
|
+
if (cell.children[cell.children.length - 1]?.kind === "toc")
|
|
6069
|
+
children.push({ paragraph: { children: [] } });
|
|
4900
6070
|
return {
|
|
4901
|
-
children
|
|
4902
|
-
...cell.widthTwips !== void 0 ? { width: { size: cell.widthTwips, type: "
|
|
4903
|
-
...cell.verticalAlign ? {
|
|
6071
|
+
children,
|
|
6072
|
+
...cell.widthTwips !== void 0 ? { width: { size: twips(cell.widthTwips), type: "twips" } } : {},
|
|
6073
|
+
...cell.verticalAlign ? {
|
|
6074
|
+
verticalAlign: cell.verticalAlign
|
|
6075
|
+
} : {},
|
|
4904
6076
|
...cell.shading ? { shading: shading(cell.shading) } : {},
|
|
4905
6077
|
...cell.margins ? { margins: cellMargins(cell.margins) } : {},
|
|
4906
6078
|
...cell.borders ? { borders: borders2(cell.borders) } : {},
|
|
4907
6079
|
...cell.columnSpan !== void 0 ? { columnSpan: cell.columnSpan } : {},
|
|
4908
6080
|
...cell.rowSpan !== void 0 ? { verticalMerge: cell.rowSpan } : {},
|
|
4909
|
-
...cell.textDirection ? {
|
|
6081
|
+
...cell.textDirection ? {
|
|
6082
|
+
textDirection: cell.textDirection
|
|
6083
|
+
} : {}
|
|
4910
6084
|
};
|
|
4911
6085
|
}
|
|
6086
|
+
function cellChildren2(cell, ctx) {
|
|
6087
|
+
return cell.children.map((child) => block(child, ctx));
|
|
6088
|
+
}
|
|
4912
6089
|
function cellMargins(margins) {
|
|
4913
|
-
const side = (value) => value === void 0 ? void 0 : { size: value, type: "
|
|
6090
|
+
const side = (value) => value === void 0 ? void 0 : { size: twips(value), type: "twips" };
|
|
4914
6091
|
const out = {};
|
|
4915
6092
|
for (const [name, value] of [
|
|
4916
6093
|
["top", margins.topTwips],
|
|
@@ -4953,47 +6130,51 @@ function section(value, ctx, closesDocument = false) {
|
|
|
4953
6130
|
properties: {
|
|
4954
6131
|
...value.properties.type ? { type: value.properties.type } : {},
|
|
4955
6132
|
...value.properties.titlePage !== void 0 ? { titlePage: value.properties.titlePage } : {},
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
...page.code !== void 0 ? { code: page.code } : {}
|
|
4963
|
-
},
|
|
4964
|
-
margin: {
|
|
4965
|
-
top: page.margins.topTwips,
|
|
4966
|
-
right: page.margins.rightTwips,
|
|
4967
|
-
bottom: page.margins.bottomTwips,
|
|
4968
|
-
left: page.margins.leftTwips,
|
|
4969
|
-
...page.margins.headerTwips !== void 0 ? { header: page.margins.headerTwips } : {},
|
|
4970
|
-
...page.margins.footerTwips !== void 0 ? { footer: page.margins.footerTwips } : {},
|
|
4971
|
-
...page.margins.gutterTwips !== void 0 ? { gutter: page.margins.gutterTwips } : {}
|
|
4972
|
-
},
|
|
4973
|
-
...value.properties.pageNumbers ? {
|
|
4974
|
-
pageNumbers: {
|
|
4975
|
-
...value.properties.pageNumbers.start !== void 0 ? { start: value.properties.pageNumbers.start } : {},
|
|
4976
|
-
...value.properties.pageNumbers.formatType ? { formatType: value.properties.pageNumbers.formatType } : {}
|
|
4977
|
-
}
|
|
4978
|
-
} : {},
|
|
4979
|
-
...value.properties.borders ? {
|
|
4980
|
-
borders: {
|
|
4981
|
-
...value.properties.borders.display ? { display: value.properties.borders.display } : {},
|
|
4982
|
-
...value.properties.borders.offsetFrom ? { offsetFrom: value.properties.borders.offsetFrom } : {},
|
|
4983
|
-
...value.properties.borders.borders ? borders2(value.properties.borders.borders) : {}
|
|
4984
|
-
}
|
|
4985
|
-
} : {}
|
|
6133
|
+
// Orientation is implied by the width/height pair, which is how this
|
|
6134
|
+
// pipeline has always expressed it; stating it as well changes `w:pgSz`.
|
|
6135
|
+
pageSize: {
|
|
6136
|
+
width: twips(page.widthTwips),
|
|
6137
|
+
height: twips(page.heightTwips),
|
|
6138
|
+
...page.code !== void 0 ? { code: page.code } : {}
|
|
4986
6139
|
},
|
|
6140
|
+
pageMargin: {
|
|
6141
|
+
top: twips(page.margins.topTwips),
|
|
6142
|
+
right: twips(page.margins.rightTwips),
|
|
6143
|
+
bottom: twips(page.margins.bottomTwips),
|
|
6144
|
+
left: twips(page.margins.leftTwips),
|
|
6145
|
+
...page.margins.headerTwips !== void 0 ? { header: twips(page.margins.headerTwips) } : {},
|
|
6146
|
+
...page.margins.footerTwips !== void 0 ? { footer: twips(page.margins.footerTwips) } : {},
|
|
6147
|
+
...page.margins.gutterTwips !== void 0 ? { gutter: twips(page.margins.gutterTwips) } : {}
|
|
6148
|
+
},
|
|
6149
|
+
...value.properties.pageNumbers ? {
|
|
6150
|
+
pageNumberType: {
|
|
6151
|
+
...value.properties.pageNumbers.start !== void 0 ? { start: value.properties.pageNumbers.start } : {},
|
|
6152
|
+
...value.properties.pageNumbers.formatType ? {
|
|
6153
|
+
format: value.properties.pageNumbers.formatType
|
|
6154
|
+
} : {}
|
|
6155
|
+
}
|
|
6156
|
+
} : {},
|
|
6157
|
+
...value.properties.borders ? {
|
|
6158
|
+
pageBorders: {
|
|
6159
|
+
...value.properties.borders.display ? {
|
|
6160
|
+
display: value.properties.borders.display
|
|
6161
|
+
} : {},
|
|
6162
|
+
...value.properties.borders.offsetFrom ? {
|
|
6163
|
+
offsetFrom: value.properties.borders.offsetFrom
|
|
6164
|
+
} : {},
|
|
6165
|
+
...value.properties.borders.borders ? borders2(value.properties.borders.borders) : {}
|
|
6166
|
+
}
|
|
6167
|
+
} : {},
|
|
4987
6168
|
...columns ? {
|
|
4988
|
-
|
|
6169
|
+
columns: {
|
|
4989
6170
|
count: columns.count,
|
|
4990
|
-
...columns.spaceTwips !== void 0 ? { space: columns.spaceTwips } : {},
|
|
6171
|
+
...columns.spaceTwips !== void 0 ? { space: twips(columns.spaceTwips) } : {},
|
|
4991
6172
|
...columns.separator !== void 0 ? { separate: columns.separator } : {},
|
|
4992
6173
|
...columns.equalWidth !== void 0 ? { equalWidth: columns.equalWidth } : {},
|
|
4993
6174
|
...columns.widths ? {
|
|
4994
6175
|
children: columns.widths.map((column) => ({
|
|
4995
|
-
width: column.widthTwips,
|
|
4996
|
-
...column.spaceTwips !== void 0 ? { space: column.spaceTwips } : {}
|
|
6176
|
+
width: twips(column.widthTwips),
|
|
6177
|
+
...column.spaceTwips !== void 0 ? { space: twips(column.spaceTwips) } : {}
|
|
4997
6178
|
}))
|
|
4998
6179
|
} : {}
|
|
4999
6180
|
}
|
|
@@ -5021,14 +6202,16 @@ function headerFooterSet(set, ctx) {
|
|
|
5021
6202
|
function sectionChildren2(value, ctx, closesDocument = false) {
|
|
5022
6203
|
const blocks = value.children.map((child) => block(child, ctx));
|
|
5023
6204
|
const last = value.children[value.children.length - 1];
|
|
5024
|
-
|
|
6205
|
+
const bookmark = value.bookmark;
|
|
6206
|
+
if (bookmark?.closes && last?.kind !== "paragraph" || closesDocument && last?.kind === "paragraph" && last.frame !== void 0)
|
|
5025
6207
|
blocks.push({
|
|
5026
6208
|
paragraph: {
|
|
5027
6209
|
children: [],
|
|
5028
6210
|
spacing: { before: 0, after: 0, line: 20, lineRule: "exact" }
|
|
5029
6211
|
}
|
|
5030
6212
|
});
|
|
5031
|
-
|
|
6213
|
+
if (!closesDocument && !bookmark?.closes && last?.kind === "toc")
|
|
6214
|
+
blocks.push({ paragraph: { children: [] } });
|
|
5032
6215
|
if (!bookmark) return blocks;
|
|
5033
6216
|
return [
|
|
5034
6217
|
...bookmark.opens ? [{ bookmarkStart: { id: bookmark.id, name: bookmark.name } }] : [],
|
|
@@ -5039,43 +6222,44 @@ function sectionChildren2(value, ctx, closesDocument = false) {
|
|
|
5039
6222
|
function numberingConfig2(numbering) {
|
|
5040
6223
|
return {
|
|
5041
6224
|
reference: numbering.reference,
|
|
5042
|
-
levels: numbering.levels.map(
|
|
5043
|
-
level
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
6225
|
+
levels: numbering.levels.map(
|
|
6226
|
+
(level) => ({
|
|
6227
|
+
level: level.level,
|
|
6228
|
+
format: level.format,
|
|
6229
|
+
text: level.text,
|
|
6230
|
+
...level.alignment ? { alignment: alignment(level.alignment) } : {},
|
|
6231
|
+
...level.suffix ? { suffix: level.suffix } : {},
|
|
6232
|
+
// Always stated. docx.js writes `w:start w:val="1"` for a level that
|
|
6233
|
+
// names none, and so did this backend until 0.14, which writes no
|
|
6234
|
+
// `w:start` at all when it is not given one; Word and LibreOffice then
|
|
6235
|
+
// count every such list from 0.
|
|
6236
|
+
start: level.start ?? 1,
|
|
6237
|
+
...level.paragraphStyleId ? { paragraphStyle: level.paragraphStyleId } : {},
|
|
5051
6238
|
...level.indent ? {
|
|
5052
6239
|
paragraph: {
|
|
5053
6240
|
indent: {
|
|
5054
|
-
...level.indent.leftTwips !== void 0 ? { left: level.indent.leftTwips } : {},
|
|
5055
|
-
...level.indent.hangingTwips !== void 0 ? { hanging: level.indent.hangingTwips } : {}
|
|
6241
|
+
...level.indent.leftTwips !== void 0 ? { left: twips(level.indent.leftTwips) } : {},
|
|
6242
|
+
...level.indent.hangingTwips !== void 0 ? { hanging: twips(level.indent.hangingTwips) } : {}
|
|
5056
6243
|
}
|
|
5057
6244
|
}
|
|
5058
6245
|
} : {},
|
|
5059
6246
|
...level.run ? { run: runProperties2(level.run) } : {}
|
|
5060
|
-
}
|
|
5061
|
-
|
|
6247
|
+
})
|
|
6248
|
+
)
|
|
5062
6249
|
};
|
|
5063
6250
|
}
|
|
5064
|
-
var
|
|
6251
|
+
var BODY_ANCHOR;
|
|
5065
6252
|
var init_emit2 = __esm({
|
|
5066
6253
|
"src/renderers/office-open/emit.ts"() {
|
|
5067
6254
|
"use strict";
|
|
5068
6255
|
init_units();
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
tight: 2,
|
|
5073
|
-
topAndBottom: 3
|
|
5074
|
-
};
|
|
6256
|
+
init_chartWorkbook();
|
|
6257
|
+
init_chartLook();
|
|
6258
|
+
init_chartParts();
|
|
5075
6259
|
BODY_ANCHOR = {
|
|
5076
|
-
top: "
|
|
5077
|
-
middle: "
|
|
5078
|
-
bottom: "
|
|
6260
|
+
top: "top",
|
|
6261
|
+
middle: "center",
|
|
6262
|
+
bottom: "bottom"
|
|
5079
6263
|
};
|
|
5080
6264
|
}
|
|
5081
6265
|
});
|
|
@@ -5135,15 +6319,34 @@ var init_styles3 = __esm({
|
|
|
5135
6319
|
var office_open_exports = {};
|
|
5136
6320
|
__export(office_open_exports, {
|
|
5137
6321
|
OFFICE_OPEN_DOCX_RENDERER_ID: () => OFFICE_OPEN_DOCX_RENDERER_ID,
|
|
6322
|
+
OFFICE_OPEN_VERSION: () => OFFICE_OPEN_VERSION,
|
|
5138
6323
|
buildDocumentOptions: () => buildDocumentOptions,
|
|
5139
6324
|
createOfficeOpenDocxRenderer: () => createOfficeOpenDocxRenderer
|
|
5140
6325
|
});
|
|
5141
|
-
import
|
|
6326
|
+
import AdmZip5 from "adm-zip";
|
|
6327
|
+
import {
|
|
6328
|
+
assertBackendVersion,
|
|
6329
|
+
installedPackageVersion
|
|
6330
|
+
} from "@json-to-office/shared/rendering/node";
|
|
6331
|
+
function installedBackendVersion() {
|
|
6332
|
+
let resolved;
|
|
6333
|
+
try {
|
|
6334
|
+
resolved = import.meta.resolve?.(OFFICE_OPEN_DOCX);
|
|
6335
|
+
} catch {
|
|
6336
|
+
resolved = void 0;
|
|
6337
|
+
}
|
|
6338
|
+
return installedPackageVersion(OFFICE_OPEN_DOCX, import.meta.url, resolved);
|
|
6339
|
+
}
|
|
5142
6340
|
async function createOfficeOpenDocxRenderer() {
|
|
5143
6341
|
const backend = await import(
|
|
5144
6342
|
/* @vite-ignore */
|
|
5145
6343
|
OFFICE_OPEN_DOCX
|
|
5146
6344
|
);
|
|
6345
|
+
assertBackendVersion(
|
|
6346
|
+
OFFICE_OPEN_DOCX,
|
|
6347
|
+
OFFICE_OPEN_VERSION,
|
|
6348
|
+
installedBackendVersion()
|
|
6349
|
+
);
|
|
5147
6350
|
if (typeof backend.generateDocument !== "function") {
|
|
5148
6351
|
throw new Error(
|
|
5149
6352
|
`${OFFICE_OPEN_DOCX} does not export generateDocument(); the installed version is not compatible with this adapter.`
|
|
@@ -5154,10 +6357,10 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5154
6357
|
format: "docx",
|
|
5155
6358
|
capabilities: OFFICE_OPEN_CAPABILITIES,
|
|
5156
6359
|
async render(ir, options) {
|
|
5157
|
-
const
|
|
6360
|
+
const charts2 = [];
|
|
5158
6361
|
const document = await buildDocumentOptions(
|
|
5159
6362
|
ir,
|
|
5160
|
-
|
|
6363
|
+
charts2,
|
|
5161
6364
|
options?.svgRasterFallback
|
|
5162
6365
|
);
|
|
5163
6366
|
const bytes = await backend.generateDocument(document, {
|
|
@@ -5166,9 +6369,10 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5166
6369
|
let raw = Buffer.from(
|
|
5167
6370
|
bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)
|
|
5168
6371
|
);
|
|
5169
|
-
if (
|
|
5170
|
-
const zip = new
|
|
5171
|
-
|
|
6372
|
+
if (ir.theme || charts2.length > 0) {
|
|
6373
|
+
const zip = new AdmZip5(raw);
|
|
6374
|
+
if (ir.theme) spliceTheme(zip, ir.theme);
|
|
6375
|
+
finishChartParts(zip, charts2);
|
|
5172
6376
|
raw = zip.toBuffer();
|
|
5173
6377
|
}
|
|
5174
6378
|
if (options?.deterministic === false)
|
|
@@ -5185,12 +6389,12 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5185
6389
|
}
|
|
5186
6390
|
};
|
|
5187
6391
|
}
|
|
5188
|
-
async function buildDocumentOptions(ir,
|
|
6392
|
+
async function buildDocumentOptions(ir, charts2 = [], svgRasterFallback) {
|
|
5189
6393
|
let nextDrawingId = 1;
|
|
5190
6394
|
const ctx = {
|
|
5191
6395
|
pictures: await prepareImages2(ir, svgRasterFallback),
|
|
5192
6396
|
nextDrawingId: () => nextDrawingId++,
|
|
5193
|
-
charts
|
|
6397
|
+
charts: charts2
|
|
5194
6398
|
};
|
|
5195
6399
|
return {
|
|
5196
6400
|
styles: emitStyles2(ir.styles),
|
|
@@ -5198,16 +6402,20 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback) {
|
|
|
5198
6402
|
(value, index) => section(value, ctx, index === ir.sections.length - 1)
|
|
5199
6403
|
),
|
|
5200
6404
|
...coreProperties2(ir),
|
|
5201
|
-
|
|
6405
|
+
settings: {
|
|
5202
6406
|
updateFields: ir.settings.updateFields,
|
|
5203
6407
|
...ir.settings.trackRevisions ? { trackRevisions: true } : {}
|
|
5204
6408
|
},
|
|
5205
|
-
...ir.numbering.length > 0 ? {
|
|
6409
|
+
...ir.numbering.length > 0 ? {
|
|
6410
|
+
numbering: {
|
|
6411
|
+
abstractNumberings: ir.numbering.map(numberingConfig2)
|
|
6412
|
+
}
|
|
6413
|
+
} : {},
|
|
5206
6414
|
...ir.footnotes.length > 0 ? { footnotes: noteBodies2(ir.footnotes, ctx) } : {},
|
|
5207
6415
|
...ir.endnotes.length > 0 ? { endnotes: noteBodies2(ir.endnotes, ctx) } : {},
|
|
5208
6416
|
...ir.comments.length > 0 ? {
|
|
5209
|
-
comments:
|
|
5210
|
-
|
|
6417
|
+
comments: ir.comments.map(
|
|
6418
|
+
(comment) => ({
|
|
5211
6419
|
id: comment.id,
|
|
5212
6420
|
author: comment.author,
|
|
5213
6421
|
...comment.initials ? { initials: comment.initials } : {},
|
|
@@ -5215,29 +6423,25 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback) {
|
|
|
5215
6423
|
children: comment.children.map(
|
|
5216
6424
|
(child) => paragraphOf(child, ctx)
|
|
5217
6425
|
)
|
|
5218
|
-
})
|
|
5219
|
-
|
|
6426
|
+
})
|
|
6427
|
+
)
|
|
5220
6428
|
} : {}
|
|
5221
6429
|
};
|
|
5222
6430
|
}
|
|
5223
6431
|
function paragraphOf(value, ctx) {
|
|
5224
6432
|
const emitted = block(value, ctx);
|
|
5225
|
-
|
|
5226
|
-
if (!asParagraph) {
|
|
6433
|
+
if (!("paragraph" in emitted) || typeof emitted.paragraph === "string") {
|
|
5227
6434
|
throw new Error(
|
|
5228
6435
|
`the office-open renderer expected a paragraph, not a "${value.kind}"`
|
|
5229
6436
|
);
|
|
5230
6437
|
}
|
|
5231
|
-
return
|
|
6438
|
+
return emitted.paragraph;
|
|
5232
6439
|
}
|
|
5233
6440
|
function noteBodies2(notes, ctx) {
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
};
|
|
5239
|
-
}
|
|
5240
|
-
return bodies;
|
|
6441
|
+
return notes.map((note) => ({
|
|
6442
|
+
id: note.id,
|
|
6443
|
+
children: note.children.map((child) => paragraphOf(child, ctx))
|
|
6444
|
+
}));
|
|
5241
6445
|
}
|
|
5242
6446
|
async function prepareImages2(ir, svgRasterFallback) {
|
|
5243
6447
|
const placements = collectImagePlacements2(ir);
|
|
@@ -5260,23 +6464,16 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5260
6464
|
if (resource.kind !== "image") continue;
|
|
5261
6465
|
const type = resource.mediaType;
|
|
5262
6466
|
const data = Buffer.from(resource.bytes);
|
|
5263
|
-
const placementData = /* @__PURE__ */ new Map();
|
|
5264
|
-
[...placements.get(resource.id) ?? []].forEach((size, index) => {
|
|
5265
|
-
placementData.set(
|
|
5266
|
-
size,
|
|
5267
|
-
index === 0 ? data : distinguishImageBytes(data, type, size)
|
|
5268
|
-
);
|
|
5269
|
-
});
|
|
5270
6467
|
resources.set(resource.id, (placement) => {
|
|
5271
6468
|
const sizeKey = placementKey(placement);
|
|
5272
6469
|
const stem = `${resource.id}-${sizeKey}`;
|
|
5273
6470
|
return {
|
|
5274
6471
|
type,
|
|
5275
|
-
//
|
|
5276
|
-
//
|
|
5277
|
-
//
|
|
5278
|
-
//
|
|
5279
|
-
data
|
|
6472
|
+
// The same bytes at every size: the backend keeps each drawing's
|
|
6473
|
+
// extent on the drawing. 0.11 kept it on its deduplicated media
|
|
6474
|
+
// entry, and an image drawn at a second size took the first one's,
|
|
6475
|
+
// unless its bytes were told apart.
|
|
6476
|
+
data,
|
|
5280
6477
|
// Named after the resource and the size it is drawn at, so two
|
|
5281
6478
|
// placements of one image at one size share a single part and a third
|
|
5282
6479
|
// at another size gets its own.
|
|
@@ -5299,104 +6496,6 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5299
6496
|
function placementKey(placement) {
|
|
5300
6497
|
return `${emuToPixels(placement.widthEmu)}x${emuToPixels(placement.heightEmu)}`;
|
|
5301
6498
|
}
|
|
5302
|
-
function distinguishImageBytes(data, mediaType, placement) {
|
|
5303
|
-
const marker = Buffer.from(`json-to-office:${placement}`, "utf8");
|
|
5304
|
-
switch (mediaType) {
|
|
5305
|
-
case "png":
|
|
5306
|
-
return addPngTextChunk(data, marker);
|
|
5307
|
-
case "jpg":
|
|
5308
|
-
return addJpegComment(data, marker);
|
|
5309
|
-
case "gif":
|
|
5310
|
-
return addGifComment(data, marker);
|
|
5311
|
-
case "svg":
|
|
5312
|
-
return Buffer.concat([
|
|
5313
|
-
data,
|
|
5314
|
-
Buffer.from(`
|
|
5315
|
-
<!-- ${marker.toString("utf8")} -->`, "utf8")
|
|
5316
|
-
]);
|
|
5317
|
-
case "bmp": {
|
|
5318
|
-
const marked = Buffer.concat([data, marker]);
|
|
5319
|
-
if (marked.length >= 14 && marked.subarray(0, 2).toString("ascii") === "BM") {
|
|
5320
|
-
marked.writeUInt32LE(marked.length, 2);
|
|
5321
|
-
}
|
|
5322
|
-
return marked;
|
|
5323
|
-
}
|
|
5324
|
-
default:
|
|
5325
|
-
return Buffer.concat([data, marker]);
|
|
5326
|
-
}
|
|
5327
|
-
}
|
|
5328
|
-
function addPngTextChunk(data, marker) {
|
|
5329
|
-
const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
5330
|
-
if (data.length < 8 || !data.subarray(0, 8).equals(signature)) {
|
|
5331
|
-
return Buffer.concat([data, marker]);
|
|
5332
|
-
}
|
|
5333
|
-
let offset = 8;
|
|
5334
|
-
while (offset + 12 <= data.length) {
|
|
5335
|
-
const payloadLength = data.readUInt32BE(offset);
|
|
5336
|
-
const chunkEnd = offset + 12 + payloadLength;
|
|
5337
|
-
if (chunkEnd > data.length) break;
|
|
5338
|
-
if (data.subarray(offset + 4, offset + 8).toString("ascii") === "IEND") {
|
|
5339
|
-
const payload = Buffer.concat([
|
|
5340
|
-
Buffer.from("json-to-office\0", "latin1"),
|
|
5341
|
-
marker
|
|
5342
|
-
]);
|
|
5343
|
-
const chunk = Buffer.alloc(12 + payload.length);
|
|
5344
|
-
chunk.writeUInt32BE(payload.length, 0);
|
|
5345
|
-
chunk.write("tEXt", 4, 4, "ascii");
|
|
5346
|
-
payload.copy(chunk, 8);
|
|
5347
|
-
chunk.writeUInt32BE(
|
|
5348
|
-
crc32(chunk.subarray(4, 8 + payload.length)),
|
|
5349
|
-
8 + payload.length
|
|
5350
|
-
);
|
|
5351
|
-
return Buffer.concat([
|
|
5352
|
-
data.subarray(0, offset),
|
|
5353
|
-
chunk,
|
|
5354
|
-
data.subarray(offset)
|
|
5355
|
-
]);
|
|
5356
|
-
}
|
|
5357
|
-
offset = chunkEnd;
|
|
5358
|
-
}
|
|
5359
|
-
throw new Error(
|
|
5360
|
-
"Cannot mark a PNG that has no intact IEND chunk; its bytes were not checked to decode before rendering"
|
|
5361
|
-
);
|
|
5362
|
-
}
|
|
5363
|
-
function addJpegComment(data, marker) {
|
|
5364
|
-
if (data.length < 2 || data[0] !== 255 || data[1] !== 216) {
|
|
5365
|
-
return Buffer.concat([data, marker]);
|
|
5366
|
-
}
|
|
5367
|
-
const comment = Buffer.alloc(4 + marker.length);
|
|
5368
|
-
comment[0] = 255;
|
|
5369
|
-
comment[1] = 254;
|
|
5370
|
-
comment.writeUInt16BE(marker.length + 2, 2);
|
|
5371
|
-
marker.copy(comment, 4);
|
|
5372
|
-
return Buffer.concat([data.subarray(0, 2), comment, data.subarray(2)]);
|
|
5373
|
-
}
|
|
5374
|
-
function addGifComment(data, marker) {
|
|
5375
|
-
const trailer = data.lastIndexOf(59);
|
|
5376
|
-
if (trailer < 0 || marker.length > 255) {
|
|
5377
|
-
return Buffer.concat([data, marker]);
|
|
5378
|
-
}
|
|
5379
|
-
const comment = Buffer.concat([
|
|
5380
|
-
Buffer.from([33, 254, marker.length]),
|
|
5381
|
-
marker,
|
|
5382
|
-
Buffer.from([0])
|
|
5383
|
-
]);
|
|
5384
|
-
return Buffer.concat([
|
|
5385
|
-
data.subarray(0, trailer),
|
|
5386
|
-
comment,
|
|
5387
|
-
data.subarray(trailer)
|
|
5388
|
-
]);
|
|
5389
|
-
}
|
|
5390
|
-
function crc32(data) {
|
|
5391
|
-
let crc = 4294967295;
|
|
5392
|
-
for (const byte of data) {
|
|
5393
|
-
crc ^= byte;
|
|
5394
|
-
for (let bit = 0; bit < 8; bit += 1) {
|
|
5395
|
-
crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
5396
|
-
}
|
|
5397
|
-
}
|
|
5398
|
-
return (crc ^ 4294967295) >>> 0;
|
|
5399
|
-
}
|
|
5400
6499
|
function collectImagePlacements2(ir) {
|
|
5401
6500
|
const placements = /* @__PURE__ */ new Map();
|
|
5402
6501
|
const record = (resourceId, placement) => {
|
|
@@ -5464,17 +6563,19 @@ function coreProperties2(ir) {
|
|
|
5464
6563
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
5465
6564
|
};
|
|
5466
6565
|
}
|
|
5467
|
-
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX, OFFICE_OPEN_CAPABILITIES;
|
|
6566
|
+
var OFFICE_OPEN_DOCX_RENDERER_ID, OFFICE_OPEN_DOCX, OFFICE_OPEN_VERSION, OFFICE_OPEN_CAPABILITIES;
|
|
5468
6567
|
var init_office_open = __esm({
|
|
5469
6568
|
"src/renderers/office-open/index.ts"() {
|
|
5470
6569
|
"use strict";
|
|
5471
6570
|
init_chartParts();
|
|
6571
|
+
init_themePart();
|
|
5472
6572
|
init_imageUtils();
|
|
5473
6573
|
init_packageDocument();
|
|
5474
6574
|
init_emit2();
|
|
5475
6575
|
init_styles3();
|
|
5476
6576
|
OFFICE_OPEN_DOCX_RENDERER_ID = "office-open";
|
|
5477
6577
|
OFFICE_OPEN_DOCX = "@office-open/docx";
|
|
6578
|
+
OFFICE_OPEN_VERSION = "0.14.6";
|
|
5478
6579
|
OFFICE_OPEN_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
5479
6580
|
"paragraphs",
|
|
5480
6581
|
"styles",
|
|
@@ -6431,6 +7532,7 @@ import {
|
|
|
6431
7532
|
assetUnreadableError
|
|
6432
7533
|
} from "@json-to-office/shared/rendering";
|
|
6433
7534
|
import { capsFormatting as capsFormatting2, synthesizeFamilyName as synthesizeFamilyName2 } from "@json-to-office/shared";
|
|
7535
|
+
import { unrenderedComponentText } from "@json-to-office/quality";
|
|
6434
7536
|
import {
|
|
6435
7537
|
isNativeVisualProps as isNativeVisualProps4
|
|
6436
7538
|
} from "@json-to-office/shared-docx";
|
|
@@ -7556,7 +8658,8 @@ function createDocumentStyles(themeNameOrObject = "consulting", language) {
|
|
|
7556
8658
|
tabStops: effectiveTabStops.map(
|
|
7557
8659
|
(ts) => ({
|
|
7558
8660
|
type: ts.type,
|
|
7559
|
-
|
|
8661
|
+
// Whole twips: `w:pos` is an integer no backend rounds.
|
|
8662
|
+
positionTwips: ts.position === "max" ? RIGHT_MARGIN_TAB_TWIPS : Math.round(ts.position),
|
|
7560
8663
|
...ts.leader && { leader: ts.leader }
|
|
7561
8664
|
})
|
|
7562
8665
|
)
|
|
@@ -9103,6 +10206,7 @@ function emptyToUndefined(formatting) {
|
|
|
9103
10206
|
}
|
|
9104
10207
|
|
|
9105
10208
|
// src/ir/compiler.ts
|
|
10209
|
+
init_chartValues();
|
|
9106
10210
|
init_types();
|
|
9107
10211
|
|
|
9108
10212
|
// src/ir/measure.ts
|
|
@@ -9135,6 +10239,49 @@ function tableWidthTwips(width, measureTwips) {
|
|
|
9135
10239
|
|
|
9136
10240
|
// src/ir/compiler.ts
|
|
9137
10241
|
init_units();
|
|
10242
|
+
|
|
10243
|
+
// src/ir/theme.ts
|
|
10244
|
+
init_colorUtils();
|
|
10245
|
+
init_styleHelpers();
|
|
10246
|
+
init_types();
|
|
10247
|
+
var THEME_COLOR_TOKENS = [
|
|
10248
|
+
["dark1", "text"],
|
|
10249
|
+
["light1", "background"],
|
|
10250
|
+
["dark2", "textSecondary"],
|
|
10251
|
+
["light2", "backgroundSecondary"],
|
|
10252
|
+
["accent1", "primary"],
|
|
10253
|
+
["accent2", "secondary"],
|
|
10254
|
+
["accent3", "accent"],
|
|
10255
|
+
["accent4", "accent4"],
|
|
10256
|
+
["accent5", "accent5"],
|
|
10257
|
+
["accent6", "accent6"]
|
|
10258
|
+
];
|
|
10259
|
+
var NOT_XML_CHARS = new RegExp(NOT_XML_CHAR.source, "gu");
|
|
10260
|
+
var xmlText = (value) => (value ?? "").replace(NOT_XML_CHARS, "").trim();
|
|
10261
|
+
function compileTheme(theme, themeName) {
|
|
10262
|
+
const colors = {};
|
|
10263
|
+
for (const [slot, token] of THEME_COLOR_TOKENS) {
|
|
10264
|
+
const hex = schemeHex(token, theme);
|
|
10265
|
+
if (hex) colors[slot] = { hex };
|
|
10266
|
+
}
|
|
10267
|
+
const headingFont = xmlText(resolveFontFamily(theme, "heading"));
|
|
10268
|
+
const bodyFont = xmlText(resolveFontFamily(theme, "body"));
|
|
10269
|
+
return {
|
|
10270
|
+
name: xmlText(theme.name) || xmlText(themeName) || "Office Theme",
|
|
10271
|
+
colors,
|
|
10272
|
+
...headingFont ? { headingFont } : {},
|
|
10273
|
+
...bodyFont ? { bodyFont } : {}
|
|
10274
|
+
};
|
|
10275
|
+
}
|
|
10276
|
+
function schemeHex(token, theme) {
|
|
10277
|
+
try {
|
|
10278
|
+
return resolveColor(token, theme);
|
|
10279
|
+
} catch {
|
|
10280
|
+
return void 0;
|
|
10281
|
+
}
|
|
10282
|
+
}
|
|
10283
|
+
|
|
10284
|
+
// src/ir/compiler.ts
|
|
9138
10285
|
var CONTENT_BOOKMARK_ID_BASE = 2e6;
|
|
9139
10286
|
var SINGLE_LINE_TWIPS = 240;
|
|
9140
10287
|
function compileDocument(structure, layout, warnings = [], images = /* @__PURE__ */ new Map(), options = {}) {
|
|
@@ -9200,6 +10347,7 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
9200
10347
|
trackRevisions: structure.trackRevisions === true,
|
|
9201
10348
|
...noProofWords(structure.theme) ? { noProofWords: noProofWords(structure.theme) } : {}
|
|
9202
10349
|
},
|
|
10350
|
+
theme: compileTheme(structure.theme, structure.themeName),
|
|
9203
10351
|
// The statistic styles are appended rather than built with the rest: a
|
|
9204
10352
|
// document that uses no statistic must keep the exact style set it had
|
|
9205
10353
|
// before the component had styles, or every recorded golden moves for a
|
|
@@ -9968,14 +11116,6 @@ function compileShape2(props, children, scope) {
|
|
|
9968
11116
|
);
|
|
9969
11117
|
}
|
|
9970
11118
|
const fill = style?.shading?.fill;
|
|
9971
|
-
const dropOutline = Boolean(fill) && Boolean(outline.outline);
|
|
9972
|
-
if (dropOutline) {
|
|
9973
|
-
warnOnce(
|
|
9974
|
-
ctx,
|
|
9975
|
-
"text-box",
|
|
9976
|
-
'[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.'
|
|
9977
|
-
);
|
|
9978
|
-
}
|
|
9979
11119
|
ctx.features.require("text-boxes", path4);
|
|
9980
11120
|
if (props.floating) ctx.features.require("floating-images", path4);
|
|
9981
11121
|
const insets = shapeInsets(
|
|
@@ -9994,7 +11134,7 @@ function compileShape2(props, children, scope) {
|
|
|
9994
11134
|
heightPx: height.pixels,
|
|
9995
11135
|
children,
|
|
9996
11136
|
...fill ? { fill: irColor(resolveColor(fill, ctx.theme)) } : {},
|
|
9997
|
-
...outline.outline
|
|
11137
|
+
...outline.outline ? { outline: outline.outline } : {},
|
|
9998
11138
|
...insets ? { insetsEmu: insets } : {},
|
|
9999
11139
|
...props.floating ? { floating: compileFloating(props.floating, ctx, path4) } : {}
|
|
10000
11140
|
}
|
|
@@ -10176,7 +11316,9 @@ function compileToc(component, scope) {
|
|
|
10176
11316
|
formatting: {
|
|
10177
11317
|
alignment: "left",
|
|
10178
11318
|
spacing: {
|
|
10179
|
-
beforeTwips:
|
|
11319
|
+
beforeTwips: wholeTwips(
|
|
11320
|
+
ctx.theme.componentDefaults?.heading?.spacing?.before ?? 240
|
|
11321
|
+
),
|
|
10180
11322
|
// ~9pt, which separates the title from the list clearly enough to
|
|
10181
11323
|
// read as a heading rather than a first entry.
|
|
10182
11324
|
afterTwips: 180
|
|
@@ -10296,8 +11438,8 @@ function compileStatistic(component, scope) {
|
|
|
10296
11438
|
const alignment2 = compileAlignment(props.alignment) ?? "center";
|
|
10297
11439
|
ctx.usesStatistic = true;
|
|
10298
11440
|
const spacing = props.spacing ? {
|
|
10299
|
-
...props.spacing.before !== void 0 ? { beforeTwips: props.spacing.before } : {},
|
|
10300
|
-
...props.spacing.after !== void 0 ? { afterTwips: props.spacing.after } : {}
|
|
11441
|
+
...props.spacing.before !== void 0 ? { beforeTwips: wholeTwips(props.spacing.before) } : {},
|
|
11442
|
+
...props.spacing.after !== void 0 ? { afterTwips: wholeTwips(props.spacing.after) } : {}
|
|
10301
11443
|
} : void 0;
|
|
10302
11444
|
if (props.format !== void 0) {
|
|
10303
11445
|
warnOnce(
|
|
@@ -10922,7 +12064,7 @@ function paragraphFormatting(props, ctx, extra = {}) {
|
|
|
10922
12064
|
if (Array.isArray(props.tabStops) && props.tabStops.length > 0) {
|
|
10923
12065
|
formatting.tabStops = props.tabStops.map(
|
|
10924
12066
|
(stop) => ({
|
|
10925
|
-
positionTwips: stop.position,
|
|
12067
|
+
positionTwips: wholeTwips(stop.position),
|
|
10926
12068
|
type: stop.type ?? "left",
|
|
10927
12069
|
...stop.leader ? { leader: stop.leader } : {}
|
|
10928
12070
|
})
|
|
@@ -10971,7 +12113,10 @@ function compileSpacing(props, ctx) {
|
|
|
10971
12113
|
}
|
|
10972
12114
|
function compileLineSpacing(value) {
|
|
10973
12115
|
if (typeof value === "number") {
|
|
10974
|
-
return {
|
|
12116
|
+
return {
|
|
12117
|
+
lineTwips: wholeTwips(value * SINGLE_LINE_TWIPS),
|
|
12118
|
+
lineRule: "auto"
|
|
12119
|
+
};
|
|
10975
12120
|
}
|
|
10976
12121
|
if (typeof value !== "object" || value === null) return void 0;
|
|
10977
12122
|
const { type, value: amount } = value;
|
|
@@ -10992,7 +12137,7 @@ function compileLineSpacing(value) {
|
|
|
10992
12137
|
};
|
|
10993
12138
|
case "multiple":
|
|
10994
12139
|
return {
|
|
10995
|
-
...amount !== void 0 ? { lineTwips: amount * SINGLE_LINE_TWIPS } : {},
|
|
12140
|
+
...amount !== void 0 ? { lineTwips: wholeTwips(amount * SINGLE_LINE_TWIPS) } : {},
|
|
10996
12141
|
lineRule: "auto"
|
|
10997
12142
|
};
|
|
10998
12143
|
default:
|
|
@@ -11212,6 +12357,7 @@ function compileImage2(component, scope) {
|
|
|
11212
12357
|
}
|
|
11213
12358
|
var DEFAULT_CHART_HEIGHT_INCHES = 3;
|
|
11214
12359
|
var MAX_CHART_TEXT_POINTS = 10;
|
|
12360
|
+
var MIN_CHART_TEXT_POINTS = 1;
|
|
11215
12361
|
function chartTextFont(theme) {
|
|
11216
12362
|
const bodySize = getThemeFonts(theme).body?.size;
|
|
11217
12363
|
let color = "000000";
|
|
@@ -11221,9 +12367,12 @@ function chartTextFont(theme) {
|
|
|
11221
12367
|
}
|
|
11222
12368
|
return {
|
|
11223
12369
|
fontFamily: resolveFontFamily(theme, "body"),
|
|
11224
|
-
fontSize: Math.
|
|
11225
|
-
|
|
11226
|
-
|
|
12370
|
+
fontSize: Math.max(
|
|
12371
|
+
MIN_CHART_TEXT_POINTS,
|
|
12372
|
+
Math.min(
|
|
12373
|
+
typeof bodySize === "number" && bodySize > 0 ? bodySize : 11,
|
|
12374
|
+
MAX_CHART_TEXT_POINTS
|
|
12375
|
+
)
|
|
11227
12376
|
),
|
|
11228
12377
|
bold: false,
|
|
11229
12378
|
color
|
|
@@ -11234,7 +12383,7 @@ function compileChart(component, scope) {
|
|
|
11234
12383
|
const props = component.props ?? {};
|
|
11235
12384
|
if (props.type === "bubble") {
|
|
11236
12385
|
throw new Error(
|
|
11237
|
-
`Chart at ${path4} is a bubble chart,
|
|
12386
|
+
`Chart at ${path4} is a bubble chart, but the docx \`chart\` component has no bubble sizes; use the pptx \`chart\` component on the pptxgenjs renderer.`
|
|
11238
12387
|
);
|
|
11239
12388
|
}
|
|
11240
12389
|
const rawSeries = Array.isArray(props.data) ? props.data : [];
|
|
@@ -11256,10 +12405,22 @@ function compileChart(component, scope) {
|
|
|
11256
12405
|
`Chart series "${label}" at ${path4} has ${labels.length} labels and ${values.length} values; they must be the same length.`
|
|
11257
12406
|
);
|
|
11258
12407
|
}
|
|
12408
|
+
if (labels.length === 0) {
|
|
12409
|
+
throw new Error(
|
|
12410
|
+
`Chart series "${label}" at ${path4} has no data points; give it at least one label and value.`
|
|
12411
|
+
);
|
|
12412
|
+
}
|
|
12413
|
+
const numbers = values.map((value) => Number(value));
|
|
12414
|
+
const bad = numbers.findIndex((value) => !Number.isFinite(value));
|
|
12415
|
+
if (bad !== -1) {
|
|
12416
|
+
throw new Error(
|
|
12417
|
+
`Chart series "${label}" at ${path4} has a value that is not a finite number (${JSON.stringify(values[bad])} at "${String(labels[bad])}").`
|
|
12418
|
+
);
|
|
12419
|
+
}
|
|
11259
12420
|
return {
|
|
11260
12421
|
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
11261
12422
|
labels: labels.map((value) => String(value)),
|
|
11262
|
-
values:
|
|
12423
|
+
values: numbers
|
|
11263
12424
|
};
|
|
11264
12425
|
});
|
|
11265
12426
|
const categories = series[0].labels;
|
|
@@ -11271,6 +12432,34 @@ function compileChart(component, scope) {
|
|
|
11271
12432
|
);
|
|
11272
12433
|
}
|
|
11273
12434
|
}
|
|
12435
|
+
if (props.type === "pie" && series.length > 1) {
|
|
12436
|
+
throw new Error(
|
|
12437
|
+
`Chart at ${path4} 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.`
|
|
12438
|
+
);
|
|
12439
|
+
}
|
|
12440
|
+
if (props.type === "pie" || props.type === "doughnut") {
|
|
12441
|
+
for (const [index, entry] of series.entries()) {
|
|
12442
|
+
const at = entry.values.findIndex((value) => value < 0);
|
|
12443
|
+
if (at === -1) continue;
|
|
12444
|
+
throw new Error(
|
|
12445
|
+
`Chart series "${entry.name ?? `series ${index}`}" at ${path4} has a negative value (${entry.values[at]} at "${entry.labels[at]}"); a ${props.type} chart draws each value as a share of the whole.`
|
|
12446
|
+
);
|
|
12447
|
+
}
|
|
12448
|
+
}
|
|
12449
|
+
if (props.type === "scatter" && series.some((entry) => entry.labels.some((label) => !isNumericLabel(label)))) {
|
|
12450
|
+
warnOnce(
|
|
12451
|
+
ctx,
|
|
12452
|
+
"chart",
|
|
12453
|
+
`Chart at ${path4} 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.`
|
|
12454
|
+
);
|
|
12455
|
+
}
|
|
12456
|
+
if ((props.type === "pie" || props.type === "doughnut") && (typeof props.catAxisTitle === "string" || typeof props.valAxisTitle === "string")) {
|
|
12457
|
+
warnOnce(
|
|
12458
|
+
ctx,
|
|
12459
|
+
"chart",
|
|
12460
|
+
`Chart at ${path4} is a ${props.type} chart, which has no axes; its axis titles are not drawn.`
|
|
12461
|
+
);
|
|
12462
|
+
}
|
|
11274
12463
|
const colors = Array.isArray(props.chartColors) ? props.chartColors.map(
|
|
11275
12464
|
(color) => resolveColor(String(color), ctx.theme)
|
|
11276
12465
|
) : chartPaletteValues(ctx.theme).flatMap((value) => {
|
|
@@ -11283,13 +12472,21 @@ function compileChart(component, scope) {
|
|
|
11283
12472
|
const contentWidthInches = scope.measureTwips / 1440;
|
|
11284
12473
|
const widthInches = typeof props.width === "number" ? props.width : contentWidthInches;
|
|
11285
12474
|
const heightInches = typeof props.height === "number" ? props.height : DEFAULT_CHART_HEIGHT_INCHES;
|
|
12475
|
+
const widthEmu = inchesToEmu(widthInches);
|
|
12476
|
+
const heightEmu = inchesToEmu(heightInches);
|
|
12477
|
+
if (!(widthEmu > 0 && heightEmu > 0)) {
|
|
12478
|
+
const inches = (value) => String(Number.isFinite(value) ? Math.round(value * 100) / 100 : value);
|
|
12479
|
+
throw new Error(
|
|
12480
|
+
`Chart at ${path4} has no room: it would be ${inches(widthInches)}\xD7${inches(heightInches)} in. Set \`width\`/\`height\`, or give it a container with space.`
|
|
12481
|
+
);
|
|
12482
|
+
}
|
|
11286
12483
|
const chart = {
|
|
11287
12484
|
kind: "chart",
|
|
11288
12485
|
chartType: props.type,
|
|
11289
12486
|
series,
|
|
11290
12487
|
colors,
|
|
11291
|
-
widthEmu
|
|
11292
|
-
heightEmu
|
|
12488
|
+
widthEmu,
|
|
12489
|
+
heightEmu,
|
|
11293
12490
|
...typeof props.title === "string" ? { title: props.title } : {},
|
|
11294
12491
|
...props.showTitle !== void 0 ? { showTitle: props.showTitle } : {},
|
|
11295
12492
|
...props.showLegend !== void 0 ? { showLegend: props.showLegend } : {},
|
|
@@ -11453,8 +12650,8 @@ function compileFrame(floating, ctx, path4) {
|
|
|
11453
12650
|
const useAbsolute = hasHorizontalOffset || hasVerticalOffset;
|
|
11454
12651
|
const frame = {
|
|
11455
12652
|
// 2in by 1in when the author gave no size.
|
|
11456
|
-
widthTwips: floating.width || 2880,
|
|
11457
|
-
heightTwips: floating.height || 1440,
|
|
12653
|
+
widthTwips: wholeTwips(floating.width || 2880),
|
|
12654
|
+
heightTwips: wholeTwips(floating.height || 1440),
|
|
11458
12655
|
anchorHorizontal: floating.horizontalPosition?.relative || "page",
|
|
11459
12656
|
anchorVertical: floating.verticalPosition?.relative || "page",
|
|
11460
12657
|
...floating.wrap?.type ? { wrap: floating.wrap.type } : {}
|
|
@@ -11467,17 +12664,21 @@ function compileFrame(floating, ctx, path4) {
|
|
|
11467
12664
|
if (typeof rawX === "string" || typeof rawY === "string") {
|
|
11468
12665
|
const hRelative = floating.horizontalPosition?.relative;
|
|
11469
12666
|
const vRelative = floating.verticalPosition?.relative;
|
|
11470
|
-
frame.xTwips =
|
|
11471
|
-
|
|
11472
|
-
|
|
12667
|
+
frame.xTwips = wholeTwips(
|
|
12668
|
+
resolveOffsetTwips(
|
|
12669
|
+
rawX,
|
|
12670
|
+
hRelative && hRelative !== "page" ? getAvailableWidthTwips(ctx.theme, ctx.themeName) : getPageWidthTwips(ctx.theme, ctx.themeName)
|
|
12671
|
+
)
|
|
11473
12672
|
);
|
|
11474
|
-
frame.yTwips =
|
|
11475
|
-
|
|
11476
|
-
|
|
12673
|
+
frame.yTwips = wholeTwips(
|
|
12674
|
+
resolveOffsetTwips(
|
|
12675
|
+
rawY,
|
|
12676
|
+
vRelative && vRelative !== "page" ? getAvailableHeightTwips(ctx.theme, ctx.themeName) : getPageHeightTwips(ctx.theme, ctx.themeName)
|
|
12677
|
+
)
|
|
11477
12678
|
);
|
|
11478
12679
|
} else {
|
|
11479
|
-
frame.xTwips = rawX;
|
|
11480
|
-
frame.yTwips = rawY;
|
|
12680
|
+
frame.xTwips = wholeTwips(rawX);
|
|
12681
|
+
frame.yTwips = wholeTwips(rawY);
|
|
11481
12682
|
}
|
|
11482
12683
|
return frame;
|
|
11483
12684
|
}
|
|
@@ -11488,7 +12689,7 @@ function compileFrame(floating, ctx, path4) {
|
|
|
11488
12689
|
function compileFloating(floating, ctx, path4) {
|
|
11489
12690
|
if (floating.wrap?.type === "tight") {
|
|
11490
12691
|
throw new Error(
|
|
11491
|
-
"Image floating wrap.type 'tight' is not supported
|
|
12692
|
+
"Image floating wrap.type 'tight' is not supported. Use 'square', 'topAndBottom', or 'none'."
|
|
11492
12693
|
);
|
|
11493
12694
|
}
|
|
11494
12695
|
const hRelative = floating.horizontalPosition?.relative;
|
|
@@ -11811,10 +13012,17 @@ function cellChildren(cell, baseStyle, scope, rowRevision) {
|
|
|
11811
13012
|
return wrap(cellVisual(content, scope));
|
|
11812
13013
|
}
|
|
11813
13014
|
if (content.name !== "paragraph") {
|
|
13015
|
+
const text2 = unrenderedComponentText(content.name);
|
|
13016
|
+
warnOnce(
|
|
13017
|
+
ctx,
|
|
13018
|
+
"table",
|
|
13019
|
+
`${scope.path} holds a "${content.name}", which a table cell cannot render, so it shows "${text2}" instead. A cell takes a string, a paragraph, an image, a visual or a highcharts chart; set statistics side by side with a columns component.`,
|
|
13020
|
+
"W_UNSUPPORTED_CELL_CONTENT"
|
|
13021
|
+
);
|
|
11814
13022
|
return wrap([
|
|
11815
13023
|
{
|
|
11816
13024
|
kind: "text",
|
|
11817
|
-
text:
|
|
13025
|
+
text: text2,
|
|
11818
13026
|
formatting: placeholderFormatting(base)
|
|
11819
13027
|
}
|
|
11820
13028
|
]);
|
|
@@ -13183,6 +14391,11 @@ init_widthUtils();
|
|
|
13183
14391
|
import probe2 from "probe-image-size";
|
|
13184
14392
|
|
|
13185
14393
|
// src/quality/text-inventory.ts
|
|
14394
|
+
import {
|
|
14395
|
+
unrenderedComponentText as unrenderedComponentText2
|
|
14396
|
+
} from "@json-to-office/quality";
|
|
14397
|
+
import { TABLE_CELL_COMPONENTS } from "@json-to-office/shared-docx";
|
|
14398
|
+
var CELL_COMPONENTS = new Set(TABLE_CELL_COMPONENTS);
|
|
13186
14399
|
function tocDepth(depth) {
|
|
13187
14400
|
const range = asRecord(depth) ?? {};
|
|
13188
14401
|
const from = typeof range.from === "number" ? range.from : 1;
|
|
@@ -13231,7 +14444,14 @@ function collectDocxTextInventory(children, basePath = "/children") {
|
|
|
13231
14444
|
add(`${path4}/content`, rec.content, cellRole, extra);
|
|
13232
14445
|
else {
|
|
13233
14446
|
const inner = asRecord(rec.content);
|
|
13234
|
-
if (inner)
|
|
14447
|
+
if (inner && typeof inner.name === "string" && !CELL_COMPONENTS.has(inner.name)) {
|
|
14448
|
+
add(
|
|
14449
|
+
`${path4}/content`,
|
|
14450
|
+
unrenderedComponentText2(inner.name),
|
|
14451
|
+
cellRole,
|
|
14452
|
+
{ ...extra, optional: true, unrendered: inner.name }
|
|
14453
|
+
);
|
|
14454
|
+
} else if (inner)
|
|
13235
14455
|
visitNode(inner, `${path4}/content`, { ...inherited, inCell: true });
|
|
13236
14456
|
}
|
|
13237
14457
|
return;
|
|
@@ -15631,18 +16851,18 @@ var docxExhibitRequiredRule = {
|
|
|
15631
16851
|
1
|
|
15632
16852
|
);
|
|
15633
16853
|
if (minimum <= 0) return [];
|
|
15634
|
-
const
|
|
16854
|
+
const charts2 = facts.filter((fact) => fact.kind === "docx/chart").length;
|
|
15635
16855
|
const tables = facts.filter(
|
|
15636
16856
|
(fact) => fact.kind === "docx/table" && fact.columns.length >= 2
|
|
15637
16857
|
).length;
|
|
15638
|
-
const exhibits =
|
|
16858
|
+
const exhibits = charts2 + tables;
|
|
15639
16859
|
if (exhibits >= minimum) return [];
|
|
15640
16860
|
return [
|
|
15641
16861
|
{
|
|
15642
16862
|
path: themeFact(facts)?.path ?? "/props",
|
|
15643
16863
|
message: exhibits === 0 ? `The document carries no data exhibit \u2014 no chart, no table of two or more columns; the ${profile?.id ?? "selected"} profile expects at least ${minimum}.` : `The document carries ${exhibits} data exhibit(s); the ${profile?.id ?? "selected"} profile expects at least ${minimum}.`,
|
|
15644
16864
|
suggestion: "Put the numbers the argument leans on into a chart-figure or a data-table block, with a takeaway and a source, where the text discusses them. A kpi-row summarises; it does not count.",
|
|
15645
|
-
context: { charts, tables, minimum }
|
|
16865
|
+
context: { charts: charts2, tables, minimum }
|
|
15646
16866
|
}
|
|
15647
16867
|
];
|
|
15648
16868
|
}
|