@json-to-office/core-docx 7.2.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1539 -471
- package/dist/index.js.map +1 -1
- package/dist/ir/chartValues.d.ts +16 -0
- package/dist/ir/chartValues.d.ts.map +1 -0
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/ir/features.d.ts.map +1 -1
- package/dist/ir/theme.d.ts +43 -0
- package/dist/ir/theme.d.ts.map +1 -0
- package/dist/ir/types.d.ts +39 -3
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/validation.d.ts +2 -1
- package/dist/ir/validation.d.ts.map +1 -1
- package/dist/plugin/example/index.js +1536 -468
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/renderers/chartText.d.ts +43 -0
- package/dist/renderers/chartText.d.ts.map +1 -0
- package/dist/renderers/docxjs/charts.d.ts +45 -0
- package/dist/renderers/docxjs/charts.d.ts.map +1 -0
- package/dist/renderers/docxjs/docxSubpath.d.ts +34 -0
- package/dist/renderers/docxjs/docxSubpath.d.ts.map +1 -0
- package/dist/renderers/docxjs/drawingGroup.d.ts +79 -0
- package/dist/renderers/docxjs/drawingGroup.d.ts.map +1 -0
- package/dist/renderers/docxjs/drawingGroupRepair.d.ts +36 -0
- package/dist/renderers/docxjs/drawingGroupRepair.d.ts.map +1 -0
- package/dist/renderers/docxjs/emit.d.ts +10 -2
- package/dist/renderers/docxjs/emit.d.ts.map +1 -1
- package/dist/renderers/docxjs/index.d.ts +2 -1
- package/dist/renderers/docxjs/index.d.ts.map +1 -1
- package/dist/renderers/docxjs/presetShapes.d.ts +233 -0
- package/dist/renderers/docxjs/presetShapes.d.ts.map +1 -0
- package/dist/renderers/office-open/chartLook.d.ts +45 -0
- package/dist/renderers/office-open/chartLook.d.ts.map +1 -0
- package/dist/renderers/office-open/chartParts.d.ts +29 -15
- package/dist/renderers/office-open/chartParts.d.ts.map +1 -1
- package/dist/renderers/office-open/emit.d.ts +25 -39
- package/dist/renderers/office-open/emit.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts +16 -4
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/renderers/office-open/themePart.d.ts +28 -0
- package/dist/renderers/office-open/themePart.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/chartWorkbook.d.ts +2 -1
- package/dist/utils/chartWorkbook.d.ts.map +1 -1
- package/dist/utils/fixFloatingImageIds.d.ts +17 -9
- package/dist/utils/fixFloatingImageIds.d.ts.map +1 -1
- package/dist/utils/packageDocument.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/renderers/office-open/cellTocs.d.ts +0 -26
- package/dist/renderers/office-open/cellTocs.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -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",
|
|
@@ -2874,6 +2875,226 @@ var init_units = __esm({
|
|
|
2874
2875
|
}
|
|
2875
2876
|
});
|
|
2876
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
|
+
|
|
2877
3098
|
// src/renderers/docxjs/emit.ts
|
|
2878
3099
|
import {
|
|
2879
3100
|
AlignmentType,
|
|
@@ -2909,7 +3130,7 @@ import {
|
|
|
2909
3130
|
WidthType,
|
|
2910
3131
|
WpsShapeRun
|
|
2911
3132
|
} from "docx";
|
|
2912
|
-
import { assertNever } from "@json-to-office/shared/rendering";
|
|
3133
|
+
import { assertNever as assertNever2 } from "@json-to-office/shared/rendering";
|
|
2913
3134
|
function complexField(instruction, formatting, leading, cachedText) {
|
|
2914
3135
|
const options = runOptions(formatting);
|
|
2915
3136
|
const fieldChar = (type, extra = {}) => new TextRun({
|
|
@@ -2946,7 +3167,12 @@ function runOptions(formatting) {
|
|
|
2946
3167
|
if (formatting.bold !== void 0) options.bold = formatting.bold;
|
|
2947
3168
|
if (formatting.italic !== void 0) options.italics = formatting.italic;
|
|
2948
3169
|
if (formatting.underline !== void 0) {
|
|
2949
|
-
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;
|
|
2950
3176
|
}
|
|
2951
3177
|
if (formatting.strike !== void 0) options.strike = formatting.strike;
|
|
2952
3178
|
if (formatting.allCaps !== void 0) options.allCaps = formatting.allCaps;
|
|
@@ -3072,21 +3298,36 @@ function inlineChildren(children, resources = /* @__PURE__ */ new Map()) {
|
|
|
3072
3298
|
case "shape":
|
|
3073
3299
|
out.push(emitShape(child, resources));
|
|
3074
3300
|
break;
|
|
3075
|
-
case "drawingGroup":
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
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
|
+
)
|
|
3082
3321
|
);
|
|
3322
|
+
break;
|
|
3323
|
+
}
|
|
3083
3324
|
case "noteReference":
|
|
3084
3325
|
out.push(
|
|
3085
3326
|
child.noteKind === "endnote" ? new EndnoteReferenceRun(child.id) : new FootnoteReferenceRun(child.id)
|
|
3086
3327
|
);
|
|
3087
3328
|
break;
|
|
3088
3329
|
default:
|
|
3089
|
-
|
|
3330
|
+
assertNever2(child, "DocxIrInline");
|
|
3090
3331
|
}
|
|
3091
3332
|
}
|
|
3092
3333
|
return out;
|
|
@@ -3291,7 +3532,7 @@ function emitBlock(block2, resources = /* @__PURE__ */ new Map()) {
|
|
|
3291
3532
|
case "toc":
|
|
3292
3533
|
return emitToc(block2);
|
|
3293
3534
|
default:
|
|
3294
|
-
return
|
|
3535
|
+
return assertNever2(block2, "DocxIrBlock");
|
|
3295
3536
|
}
|
|
3296
3537
|
}
|
|
3297
3538
|
function emitToc(block2) {
|
|
@@ -3435,6 +3676,7 @@ var ALIGNMENT2, PAGE_FIELDS, isSequenceField, WRAP_TYPE, ThemedTableOfContents,
|
|
|
3435
3676
|
var init_emit = __esm({
|
|
3436
3677
|
"src/renderers/docxjs/emit.ts"() {
|
|
3437
3678
|
"use strict";
|
|
3679
|
+
init_charts();
|
|
3438
3680
|
ALIGNMENT2 = {
|
|
3439
3681
|
left: AlignmentType.LEFT,
|
|
3440
3682
|
center: AlignmentType.CENTER,
|
|
@@ -3733,10 +3975,13 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3733
3975
|
const rename = new Map(
|
|
3734
3976
|
ordered.map((id, index) => [id, `rId${highest + 1 + index}`])
|
|
3735
3977
|
);
|
|
3736
|
-
const rewrite = (xml) => xml.replace(
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
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
|
+
);
|
|
3740
3985
|
updates.push({ name: relsName, xml: rewrite(relsXml) });
|
|
3741
3986
|
if (partEntry) {
|
|
3742
3987
|
updates.push({ name: partName, xml: rewrite(partXml) });
|
|
@@ -3747,17 +3992,62 @@ function canonicalizeRelationshipIds(zip) {
|
|
|
3747
3992
|
if (entry) zip.updateFile(entry, Buffer.from(update.xml, "utf8"));
|
|
3748
3993
|
}
|
|
3749
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
|
+
}
|
|
3750
4042
|
function canonicalizeDocxBuffer(buffer, generatedAt = DEFAULT_GENERATION_DATE) {
|
|
3751
4043
|
const zip = new AdmZip(buffer);
|
|
3752
4044
|
normalizeTextCase(zip);
|
|
3753
4045
|
canonicalizeRelationshipIds(zip);
|
|
4046
|
+
canonicalizeEmbeddedPackages(zip, generatedAt);
|
|
3754
4047
|
const isoTimestamp = generatedAt.toISOString();
|
|
3755
4048
|
const coreProperties3 = zip.getEntry("docProps/core.xml");
|
|
3756
4049
|
if (coreProperties3) {
|
|
3757
|
-
const normalized = coreProperties3.getData().toString("utf8").replace(
|
|
3758
|
-
/(<dcterms:(?:created|modified)\b[^>]*>)[^<]*(<\/dcterms:(?:created|modified)>)/g,
|
|
3759
|
-
`$1${isoTimestamp}$2`
|
|
3760
|
-
);
|
|
4050
|
+
const normalized = coreProperties3.getData().toString("utf8").replace(CORE_TIMESTAMP, `$1${isoTimestamp}$2`);
|
|
3761
4051
|
zip.updateFile(coreProperties3, Buffer.from(normalized, "utf8"));
|
|
3762
4052
|
}
|
|
3763
4053
|
const zipTimestamp = toDosTime(generatedAt);
|
|
@@ -3770,35 +4060,567 @@ function normalizeDocxCaseBuffer(buffer) {
|
|
|
3770
4060
|
const zip = new AdmZip(buffer);
|
|
3771
4061
|
return normalizeTextCase(zip) ? zip.toBuffer() : buffer;
|
|
3772
4062
|
}
|
|
3773
|
-
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID;
|
|
4063
|
+
var DEFAULT_GENERATION_DATE, STABLE_RELATIONSHIP_ID, CORE_TIMESTAMP, EMBEDDED_OFFICE_PACKAGE, MAX_EMBEDDED_DEPTH;
|
|
3774
4064
|
var init_packageDocument = __esm({
|
|
3775
4065
|
"src/utils/packageDocument.ts"() {
|
|
3776
4066
|
"use strict";
|
|
3777
4067
|
init_normalizeTextCase();
|
|
3778
4068
|
DEFAULT_GENERATION_DATE = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
|
|
3779
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;
|
|
3780
4073
|
}
|
|
3781
4074
|
});
|
|
3782
4075
|
|
|
3783
4076
|
// src/utils/fixFloatingImageIds.ts
|
|
3784
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
|
+
}
|
|
3785
4084
|
function fixFloatingImageIdsInBuffer(buffer) {
|
|
3786
4085
|
const zip = new AdmZip2(buffer);
|
|
3787
|
-
|
|
3788
|
-
if (!documentEntry) {
|
|
4086
|
+
if (!zip.getEntry("word/document.xml")) {
|
|
3789
4087
|
throw new Error("document.xml not found in DOCX");
|
|
3790
4088
|
}
|
|
4089
|
+
const parts = zip.getEntries().filter((entry) => DRAWING_PART.test(entry.entryName)).sort((a, b) => compareDrawingParts(a.entryName, b.entryName));
|
|
3791
4090
|
let idCounter = 1;
|
|
3792
|
-
const
|
|
3793
|
-
const
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
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
|
+
}
|
|
3797
4099
|
return zip.toBuffer();
|
|
3798
4100
|
}
|
|
4101
|
+
var DRAWING_PART, RANK;
|
|
3799
4102
|
var init_fixFloatingImageIds = __esm({
|
|
3800
4103
|
"src/utils/fixFloatingImageIds.ts"() {
|
|
3801
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, "\\$&");
|
|
3802
4624
|
}
|
|
3803
4625
|
});
|
|
3804
4626
|
|
|
@@ -3827,18 +4649,32 @@ function createDocxJsRenderer() {
|
|
|
3827
4649
|
format: "docx",
|
|
3828
4650
|
capabilities: DOCXJS_CAPABILITIES,
|
|
3829
4651
|
async render(ir, renderOptions) {
|
|
3830
|
-
|
|
4652
|
+
await loadDocxCharts();
|
|
4653
|
+
const prepared = await prepareImages(
|
|
3831
4654
|
ir,
|
|
3832
4655
|
renderOptions?.svgRasterFallback
|
|
3833
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
|
+
}
|
|
3834
4669
|
const document = buildDocument(ir, resources);
|
|
3835
4670
|
const packed = await Packer.toBuffer(document);
|
|
3836
4671
|
const fixed = fixFloatingImageIdsInBuffer(packed);
|
|
4672
|
+
const repaired = markers ? repairDrawingGroupsInBuffer(fixed, markers) : fixed;
|
|
3837
4673
|
if (renderOptions?.deterministic === false)
|
|
3838
|
-
return new Uint8Array(normalizeDocxCaseBuffer(
|
|
4674
|
+
return new Uint8Array(normalizeDocxCaseBuffer(repaired));
|
|
3839
4675
|
return new Uint8Array(
|
|
3840
4676
|
canonicalizeDocxBuffer(
|
|
3841
|
-
|
|
4677
|
+
repaired,
|
|
3842
4678
|
resolveGenerationDate({
|
|
3843
4679
|
deterministic: renderOptions?.deterministic,
|
|
3844
4680
|
generatedAt: renderOptions?.generatedAt
|
|
@@ -3851,6 +4687,7 @@ function createDocxJsRenderer() {
|
|
|
3851
4687
|
function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
3852
4688
|
return new Document({
|
|
3853
4689
|
styles: emitStyles(ir.styles),
|
|
4690
|
+
...ir.theme ? { theme: themeOptions(ir.theme) } : {},
|
|
3854
4691
|
sections: ir.sections.map(
|
|
3855
4692
|
(section2, index) => sectionOptions(section2, resources, index === ir.sections.length - 1)
|
|
3856
4693
|
),
|
|
@@ -3882,6 +4719,21 @@ function buildDocument(ir, resources = /* @__PURE__ */ new Map()) {
|
|
|
3882
4719
|
} : {}
|
|
3883
4720
|
});
|
|
3884
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
|
+
}
|
|
3885
4737
|
function noteBodies(notes, resources) {
|
|
3886
4738
|
const bodies = {};
|
|
3887
4739
|
for (const note of notes) {
|
|
@@ -3919,7 +4771,7 @@ function numberingConfig(numbering) {
|
|
|
3919
4771
|
};
|
|
3920
4772
|
}
|
|
3921
4773
|
async function prepareImages(ir, svgRasterFallback) {
|
|
3922
|
-
const placements = collectImagePlacements(ir);
|
|
4774
|
+
const { placements, drawingGroups } = collectImagePlacements(ir);
|
|
3923
4775
|
const jobs = [];
|
|
3924
4776
|
for (const resource of ir.resources) {
|
|
3925
4777
|
if (resource.kind !== "image" || resource.mediaType !== "svg") continue;
|
|
@@ -3967,16 +4819,55 @@ async function prepareImages(ir, svgRasterFallback) {
|
|
|
3967
4819
|
});
|
|
3968
4820
|
});
|
|
3969
4821
|
}
|
|
3970
|
-
|
|
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 };
|
|
3971
4847
|
}
|
|
3972
4848
|
function collectImagePlacements(ir) {
|
|
3973
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
|
+
};
|
|
3974
4857
|
const visitInline = (inline) => {
|
|
3975
4858
|
if (inline.kind === "image") {
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
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
|
+
}
|
|
3980
4871
|
return;
|
|
3981
4872
|
}
|
|
3982
4873
|
if (inline.kind === "hyperlink" || inline.kind === "revision") {
|
|
@@ -4007,7 +4898,7 @@ function collectImagePlacements(ir) {
|
|
|
4007
4898
|
for (const note of [...ir.footnotes, ...ir.endnotes]) {
|
|
4008
4899
|
note.children.forEach(visitBlock);
|
|
4009
4900
|
}
|
|
4010
|
-
return placements;
|
|
4901
|
+
return { placements, drawingGroups };
|
|
4011
4902
|
}
|
|
4012
4903
|
function sectionOptions(section2, resources, closesDocument = false) {
|
|
4013
4904
|
const { page, columns } = section2.properties;
|
|
@@ -4120,17 +5011,26 @@ function coreProperties(ir) {
|
|
|
4120
5011
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
4121
5012
|
};
|
|
4122
5013
|
}
|
|
4123
|
-
var DOCXJS_RENDERER_ID, DOCXJS_CAPABILITIES;
|
|
5014
|
+
var DOCXJS_RENDERER_ID, shapes, DOCXJS_CAPABILITIES;
|
|
4124
5015
|
var init_docxjs = __esm({
|
|
4125
5016
|
"src/renderers/docxjs/index.ts"() {
|
|
4126
5017
|
"use strict";
|
|
4127
5018
|
init_styles2();
|
|
5019
|
+
init_charts();
|
|
4128
5020
|
init_imageUtils();
|
|
4129
5021
|
init_packageDocument();
|
|
4130
5022
|
init_fixFloatingImageIds();
|
|
4131
5023
|
init_emit();
|
|
5024
|
+
init_docxSubpath();
|
|
5025
|
+
init_drawingGroup();
|
|
5026
|
+
init_drawingGroupRepair();
|
|
4132
5027
|
init_units();
|
|
4133
5028
|
DOCXJS_RENDERER_ID = "docxjs";
|
|
5029
|
+
shapes = docxSubpath(
|
|
5030
|
+
"docx/shapes",
|
|
5031
|
+
"visual",
|
|
5032
|
+
() => import("docx/shapes")
|
|
5033
|
+
);
|
|
4134
5034
|
DOCXJS_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
4135
5035
|
"paragraphs",
|
|
4136
5036
|
"styles",
|
|
@@ -4143,8 +5043,10 @@ var init_docxjs = __esm({
|
|
|
4143
5043
|
"images",
|
|
4144
5044
|
"floating-images",
|
|
4145
5045
|
"svg-images",
|
|
5046
|
+
"charts",
|
|
4146
5047
|
"text-frames",
|
|
4147
5048
|
"text-boxes",
|
|
5049
|
+
"drawing-groups",
|
|
4148
5050
|
"toc",
|
|
4149
5051
|
"cached-toc",
|
|
4150
5052
|
"fields",
|
|
@@ -4165,183 +5067,331 @@ var init_docxjs = __esm({
|
|
|
4165
5067
|
}
|
|
4166
5068
|
});
|
|
4167
5069
|
|
|
4168
|
-
// src/
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
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 {};
|
|
4182
5083
|
}
|
|
4183
|
-
|
|
4184
|
-
|
|
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 {};
|
|
5145
|
+
}
|
|
5146
|
+
}
|
|
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;
|
|
4185
5184
|
}
|
|
4186
|
-
return new Uint8Array(zip.toBuffer());
|
|
4187
5185
|
}
|
|
4188
|
-
var
|
|
4189
|
-
var
|
|
4190
|
-
"src/
|
|
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"() {
|
|
4191
5189
|
"use strict";
|
|
4192
|
-
|
|
4193
|
-
|
|
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 };
|
|
4194
5218
|
}
|
|
4195
5219
|
});
|
|
4196
5220
|
|
|
4197
5221
|
// src/renderers/office-open/chartParts.ts
|
|
4198
5222
|
import {
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
matchChartParts,
|
|
4202
|
-
spliceChartXml
|
|
5223
|
+
finishChartXml,
|
|
5224
|
+
matchChartParts
|
|
4203
5225
|
} from "@json-to-office/shared/rendering";
|
|
4204
|
-
function
|
|
4205
|
-
const
|
|
4206
|
-
const textFont =
|
|
4207
|
-
const axisTitleFont =
|
|
4208
|
-
const chartTitleFont =
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
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 } : {}
|
|
4212
5239
|
};
|
|
4213
5240
|
return {
|
|
5241
|
+
...look,
|
|
4214
5242
|
chartType: chart.chartType,
|
|
4215
5243
|
series: chart.series,
|
|
4216
5244
|
colors: chart.colors,
|
|
5245
|
+
...chart.title && chart.showTitle !== false ? { title: chart.title } : {},
|
|
4217
5246
|
textFont,
|
|
4218
5247
|
titleFont: chartTitleFont,
|
|
4219
5248
|
...chart.legendPosition ? { legendPosition: chart.legendPosition } : {},
|
|
4220
|
-
...
|
|
4221
|
-
|
|
4222
|
-
title: chart.categoryAxisTitle,
|
|
4223
|
-
titleFont: axisTitleFont
|
|
4224
|
-
}
|
|
4225
|
-
} : {},
|
|
4226
|
-
...chart.valueAxisTitle ? {
|
|
4227
|
-
valueAxis: { title: chart.valueAxisTitle, titleFont: axisTitleFont }
|
|
4228
|
-
} : {}
|
|
5249
|
+
...Object.keys(categoryAxis).length > 0 ? { categoryAxis } : {},
|
|
5250
|
+
...Object.keys(valueAxis).length > 0 ? { valueAxis } : {}
|
|
4229
5251
|
};
|
|
4230
5252
|
}
|
|
4231
|
-
function
|
|
4232
|
-
|
|
4233
|
-
if (!entry) return;
|
|
4234
|
-
const xml = entry.getData().toString("utf8");
|
|
4235
|
-
if (xml.includes(`Extension="xlsx"`)) return;
|
|
4236
|
-
zip.updateFile(
|
|
4237
|
-
entry,
|
|
4238
|
-
Buffer.from(
|
|
4239
|
-
xml.replace(
|
|
4240
|
-
'<Default Extension="xml"',
|
|
4241
|
-
`<Default Extension="xlsx" ContentType="${CHART_WORKBOOK_CONTENT_TYPE}"/><Default Extension="xml"`
|
|
4242
|
-
),
|
|
4243
|
-
"utf8"
|
|
4244
|
-
)
|
|
4245
|
-
);
|
|
4246
|
-
}
|
|
4247
|
-
function spliceChartParts(zip, charts) {
|
|
4248
|
-
if (charts.length === 0) return;
|
|
5253
|
+
function finishChartParts(zip, charts2) {
|
|
5254
|
+
if (charts2.length === 0) return;
|
|
4249
5255
|
const parts = zip.getEntries().map((entry) => entry.entryName).map((name) => name.match(/^word\/charts\/chart(\d+)\.xml$/)).filter((match) => match !== null).map(
|
|
4250
5256
|
(match) => [
|
|
4251
5257
|
Number(match[1]),
|
|
4252
5258
|
zip.getEntry(match[0]).getData().toString("utf8")
|
|
4253
5259
|
]
|
|
4254
5260
|
);
|
|
4255
|
-
|
|
4256
|
-
|
|
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;
|
|
4257
5265
|
zip.updateFile(
|
|
4258
5266
|
zip.getEntry(`word/charts/chart${ordinal}.xml`),
|
|
4259
|
-
Buffer.from(
|
|
4260
|
-
);
|
|
4261
|
-
zip.addFile(
|
|
4262
|
-
`word/embeddings/${workbookName}`,
|
|
4263
|
-
Buffer.from(buildChartWorkbook(chart.series))
|
|
4264
|
-
);
|
|
4265
|
-
zip.addFile(
|
|
4266
|
-
`word/charts/_rels/chart${ordinal}.xml.rels`,
|
|
4267
|
-
Buffer.from(chartWorkbookRelsXml(workbookName), "utf8")
|
|
5267
|
+
Buffer.from(finished, "utf8")
|
|
4268
5268
|
);
|
|
4269
5269
|
}
|
|
4270
|
-
declareWorkbookContentType(zip);
|
|
4271
5270
|
}
|
|
4272
|
-
var CHART_TITLE_SCALE;
|
|
4273
5271
|
var init_chartParts = __esm({
|
|
4274
5272
|
"src/renderers/office-open/chartParts.ts"() {
|
|
4275
5273
|
"use strict";
|
|
4276
|
-
|
|
4277
|
-
|
|
5274
|
+
init_chartText();
|
|
5275
|
+
init_chartLook();
|
|
4278
5276
|
}
|
|
4279
5277
|
});
|
|
4280
5278
|
|
|
4281
|
-
// src/renderers/office-open/
|
|
4282
|
-
function
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
for (const entry of zip.getEntries()) {
|
|
4286
|
-
if (!TABLE_PARTS.test(entry.entryName)) continue;
|
|
4287
|
-
const original = entry.getData().toString("utf8");
|
|
4288
|
-
let xml = original;
|
|
4289
|
-
for (const toc of tocs) {
|
|
4290
|
-
const start = markerParagraph(xml, toc.start);
|
|
4291
|
-
if (!start) continue;
|
|
4292
|
-
const end = markerParagraph(xml, toc.end);
|
|
4293
|
-
if (spliced.has(toc) || !end || end.from < start.to) {
|
|
4294
|
-
throw new Error(
|
|
4295
|
-
`the office-open renderer lost track of a table of contents in a table cell (${entry.entryName})`
|
|
4296
|
-
);
|
|
4297
|
-
}
|
|
4298
|
-
xml = xml.slice(0, start.from) + stringifyTableOfContents(
|
|
4299
|
-
toc.alias,
|
|
4300
|
-
toc.options,
|
|
4301
|
-
xml.slice(start.to, end.from)
|
|
4302
|
-
) + xml.slice(end.to);
|
|
4303
|
-
spliced.add(toc);
|
|
4304
|
-
}
|
|
4305
|
-
if (xml !== original) zip.updateFile(entry, Buffer.from(xml, "utf8"));
|
|
4306
|
-
}
|
|
4307
|
-
if (spliced.size !== tocs.length) {
|
|
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) {
|
|
4308
5283
|
throw new Error(
|
|
4309
|
-
`
|
|
5284
|
+
`office-open's theme part has ${count} ${what}, expected one`
|
|
4310
5285
|
);
|
|
4311
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"));
|
|
4312
5323
|
}
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
xml
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
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`
|
|
4324
5353
|
);
|
|
4325
5354
|
}
|
|
4326
|
-
|
|
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());
|
|
4327
5376
|
}
|
|
4328
|
-
var
|
|
4329
|
-
var
|
|
4330
|
-
"src/
|
|
5377
|
+
var WORKBOOK_TIMESTAMP;
|
|
5378
|
+
var init_chartWorkbook = __esm({
|
|
5379
|
+
"src/utils/chartWorkbook.ts"() {
|
|
4331
5380
|
"use strict";
|
|
4332
|
-
|
|
5381
|
+
init_packageDocument();
|
|
5382
|
+
WORKBOOK_TIMESTAMP = toDosTime(DEFAULT_GENERATION_DATE);
|
|
4333
5383
|
}
|
|
4334
5384
|
});
|
|
4335
5385
|
|
|
4336
5386
|
// src/renderers/office-open/emit.ts
|
|
4337
|
-
import { assertNever as
|
|
5387
|
+
import { assertNever as assertNever3 } from "@json-to-office/shared/rendering";
|
|
5388
|
+
import { chartLook, withSeriesLook } from "@json-to-office/shared/rendering";
|
|
4338
5389
|
function emptyContext() {
|
|
4339
5390
|
let next = 1;
|
|
4340
5391
|
return {
|
|
4341
5392
|
pictures: /* @__PURE__ */ new Map(),
|
|
4342
5393
|
nextDrawingId: () => next++,
|
|
4343
|
-
charts: []
|
|
4344
|
-
cellTocs: []
|
|
5394
|
+
charts: []
|
|
4345
5395
|
};
|
|
4346
5396
|
}
|
|
4347
5397
|
function simpleField(instruction, cachedText) {
|
|
@@ -4382,18 +5432,19 @@ function runProperties2(formatting) {
|
|
|
4382
5432
|
if (formatting.doubleStrike !== void 0) {
|
|
4383
5433
|
out.doubleStrike = formatting.doubleStrike;
|
|
4384
5434
|
}
|
|
4385
|
-
if (formatting.superScript) out.
|
|
4386
|
-
if (formatting.subScript) out.
|
|
5435
|
+
if (formatting.superScript) out.verticalAlign = "superscript";
|
|
5436
|
+
if (formatting.subScript) out.verticalAlign = "subscript";
|
|
4387
5437
|
if (formatting.smallCaps !== void 0) out.smallCaps = formatting.smallCaps;
|
|
4388
5438
|
if (formatting.allCaps !== void 0) out.allCaps = formatting.allCaps;
|
|
4389
|
-
if (formatting.highlight !== void 0)
|
|
5439
|
+
if (formatting.highlight !== void 0) {
|
|
5440
|
+
out.highlight = formatting.highlight;
|
|
5441
|
+
}
|
|
4390
5442
|
if (formatting.shading) out.shading = shading(formatting.shading);
|
|
4391
5443
|
if (formatting.scalePercent !== void 0)
|
|
4392
5444
|
out.scale = formatting.scalePercent;
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
out.characterSpacing = twentieths === 0 && stated !== 0 ? "0pt" : twentieths;
|
|
5445
|
+
const stated = formatting.characterSpacingTwentieths;
|
|
5446
|
+
if (stated !== void 0 && stated !== 0) {
|
|
5447
|
+
out.characterSpacing = twips(stated);
|
|
4397
5448
|
}
|
|
4398
5449
|
if (formatting.language) out.language = { value: formatting.language };
|
|
4399
5450
|
if (formatting.noProof !== void 0) out.noProof = formatting.noProof;
|
|
@@ -4423,7 +5474,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4423
5474
|
switch (child.kind) {
|
|
4424
5475
|
case "lineBreak":
|
|
4425
5476
|
pendingBreaks += 1;
|
|
4426
|
-
if (child.clear && child.clear !== "none")
|
|
5477
|
+
if (child.clear && child.clear !== "none") {
|
|
5478
|
+
pendingClear = child.clear;
|
|
5479
|
+
}
|
|
4427
5480
|
break;
|
|
4428
5481
|
case "text":
|
|
4429
5482
|
out.push({
|
|
@@ -4461,7 +5514,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4461
5514
|
case "drawingGroup": {
|
|
4462
5515
|
const pending = breakOption();
|
|
4463
5516
|
if (pending.break) out.push(pending);
|
|
4464
|
-
out.push({ wpgGroup:
|
|
5517
|
+
out.push({ wpgGroup: drawingGroupOptions2(child, ctx) });
|
|
4465
5518
|
break;
|
|
4466
5519
|
}
|
|
4467
5520
|
case "hyperlink":
|
|
@@ -4491,8 +5544,9 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4491
5544
|
out.push({ wpsShape: shapeOptions(child, ctx) });
|
|
4492
5545
|
break;
|
|
4493
5546
|
case "chart":
|
|
4494
|
-
|
|
4495
|
-
|
|
5547
|
+
out.push({
|
|
5548
|
+
chart: chartOptions(child, ctx, ctx.charts?.push(child) ?? 1)
|
|
5549
|
+
});
|
|
4496
5550
|
break;
|
|
4497
5551
|
case "noteReference":
|
|
4498
5552
|
out.push(
|
|
@@ -4500,7 +5554,7 @@ function inlineChildren2(children, ctx = emptyContext()) {
|
|
|
4500
5554
|
);
|
|
4501
5555
|
break;
|
|
4502
5556
|
default:
|
|
4503
|
-
|
|
5557
|
+
assertNever3(child, "DocxIrInline");
|
|
4504
5558
|
}
|
|
4505
5559
|
}
|
|
4506
5560
|
return out;
|
|
@@ -4541,8 +5595,11 @@ function floatingOptions2(floating) {
|
|
|
4541
5595
|
...floating.vertical ? { verticalPosition: position(floating.vertical) } : {},
|
|
4542
5596
|
...floating.wrap ? {
|
|
4543
5597
|
wrap: {
|
|
4544
|
-
|
|
4545
|
-
|
|
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
|
+
} : {}
|
|
4546
5603
|
}
|
|
4547
5604
|
} : {},
|
|
4548
5605
|
...floating.margins ? {
|
|
@@ -4569,66 +5626,92 @@ function imageMedia(ctx, resourceId, placement) {
|
|
|
4569
5626
|
}
|
|
4570
5627
|
function pictureOptions(image, ctx) {
|
|
4571
5628
|
const media = imageMedia(ctx, image.resourceId, image);
|
|
4572
|
-
|
|
4573
|
-
type:
|
|
5629
|
+
const source = media.type === "svg" ? {
|
|
5630
|
+
type: "svg",
|
|
4574
5631
|
data: media.data,
|
|
4575
|
-
//
|
|
4576
|
-
//
|
|
4577
|
-
|
|
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,
|
|
4578
5641
|
// Raw numbers are EMUs in @office-open/docx. Passing pixels here makes a
|
|
4579
5642
|
// normal image only a few hundred EMUs wide, effectively a dot.
|
|
4580
5643
|
transformation: { width: image.widthEmu, height: image.heightEmu },
|
|
4581
5644
|
// The id is stated rather than left to the backend's process-global
|
|
4582
|
-
// counter. `name` stays empty, which is what
|
|
4583
|
-
|
|
4584
|
-
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: "" },
|
|
4585
5647
|
...image.floating ? { floating: floatingOptions2(image.floating) } : {}
|
|
4586
5648
|
// No `description` or `title`: no DOCX this pipeline has produced carries
|
|
4587
5649
|
// `wp:docPr` alt text, and the compiler warns so the gap is visible rather
|
|
4588
5650
|
// than silent.
|
|
4589
5651
|
};
|
|
4590
5652
|
}
|
|
4591
|
-
function
|
|
5653
|
+
function drawingGroupOptions2(group, ctx) {
|
|
4592
5654
|
const id = ctx.nextDrawingId();
|
|
4593
5655
|
return {
|
|
4594
5656
|
altText: {
|
|
4595
5657
|
id: String(id),
|
|
5658
|
+
name: "",
|
|
4596
5659
|
...group.altText ? { description: group.altText } : {}
|
|
4597
5660
|
},
|
|
4598
5661
|
transformation: { width: group.widthEmu, height: group.heightEmu },
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
5662
|
+
childOffsetX: 0,
|
|
5663
|
+
childOffsetY: 0,
|
|
5664
|
+
childExtentWidth: group.canvasWidthEmu,
|
|
5665
|
+
childExtentHeight: group.canvasHeightEmu,
|
|
5666
|
+
children: group.children.map((child) => groupChild2(child, ctx)),
|
|
4602
5667
|
...group.floating ? { floating: floatingOptions2(group.floating) } : {}
|
|
4603
5668
|
};
|
|
4604
5669
|
}
|
|
4605
|
-
function chartOptions(chart, ctx) {
|
|
5670
|
+
function chartOptions(chart, ctx, ordinal) {
|
|
4606
5671
|
const id = ctx.nextDrawingId();
|
|
5672
|
+
const input = chartInput(chart);
|
|
5673
|
+
const look = chartLook(input);
|
|
4607
5674
|
return {
|
|
4608
5675
|
type: chart.chartType,
|
|
4609
5676
|
categories: chart.series[0]?.labels ?? [],
|
|
4610
|
-
series: chart.series.map(
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
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,
|
|
4615
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
|
+
},
|
|
4616
5698
|
transformation: { width: chart.widthEmu, height: chart.heightEmu },
|
|
4617
5699
|
altText: {
|
|
4618
5700
|
id: String(id),
|
|
5701
|
+
name: "",
|
|
4619
5702
|
...chart.altText ? { description: chart.altText } : {}
|
|
4620
5703
|
},
|
|
4621
5704
|
...chart.floating ? { floating: floatingOptions2(chart.floating) } : {}
|
|
4622
5705
|
};
|
|
4623
5706
|
}
|
|
4624
|
-
function
|
|
5707
|
+
function groupChild2(child, ctx) {
|
|
4625
5708
|
return child.kind === "shape" ? groupShape(child, ctx) : groupPicture(child, ctx);
|
|
4626
5709
|
}
|
|
4627
5710
|
function groupShape(shape, ctx) {
|
|
4628
5711
|
const id = ctx.nextDrawingId();
|
|
4629
5712
|
return {
|
|
4630
5713
|
type: "wps",
|
|
4631
|
-
transformation:
|
|
5714
|
+
transformation: childTransformation2(shape.frame),
|
|
4632
5715
|
data: {
|
|
4633
5716
|
nonVisualProperties: {
|
|
4634
5717
|
id,
|
|
@@ -4637,7 +5720,7 @@ function groupShape(shape, ctx) {
|
|
|
4637
5720
|
// to hold text, and it changes how the object behaves on selection.
|
|
4638
5721
|
...shape.isTextBox ? { textBox: "1" } : {}
|
|
4639
5722
|
},
|
|
4640
|
-
|
|
5723
|
+
geometry: shape.geometry,
|
|
4641
5724
|
...shape.fill ? { fill: drawingFill(shape.fill) } : {},
|
|
4642
5725
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
4643
5726
|
children: (shape.text?.paragraphs ?? []).map(
|
|
@@ -4663,7 +5746,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4663
5746
|
fileName: media.fallbackFileName
|
|
4664
5747
|
}
|
|
4665
5748
|
} : {},
|
|
4666
|
-
transformation:
|
|
5749
|
+
transformation: childTransformation2(picture2.frame),
|
|
4667
5750
|
nonVisualProperties: {
|
|
4668
5751
|
id,
|
|
4669
5752
|
...picture2.name ? { name: picture2.name } : {},
|
|
@@ -4672,11 +5755,7 @@ function groupPicture(picture2, ctx) {
|
|
|
4672
5755
|
...picture2.crop ? { sourceRectangle: sourceRectangle(picture2.crop) } : {}
|
|
4673
5756
|
};
|
|
4674
5757
|
}
|
|
4675
|
-
function
|
|
4676
|
-
const flip = {
|
|
4677
|
-
...frame.flipHorizontal ? { horizontal: true } : {},
|
|
4678
|
-
...frame.flipVertical ? { vertical: true } : {}
|
|
4679
|
-
};
|
|
5758
|
+
function childTransformation2(frame) {
|
|
4680
5759
|
return {
|
|
4681
5760
|
offset: {
|
|
4682
5761
|
emus: { x: frame.xEmu, y: frame.yEmu },
|
|
@@ -4692,7 +5771,8 @@ function childTransformation(frame) {
|
|
|
4692
5771
|
},
|
|
4693
5772
|
// Degrees: the backend multiplies by 60000 on the way into `@rot`.
|
|
4694
5773
|
...frame.rotationDegrees !== void 0 ? { rotation: frame.rotationDegrees } : {},
|
|
4695
|
-
...
|
|
5774
|
+
...frame.flipHorizontal ? { flipHorizontal: true } : {},
|
|
5775
|
+
...frame.flipVertical ? { flipVertical: true } : {}
|
|
4696
5776
|
};
|
|
4697
5777
|
}
|
|
4698
5778
|
function drawingFill(fill) {
|
|
@@ -4700,7 +5780,6 @@ function drawingFill(fill) {
|
|
|
4700
5780
|
return {
|
|
4701
5781
|
type: "solid",
|
|
4702
5782
|
color: {
|
|
4703
|
-
type: "rgb",
|
|
4704
5783
|
value: fill.color.hex,
|
|
4705
5784
|
// Transparency becomes an alpha transform on the colour. DrawingML
|
|
4706
5785
|
// states *opacity*, so the value is the complement of what the author
|
|
@@ -4742,7 +5821,7 @@ function sourceRectangle(crop) {
|
|
|
4742
5821
|
function shapeOptions(shape, ctx) {
|
|
4743
5822
|
const id = String(ctx.nextDrawingId());
|
|
4744
5823
|
return {
|
|
4745
|
-
altText: { id },
|
|
5824
|
+
altText: { id, name: "" },
|
|
4746
5825
|
children: shape.children.map((child) => paragraph(child, ctx)),
|
|
4747
5826
|
// Raw transformation numbers are EMUs in @office-open/docx, while the IR
|
|
4748
5827
|
// deliberately stores native shape dimensions in pixels.
|
|
@@ -4753,7 +5832,7 @@ function shapeOptions(shape, ctx) {
|
|
|
4753
5832
|
...shape.fill ? {
|
|
4754
5833
|
fill: {
|
|
4755
5834
|
type: "solid",
|
|
4756
|
-
color: {
|
|
5835
|
+
color: { value: shape.fill.hex }
|
|
4757
5836
|
}
|
|
4758
5837
|
} : {},
|
|
4759
5838
|
...shape.outline ? { outline: drawingOutline(shape.outline) } : {},
|
|
@@ -4858,13 +5937,19 @@ function frameOptions2(frame) {
|
|
|
4858
5937
|
...frame.anchorLock !== void 0 ? { anchorLock: frame.anchorLock } : {},
|
|
4859
5938
|
...frame.rule ? { rule: frame.rule } : {}
|
|
4860
5939
|
};
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
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 {
|
|
4866
5948
|
type: "alignment",
|
|
4867
|
-
alignment: {
|
|
5949
|
+
alignment: {
|
|
5950
|
+
x: frame.xAlign,
|
|
5951
|
+
y: frame.yAlign
|
|
5952
|
+
},
|
|
4868
5953
|
...base
|
|
4869
5954
|
};
|
|
4870
5955
|
}
|
|
@@ -4885,7 +5970,7 @@ function block(value, ctx = emptyContext()) {
|
|
|
4885
5970
|
case "toc":
|
|
4886
5971
|
return { toc: tableOfContents(value) };
|
|
4887
5972
|
default:
|
|
4888
|
-
return
|
|
5973
|
+
return assertNever3(value, "DocxIrBlock");
|
|
4889
5974
|
}
|
|
4890
5975
|
}
|
|
4891
5976
|
function tocEntry(entry) {
|
|
@@ -4904,6 +5989,7 @@ function tableOfContents(value) {
|
|
|
4904
5989
|
headingStyleRange: `${value.headingRange.from}-${value.headingRange.to}`
|
|
4905
5990
|
} : {},
|
|
4906
5991
|
...value.styleLevels?.length ? {
|
|
5992
|
+
// `StyleLevel` is a class the backend only reads the two fields of.
|
|
4907
5993
|
stylesWithLevels: value.styleLevels.map((style) => ({
|
|
4908
5994
|
styleName: style.styleName,
|
|
4909
5995
|
level: style.level
|
|
@@ -4925,14 +6011,16 @@ function table(value, ctx) {
|
|
|
4925
6011
|
// unstated columns comes out fractional, and the XML would carry it
|
|
4926
6012
|
// verbatim; floored here, as the docxjs backend floors it.
|
|
4927
6013
|
size: value.width.kind === "auto" ? 0 : value.width.kind === "twips" ? twips(value.width.value) : value.width.value,
|
|
4928
|
-
type: value.width.kind === "twips" ? "
|
|
6014
|
+
type: value.width.kind === "twips" ? "twips" : value.width.kind === "percent" ? "percent" : "auto"
|
|
4929
6015
|
},
|
|
4930
6016
|
layout: value.layout,
|
|
4931
6017
|
// An empty grid is a table with nothing to say about its columns, which is
|
|
4932
6018
|
// not the same as one whose columns are all zero wide. The compiler hands
|
|
4933
6019
|
// over every grid in twips; floored for the same reason as the width.
|
|
4934
6020
|
...value.columnGrid.values.length > 0 ? { columnWidths: value.columnGrid.values.map(twips) } : {},
|
|
4935
|
-
...value.alignment ? {
|
|
6021
|
+
...value.alignment ? {
|
|
6022
|
+
alignment: alignment(value.alignment)
|
|
6023
|
+
} : {},
|
|
4936
6024
|
...value.borders ? { borders: borders2(value.borders) } : {},
|
|
4937
6025
|
...value.cellMargins ? { margins: cellMargins(value.cellMargins) } : {},
|
|
4938
6026
|
...value.floating ? { float: tableFloat2(value.floating) } : {}
|
|
@@ -4977,52 +6065,29 @@ function tableRow(row, ctx) {
|
|
|
4977
6065
|
}
|
|
4978
6066
|
function tableCell(cell, ctx) {
|
|
4979
6067
|
const children = cellChildren2(cell, ctx);
|
|
4980
|
-
if (cell.children[cell.children.length - 1]?.kind
|
|
6068
|
+
if (cell.children[cell.children.length - 1]?.kind === "toc")
|
|
4981
6069
|
children.push({ paragraph: { children: [] } });
|
|
4982
6070
|
return {
|
|
4983
6071
|
children,
|
|
4984
|
-
...cell.widthTwips !== void 0 ? { width: { size: twips(cell.widthTwips), type: "
|
|
4985
|
-
...cell.verticalAlign ? {
|
|
6072
|
+
...cell.widthTwips !== void 0 ? { width: { size: twips(cell.widthTwips), type: "twips" } } : {},
|
|
6073
|
+
...cell.verticalAlign ? {
|
|
6074
|
+
verticalAlign: cell.verticalAlign
|
|
6075
|
+
} : {},
|
|
4986
6076
|
...cell.shading ? { shading: shading(cell.shading) } : {},
|
|
4987
6077
|
...cell.margins ? { margins: cellMargins(cell.margins) } : {},
|
|
4988
6078
|
...cell.borders ? { borders: borders2(cell.borders) } : {},
|
|
4989
6079
|
...cell.columnSpan !== void 0 ? { columnSpan: cell.columnSpan } : {},
|
|
4990
6080
|
...cell.rowSpan !== void 0 ? { verticalMerge: cell.rowSpan } : {},
|
|
4991
|
-
...cell.textDirection ? {
|
|
6081
|
+
...cell.textDirection ? {
|
|
6082
|
+
textDirection: cell.textDirection
|
|
6083
|
+
} : {}
|
|
4992
6084
|
};
|
|
4993
6085
|
}
|
|
4994
6086
|
function cellChildren2(cell, ctx) {
|
|
4995
|
-
|
|
4996
|
-
for (const child of cell.children) {
|
|
4997
|
-
if (child.kind !== "toc") {
|
|
4998
|
-
children.push(block(child, ctx));
|
|
4999
|
-
continue;
|
|
5000
|
-
}
|
|
5001
|
-
const { alias, entries, ...options } = tableOfContents(child);
|
|
5002
|
-
const index = ctx.cellTocs.length;
|
|
5003
|
-
const toc = {
|
|
5004
|
-
start: cellTocMarker(index, "start"),
|
|
5005
|
-
end: cellTocMarker(index, "end"),
|
|
5006
|
-
alias: String(alias),
|
|
5007
|
-
options
|
|
5008
|
-
};
|
|
5009
|
-
ctx.cellTocs.push(toc);
|
|
5010
|
-
children.push(
|
|
5011
|
-
markerParagraph2(toc.start),
|
|
5012
|
-
...entries ?? [],
|
|
5013
|
-
markerParagraph2(toc.end)
|
|
5014
|
-
);
|
|
5015
|
-
}
|
|
5016
|
-
return children;
|
|
5017
|
-
}
|
|
5018
|
-
function cellTocMarker(index, edge) {
|
|
5019
|
-
return `\uE000jto-cell-toc-${index}-${edge}\uE000`;
|
|
5020
|
-
}
|
|
5021
|
-
function markerParagraph2(text) {
|
|
5022
|
-
return { paragraph: { children: [{ text }] } };
|
|
6087
|
+
return cell.children.map((child) => block(child, ctx));
|
|
5023
6088
|
}
|
|
5024
6089
|
function cellMargins(margins) {
|
|
5025
|
-
const side = (value) => value === void 0 ? void 0 : { size: twips(value), type: "
|
|
6090
|
+
const side = (value) => value === void 0 ? void 0 : { size: twips(value), type: "twips" };
|
|
5026
6091
|
const out = {};
|
|
5027
6092
|
for (const [name, value] of [
|
|
5028
6093
|
["top", margins.topTwips],
|
|
@@ -5065,39 +6130,43 @@ function section(value, ctx, closesDocument = false) {
|
|
|
5065
6130
|
properties: {
|
|
5066
6131
|
...value.properties.type ? { type: value.properties.type } : {},
|
|
5067
6132
|
...value.properties.titlePage !== void 0 ? { titlePage: value.properties.titlePage } : {},
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
...page.code !== void 0 ? { code: page.code } : {}
|
|
5075
|
-
},
|
|
5076
|
-
margin: {
|
|
5077
|
-
top: twips(page.margins.topTwips),
|
|
5078
|
-
right: twips(page.margins.rightTwips),
|
|
5079
|
-
bottom: twips(page.margins.bottomTwips),
|
|
5080
|
-
left: twips(page.margins.leftTwips),
|
|
5081
|
-
...page.margins.headerTwips !== void 0 ? { header: twips(page.margins.headerTwips) } : {},
|
|
5082
|
-
...page.margins.footerTwips !== void 0 ? { footer: twips(page.margins.footerTwips) } : {},
|
|
5083
|
-
...page.margins.gutterTwips !== void 0 ? { gutter: twips(page.margins.gutterTwips) } : {}
|
|
5084
|
-
},
|
|
5085
|
-
...value.properties.pageNumbers ? {
|
|
5086
|
-
pageNumbers: {
|
|
5087
|
-
...value.properties.pageNumbers.start !== void 0 ? { start: value.properties.pageNumbers.start } : {},
|
|
5088
|
-
...value.properties.pageNumbers.formatType ? { formatType: value.properties.pageNumbers.formatType } : {}
|
|
5089
|
-
}
|
|
5090
|
-
} : {},
|
|
5091
|
-
...value.properties.borders ? {
|
|
5092
|
-
borders: {
|
|
5093
|
-
...value.properties.borders.display ? { display: value.properties.borders.display } : {},
|
|
5094
|
-
...value.properties.borders.offsetFrom ? { offsetFrom: value.properties.borders.offsetFrom } : {},
|
|
5095
|
-
...value.properties.borders.borders ? borders2(value.properties.borders.borders) : {}
|
|
5096
|
-
}
|
|
5097
|
-
} : {}
|
|
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 } : {}
|
|
5098
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
|
+
} : {},
|
|
5099
6168
|
...columns ? {
|
|
5100
|
-
|
|
6169
|
+
columns: {
|
|
5101
6170
|
count: columns.count,
|
|
5102
6171
|
...columns.spaceTwips !== void 0 ? { space: twips(columns.spaceTwips) } : {},
|
|
5103
6172
|
...columns.separator !== void 0 ? { separate: columns.separator } : {},
|
|
@@ -5141,6 +6210,8 @@ function sectionChildren2(value, ctx, closesDocument = false) {
|
|
|
5141
6210
|
spacing: { before: 0, after: 0, line: 20, lineRule: "exact" }
|
|
5142
6211
|
}
|
|
5143
6212
|
});
|
|
6213
|
+
if (!closesDocument && !bookmark?.closes && last?.kind === "toc")
|
|
6214
|
+
blocks.push({ paragraph: { children: [] } });
|
|
5144
6215
|
if (!bookmark) return blocks;
|
|
5145
6216
|
return [
|
|
5146
6217
|
...bookmark.opens ? [{ bookmarkStart: { id: bookmark.id, name: bookmark.name } }] : [],
|
|
@@ -5151,15 +6222,19 @@ function sectionChildren2(value, ctx, closesDocument = false) {
|
|
|
5151
6222
|
function numberingConfig2(numbering) {
|
|
5152
6223
|
return {
|
|
5153
6224
|
reference: numbering.reference,
|
|
5154
|
-
levels: numbering.levels.map(
|
|
5155
|
-
level
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
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 } : {},
|
|
5163
6238
|
...level.indent ? {
|
|
5164
6239
|
paragraph: {
|
|
5165
6240
|
indent: {
|
|
@@ -5169,25 +6244,22 @@ function numberingConfig2(numbering) {
|
|
|
5169
6244
|
}
|
|
5170
6245
|
} : {},
|
|
5171
6246
|
...level.run ? { run: runProperties2(level.run) } : {}
|
|
5172
|
-
}
|
|
5173
|
-
|
|
6247
|
+
})
|
|
6248
|
+
)
|
|
5174
6249
|
};
|
|
5175
6250
|
}
|
|
5176
|
-
var
|
|
6251
|
+
var BODY_ANCHOR;
|
|
5177
6252
|
var init_emit2 = __esm({
|
|
5178
6253
|
"src/renderers/office-open/emit.ts"() {
|
|
5179
6254
|
"use strict";
|
|
5180
6255
|
init_units();
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
tight: 2,
|
|
5185
|
-
topAndBottom: 3
|
|
5186
|
-
};
|
|
6256
|
+
init_chartWorkbook();
|
|
6257
|
+
init_chartLook();
|
|
6258
|
+
init_chartParts();
|
|
5187
6259
|
BODY_ANCHOR = {
|
|
5188
|
-
top: "
|
|
5189
|
-
middle: "
|
|
5190
|
-
bottom: "
|
|
6260
|
+
top: "top",
|
|
6261
|
+
middle: "center",
|
|
6262
|
+
bottom: "bottom"
|
|
5191
6263
|
};
|
|
5192
6264
|
}
|
|
5193
6265
|
});
|
|
@@ -5247,37 +6319,49 @@ var init_styles3 = __esm({
|
|
|
5247
6319
|
var office_open_exports = {};
|
|
5248
6320
|
__export(office_open_exports, {
|
|
5249
6321
|
OFFICE_OPEN_DOCX_RENDERER_ID: () => OFFICE_OPEN_DOCX_RENDERER_ID,
|
|
6322
|
+
OFFICE_OPEN_VERSION: () => OFFICE_OPEN_VERSION,
|
|
5250
6323
|
buildDocumentOptions: () => buildDocumentOptions,
|
|
5251
6324
|
createOfficeOpenDocxRenderer: () => createOfficeOpenDocxRenderer
|
|
5252
6325
|
});
|
|
5253
|
-
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
|
+
}
|
|
5254
6340
|
async function createOfficeOpenDocxRenderer() {
|
|
5255
6341
|
const backend = await import(
|
|
5256
6342
|
/* @vite-ignore */
|
|
5257
6343
|
OFFICE_OPEN_DOCX
|
|
5258
6344
|
);
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
);
|
|
5267
|
-
|
|
6345
|
+
assertBackendVersion(
|
|
6346
|
+
OFFICE_OPEN_DOCX,
|
|
6347
|
+
OFFICE_OPEN_VERSION,
|
|
6348
|
+
installedBackendVersion()
|
|
6349
|
+
);
|
|
6350
|
+
if (typeof backend.generateDocument !== "function") {
|
|
6351
|
+
throw new Error(
|
|
6352
|
+
`${OFFICE_OPEN_DOCX} does not export generateDocument(); the installed version is not compatible with this adapter.`
|
|
6353
|
+
);
|
|
5268
6354
|
}
|
|
5269
6355
|
return {
|
|
5270
6356
|
id: OFFICE_OPEN_DOCX_RENDERER_ID,
|
|
5271
6357
|
format: "docx",
|
|
5272
6358
|
capabilities: OFFICE_OPEN_CAPABILITIES,
|
|
5273
6359
|
async render(ir, options) {
|
|
5274
|
-
const
|
|
5275
|
-
const cellTocs = [];
|
|
6360
|
+
const charts2 = [];
|
|
5276
6361
|
const document = await buildDocumentOptions(
|
|
5277
6362
|
ir,
|
|
5278
|
-
|
|
5279
|
-
options?.svgRasterFallback
|
|
5280
|
-
cellTocs
|
|
6363
|
+
charts2,
|
|
6364
|
+
options?.svgRasterFallback
|
|
5281
6365
|
);
|
|
5282
6366
|
const bytes = await backend.generateDocument(document, {
|
|
5283
6367
|
type: "uint8array"
|
|
@@ -5285,10 +6369,10 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5285
6369
|
let raw = Buffer.from(
|
|
5286
6370
|
bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)
|
|
5287
6371
|
);
|
|
5288
|
-
if (
|
|
5289
|
-
const zip = new
|
|
5290
|
-
|
|
5291
|
-
|
|
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);
|
|
5292
6376
|
raw = zip.toBuffer();
|
|
5293
6377
|
}
|
|
5294
6378
|
if (options?.deterministic === false)
|
|
@@ -5305,13 +6389,12 @@ async function createOfficeOpenDocxRenderer() {
|
|
|
5305
6389
|
}
|
|
5306
6390
|
};
|
|
5307
6391
|
}
|
|
5308
|
-
async function buildDocumentOptions(ir,
|
|
6392
|
+
async function buildDocumentOptions(ir, charts2 = [], svgRasterFallback) {
|
|
5309
6393
|
let nextDrawingId = 1;
|
|
5310
6394
|
const ctx = {
|
|
5311
6395
|
pictures: await prepareImages2(ir, svgRasterFallback),
|
|
5312
6396
|
nextDrawingId: () => nextDrawingId++,
|
|
5313
|
-
charts
|
|
5314
|
-
cellTocs
|
|
6397
|
+
charts: charts2
|
|
5315
6398
|
};
|
|
5316
6399
|
return {
|
|
5317
6400
|
styles: emitStyles2(ir.styles),
|
|
@@ -5319,16 +6402,20 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback, cellTocs
|
|
|
5319
6402
|
(value, index) => section(value, ctx, index === ir.sections.length - 1)
|
|
5320
6403
|
),
|
|
5321
6404
|
...coreProperties2(ir),
|
|
5322
|
-
|
|
6405
|
+
settings: {
|
|
5323
6406
|
updateFields: ir.settings.updateFields,
|
|
5324
6407
|
...ir.settings.trackRevisions ? { trackRevisions: true } : {}
|
|
5325
6408
|
},
|
|
5326
|
-
...ir.numbering.length > 0 ? {
|
|
6409
|
+
...ir.numbering.length > 0 ? {
|
|
6410
|
+
numbering: {
|
|
6411
|
+
abstractNumberings: ir.numbering.map(numberingConfig2)
|
|
6412
|
+
}
|
|
6413
|
+
} : {},
|
|
5327
6414
|
...ir.footnotes.length > 0 ? { footnotes: noteBodies2(ir.footnotes, ctx) } : {},
|
|
5328
6415
|
...ir.endnotes.length > 0 ? { endnotes: noteBodies2(ir.endnotes, ctx) } : {},
|
|
5329
6416
|
...ir.comments.length > 0 ? {
|
|
5330
|
-
comments:
|
|
5331
|
-
|
|
6417
|
+
comments: ir.comments.map(
|
|
6418
|
+
(comment) => ({
|
|
5332
6419
|
id: comment.id,
|
|
5333
6420
|
author: comment.author,
|
|
5334
6421
|
...comment.initials ? { initials: comment.initials } : {},
|
|
@@ -5336,29 +6423,25 @@ async function buildDocumentOptions(ir, charts = [], svgRasterFallback, cellTocs
|
|
|
5336
6423
|
children: comment.children.map(
|
|
5337
6424
|
(child) => paragraphOf(child, ctx)
|
|
5338
6425
|
)
|
|
5339
|
-
})
|
|
5340
|
-
|
|
6426
|
+
})
|
|
6427
|
+
)
|
|
5341
6428
|
} : {}
|
|
5342
6429
|
};
|
|
5343
6430
|
}
|
|
5344
6431
|
function paragraphOf(value, ctx) {
|
|
5345
6432
|
const emitted = block(value, ctx);
|
|
5346
|
-
|
|
5347
|
-
if (!asParagraph) {
|
|
6433
|
+
if (!("paragraph" in emitted) || typeof emitted.paragraph === "string") {
|
|
5348
6434
|
throw new Error(
|
|
5349
6435
|
`the office-open renderer expected a paragraph, not a "${value.kind}"`
|
|
5350
6436
|
);
|
|
5351
6437
|
}
|
|
5352
|
-
return
|
|
6438
|
+
return emitted.paragraph;
|
|
5353
6439
|
}
|
|
5354
6440
|
function noteBodies2(notes, ctx) {
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
};
|
|
5360
|
-
}
|
|
5361
|
-
return bodies;
|
|
6441
|
+
return notes.map((note) => ({
|
|
6442
|
+
id: note.id,
|
|
6443
|
+
children: note.children.map((child) => paragraphOf(child, ctx))
|
|
6444
|
+
}));
|
|
5362
6445
|
}
|
|
5363
6446
|
async function prepareImages2(ir, svgRasterFallback) {
|
|
5364
6447
|
const placements = collectImagePlacements2(ir);
|
|
@@ -5381,23 +6464,16 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5381
6464
|
if (resource.kind !== "image") continue;
|
|
5382
6465
|
const type = resource.mediaType;
|
|
5383
6466
|
const data = Buffer.from(resource.bytes);
|
|
5384
|
-
const placementData = /* @__PURE__ */ new Map();
|
|
5385
|
-
[...placements.get(resource.id) ?? []].forEach((size, index) => {
|
|
5386
|
-
placementData.set(
|
|
5387
|
-
size,
|
|
5388
|
-
index === 0 ? data : distinguishImageBytes(data, type, size)
|
|
5389
|
-
);
|
|
5390
|
-
});
|
|
5391
6467
|
resources.set(resource.id, (placement) => {
|
|
5392
6468
|
const sizeKey = placementKey(placement);
|
|
5393
6469
|
const stem = `${resource.id}-${sizeKey}`;
|
|
5394
6470
|
return {
|
|
5395
6471
|
type,
|
|
5396
|
-
//
|
|
5397
|
-
//
|
|
5398
|
-
//
|
|
5399
|
-
//
|
|
5400
|
-
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,
|
|
5401
6477
|
// Named after the resource and the size it is drawn at, so two
|
|
5402
6478
|
// placements of one image at one size share a single part and a third
|
|
5403
6479
|
// at another size gets its own.
|
|
@@ -5420,104 +6496,6 @@ async function prepareImages2(ir, svgRasterFallback) {
|
|
|
5420
6496
|
function placementKey(placement) {
|
|
5421
6497
|
return `${emuToPixels(placement.widthEmu)}x${emuToPixels(placement.heightEmu)}`;
|
|
5422
6498
|
}
|
|
5423
|
-
function distinguishImageBytes(data, mediaType, placement) {
|
|
5424
|
-
const marker = Buffer.from(`json-to-office:${placement}`, "utf8");
|
|
5425
|
-
switch (mediaType) {
|
|
5426
|
-
case "png":
|
|
5427
|
-
return addPngTextChunk(data, marker);
|
|
5428
|
-
case "jpg":
|
|
5429
|
-
return addJpegComment(data, marker);
|
|
5430
|
-
case "gif":
|
|
5431
|
-
return addGifComment(data, marker);
|
|
5432
|
-
case "svg":
|
|
5433
|
-
return Buffer.concat([
|
|
5434
|
-
data,
|
|
5435
|
-
Buffer.from(`
|
|
5436
|
-
<!-- ${marker.toString("utf8")} -->`, "utf8")
|
|
5437
|
-
]);
|
|
5438
|
-
case "bmp": {
|
|
5439
|
-
const marked = Buffer.concat([data, marker]);
|
|
5440
|
-
if (marked.length >= 14 && marked.subarray(0, 2).toString("ascii") === "BM") {
|
|
5441
|
-
marked.writeUInt32LE(marked.length, 2);
|
|
5442
|
-
}
|
|
5443
|
-
return marked;
|
|
5444
|
-
}
|
|
5445
|
-
default:
|
|
5446
|
-
return Buffer.concat([data, marker]);
|
|
5447
|
-
}
|
|
5448
|
-
}
|
|
5449
|
-
function addPngTextChunk(data, marker) {
|
|
5450
|
-
const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
5451
|
-
if (data.length < 8 || !data.subarray(0, 8).equals(signature)) {
|
|
5452
|
-
return Buffer.concat([data, marker]);
|
|
5453
|
-
}
|
|
5454
|
-
let offset = 8;
|
|
5455
|
-
while (offset + 12 <= data.length) {
|
|
5456
|
-
const payloadLength = data.readUInt32BE(offset);
|
|
5457
|
-
const chunkEnd = offset + 12 + payloadLength;
|
|
5458
|
-
if (chunkEnd > data.length) break;
|
|
5459
|
-
if (data.subarray(offset + 4, offset + 8).toString("ascii") === "IEND") {
|
|
5460
|
-
const payload = Buffer.concat([
|
|
5461
|
-
Buffer.from("json-to-office\0", "latin1"),
|
|
5462
|
-
marker
|
|
5463
|
-
]);
|
|
5464
|
-
const chunk = Buffer.alloc(12 + payload.length);
|
|
5465
|
-
chunk.writeUInt32BE(payload.length, 0);
|
|
5466
|
-
chunk.write("tEXt", 4, 4, "ascii");
|
|
5467
|
-
payload.copy(chunk, 8);
|
|
5468
|
-
chunk.writeUInt32BE(
|
|
5469
|
-
crc32(chunk.subarray(4, 8 + payload.length)),
|
|
5470
|
-
8 + payload.length
|
|
5471
|
-
);
|
|
5472
|
-
return Buffer.concat([
|
|
5473
|
-
data.subarray(0, offset),
|
|
5474
|
-
chunk,
|
|
5475
|
-
data.subarray(offset)
|
|
5476
|
-
]);
|
|
5477
|
-
}
|
|
5478
|
-
offset = chunkEnd;
|
|
5479
|
-
}
|
|
5480
|
-
throw new Error(
|
|
5481
|
-
"Cannot mark a PNG that has no intact IEND chunk; its bytes were not checked to decode before rendering"
|
|
5482
|
-
);
|
|
5483
|
-
}
|
|
5484
|
-
function addJpegComment(data, marker) {
|
|
5485
|
-
if (data.length < 2 || data[0] !== 255 || data[1] !== 216) {
|
|
5486
|
-
return Buffer.concat([data, marker]);
|
|
5487
|
-
}
|
|
5488
|
-
const comment = Buffer.alloc(4 + marker.length);
|
|
5489
|
-
comment[0] = 255;
|
|
5490
|
-
comment[1] = 254;
|
|
5491
|
-
comment.writeUInt16BE(marker.length + 2, 2);
|
|
5492
|
-
marker.copy(comment, 4);
|
|
5493
|
-
return Buffer.concat([data.subarray(0, 2), comment, data.subarray(2)]);
|
|
5494
|
-
}
|
|
5495
|
-
function addGifComment(data, marker) {
|
|
5496
|
-
const trailer = data.lastIndexOf(59);
|
|
5497
|
-
if (trailer < 0 || marker.length > 255) {
|
|
5498
|
-
return Buffer.concat([data, marker]);
|
|
5499
|
-
}
|
|
5500
|
-
const comment = Buffer.concat([
|
|
5501
|
-
Buffer.from([33, 254, marker.length]),
|
|
5502
|
-
marker,
|
|
5503
|
-
Buffer.from([0])
|
|
5504
|
-
]);
|
|
5505
|
-
return Buffer.concat([
|
|
5506
|
-
data.subarray(0, trailer),
|
|
5507
|
-
comment,
|
|
5508
|
-
data.subarray(trailer)
|
|
5509
|
-
]);
|
|
5510
|
-
}
|
|
5511
|
-
function crc32(data) {
|
|
5512
|
-
let crc = 4294967295;
|
|
5513
|
-
for (const byte of data) {
|
|
5514
|
-
crc ^= byte;
|
|
5515
|
-
for (let bit = 0; bit < 8; bit += 1) {
|
|
5516
|
-
crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
5517
|
-
}
|
|
5518
|
-
}
|
|
5519
|
-
return (crc ^ 4294967295) >>> 0;
|
|
5520
|
-
}
|
|
5521
6499
|
function collectImagePlacements2(ir) {
|
|
5522
6500
|
const placements = /* @__PURE__ */ new Map();
|
|
5523
6501
|
const record = (resourceId, placement) => {
|
|
@@ -5585,18 +6563,19 @@ function coreProperties2(ir) {
|
|
|
5585
6563
|
...metadata.custom?.length ? { customProperties: metadata.custom } : {}
|
|
5586
6564
|
};
|
|
5587
6565
|
}
|
|
5588
|
-
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;
|
|
5589
6567
|
var init_office_open = __esm({
|
|
5590
6568
|
"src/renderers/office-open/index.ts"() {
|
|
5591
6569
|
"use strict";
|
|
5592
6570
|
init_chartParts();
|
|
5593
|
-
|
|
6571
|
+
init_themePart();
|
|
5594
6572
|
init_imageUtils();
|
|
5595
6573
|
init_packageDocument();
|
|
5596
6574
|
init_emit2();
|
|
5597
6575
|
init_styles3();
|
|
5598
6576
|
OFFICE_OPEN_DOCX_RENDERER_ID = "office-open";
|
|
5599
6577
|
OFFICE_OPEN_DOCX = "@office-open/docx";
|
|
6578
|
+
OFFICE_OPEN_VERSION = "0.14.6";
|
|
5600
6579
|
OFFICE_OPEN_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
5601
6580
|
"paragraphs",
|
|
5602
6581
|
"styles",
|
|
@@ -9227,6 +10206,7 @@ function emptyToUndefined(formatting) {
|
|
|
9227
10206
|
}
|
|
9228
10207
|
|
|
9229
10208
|
// src/ir/compiler.ts
|
|
10209
|
+
init_chartValues();
|
|
9230
10210
|
init_types();
|
|
9231
10211
|
|
|
9232
10212
|
// src/ir/measure.ts
|
|
@@ -9259,6 +10239,49 @@ function tableWidthTwips(width, measureTwips) {
|
|
|
9259
10239
|
|
|
9260
10240
|
// src/ir/compiler.ts
|
|
9261
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
|
|
9262
10285
|
var CONTENT_BOOKMARK_ID_BASE = 2e6;
|
|
9263
10286
|
var SINGLE_LINE_TWIPS = 240;
|
|
9264
10287
|
function compileDocument(structure, layout, warnings = [], images = /* @__PURE__ */ new Map(), options = {}) {
|
|
@@ -9324,6 +10347,7 @@ function compileDocument(structure, layout, warnings = [], images = /* @__PURE__
|
|
|
9324
10347
|
trackRevisions: structure.trackRevisions === true,
|
|
9325
10348
|
...noProofWords(structure.theme) ? { noProofWords: noProofWords(structure.theme) } : {}
|
|
9326
10349
|
},
|
|
10350
|
+
theme: compileTheme(structure.theme, structure.themeName),
|
|
9327
10351
|
// The statistic styles are appended rather than built with the rest: a
|
|
9328
10352
|
// document that uses no statistic must keep the exact style set it had
|
|
9329
10353
|
// before the component had styles, or every recorded golden moves for a
|
|
@@ -10092,14 +11116,6 @@ function compileShape2(props, children, scope) {
|
|
|
10092
11116
|
);
|
|
10093
11117
|
}
|
|
10094
11118
|
const fill = style?.shading?.fill;
|
|
10095
|
-
const dropOutline = Boolean(fill) && Boolean(outline.outline);
|
|
10096
|
-
if (dropOutline) {
|
|
10097
|
-
warnOnce(
|
|
10098
|
-
ctx,
|
|
10099
|
-
"text-box",
|
|
10100
|
-
'[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.'
|
|
10101
|
-
);
|
|
10102
|
-
}
|
|
10103
11119
|
ctx.features.require("text-boxes", path4);
|
|
10104
11120
|
if (props.floating) ctx.features.require("floating-images", path4);
|
|
10105
11121
|
const insets = shapeInsets(
|
|
@@ -10118,7 +11134,7 @@ function compileShape2(props, children, scope) {
|
|
|
10118
11134
|
heightPx: height.pixels,
|
|
10119
11135
|
children,
|
|
10120
11136
|
...fill ? { fill: irColor(resolveColor(fill, ctx.theme)) } : {},
|
|
10121
|
-
...outline.outline
|
|
11137
|
+
...outline.outline ? { outline: outline.outline } : {},
|
|
10122
11138
|
...insets ? { insetsEmu: insets } : {},
|
|
10123
11139
|
...props.floating ? { floating: compileFloating(props.floating, ctx, path4) } : {}
|
|
10124
11140
|
}
|
|
@@ -11341,6 +12357,7 @@ function compileImage2(component, scope) {
|
|
|
11341
12357
|
}
|
|
11342
12358
|
var DEFAULT_CHART_HEIGHT_INCHES = 3;
|
|
11343
12359
|
var MAX_CHART_TEXT_POINTS = 10;
|
|
12360
|
+
var MIN_CHART_TEXT_POINTS = 1;
|
|
11344
12361
|
function chartTextFont(theme) {
|
|
11345
12362
|
const bodySize = getThemeFonts(theme).body?.size;
|
|
11346
12363
|
let color = "000000";
|
|
@@ -11350,9 +12367,12 @@ function chartTextFont(theme) {
|
|
|
11350
12367
|
}
|
|
11351
12368
|
return {
|
|
11352
12369
|
fontFamily: resolveFontFamily(theme, "body"),
|
|
11353
|
-
fontSize: Math.
|
|
11354
|
-
|
|
11355
|
-
|
|
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
|
+
)
|
|
11356
12376
|
),
|
|
11357
12377
|
bold: false,
|
|
11358
12378
|
color
|
|
@@ -11363,7 +12383,7 @@ function compileChart(component, scope) {
|
|
|
11363
12383
|
const props = component.props ?? {};
|
|
11364
12384
|
if (props.type === "bubble") {
|
|
11365
12385
|
throw new Error(
|
|
11366
|
-
`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.`
|
|
11367
12387
|
);
|
|
11368
12388
|
}
|
|
11369
12389
|
const rawSeries = Array.isArray(props.data) ? props.data : [];
|
|
@@ -11385,10 +12405,22 @@ function compileChart(component, scope) {
|
|
|
11385
12405
|
`Chart series "${label}" at ${path4} has ${labels.length} labels and ${values.length} values; they must be the same length.`
|
|
11386
12406
|
);
|
|
11387
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
|
+
}
|
|
11388
12420
|
return {
|
|
11389
12421
|
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
11390
12422
|
labels: labels.map((value) => String(value)),
|
|
11391
|
-
values:
|
|
12423
|
+
values: numbers
|
|
11392
12424
|
};
|
|
11393
12425
|
});
|
|
11394
12426
|
const categories = series[0].labels;
|
|
@@ -11400,6 +12432,34 @@ function compileChart(component, scope) {
|
|
|
11400
12432
|
);
|
|
11401
12433
|
}
|
|
11402
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
|
+
}
|
|
11403
12463
|
const colors = Array.isArray(props.chartColors) ? props.chartColors.map(
|
|
11404
12464
|
(color) => resolveColor(String(color), ctx.theme)
|
|
11405
12465
|
) : chartPaletteValues(ctx.theme).flatMap((value) => {
|
|
@@ -11412,13 +12472,21 @@ function compileChart(component, scope) {
|
|
|
11412
12472
|
const contentWidthInches = scope.measureTwips / 1440;
|
|
11413
12473
|
const widthInches = typeof props.width === "number" ? props.width : contentWidthInches;
|
|
11414
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
|
+
}
|
|
11415
12483
|
const chart = {
|
|
11416
12484
|
kind: "chart",
|
|
11417
12485
|
chartType: props.type,
|
|
11418
12486
|
series,
|
|
11419
12487
|
colors,
|
|
11420
|
-
widthEmu
|
|
11421
|
-
heightEmu
|
|
12488
|
+
widthEmu,
|
|
12489
|
+
heightEmu,
|
|
11422
12490
|
...typeof props.title === "string" ? { title: props.title } : {},
|
|
11423
12491
|
...props.showTitle !== void 0 ? { showTitle: props.showTitle } : {},
|
|
11424
12492
|
...props.showLegend !== void 0 ? { showLegend: props.showLegend } : {},
|
|
@@ -11621,7 +12689,7 @@ function compileFrame(floating, ctx, path4) {
|
|
|
11621
12689
|
function compileFloating(floating, ctx, path4) {
|
|
11622
12690
|
if (floating.wrap?.type === "tight") {
|
|
11623
12691
|
throw new Error(
|
|
11624
|
-
"Image floating wrap.type 'tight' is not supported
|
|
12692
|
+
"Image floating wrap.type 'tight' is not supported. Use 'square', 'topAndBottom', or 'none'."
|
|
11625
12693
|
);
|
|
11626
12694
|
}
|
|
11627
12695
|
const hRelative = floating.horizontalPosition?.relative;
|
|
@@ -15783,18 +16851,18 @@ var docxExhibitRequiredRule = {
|
|
|
15783
16851
|
1
|
|
15784
16852
|
);
|
|
15785
16853
|
if (minimum <= 0) return [];
|
|
15786
|
-
const
|
|
16854
|
+
const charts2 = facts.filter((fact) => fact.kind === "docx/chart").length;
|
|
15787
16855
|
const tables = facts.filter(
|
|
15788
16856
|
(fact) => fact.kind === "docx/table" && fact.columns.length >= 2
|
|
15789
16857
|
).length;
|
|
15790
|
-
const exhibits =
|
|
16858
|
+
const exhibits = charts2 + tables;
|
|
15791
16859
|
if (exhibits >= minimum) return [];
|
|
15792
16860
|
return [
|
|
15793
16861
|
{
|
|
15794
16862
|
path: themeFact(facts)?.path ?? "/props",
|
|
15795
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}.`,
|
|
15796
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.",
|
|
15797
|
-
context: { charts, tables, minimum }
|
|
16865
|
+
context: { charts: charts2, tables, minimum }
|
|
15798
16866
|
}
|
|
15799
16867
|
];
|
|
15800
16868
|
}
|