reamkit 1.7.0 → 1.10.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 (46) hide show
  1. package/README.md +21 -3
  2. package/dist/esm/core/converter/facade.js +2 -0
  3. package/dist/esm/core/converter/ream.d.ts +1 -0
  4. package/dist/esm/core/converter/ream.js +2 -1
  5. package/dist/esm/core/document-model/types.d.ts +3 -1
  6. package/dist/esm/core/drawingml/shape-render.d.ts +3 -1
  7. package/dist/esm/core/drawingml/shape-render.js +27 -1
  8. package/dist/esm/core/vector.d.ts +10 -0
  9. package/dist/esm/html/html-writer.js +4 -2
  10. package/dist/esm/layout/styled-layout.js +5 -2
  11. package/dist/esm/pdf/shading.d.ts +12 -0
  12. package/dist/esm/pdf/shading.js +152 -0
  13. package/dist/esm/pdf/styled-page-emitter.js +29 -4
  14. package/dist/esm/pdf/vector-graphics.d.ts +1 -1
  15. package/dist/esm/pdf/vector-graphics.js +5 -3
  16. package/dist/esm/pdf-reader/ccitt.d.ts +15 -0
  17. package/dist/esm/pdf-reader/ccitt.js +394 -0
  18. package/dist/esm/pdf-reader/content.d.ts +6 -2
  19. package/dist/esm/pdf-reader/content.js +54 -13
  20. package/dist/esm/pdf-reader/decrypt.d.ts +1 -1
  21. package/dist/esm/pdf-reader/decrypt.js +20 -8
  22. package/dist/esm/pdf-reader/document.d.ts +1 -1
  23. package/dist/esm/pdf-reader/document.js +4 -4
  24. package/dist/esm/pdf-reader/flow-build.js +17 -6
  25. package/dist/esm/pdf-reader/image-decode.js +115 -7
  26. package/dist/esm/pdf-reader/layout.js +45 -7
  27. package/dist/esm/pdf-reader/reader.d.ts +1 -1
  28. package/dist/esm/pdf-reader/reader.js +5 -5
  29. package/dist/esm/pdf-reader/shading.d.ts +3 -0
  30. package/dist/esm/pdf-reader/shading.js +147 -0
  31. package/dist/esm/pdf-reader/text.js +47 -13
  32. package/dist/esm/pdf-reader/vector.d.ts +5 -1
  33. package/dist/esm/pdf-reader/vector.js +15 -6
  34. package/dist/esm/pptx/placeholder-cascade.d.ts +9 -0
  35. package/dist/esm/pptx/placeholder-cascade.js +77 -0
  36. package/dist/esm/pptx/pptx-reader.d.ts +4 -0
  37. package/dist/esm/pptx/pptx-reader.js +213 -0
  38. package/dist/esm/pptx/slide-parser.d.ts +18 -0
  39. package/dist/esm/pptx/slide-parser.js +359 -0
  40. package/dist/esm/pptx/sp-helpers.d.ts +17 -0
  41. package/dist/esm/pptx/sp-helpers.js +60 -0
  42. package/dist/esm/svg/svg-writer.js +12 -5
  43. package/dist/esm/word/docx-writer.js +8 -1
  44. package/dist/esm/word/drawing-parser.d.ts +4 -0
  45. package/dist/esm/word/drawing-parser.js +29 -18
  46. package/package.json +4 -2
@@ -1,5 +1,6 @@
1
1
  import { FEATURES } from "../core/ir/features.js";
2
2
  import { svgPathData } from "../core/vector.js";
3
+ import { gradientSvgDef } from "../core/drawingml/shape-render.js";
3
4
  import { paintPlan } from "../layout/page-doc.js";
4
5
  import { toBase64 } from "../core/bytes.js";
5
6
  //#region src/svg/svg-writer.ts
@@ -12,10 +13,11 @@ function writeSvg(laid, opts = {}) {
12
13
  const parts = [];
13
14
  parts.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${fmt(width)}" height="${fmt(height)}" viewBox="0 0 ${fmt(width)} ${fmt(height)}">`);
14
15
  let yOffset = 0;
16
+ const idc = { n: 0 };
15
17
  laid.pages.forEach((page, i) => {
16
18
  parts.push(`<g transform="translate(0 ${fmt(yOffset)})" data-page="${i + 1}">`);
17
19
  parts.push(`<rect x="0" y="0" width="${fmt(page.width)}" height="${fmt(page.height)}" fill="#ffffff" stroke="#cccccc"/>`);
18
- emitPage(parts, page, laid, losses);
20
+ emitPage(parts, page, laid, losses, idc);
19
21
  parts.push("</g>");
20
22
  yOffset += page.height + gap;
21
23
  });
@@ -36,7 +38,7 @@ var svgWriter = {
36
38
  ]),
