reamkit 1.1.0 → 1.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.
Files changed (68) hide show
  1. package/README.md +11 -5
  2. package/dist/esm/{layout → core}/arc-to-bezier.d.ts +1 -1
  3. package/dist/esm/{layout → core}/arc-to-bezier.js +2 -2
  4. package/dist/esm/core/converter/project.js +2 -0
  5. package/dist/esm/core/converter/ream.js +4 -3
  6. package/dist/esm/core/document-model/index.d.ts +1 -1
  7. package/dist/esm/core/document-model/types.d.ts +60 -0
  8. package/dist/esm/{layout → core/drawingml}/chart-geometry.d.ts +2 -2
  9. package/dist/esm/{layout → core/drawingml}/chart-geometry.js +79 -117
  10. package/dist/esm/core/drawingml/chart-parser.d.ts +3 -0
  11. package/dist/esm/core/drawingml/chart-parser.js +28 -1
  12. package/dist/esm/{layout → core/drawingml}/preset-geometry.d.ts +2 -2
  13. package/dist/esm/{layout → core/drawingml}/preset-geometry.js +3 -3
  14. package/dist/esm/core/drawingml/shape-render.d.ts +8 -0
  15. package/dist/esm/core/drawingml/shape-render.js +71 -0
  16. package/dist/esm/core/ir/features.d.ts +1 -0
  17. package/dist/esm/core/ir/features.js +1 -0
  18. package/dist/esm/core/ir/flow.d.ts +3 -0
  19. package/dist/esm/core/links.d.ts +6 -0
  20. package/dist/esm/core/links.js +19 -0
  21. package/dist/esm/core/numbering/apply.js +5 -2
  22. package/dist/esm/core/opc/index.d.ts +1 -0
  23. package/dist/esm/core/opc/package.js +3 -2
  24. package/dist/esm/core/opc/relationship-types.d.ts +1 -0
  25. package/dist/esm/core/opc/relationship-types.js +5 -2
  26. package/dist/esm/core/style-cascade/index.d.ts +1 -0
  27. package/dist/esm/core/style-cascade/index.js +1 -0
  28. package/dist/esm/core/style-cascade/table.d.ts +2 -0
  29. package/dist/esm/core/style-cascade/table.js +161 -0
  30. package/dist/esm/core/vector.d.ts +2 -0
  31. package/dist/esm/core/vector.js +19 -1
  32. package/dist/esm/excel/print-model.d.ts +3 -0
  33. package/dist/esm/excel/print-model.js +4 -8
  34. package/dist/esm/excel/sheet-drawing.d.ts +9 -0
  35. package/dist/esm/excel/sheet-drawing.js +113 -0
  36. package/dist/esm/excel/worksheet-parser.d.ts +1 -0
  37. package/dist/esm/excel/worksheet-parser.js +4 -1
  38. package/dist/esm/excel/xlsx-reader.js +41 -0
  39. package/dist/esm/excel/xlsx-to-pdf.js +25 -18
  40. package/dist/esm/html/html-writer.js +188 -16
  41. package/dist/esm/index.d.ts +1 -0
  42. package/dist/esm/layout/page-doc.d.ts +4 -0
  43. package/dist/esm/layout/styled-layout.d.ts +21 -3
  44. package/dist/esm/layout/styled-layout.js +745 -259
  45. package/dist/esm/pdf/encryption.d.ts +34 -0
  46. package/dist/esm/pdf/encryption.js +143 -0
  47. package/dist/esm/pdf/index.d.ts +2 -1
  48. package/dist/esm/pdf/struct-tree.d.ts +7 -1
  49. package/dist/esm/pdf/struct-tree.js +22 -6
  50. package/dist/esm/pdf/styled-page-emitter.d.ts +3 -1
  51. package/dist/esm/pdf/styled-page-emitter.js +185 -35
  52. package/dist/esm/pdf/styled-page-renderer.d.ts +1 -0
  53. package/dist/esm/pdf/styled-page-renderer.js +17 -2
  54. package/dist/esm/pdf/writer.d.ts +2 -0
  55. package/dist/esm/pdf/writer.js +6 -1
  56. package/dist/esm/pdf/xmp.d.ts +1 -0
  57. package/dist/esm/pdf/xmp.js +4 -0
  58. package/dist/esm/svg/svg-writer.js +2 -6
  59. package/dist/esm/word/document-parser.d.ts +3 -0
  60. package/dist/esm/word/document-parser.js +214 -23
  61. package/dist/esm/word/docx-reader.js +37 -15
  62. package/dist/esm/word/docx-to-pdf.js +23 -13
  63. package/dist/esm/word/drawing-parser.d.ts +4 -1
  64. package/dist/esm/word/drawing-parser.js +53 -2
  65. package/dist/esm/word/index.d.ts +2 -2
  66. package/dist/esm/word/styles-parser.js +134 -1
  67. package/dist/esm/word/table-parser.js +35 -0
  68. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { BodyElement, ShapeFill, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform } from '../core/document-model/index.js';
