reamkit 1.3.0 → 1.5.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/README.md +14 -9
- package/dist/esm/core/converter/facade.d.ts +12 -6
- package/dist/esm/core/converter/facade.js +39 -3
- package/dist/esm/core/converter/ream.d.ts +5 -3
- package/dist/esm/core/converter/ream.js +26 -3
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +18 -0
- package/dist/esm/core/drawingml/sparkline-geometry.d.ts +8 -0
- package/dist/esm/core/drawingml/sparkline-geometry.js +111 -0
- package/dist/esm/core/ir/adapters.d.ts +5 -5
- package/dist/esm/core/ir/sheet.d.ts +31 -0
- package/dist/esm/core/opc/index.d.ts +2 -0
- package/dist/esm/core/opc/index.js +1 -0
- package/dist/esm/core/opc/opc-writer.d.ts +28 -0
- package/dist/esm/core/opc/opc-writer.js +60 -0
- package/dist/esm/core/opc/relationships.js +1 -0
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -0
- package/dist/esm/core/spreadsheet-model/types.d.ts +184 -0
- package/dist/esm/excel/conditional-format.d.ts +16 -0
- package/dist/esm/excel/conditional-format.js +305 -0
- package/dist/esm/excel/index.d.ts +4 -3
- package/dist/esm/excel/print-model.d.ts +2 -1
- package/dist/esm/excel/print-model.js +114 -2
- package/dist/esm/excel/sheet-drawing.d.ts +1 -1
- package/dist/esm/excel/sheet-to-flow.d.ts +3 -0
- package/dist/esm/excel/sheet-to-flow.js +51 -0
- package/dist/esm/excel/styles-parser.d.ts +1 -50
- package/dist/esm/excel/styles-parser.js +38 -1
- package/dist/esm/excel/table-parser.d.ts +2 -0
- package/dist/esm/excel/table-parser.js +51 -0
- package/dist/esm/excel/workbook-parser.d.ts +1 -5
- package/dist/esm/excel/worksheet-parser.d.ts +1 -60
- package/dist/esm/excel/worksheet-parser.js +239 -1
- package/dist/esm/excel/xlsx-reader.d.ts +3 -1
- package/dist/esm/excel/xlsx-reader.js +86 -51
- package/dist/esm/excel/xlsx-writer.d.ts +4 -0
- package/dist/esm/excel/xlsx-writer.js +271 -0
- package/dist/esm/html/html-writer.js +27 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/layout/styled-layout.js +91 -1
- package/dist/esm/word/document-parser.js +47 -13
- package/dist/esm/word/docx-writer.d.ts +4 -0
- package/dist/esm/word/docx-writer.js +602 -0
- package/dist/esm/word/drawing-parser.d.ts +1 -0
- package/dist/esm/word/drawing-parser.js +37 -2
- package/package.json +5 -3
|
@@ -12,6 +12,7 @@ import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "../core/style-
|
|
|
12
12
|
import { resolveParagraphProperties, resolveRunProperties } from "../core/style-cascade/resolver.js";
|
|
13
13
|
import "../core/style-cascade/index.js";
|
|
14
14
|
import { PathBuilder, flipTransform } from "../core/vector.js";
|
|
15
|
+
import { buildSparkline } from "../core/drawingml/sparkline-geometry.js";
|
|
15
16
|
import { arcPoint, arcToBeziers } from "../core/arc-to-bezier.js";
|
|
16
17
|
import { buildChartScene } from "../core/drawingml/chart-geometry.js";
|
|
17
18
|
import { layoutMath, mathGlyphSegments, variantStyle } from "./math-layout.js";
|
|
@@ -560,6 +561,31 @@ function buildChartLayout(chart, widthPt, heightPt, font) {
|
|
|
560
561
|
function rectAtPath(x, y, w, h) {
|
|
561
562
|
return new PathBuilder().moveTo(x, y).lineTo(x + w, y).lineTo(x + w, y + h).lineTo(x, y + h).close().build();
|
|
562
563
|
}
|
|
564
|
+
var CF_ICON_SIZE_PT = 9;
|
|
565
|
+
var CF_ICON_GUTTER_PT = 12;
|
|
566
|
+
function buildCellIconShape(icon, size) {
|
|
567
|
+
return {
|
|
568
|
+
paths: [cellIconPath(icon.shape, size)],
|
|
569
|
+
fillColorHex: icon.colorHex
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function cellIconPath(shape, s) {
|
|
573
|
+
switch (shape) {
|
|
574
|
+
case "square": return rectAtPath(s * .12, s * .12, s * .76, s * .76);
|
|
575
|
+
case "diamond": return new PathBuilder().moveTo(s / 2, s * .92).lineTo(s * .92, s / 2).lineTo(s / 2, s * .08).lineTo(s * .08, s / 2).close().build();
|
|
576
|
+
case "triangleUp": return trianglePath([s / 2, s * .9], [s * .1, s * .12], [s * .9, s * .12]);
|
|
577
|
+
case "triangleDown": return trianglePath([s / 2, s * .1], [s * .1, s * .88], [s * .9, s * .88]);
|
|
578
|
+
case "triangleRight": return trianglePath([s * .9, s / 2], [s * .12, s * .1], [s * .12, s * .9]);
|
|
579
|
+
case "circle": return circlePath(s / 2, s / 2, s * .42);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
function trianglePath(a, b, c) {
|
|
583
|
+
return new PathBuilder().moveTo(a[0], a[1]).lineTo(b[0], b[1]).lineTo(c[0], c[1]).close().build();
|
|
584
|
+
}
|
|
585
|
+
function circlePath(cx, cy, r) {
|
|
586
|
+
const k = .5522847498307936 * r;
|
|
587
|
+
return new PathBuilder().moveTo(cx + r, cy).cubicTo(cx + r, cy + k, cx + k, cy + r, cx, cy + r).cubicTo(cx - k, cy + r, cx - r, cy + k, cx - r, cy).cubicTo(cx - r, cy - k, cx - k, cy - r, cx, cy - r).cubicTo(cx + k, cy - r, cx + r, cy - k, cx + r, cy).close().build();
|
|
588
|
+
}
|
|
563
589
|
function rectPrim(r) {
|
|
564
590
|
return {
|
|
565
591
|
paths: [rectAtPath(r.x, r.y, r.w, r.h)],
|
|
@@ -1431,8 +1457,9 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
1431
1457
|
const tableMar = tableProps.defaultCellMargins;
|
|
1432
1458
|
const padTopPt = cellMar?.top ?? tableMar?.top ?? 0;
|
|
1433
1459
|
const padBottomPt = cellMar?.bottom ?? tableMar?.bottom ?? 0;
|
|
1434
|
-
const
|
|
1460
|
+
const padLeftBase = cellMar?.left ?? tableMar?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1435
1461
|
const padRightPt = cellMar?.right ?? tableMar?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1462
|
+
const padLeftPt = padLeftBase + (cell.properties.icon ? CF_ICON_GUTTER_PT : 0);
|
|
1436
1463
|
const innerWidth = Math.max(1, widthPt - padLeftPt - padRightPt);
|
|
1437
1464
|
const lines = [];
|
|
1438
1465
|
const nestedTables = [];
|
|
@@ -1462,6 +1489,9 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
1462
1489
|
padLeftPt,
|
|
1463
1490
|
borders,
|
|
1464
1491
|
...cell.properties.shading?.colorHex ? { shadingColorHex: cell.properties.shading.colorHex } : {},
|
|
1492
|
+
...cell.properties.dataBar ? { dataBar: cell.properties.dataBar } : {},
|
|
1493
|
+
...cell.properties.icon ? { icon: cell.properties.icon } : {},
|
|
1494
|
+
...cell.properties.sparkline ? { sparkline: cell.properties.sparkline } : {},
|
|
1465
1495
|
lines,
|
|
1466
1496
|
...nestedTables.length > 0 ? { nestedTables } : {},
|
|
1467
1497
|
contentHeightPt,
|
|
@@ -2084,6 +2114,66 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
2084
2114
|
height: pt(row.heightPt),
|
|
2085
2115
|
fillColorHex: cell.shadingColorHex
|
|
2086
2116
|
});
|
|
2117
|
+
if (cell.dataBar && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
2118
|
+
const start = Math.max(0, Math.min(1, cell.dataBar.startFraction ?? 0));
|
|
2119
|
+
const barWidth = cell.widthPt * Math.max(0, Math.min(1, cell.dataBar.fraction));
|
|
2120
|
+
if (barWidth > 0) out.push({
|
|
2121
|
+
type: "fill",
|
|
2122
|
+
x: pt(cellX + cell.widthPt * start),
|
|
2123
|
+
y: pt(pageHeight - rowBottom - row.heightPt),
|
|
2124
|
+
width: pt(barWidth),
|
|
2125
|
+
height: pt(row.heightPt),
|
|
2126
|
+
fillColorHex: cell.dataBar.colorHex
|
|
2127
|
+
});
|
|
2128
|
+
}
|
|
2129
|
+
if (cell.icon && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
2130
|
+
const iconSize = Math.min(CF_ICON_SIZE_PT, Math.max(0, row.heightPt - 1));
|
|
2131
|
+
if (iconSize > 0) {
|
|
2132
|
+
const iconX = cellX + (CF_ICON_GUTTER_PT - iconSize) / 2;
|
|
2133
|
+
const iconBottomYUp = rowBottom + (row.heightPt - iconSize) / 2;
|
|
2134
|
+
const { paths, fillColorHex } = buildCellIconShape(cell.icon, iconSize);
|
|
2135
|
+
out.push({
|
|
2136
|
+
type: "shape",
|
|
2137
|
+
shape: {
|
|
2138
|
+
paths,
|
|
2139
|
+
fillColorHex,
|
|
2140
|
+
transform: flipTransform([
|
|
2141
|
+
1,
|
|
2142
|
+
0,
|
|
2143
|
+
0,
|
|
2144
|
+
1,
|
|
2145
|
+
iconX,
|
|
2146
|
+
iconBottomYUp
|
|
2147
|
+
], pageHeight)
|
|
2148
|
+
}
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
if (cell.sparkline && cell.sparkline.values.length > 0 && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
2153
|
+
const inset = 1.5;
|
|
2154
|
+
const sw = cell.widthPt - 2 * inset;
|
|
2155
|
+
const sh = row.heightPt - 2 * inset;
|
|
2156
|
+
if (sw > 0 && sh > 0) {
|
|
2157
|
+
const prims = buildSparkline(cell.sparkline.kind, cell.sparkline.values, sw, sh, cell.sparkline.colorHex);
|
|
2158
|
+
const transform = flipTransform([
|
|
2159
|
+
1,
|
|
2160
|
+
0,
|
|
2161
|
+
0,
|
|
2162
|
+
1,
|
|
2163
|
+
cellX + inset,
|
|
2164
|
+
rowBottom + inset
|
|
2165
|
+
], pageHeight);
|
|
2166
|
+
for (const prim of prims) out.push({
|
|
2167
|
+
type: "shape",
|
|
2168
|
+
shape: {
|
|
2169
|
+
paths: prim.paths,
|
|
2170
|
+
...prim.fillColorHex ? { fillColorHex: prim.fillColorHex } : {},
|
|
2171
|
+
...prim.stroke ? { stroke: prim.stroke } : {},
|
|
2172
|
+
transform
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2087
2177
|
emitCellBorders(out, cell, cellX, rowBottom, row.heightPt, pageHeight, row.rowIdx, row.rowCount, colCount);
|
|
2088
2178
|
if (cell.mergeRole === "middle" || cell.mergeRole === "end") continue;
|
|
2089
2179
|
let textY = rowTop - cell.padTopPt;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { twipsToPt } from "../core/ir/units.js";
|
|
2
|
-
import { poAttr, poChildren, poFindByPath, poIntAttr, poIs, poText } from "../core/po-helpers.js";
|
|
2
|
+
import { poAttr, poChildren, poFindByPath, poFindDescendant, poIntAttr, poIs, poText } from "../core/po-helpers.js";
|
|
3
3
|
import { defaultColorResolver } from "../core/drawingml/colors.js";
|
|
4
4
|
import { parseOMath } from "./omml-parser.js";
|
|
5
|
-
import { expandMcChildren, parseDrawing } from "./drawing-parser.js";
|
|
5
|
+
import { expandMcChildren, parseDrawing, parseVmlPicture } from "./drawing-parser.js";
|
|
6
6
|
import { parseRunProperties } from "./run-properties.js";
|
|
7
7
|
import { parseParagraphProperties } from "./paragraph-properties.js";
|
|
8
8
|
import { poElementToFlat } from "./po-to-flat.js";
|
|
@@ -178,20 +178,44 @@ function parseBodyElements(children, ctx = DEFAULT_PARSE_CONTEXT) {
|
|
|
178
178
|
}
|
|
179
179
|
return out;
|
|
180
180
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
181
|
+
var COLLAPSE_TRANSPARENT_TAGS = new Set([
|
|
182
|
+
"w:ins",
|
|
183
|
+
"w:moveTo",
|
|
184
|
+
"w:sdt",
|
|
185
|
+
"w:sdtContent",
|
|
186
|
+
"w:smartTag"
|
|
187
|
+
]);
|
|
188
|
+
function scanForLoneDrawing(container, acc) {
|
|
189
|
+
for (const child of expandMcChildren(poChildren(container))) {
|
|
190
|
+
if (poIs(child, "w:pPr")) continue;
|
|
191
|
+
if (poIs(child, "w:r")) {
|
|
192
|
+
for (const rc of expandMcChildren(poChildren(child))) if (poIs(rc, "w:drawing")) {
|
|
193
|
+
if (!acc.drawing) acc.drawing = rc;
|
|
194
|
+
} else if (poIs(rc, "w:pict") || poIs(rc, "w:object")) {
|
|
195
|
+
if (!acc.vml && poFindDescendant(rc, "v:imagedata") !== void 0) acc.vml = rc;
|
|
196
|
+
} else if (poIs(rc, "w:t") && poText(rc).length > 0) acc.hasOther = true;
|
|
197
|
+
else if (poIs(rc, "w:tab") || poIs(rc, "w:br") || poIs(rc, "w:noBreakHyphen")) acc.hasOther = true;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (poIs(child, "m:oMath") || poIs(child, "m:oMathPara")) {
|
|
201
|
+
acc.hasOther = true;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const tag = elementTag(child);
|
|
205
|
+
if (tag && COLLAPSE_TRANSPARENT_TAGS.has(tag)) scanForLoneDrawing(child, acc);
|
|
206
|
+
else if (tag && RUN_CONTAINER_TAGS.has(tag)) acc.hasOther = true;
|
|
190
207
|
}
|
|
191
|
-
|
|
208
|
+
}
|
|
209
|
+
function tryExtractDrawingFromParagraph(p, ctx) {
|
|
210
|
+
const scan = { hasOther: false };
|
|
211
|
+
scanForLoneDrawing(p, scan);
|
|
212
|
+
const { drawing, vml } = scan;
|
|
213
|
+
if (scan.hasOther || !drawing && !vml) return null;
|
|
214
|
+
const fromVml = drawing === void 0;
|
|
192
215
|
const parseBody = (children) => parseBodyElements(children, ctx);
|
|
193
|
-
const content = parseDrawing(drawing, ctx.resolveColor, parseBody);
|
|
216
|
+
const content = fromVml ? parseVmlPicture(vml) : parseDrawing(drawing, ctx.resolveColor, parseBody);
|
|
194
217
|
if (!content) return null;
|
|
218
|
+
if (fromVml && content.kind === "image" && ctx.resolveImage?.(content.imageId) === void 0) return null;
|
|
195
219
|
const pPrNode = poChildren(p).find((c) => poIs(c, "w:pPr"));
|
|
196
220
|
const paragraphProperties = pPrNode ? parseParagraphProperties(poElementToFlat(pPrNode)) : {};
|
|
197
221
|
if (content.kind === "image") {
|
|
@@ -435,6 +459,16 @@ function parseRun(r, ctx) {
|
|
|
435
459
|
height: content.height
|
|
436
460
|
};
|
|
437
461
|
}
|
|
462
|
+
} else if (poIs(child, "w:pict") || poIs(child, "w:object")) {
|
|
463
|
+
const content = parseVmlPicture(child);
|
|
464
|
+
if (content && content.kind === "image") {
|
|
465
|
+
const resource = ctx.resolveImage?.(content.imageId);
|
|
466
|
+
if (resource) inlineImage = {
|
|
467
|
+
resource,
|
|
468
|
+
width: content.width,
|
|
469
|
+
height: content.height
|
|
470
|
+
};
|
|
471
|
+
}
|
|
438
472
|
}
|
|
439
473
|
}
|
|
440
474
|
return {
|