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.
Files changed (47) hide show
  1. package/README.md +14 -9
  2. package/dist/esm/core/converter/facade.d.ts +12 -6
  3. package/dist/esm/core/converter/facade.js +39 -3
  4. package/dist/esm/core/converter/ream.d.ts +5 -3
  5. package/dist/esm/core/converter/ream.js +26 -3
  6. package/dist/esm/core/document-model/index.d.ts +1 -1
  7. package/dist/esm/core/document-model/types.d.ts +18 -0
  8. package/dist/esm/core/drawingml/sparkline-geometry.d.ts +8 -0
  9. package/dist/esm/core/drawingml/sparkline-geometry.js +111 -0
  10. package/dist/esm/core/ir/adapters.d.ts +5 -5
  11. package/dist/esm/core/ir/sheet.d.ts +31 -0
  12. package/dist/esm/core/opc/index.d.ts +2 -0
  13. package/dist/esm/core/opc/index.js +1 -0
  14. package/dist/esm/core/opc/opc-writer.d.ts +28 -0
  15. package/dist/esm/core/opc/opc-writer.js +60 -0
  16. package/dist/esm/core/opc/relationships.js +1 -0
  17. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -0
  18. package/dist/esm/core/spreadsheet-model/types.d.ts +184 -0
  19. package/dist/esm/excel/conditional-format.d.ts +16 -0
  20. package/dist/esm/excel/conditional-format.js +305 -0
  21. package/dist/esm/excel/index.d.ts +4 -3
  22. package/dist/esm/excel/print-model.d.ts +2 -1
  23. package/dist/esm/excel/print-model.js +114 -2
  24. package/dist/esm/excel/sheet-drawing.d.ts +1 -1
  25. package/dist/esm/excel/sheet-to-flow.d.ts +3 -0
  26. package/dist/esm/excel/sheet-to-flow.js +51 -0
  27. package/dist/esm/excel/styles-parser.d.ts +1 -50
  28. package/dist/esm/excel/styles-parser.js +38 -1
  29. package/dist/esm/excel/table-parser.d.ts +2 -0
  30. package/dist/esm/excel/table-parser.js +51 -0
  31. package/dist/esm/excel/workbook-parser.d.ts +1 -5
  32. package/dist/esm/excel/worksheet-parser.d.ts +1 -60
  33. package/dist/esm/excel/worksheet-parser.js +239 -1
  34. package/dist/esm/excel/xlsx-reader.d.ts +3 -1
  35. package/dist/esm/excel/xlsx-reader.js +86 -51
  36. package/dist/esm/excel/xlsx-writer.d.ts +4 -0
  37. package/dist/esm/excel/xlsx-writer.js +271 -0
  38. package/dist/esm/html/html-writer.js +27 -0
  39. package/dist/esm/index.d.ts +1 -0
  40. package/dist/esm/index.js +2 -1
  41. package/dist/esm/layout/styled-layout.js +91 -1
  42. package/dist/esm/word/document-parser.js +47 -13
  43. package/dist/esm/word/docx-writer.d.ts +4 -0
  44. package/dist/esm/word/docx-writer.js +602 -0
  45. package/dist/esm/word/drawing-parser.d.ts +1 -0
  46. package/dist/esm/word/drawing-parser.js +37 -2
  47. 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 padLeftPt = cellMar?.left ?? tableMar?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
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
- function tryExtractDrawingFromParagraph(p, ctx) {
182
- let drawing;
183
- let hasText = false;
184
- for (const child of poChildren(p)) {
185
- if (!poIs(child, "w:r")) continue;
186
- for (const runChild of expandMcChildren(poChildren(child))) if (poIs(runChild, "w:drawing")) {
187
- if (!drawing) drawing = runChild;
188
- } else if (poIs(runChild, "w:t") && poText(runChild).length > 0) hasText = true;
189
- else if (poIs(runChild, "w:tab") || poIs(runChild, "w:br") || poIs(runChild, "w:noBreakHyphen")) hasText = true;
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
- if (!drawing || hasText) return null;
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 {
@@ -0,0 +1,4 @@
1
+ import { DocumentWriter, WriteResult } from '../core/ir/adapters.js';
2
+ import { FlowDoc } from '../core/ir/flow.js';
3
+ export declare function writeDocx(flow: FlowDoc): WriteResult;
4
+ export declare const docxWriter: DocumentWriter<FlowDoc>;