1
+ import { BodyElement, FloatAnchor, ShapeFill, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform } from '../core/document-model/index.js';
2
2
  import { ColorResolver } from '../core/drawingml/colors.js';
3
3
  import { PoNode } from '../core/po-helpers.js';
4
4
  import { Pt } from '../core/ir/index.js';
@@ -18,16 +18,19 @@ export type DrawingContent = {
18
18
  readonly width: Pt;
19
19
  readonly height: Pt;
20
20
  readonly altText?: string;
21
+ readonly float?: FloatAnchor;
21
22
  } | {
22
23
  readonly kind: 'shape';
23
24
  readonly data: ShapeData;
24
25
  readonly altText?: string;
26
+ readonly float?: FloatAnchor;
25
27
  } | {
26
28
  readonly kind: 'chart';
27
29
  readonly chartRelId: string;
28
30
  readonly width: Pt;
29
31
  readonly height: Pt;
30
32
  readonly altText?: string;
33
+ readonly float?: FloatAnchor;
31
34
  };
32
35
  export declare function resolveMc(altContent: PoNode): ReadonlyArray<PoNode>;
33
36
  export declare function expandMcChildren(children: ReadonlyArray<PoNode>): Array<PoNode>;
@@ -1,10 +1,57 @@
1
1
  import { emuToPt } from "../core/ir/units.js";
2
- import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poTag } from "../core/po-helpers.js";
2
+ import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poTag, poText } from "../core/po-helpers.js";
3
3
  import { resolveColorNode } from "../core/drawingml/colors.js";
4
4
  //#region src/word/drawing-parser.ts
5
5
  var WPS_URI = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
6
6
  var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
7
7
  var UNDERSTOOD_NS = new Set(["wps"]);