37
39
  write: (doc, opts) => writeSvg(doc, opts ?? {})
38
40
  };
39
- function emitPage(out, page, laid, losses) {
41
+ function emitPage(out, page, laid, losses, idc) {
40
42
  const plan = paintPlan(page.commands);
41
43
  for (const f of plan.fills) out.push(`<rect x="${fmt(f.x)}" y="${fmt(f.y)}" width="${fmt(f.width)}" height="${fmt(f.height)}" fill="#${f.fillColorHex}"/>`);
42
44
  for (const img of plan.images) {
@@ -71,7 +73,7 @@ function emitPage(out, page, laid, losses) {
71
73
  ];
72
74
  out.push(`<line x1="${fmt(ax)}" y1="${fmt(ay)}" x2="${fmt(bx)}" y2="${fmt(by)}" stroke="#${b.borderColorHex}" stroke-width="${fmt(b.borderSizePt)}"/>`);
73
75
  }
74
- for (const sh of plan.shapes) emitShape(out, sh.shape);
76
+ for (const sh of plan.shapes) emitShape(out, sh.shape, idc);
75
77
  for (const t of plan.lines) emitTextLine(out, t, losses);
76
78
  }
77
79
  function emitTextLine(out, item, losses) {
@@ -95,10 +97,15 @@ function emitTextLine(out, item, losses) {
95
97
  x += tok.widthPt;
96
98
  }
97
99
  }
98
- function emitShape(out, shape) {
100
+ function emitShape(out, shape, idc) {
99
101
  const [a, b, c, d, e, f] = shape.transform;
100
102
  const transform = `matrix(${fmt(a)} ${fmt(b)} ${fmt(c)} ${fmt(d)} ${fmt(e)} ${fmt(f)})`;
101
- const fill = shape.fillColorHex ? `#${shape.fillColorHex}` : "none";
103
+ let fill;
104
+ if (shape.fillGradient) {
105
+ const id = `grad${idc.n++}`;
106
+ out.push(gradientSvgDef(id, shape.fillGradient));
107
+ fill = `url(#${id})`;
108
+ } else fill = shape.fillColorHex ? `#${shape.fillColorHex}` : "none";
102
109
  const stroke = shape.stroke ? ` stroke="#${shape.stroke.colorHex}" stroke-width="${fmt(shape.stroke.widthPt)}"` : "";
103
110
  for (const path of shape.paths) {
104
111
  const d2 = pathData(path.segments);
@@ -359,7 +359,14 @@ function geomXml(g) {
359
359
  return `<a:prstGeom prst="${escapeAttr(g.preset ?? "rect")}"><a:avLst>${gds}</a:avLst></a:prstGeom>`;
360
360
  }
361
361
  function fillXml(f) {
362
- return f.kind === "solid" && f.colorHex ? `<a:solidFill><a:srgbClr val="${f.colorHex}"/></a:solidFill>` : "<a:noFill/>";
362
+ if (f.kind === "solid" && f.colorHex) return `<a:solidFill><a:srgbClr val="${f.colorHex}"/></a:solidFill>`;
363
+ if (f.kind === "gradient" && f.gradient) return gradFillXml(f.gradient);
364
+ return "<a:noFill/>";
365
+ }
366
+ function gradFillXml(g) {
367
+ return `<a:gradFill><a:gsLst>${g.stops.map((s) => {
368
+ return `<a:gs pos="${Math.round(Math.max(0, Math.min(1, s.offset)) * 1e5)}"><a:srgbClr val="${s.colorHex}"/></a:gs>`;
369
+ }).join("")}</a:gsLst>${g.kind === "radial" ? "<a:path path=\"circle\"/>" : `<a:lin ang="${Math.round(((g.angle ?? 0) % 360 + 360) % 360 * 6e4)}" scaled="1"/>`}</a:gradFill>`;
363
370
  }
364
371
  function lineXml(l) {
365
372
  const w = l.width !== void 0 ? ` w="${Math.round(l.width * EMU_PER_PT)}"` : "";
@@ -36,3 +36,7 @@ export declare function resolveMc(altContent: PoNode): ReadonlyArray<PoNode>;
36
36
  export declare function expandMcChildren(children: ReadonlyArray<PoNode>): Array<PoNode>;
37
37
  export declare function parseDrawing(drawing: PoNode, resolveColor: ColorResolver, parseBody?: ParseBody): DrawingContent | null;
38
38
  export declare function parseVmlPicture(node: PoNode): DrawingContent | null;
39
+ export declare function parsePrstGeom(prst: PoNode): ShapeGeometry;
40
+ export declare function parseCustGeom(cust: PoNode): ShapeGeometry;
41
+ export declare function parseFill(spPr: PoNode, resolveColor: ColorResolver): ShapeFill;
42
+ export declare function parseLine(spPr: PoNode, resolveColor: ColorResolver): ShapeLine | undefined;
@@ -353,10 +353,10 @@ function parseFill(spPr, resolveColor) {
353
353
  } : { kind: "none" };
354
354
  }
355
355
  if (poIs(child, "a:gradFill")) {
356
- const hex = colorFromGradient(child, resolveColor);
357
- return hex ? {
358
- kind: "solid",
359
- colorHex: hex
356
+ const gradient = parseGradient(child, resolveColor);
357
+ return gradient ? {
358
+ kind: "gradient",
359
+ gradient
360
360
  } : { kind: "none" };
361
361
  }
362
362
  }
@@ -404,13 +404,10 @@ function colorFromContainer(parent, resolveColor) {
404
404
  if (hex) return hex;
405
405
  }
406
406
  }
407
- function colorFromGradient(grad, resolveColor) {
407
+ function parseGradient(grad, resolveColor) {
408
408
  const gsLst = poChildren(grad).find((c) => poIs(c, "a:gsLst"));
409
409
  if (!gsLst) return void 0;
410
- let r = 0;
411
- let g = 0;
412
- let b = 0;
413
- let n = 0;
410
+ const stops = [];
414
411
  for (const gs of poChildren(gsLst)) {
415
412
  if (!poIs(gs, "a:gs")) continue;
416
413
  let hex;
@@ -419,15 +416,29 @@ function colorFromGradient(grad, resolveColor) {
419
416
  if (hex) break;
420
417
  }
421
418
  if (!hex) continue;
422
- const num = parseInt(hex, 16);
423
- r += num >> 16 & 255;
424
- g += num >> 8 & 255;
425
- b += num & 255;
426
- n++;
419
+ const pos = poIntAttr(gs, "pos");
420
+ const offset = pos !== void 0 ? clampUnit(pos / 1e5) : stops.length === 0 ? 0 : 1;
421
+ stops.push({
422
+ offset,
423
+ colorHex: hex
424
+ });
427
425
  }
428
- if (n === 0) return void 0;
429
- const toHex = (x) => Math.round(x / n).toString(16).padStart(2, "0");
430
- return (toHex(r) + toHex(g) + toHex(b)).toUpperCase();
426
+ if (stops.length === 0) return void 0;
427
+ stops.sort((a, b) => a.offset - b.offset);
428
+ if (poChildren(grad).some((c) => poIs(c, "a:path"))) return {
429
+ kind: "radial",
430
+ stops
431
+ };
432
+ const lin = poChildren(grad).find((c) => poIs(c, "a:lin"));
433
+ const ang = lin ? poIntAttr(lin, "ang") : void 0;
434
+ return {
435
+ kind: "linear",
436
+ angle: ang !== void 0 ? ang / 6e4 % 360 : 0,
437
+ stops
438
+ };
439
+ }
440
+ function clampUnit(x) {
441
+ return x < 0 ? 0 : x > 1 ? 1 : x;
431
442
  }
432
443
  //#endregion
433
- export { expandMcChildren, parseDrawing, parseVmlPicture };
444
+ export { expandMcChildren, parseCustGeom, parseDrawing, parseFill, parseLine, parsePrstGeom, parseVmlPicture };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "reamkit",
3
- "version": "1.7.0",
4
- "description": "Ream — convert DOCX, XLSX and PDF to PDF, SVG, HTML, DOCX and XLSX, built from scratch on the ECMA-376 and ISO 32000 specifications. Parse once, convert anywhere.",
3
+ "version": "1.10.0",
4
+ "description": "Ream — convert DOCX, XLSX, PPTX and PDF to PDF, SVG, HTML, DOCX and XLSX, 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>",
7
7
  "repository": {
@@ -38,6 +38,7 @@
38
38
  "keywords": [
39
39
  "docx",
40
40
  "xlsx",
41
+ "pptx",
41
42
  "pdf",
42
43
  "ooxml",
43
44
  "ecma-376",
@@ -46,6 +47,7 @@
46
47
  "office",
47
48
  "word",
48
49
  "excel",
50
+ "powerpoint",
49
51
  "converter"
50
52
  ],
51
53
  "scripts": {