8
+ function parseFloatAnchor(anchor) {
9
+ if (!poIs(anchor, "wp:anchor")) return void 0;
10
+ const behindRaw = poAttr(anchor, "behindDoc");
11
+ const behind = behindRaw === "1" || behindRaw === "true";
12
+ let wrap = "none";
13
+ for (const child of poChildren(anchor)) if (poIs(child, "wp:wrapSquare")) wrap = "square";
14
+ else if (poIs(child, "wp:wrapTight")) wrap = "tight";
15
+ else if (poIs(child, "wp:wrapThrough")) wrap = "through";
16
+ else if (poIs(child, "wp:wrapTopAndBottom")) wrap = "topAndBottom";
17
+ const posH = parseAnchorPos(anchor, "wp:positionH", [
18
+ "margin",
19
+ "page",
20
+ "column"
21
+ ]);
22
+ const posV = parseAnchorPos(anchor, "wp:positionV", [
23
+ "margin",
24
+ "page",
25
+ "paragraph",
26
+ "line"
27
+ ]);
28
+ return {
29
+ wrap,
30
+ ...behind ? { behind: true } : {},
31
+ ...posH ? { posH } : {},
32
+ ...posV ? { posV } : {}
33
+ };
34
+ }
35
+ var ANCHOR_ALIGNS = new Set([
36
+ "left",
37
+ "center",
38
+ "right"
39
+ ]);
40
+ function parseAnchorPos(anchor, tag, allowed) {
41
+ const pos = poChildren(anchor).find((c) => poIs(c, tag));
42
+ if (!pos) return void 0;
43
+ const relRaw = poAttr(pos, "relativeFrom") ?? "margin";
44
+ const relativeFrom = allowed.includes(relRaw) ? relRaw : allowed[0];
45
+ const offsetNode = poChildren(pos).find((c) => poIs(c, "wp:posOffset"));
46
+ const offsetRaw = offsetNode ? Number(poText(offsetNode).trim()) : NaN;
47
+ const alignNode = poChildren(pos).find((c) => poIs(c, "wp:align"));
48
+ const alignRaw = alignNode ? poText(alignNode).trim() : "";
49
+ return {
50
+ relativeFrom,
51
+ ...Number.isFinite(offsetRaw) ? { offsetPt: emuToPt(offsetRaw) } : {},
52
+ ...tag === "wp:positionH" && ANCHOR_ALIGNS.has(alignRaw) ? { align: alignRaw } : {}
53
+ };
54
+ }
8
55
  function resolveMc(altContent) {
9
56
  for (const choice of poChildren(altContent)) {
10
57
  if (!poIs(choice, "mc:Choice")) continue;
@@ -30,7 +77,11 @@ function parseDrawing(drawing, resolveColor, parseBody) {
30
77
  const descr = docPr ? poAttr(docPr, "descr") : void 0;
31
78
  const title = docPr ? poAttr(docPr, "title") : void 0;
32
79
  const altText = (descr ?? title)?.trim() || void 0;
33
- const alt = altText ? { altText } : {};
80
+ const float = parseFloatAnchor(anchor);
81
+ const alt = {
82
+ ...altText ? { altText } : {},
83
+ ...float ? { float } : {}
84
+ };
34
85
  const graphicData = poFindDescendant(anchor, "a:graphicData");
35
86
  const uri = graphicData ? poAttr(graphicData, "uri") : void 0;
36
87
  if (graphicData && uri === WPS_URI) {
@@ -1,6 +1,6 @@
1
- export type { ImageResolver, ParseContext } from './document-parser.js';
1
+ export type { HyperlinkResolver, ImageResolver, ParseContext } from './document-parser.js';
2
2
  export { extractParagraphs } from './text-extractor.js';
3
- export { parseDocument, parseBodyElements, parseSection, parseSections, parseHeaderFooter, EMPTY_SECTION, } from './document-parser.js';
3
+ export { parseDocument, parseBodyElements, parseSection, parseSections, parseHeaderFooter, parseNotes, EMPTY_SECTION, } from './document-parser.js';
4
4
  export { parseRunProperties } from './run-properties.js';
5
5
  export { parseParagraphProperties } from './paragraph-properties.js';
6
6
  export { parseStyles } from './styles-parser.js';
@@ -1,3 +1,4 @@
1
+ import { eighthPtToPt, twipsToPt } from "../core/ir/units.js";
1
2
  import { EMPTY_STYLE_SHEET } from "../core/style-cascade/resolver.js";
2
3
  import "../core/style-cascade/index.js";
3
4
  import { asArray, asElement, getAttr, getVal } from "./xml-helpers.js";
@@ -50,7 +51,8 @@ function parseStyles(stylesXml) {
50
51
  ...basedOnVal ? { basedOn: basedOnVal } : {},
51
52
  isDefault,
52
53
  runProperties: parseRunProperties(el["w:rPr"]),
53
- paragraphProperties: parseParagraphProperties(el["w:pPr"])
54
+ paragraphProperties: parseParagraphProperties(el["w:pPr"]),
55
+ ...type === "table" ? parseTableStyleParts(el) : {}
54
56
  };
55
57
  styles.set(id, style);
56
58
  }
@@ -60,5 +62,136 @@ function parseStyles(stylesXml) {
60
62
  styles
61
63
  };
62
64
  }
65
+ var CONDITION_TYPES = new Set([
66
+ "wholeTable",
67
+ "band1Vert",
68
+ "band2Vert",
69
+ "band1Horz",
70
+ "band2Horz",
71
+ "firstCol",
72
+ "lastCol",
73
+ "firstRow",
74
+ "lastRow",
75
+ "nwCell",
76
+ "neCell",
77
+ "swCell",
78
+ "seCell"
79
+ ]);
80
+ function parseTableStyleParts(el) {
81
+ const out = {};
82
+ const base = parseTableStyleLayer(el);
83
+ if (base) out.tableLayer = base;
84
+ const tblPr = asElement(el["w:tblPr"]);
85
+ if (tblPr) {
86
+ const rowBand = intVal(tblPr["w:tblStyleRowBandSize"]);
87
+ const colBand = intVal(tblPr["w:tblStyleColBandSize"]);
88
+ if (rowBand !== void 0 && rowBand > 0) out.rowBandSize = rowBand;
89
+ if (colBand !== void 0 && colBand > 0) out.colBandSize = colBand;
90
+ }
91
+ const conditions = [];
92
+ for (const c of asArray(el["w:tblStylePr"])) {
93
+ const cond = asElement(c);
94
+ if (!cond) continue;
95
+ const typeAttr = getAttr(cond, "type");
96
+ if (!typeAttr || !CONDITION_TYPES.has(typeAttr)) continue;
97
+ const layer = parseTableStyleLayer(cond);
98
+ if (layer) conditions.push({
99
+ type: typeAttr,
100
+ layer
101
+ });
102
+ }
103
+ if (conditions.length > 0) out.tableConditions = conditions;
104
+ return out;
105
+ }
106
+ function parseTableStyleLayer(el) {
107
+ const tblPr = asElement(el["w:tblPr"]);
108
+ const tcPr = asElement(el["w:tcPr"]);
109
+ const borders = parseFlatBorders(tblPr ? asElement(tblPr["w:tblBorders"]) : void 0) ?? parseFlatBorders(tcPr ? asElement(tcPr["w:tcBorders"]) : void 0);
110
+ const cellMargins = parseFlatCellMargins(tblPr ? asElement(tblPr["w:tblCellMar"]) : void 0);
111
+ const shading = parseFlatShading(tcPr ? tcPr["w:shd"] : void 0);
112
+ const runProperties = parseRunProperties(el["w:rPr"]);
113
+ const paragraphProperties = parseParagraphProperties(el["w:pPr"]);
114
+ const layer = {
115
+ ...borders ? { borders } : {},
116
+ ...cellMargins ? { cellMargins } : {},
117
+ ...shading ? { shading } : {},
118
+ ...Object.keys(runProperties).length > 0 ? { runProperties } : {},
119
+ ...Object.keys(paragraphProperties).length > 0 ? { paragraphProperties } : {}
120
+ };
121
+ return Object.keys(layer).length > 0 ? layer : void 0;
122
+ }
123
+ var FLAT_BORDER_STYLES = new Set([
124
+ "none",
125
+ "single",
126
+ "double",
127
+ "thick",
128
+ "dotted",
129
+ "dashed"
130
+ ]);
131
+ function parseFlatBorder(node) {
132
+ const el = asElement(node);
133
+ if (!el) return void 0;
134
+ const val = getAttr(el, "val");
135
+ if (!val || !FLAT_BORDER_STYLES.has(val)) return void 0;
136
+ const szRaw = getAttr(el, "sz");
137
+ const sz = szRaw !== void 0 ? Number(szRaw) : NaN;
138
+ const color = getAttr(el, "color");
139
+ return {
140
+ style: val,
141
+ ...Number.isFinite(sz) ? { width: eighthPtToPt(sz) } : {},
142
+ ...color && color !== "auto" && /^[0-9A-Fa-f]{6}$/.test(color) ? { colorHex: color.toUpperCase() } : {}
143
+ };
144
+ }
145
+ function parseFlatBorders(el) {
146
+ if (!el) return void 0;
147
+ const top = parseFlatBorder(el["w:top"]);
148
+ const right = parseFlatBorder(el["w:right"] ?? el["w:end"]);
149
+ const bottom = parseFlatBorder(el["w:bottom"]);
150
+ const left = parseFlatBorder(el["w:left"] ?? el["w:start"]);
151
+ const insideH = parseFlatBorder(el["w:insideH"]);
152
+ const insideV = parseFlatBorder(el["w:insideV"]);
153
+ const out = {
154
+ ...top ? { top } : {},
155
+ ...right ? { right } : {},
156
+ ...bottom ? { bottom } : {},
157
+ ...left ? { left } : {},
158
+ ...insideH ? { insideH } : {},
159
+ ...insideV ? { insideV } : {}
160
+ };
161
+ return Object.keys(out).length > 0 ? out : void 0;
162
+ }
163
+ function parseFlatCellMargins(el) {
164
+ if (!el) return void 0;
165
+ const read = (node) => {
166
+ const m = asElement(node);
167
+ if (!m) return void 0;
168
+ const w = getAttr(m, "w");
169
+ const n = w !== void 0 ? Number(w) : NaN;
170
+ return Number.isFinite(n) ? n : void 0;
171
+ };
172
+ const top = read(el["w:top"]);
173
+ const bottom = read(el["w:bottom"]);
174
+ const left = read(el["w:left"] ?? el["w:start"]);
175
+ const right = read(el["w:right"] ?? el["w:end"]);
176
+ const out = {
177
+ ...top !== void 0 ? { top: twipsToPt(top) } : {},
178
+ ...bottom !== void 0 ? { bottom: twipsToPt(bottom) } : {},
179
+ ...left !== void 0 ? { left: twipsToPt(left) } : {},
180
+ ...right !== void 0 ? { right: twipsToPt(right) } : {}
181
+ };
182
+ return Object.keys(out).length > 0 ? out : void 0;
183
+ }
184
+ function parseFlatShading(node) {
185
+ const el = asElement(node);
186
+ if (!el) return void 0;
187
+ const fill = getAttr(el, "fill");
188
+ if (fill && fill !== "auto" && /^[0-9A-Fa-f]{6}$/.test(fill)) return { colorHex: fill.toUpperCase() };
189
+ }
190
+ function intVal(node) {
191
+ const v = getVal(node);
192
+ if (v === void 0) return void 0;
193
+ const n = Number(v);
194
+ return Number.isFinite(n) ? n : void 0;
195
+ }
63
196
  //#endregion
64
197
  export { parseStyles };
@@ -80,6 +80,16 @@ function resolveMergeRoles(rows) {
80
80
  function parseTableProperties(tblPr) {
81
81
  if (!tblPr) return {};
82
82
  const out = {};
83
+ const tblStyle = poFirstChild(tblPr, "w:tblStyle");
84
+ if (tblStyle) {
85
+ const id = poVal(tblStyle);
86
+ if (id) out.styleId = id;
87
+ }
88
+ const tblLook = poFirstChild(tblPr, "w:tblLook");
89
+ if (tblLook) {
90
+ const look = parseTableLook(tblLook);
91
+ if (look) out.look = look;
92
+ }
83
93
  const tblW = poFirstChild(tblPr, "w:tblW");
84
94
  if (tblW) {
85
95
  const w = poIntAttr(tblW, "w");
@@ -99,6 +109,31 @@ function parseTableProperties(tblPr) {
99
109
  if (margins) out.defaultCellMargins = margins;
100
110
  return out;
101
111
  }
112
+ function parseTableLook(node) {
113
+ const flag = (name, bit) => {
114
+ const attr = poAttr(node, name);
115
+ if (attr !== void 0) return attr === "1" || attr === "true";
116
+ const valRaw = poAttr(node, "val");
117
+ if (valRaw === void 0) return void 0;
118
+ const mask = parseInt(valRaw, 16);
119
+ return Number.isFinite(mask) ? (mask & bit) !== 0 : void 0;
120
+ };
121
+ const firstRow = flag("firstRow", 32);
122
+ const lastRow = flag("lastRow", 64);
123
+ const firstColumn = flag("firstColumn", 128);
124
+ const lastColumn = flag("lastColumn", 256);
125
+ const noHBand = flag("noHBand", 512);
126
+ const noVBand = flag("noVBand", 1024);
127
+ const out = {
128
+ ...firstRow !== void 0 ? { firstRow } : {},
129
+ ...lastRow !== void 0 ? { lastRow } : {},
130
+ ...firstColumn !== void 0 ? { firstColumn } : {},
131
+ ...lastColumn !== void 0 ? { lastColumn } : {},
132
+ ...noHBand !== void 0 ? { noHBand } : {},
133
+ ...noVBand !== void 0 ? { noVBand } : {}
134
+ };
135
+ return Object.keys(out).length > 0 ? out : void 0;
136
+ }
102
137
  function parseTableGrid(tblGrid) {
103
138
  if (!tblGrid) return [];
104
139
  const cols = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reamkit",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Ream — DOCX/XLSX to PDF (and SVG), built from scratch on the ECMA-376 and ISO 32000 specifications. Parse once, convert anywhere.",
5
5
  "license": "MIT",
6
6
  "author": "Alex Krassavin <info@reamkit.dev>",