reamkit 0.1.0-alpha.0 → 1.0.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 (175) hide show
  1. package/README.md +106 -30
  2. package/dist/esm/{bidi → core/bidi}/algorithm.js +1 -1
  3. package/dist/esm/{bidi → core/bidi}/char-types.js +1 -1
  4. package/dist/esm/{bidi → core/bidi}/index.js +1 -1
  5. package/dist/esm/core/bytes.d.ts +1 -0
  6. package/dist/esm/core/bytes.js +11 -0
  7. package/dist/esm/core/converter/facade.d.ts +45 -0
  8. package/dist/esm/core/converter/facade.js +89 -0
  9. package/dist/esm/core/converter/index.d.ts +4 -0
  10. package/dist/esm/core/converter/project.d.ts +4 -0
  11. package/dist/esm/core/converter/project.js +16 -0
  12. package/dist/esm/core/converter/ream.d.ts +35 -0
  13. package/dist/esm/core/converter/ream.js +100 -0
  14. package/dist/esm/{crypto → core/crypto}/asn1.js +1 -1
  15. package/dist/esm/{crypto → core/crypto}/cms.js +1 -1
  16. package/dist/esm/core/document-model/index.d.ts +1 -0
  17. package/dist/esm/{document-model → core/document-model}/types.d.ts +57 -41
  18. package/dist/esm/{ooxml → core}/drawingml/chart-parser.d.ts +1 -1
  19. package/dist/esm/{ooxml → core}/drawingml/chart-parser.js +6 -29
  20. package/dist/esm/{ooxml → core}/drawingml/colors.d.ts +3 -0
  21. package/dist/esm/{ooxml → core}/drawingml/colors.js +32 -2
  22. package/dist/esm/{ooxml → core}/drawingml/theme-parser.js +2 -2
  23. package/dist/esm/{font → core/font}/arabic-joining.js +1 -1
  24. package/dist/esm/{font → core/font}/binary-reader.js +1 -1
  25. package/dist/esm/{font → core/font}/font-registry.d.ts +1 -0
  26. package/dist/esm/{font → core/font}/font-registry.js +17 -16
  27. package/dist/esm/{font → core/font}/index.d.ts +1 -0
  28. package/dist/esm/{font → core/font}/opentype-layout.js +1 -1
  29. package/dist/esm/{font → core/font}/ttf-parser.js +1 -1
  30. package/dist/esm/{font → core/font}/ttf-subset.js +1 -1
  31. package/dist/esm/core/fonts/provider.d.ts +60 -0
  32. package/dist/esm/core/fonts/provider.js +163 -0
  33. package/dist/esm/{fonts → core/fonts}/remote-fonts.js +1 -1
  34. package/dist/esm/{hyphenation → core/hyphenation}/index.js +1 -1
  35. package/dist/esm/{hyphenation → core/hyphenation}/liang.js +1 -1
  36. package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.js +1 -1
  37. package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.js +1 -1
  38. package/dist/esm/core/ir/adapters.d.ts +37 -0
  39. package/dist/esm/core/ir/features.d.ts +25 -0
  40. package/dist/esm/core/ir/features.js +24 -0
  41. package/dist/esm/core/ir/flow.d.ts +24 -0
  42. package/dist/esm/core/ir/index.d.ts +11 -0
  43. package/dist/esm/core/ir/loss.d.ts +22 -0
  44. package/dist/esm/core/ir/loss.js +15 -0
  45. package/dist/esm/core/ir/resources.d.ts +16 -0
  46. package/dist/esm/core/ir/resources.js +50 -0
  47. package/dist/esm/core/ir/units.d.ts +16 -0
  48. package/dist/esm/core/ir/units.js +41 -0
  49. package/dist/esm/core/line-breaker/index.d.ts +2 -0
  50. package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.js +1 -1
  51. package/dist/esm/{numbering → core/numbering}/state.js +1 -1
  52. package/dist/esm/{opc → core/opc}/core-properties.js +1 -1
  53. package/dist/esm/{opc → core/opc}/package.js +1 -1
  54. package/dist/esm/{opc → core/opc}/relationship-types.js +1 -1
  55. package/dist/esm/{opc → core/opc}/relationships.js +1 -1
  56. package/dist/esm/{ooxml/wordproc → core}/po-helpers.js +1 -1
  57. package/dist/esm/{style-cascade → core/style-cascade}/index.d.ts +2 -2
  58. package/dist/esm/core/style-cascade/index.js +2 -0
  59. package/dist/esm/{style-cascade → core/style-cascade}/resolver.d.ts +1 -0
  60. package/dist/esm/{style-cascade → core/style-cascade}/resolver.js +14 -9
  61. package/dist/esm/{style-cascade → core/style-cascade}/types.d.ts +8 -7
  62. package/dist/esm/{style-cascade → core/style-cascade}/types.js +9 -8
  63. package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.js +1 -1
  64. package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.js +1 -1
  65. package/dist/esm/{ooxml/spreadsheet → excel}/index.d.ts +1 -1
  66. package/dist/esm/{ooxml/spreadsheet → excel}/number-format.js +1 -1
  67. package/dist/esm/excel/print-model.d.ts +18 -0
  68. package/dist/esm/{converter/xlsx-to-pdf.js → excel/print-model.js} +39 -148
  69. package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.js +1 -1
  70. package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.js +1 -1
  71. package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.js +1 -1
  72. package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.js +1 -1
  73. package/dist/esm/excel/xlsx-reader.d.ts +4 -0
  74. package/dist/esm/excel/xlsx-reader.js +91 -0
  75. package/dist/esm/{converter → excel}/xlsx-to-pdf.d.ts +13 -2
  76. package/dist/esm/excel/xlsx-to-pdf.js +69 -0
  77. package/dist/esm/index.d.ts +23 -8
  78. package/dist/esm/index.js +18 -11
  79. package/dist/esm/pdf/chart-geometry.d.ts +1 -1
  80. package/dist/esm/pdf/cid-font.d.ts +7 -1
  81. package/dist/esm/pdf/cid-font.js +33 -22
  82. package/dist/esm/pdf/image-xobject.d.ts +13 -0
  83. package/dist/esm/pdf/image-xobject.js +55 -54
  84. package/dist/esm/pdf/index.d.ts +2 -2
  85. package/dist/esm/pdf/math-layout.d.ts +1 -1
  86. package/dist/esm/pdf/preset-geometry.d.ts +1 -1
  87. package/dist/esm/pdf/signature.js +4 -4
  88. package/dist/esm/pdf/styled-page-emitter.d.ts +5 -0
  89. package/dist/esm/pdf/styled-page-emitter.js +542 -0
  90. package/dist/esm/pdf/styled-page-renderer.d.ts +189 -14
  91. package/dist/esm/pdf/styled-page-renderer.js +168 -654
  92. package/dist/esm/pdf/text-page-renderer.d.ts +1 -1
  93. package/dist/esm/svg/svg-writer.d.ts +8 -0
  94. package/dist/esm/svg/svg-writer.js +138 -0
  95. package/dist/esm/word/document-parser.d.ts +16 -0
  96. package/dist/esm/{ooxml/wordproc → word}/document-parser.js +55 -47
  97. package/dist/esm/word/docx-reader.d.ts +4 -0
  98. package/dist/esm/word/docx-reader.js +190 -0
  99. package/dist/esm/word/docx-to-pdf.d.ts +34 -0
  100. package/dist/esm/word/docx-to-pdf.js +112 -0
  101. package/dist/esm/{ooxml/wordproc → word}/drawing-parser.d.ts +10 -9
  102. package/dist/esm/{ooxml/wordproc → word}/drawing-parser.js +15 -42
  103. package/dist/esm/{ooxml/wordproc → word}/font-table.d.ts +2 -2
  104. package/dist/esm/{ooxml/wordproc → word}/font-table.js +2 -2
  105. package/dist/esm/{ooxml/wordproc → word}/index.d.ts +3 -2
  106. package/dist/esm/{ooxml/wordproc → word}/numbering-parser.d.ts +1 -1
  107. package/dist/esm/{ooxml/wordproc → word}/numbering-parser.js +1 -1
  108. package/dist/esm/{ooxml/math → word}/omml-parser.d.ts +2 -2
  109. package/dist/esm/{ooxml/math → word}/omml-parser.js +2 -2
  110. package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.d.ts +1 -1
  111. package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.js +9 -8
  112. package/dist/esm/{ooxml/wordproc → word}/po-to-flat.d.ts +1 -1
  113. package/dist/esm/{ooxml/wordproc → word}/po-to-flat.js +2 -2
  114. package/dist/esm/{ooxml/wordproc → word}/run-properties.d.ts +1 -1
  115. package/dist/esm/{ooxml/wordproc → word}/run-properties.js +3 -2
  116. package/dist/esm/{ooxml/wordproc → word}/settings-parser.js +2 -2
  117. package/dist/esm/word/styles-parser.d.ts +2 -0
  118. package/dist/esm/{ooxml/wordproc → word}/styles-parser.js +4 -7
  119. package/dist/esm/word/table-parser.d.ts +4 -0
  120. package/dist/esm/{ooxml/wordproc → word}/table-parser.js +80 -26
  121. package/dist/esm/{ooxml/wordproc → word}/xml-helpers.js +1 -1
  122. package/package.json +5 -6
  123. package/dist/esm/converter/docx-to-pdf.d.ts +0 -15
  124. package/dist/esm/converter/docx-to-pdf.js +0 -227
  125. package/dist/esm/converter/index.d.ts +0 -4
  126. package/dist/esm/converter/index.js +0 -2
  127. package/dist/esm/document-model/index.d.ts +0 -1
  128. package/dist/esm/line-breaker/index.d.ts +0 -2
  129. package/dist/esm/ooxml/index.d.ts +0 -1
  130. package/dist/esm/ooxml/wordproc/document-parser.d.ts +0 -9
  131. package/dist/esm/ooxml/wordproc/styles-parser.d.ts +0 -3
  132. package/dist/esm/ooxml/wordproc/table-parser.d.ts +0 -3
  133. /package/dist/esm/{bidi → core/bidi}/algorithm.d.ts +0 -0
  134. /package/dist/esm/{bidi → core/bidi}/char-types.d.ts +0 -0
  135. /package/dist/esm/{bidi → core/bidi}/index.d.ts +0 -0
  136. /package/dist/esm/{crypto → core/crypto}/asn1.d.ts +0 -0
  137. /package/dist/esm/{crypto → core/crypto}/cms.d.ts +0 -0
  138. /package/dist/esm/{crypto → core/crypto}/index.d.ts +0 -0
  139. /package/dist/esm/{crypto → core/crypto}/index.js +0 -0
  140. /package/dist/esm/{document-model → core/document-model}/index.js +0 -0
  141. /package/dist/esm/{ooxml → core}/drawingml/theme-parser.d.ts +0 -0
  142. /package/dist/esm/{font → core/font}/arabic-joining.d.ts +0 -0
  143. /package/dist/esm/{font → core/font}/binary-reader.d.ts +0 -0
  144. /package/dist/esm/{font → core/font}/opentype-layout.d.ts +0 -0
  145. /package/dist/esm/{font → core/font}/ttf-parser.d.ts +0 -0
  146. /package/dist/esm/{font → core/font}/ttf-subset.d.ts +0 -0
  147. /package/dist/esm/{fonts → core/fonts}/index.d.ts +0 -0
  148. /package/dist/esm/{fonts → core/fonts}/remote-fonts.d.ts +0 -0
  149. /package/dist/esm/{hyphenation → core/hyphenation}/index.d.ts +0 -0
  150. /package/dist/esm/{hyphenation → core/hyphenation}/liang.d.ts +0 -0
  151. /package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.d.ts +0 -0
  152. /package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.d.ts +0 -0
  153. /package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.d.ts +0 -0
  154. /package/dist/esm/{numbering → core/numbering}/index.d.ts +0 -0
  155. /package/dist/esm/{numbering → core/numbering}/state.d.ts +0 -0
  156. /package/dist/esm/{opc → core/opc}/core-properties.d.ts +0 -0
  157. /package/dist/esm/{opc → core/opc}/index.d.ts +0 -0
  158. /package/dist/esm/{opc → core/opc}/index.js +0 -0
  159. /package/dist/esm/{opc → core/opc}/package.d.ts +0 -0
  160. /package/dist/esm/{opc → core/opc}/relationship-types.d.ts +0 -0
  161. /package/dist/esm/{opc → core/opc}/relationships.d.ts +0 -0
  162. /package/dist/esm/{ooxml/wordproc → core}/po-helpers.d.ts +0 -0
  163. /package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.d.ts +0 -0
  164. /package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.d.ts +0 -0
  165. /package/dist/esm/{ooxml/spreadsheet → excel}/index.js +0 -0
  166. /package/dist/esm/{ooxml/spreadsheet → excel}/number-format.d.ts +0 -0
  167. /package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.d.ts +0 -0
  168. /package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.d.ts +0 -0
  169. /package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.d.ts +0 -0
  170. /package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.d.ts +0 -0
  171. /package/dist/esm/{ooxml/wordproc → word}/index.js +0 -0
  172. /package/dist/esm/{ooxml/wordproc → word}/settings-parser.d.ts +0 -0
  173. /package/dist/esm/{ooxml/wordproc → word}/text-extractor.d.ts +0 -0
  174. /package/dist/esm/{ooxml/wordproc → word}/text-extractor.js +0 -0
  175. /package/dist/esm/{ooxml/wordproc → word}/xml-helpers.d.ts +0 -0
@@ -1,4 +1,4 @@
1
- import { ParsedTtf } from '../font/index.js';
1
+ import { ParsedTtf } from '../core/font/index.js';
2
2
  export type FontInput = ParsedTtf | {
3
3
  readonly bytes: Uint8Array;
4
4
  };
@@ -0,0 +1,8 @@
1
+ import { DocumentWriter, WriteResult } from '../core/ir/adapters.js';
2
+ import { LaidOutDocument } from '../pdf/styled-page-renderer.js';
3
+ export interface SvgWriteOptions {
4
+ /** Gap between stacked pages, in px/pt (default 12). */
5
+ readonly pageGap?: number;
6
+ }
7
+ export declare function writeSvg(laid: LaidOutDocument, opts?: SvgWriteOptions): WriteResult;
8
+ export declare const svgWriter: DocumentWriter<LaidOutDocument>;
@@ -0,0 +1,138 @@
1
+ import { FEATURES } from "../core/ir/features.js";
2
+ import { paintPlan } from "../pdf/styled-page-renderer.js";
3
+ //#region src/svg/svg-writer.ts
4
+ var PAGE_GAP = 12;
5
+ function writeSvg(laid, opts = {}) {
6
+ const gap = opts.pageGap ?? PAGE_GAP;
7
+ const losses = [];
8
+ const width = Math.max(1, ...laid.pages.map((p) => p.width));
9
+ const height = laid.pages.reduce((s, p) => s + p.height, 0) + gap * Math.max(0, laid.pages.length - 1);
10
+ const parts = [];
11
+ parts.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${fmt(width)}" height="${fmt(height)}" viewBox="0 0 ${fmt(width)} ${fmt(height)}">`);
12
+ let yOffset = 0;
13
+ laid.pages.forEach((page, i) => {
14
+ parts.push(`<g transform="translate(0 ${fmt(yOffset)})" data-page="${i + 1}">`);
15
+ parts.push(`<rect x="0" y="0" width="${fmt(page.width)}" height="${fmt(page.height)}" fill="#ffffff" stroke="#cccccc"/>`);
16
+ emitPage(parts, page, laid, losses);
17
+ parts.push("</g>");
18
+ yOffset += page.height + gap;
19
+ });
20
+ parts.push("</svg>");
21
+ return {
22
+ bytes: new TextEncoder().encode(parts.join("\n")),
23
+ losses
24
+ };
25
+ }
26
+ var svgWriter = {
27
+ id: "svg",
28
+ consumes: "page",
29
+ supports: new Set([
30
+ FEATURES.text,
31
+ FEATURES.tables,
32
+ FEATURES.images,
33
+ FEATURES.shapes
34
+ ]),
35
+ write: (doc, opts) => writeSvg(doc, opts ?? {})
36
+ };
37
+ function emitPage(out, page, laid, losses) {
38
+ const H = page.height;
39
+ const plan = paintPlan(page.commands);
40
+ for (const f of plan.fills) out.push(`<rect x="${fmt(f.x)}" y="${fmt(H - f.y - f.height)}" width="${fmt(f.width)}" height="${fmt(f.height)}" fill="#${f.fillColorHex}"/>`);
41
+ for (const img of plan.images) {
42
+ const href = imageHref(img.imageResourceName, laid);
43
+ if (!href) continue;
44
+ out.push(`<image x="${fmt(img.x)}" y="${fmt(H - img.y - img.height)}" width="${fmt(img.width)}" height="${fmt(img.height)}" href="${href}" preserveAspectRatio="none"/>`);
45
+ }
46
+ for (const b of plan.borders) {
47
+ const x2 = b.x + b.width;
48
+ const yTop = H - b.y - b.height;
49
+ const yBottom = H - b.y;
50
+ const [ax, ay, bx, by] = b.side === "top" ? [
51
+ b.x,
52
+ yTop,
53
+ x2,
54
+ yTop
55
+ ] : b.side === "bottom" ? [
56
+ b.x,
57
+ yBottom,
58
+ x2,
59
+ yBottom
60
+ ] : b.side === "left" ? [
61
+ b.x,
62
+ yTop,
63
+ b.x,
64
+ yBottom
65
+ ] : [
66
+ x2,
67
+ yTop,
68
+ x2,
69
+ yBottom
70
+ ];
71
+ out.push(`<line x1="${fmt(ax)}" y1="${fmt(ay)}" x2="${fmt(bx)}" y2="${fmt(by)}" stroke="#${b.borderColorHex}" stroke-width="${fmt(b.borderSizePt)}"/>`);
72
+ }
73
+ for (const sh of plan.shapes) emitShape(out, sh.shape, H);
74
+ for (const t of plan.lines) emitTextLine(out, t, H, losses);
75
+ }
76
+ function emitTextLine(out, item, pageHeight, losses) {
77
+ const y = pageHeight - item.baselineY;
78
+ let x = item.originX;
79
+ for (const tok of item.line.tokens) {
80
+ if (tok.kind === "image") {
81
+ x += tok.widthPt;
82
+ continue;
83
+ }
84
+ if (tok.kind === "math") {
85
+ losses.push({
86
+ severity: "dropped",
87
+ feature: FEATURES.math,
88
+ detail: "inline math box not rendered by the SVG writer (v0)"
89
+ });
90
+ x += tok.widthPt;
91
+ continue;
92
+ }
93
+ if (tok.text.trim().length > 0) out.push(`<text x="${fmt(x)}" y="${fmt(y)}" font-family="sans-serif" font-size="${fmt(tok.fontSizePt)}" fill="#${tok.resolvedRun.colorHex}">${escapeXml(tok.text)}</text>`);
94
+ x += tok.widthPt;
95
+ }
96
+ }
97
+ function emitShape(out, shape, pageHeight) {
98
+ const [a, b, c, d, e, f] = shape.transform;
99
+ const transform = `matrix(${fmt(a)} ${fmt(-b)} ${fmt(-c)} ${fmt(d)} ${fmt(e)} ${fmt(pageHeight - f)})`;
100
+ const fill = shape.fillColorHex ? `#${shape.fillColorHex}` : "none";
101
+ const stroke = shape.stroke ? ` stroke="#${shape.stroke.colorHex}" stroke-width="${fmt(shape.stroke.widthPt)}"` : "";
102
+ for (const path of shape.paths) {
103
+ const d2 = pathData(path.segments);
104
+ const rule = path.fillRule === "evenodd" ? " fill-rule=\"evenodd\"" : "";
105
+ out.push(`<path d="${d2}" fill="${fill}"${rule}${stroke} transform="${transform}"/>`);
106
+ }
107
+ }
108
+ function pathData(segments) {
109
+ const parts = [];
110
+ for (const s of segments) if (s.op === "move") parts.push(`M ${fmt(s.x)} ${fmt(-s.y)}`);
111
+ else if (s.op === "line") parts.push(`L ${fmt(s.x)} ${fmt(-s.y)}`);
112
+ else if (s.op === "cubic") parts.push(`C ${fmt(s.x1)} ${fmt(-s.y1)} ${fmt(s.x2)} ${fmt(-s.y2)} ${fmt(s.x)} ${fmt(-s.y)}`);
113
+ else parts.push("Z");
114
+ return parts.join(" ");
115
+ }
116
+ function imageHref(resourceName, laid) {
117
+ if (!resourceName) return void 0;
118
+ for (const [resourceId, res] of laid.imageResources) {
119
+ if (res.resourceName !== resourceName) continue;
120
+ const bytes = laid.resources.get(resourceId);
121
+ if (!bytes) return void 0;
122
+ return `data:${res.prepared.mimeType};base64,${toBase64(bytes)}`;
123
+ }
124
+ }
125
+ function toBase64(bytes) {
126
+ let bin = "";
127
+ for (const b of bytes) bin += String.fromCharCode(b);
128
+ return btoa(bin);
129
+ }
130
+ function escapeXml(s) {
131
+ return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
132
+ }
133
+ function fmt(n) {
134
+ const r = Math.round(n * 100) / 100;
135
+ return Object.is(r, -0) ? "0" : String(r);
136
+ }
137
+ //#endregion
138
+ export { svgWriter, writeSvg };
@@ -0,0 +1,16 @@
1
+ import { BodyElement, Section, SectionProperties } from '../core/document-model/index.js';
2
+ import { ColorResolver } from '../core/drawingml/colors.js';
3
+ import { ResourceId } from '../core/ir/index.js';
4
+ import { PoNode } from '../core/po-helpers.js';
5
+ export type ImageResolver = (relId: string) => ResourceId | undefined;
6
+ export interface ParseContext {
7
+ readonly resolveColor: ColorResolver;
8
+ readonly resolveImage?: ImageResolver;
9
+ }
10
+ export declare const DEFAULT_PARSE_CONTEXT: ParseContext;
11
+ export declare function parseDocument(documentXml: Uint8Array, ctx?: ParseContext): Array<BodyElement>;
12
+ export declare const EMPTY_SECTION: SectionProperties;
13
+ export declare function parseSection(documentXml: Uint8Array): SectionProperties;
14
+ export declare function parseSections(documentXml: Uint8Array): Array<Section>;
15
+ export declare function parseHeaderFooter(xml: Uint8Array, ctx?: ParseContext): Array<BodyElement>;
16
+ export declare function parseBodyElements(children: ReadonlyArray<PoNode>, ctx?: ParseContext): Array<BodyElement>;
@@ -1,13 +1,14 @@
1
- import { poAttr, poChildren, poFindByPath, poIntAttr, poIs, poText } from "./po-helpers.js";
2
- import { defaultColorResolver } from "../drawingml/colors.js";
3
- import { parseOMath } from "../math/omml-parser.js";
1
+ import { twipsToPt } from "../core/ir/units.js";
2
+ import { poAttr, poChildren, poFindByPath, poIntAttr, poIs, poText } from "../core/po-helpers.js";
3
+ import { defaultColorResolver } from "../core/drawingml/colors.js";
4
+ import { parseOMath } from "./omml-parser.js";
4
5
  import { expandMcChildren, parseDrawing } from "./drawing-parser.js";
5
6
  import { parseRunProperties } from "./run-properties.js";
6
7
  import { parseParagraphProperties } from "./paragraph-properties.js";
7
8
  import { poElementToFlat } from "./po-to-flat.js";
8
9
  import { parseTable } from "./table-parser.js";
9
10
  import { XMLParser } from "fast-xml-parser";
10
- //#region src/ooxml/wordproc/document-parser.ts
11
+ //#region src/word/document-parser.ts
11
12
  var decoder = new TextDecoder("utf-8");
12
13
  var parser = new XMLParser({
13
14
  ignoreAttributes: false,
@@ -26,11 +27,12 @@ var RUN_CONTAINER_TAGS = new Set([
26
27
  "w:ins",
27
28
  "w:moveTo"
28
29
  ]);
29
- function parseDocument(documentXml, resolveColor = defaultColorResolver) {
30
+ var DEFAULT_PARSE_CONTEXT = { resolveColor: defaultColorResolver };
31
+ function parseDocument(documentXml, ctx = DEFAULT_PARSE_CONTEXT) {
30
32
  const xml = decoder.decode(documentXml);
31
33
  const body = poFindByPath(parser.parse(xml), ["w:document", "w:body"]);
32
34
  if (!body) return [];
33
- return parseBodyElements(poChildren(body), resolveColor);
35
+ return parseBodyElements(poChildren(body), ctx);
34
36
  }
35
37
  var HF_TYPES = new Set([
36
38
  "default",
@@ -83,8 +85,8 @@ function parseSectPrNode(sectPr) {
83
85
  const h = poIntAttr(child, "h");
84
86
  const orientRaw = poAttr(child, "orient");
85
87
  if (w !== void 0 && h !== void 0) pageSize = {
86
- widthTwips: w,
87
- heightTwips: h,
88
+ width: twipsToPt(w),
89
+ height: twipsToPt(h),
88
90
  ...orientRaw === "portrait" || orientRaw === "landscape" ? { orientation: orientRaw } : {}
89
91
  };
90
92
  } else if (poIs(child, "w:pgMar")) {
@@ -95,12 +97,12 @@ function parseSectPrNode(sectPr) {
95
97
  const header = poIntAttr(child, "header");
96
98
  const footer = poIntAttr(child, "footer");
97
99
  margins = {
98
- topTwips: top ?? 1440,
99
- rightTwips: right ?? 1440,
100
- bottomTwips: bottom ?? 1440,
101
- leftTwips: left ?? 1440,
102
- ...header !== void 0 ? { headerTwips: header } : {},
103
- ...footer !== void 0 ? { footerTwips: footer } : {}
100
+ top: twipsToPt(top ?? 1440),
101
+ right: twipsToPt(right ?? 1440),
102
+ bottom: twipsToPt(bottom ?? 1440),
103
+ left: twipsToPt(left ?? 1440),
104
+ ...header !== void 0 ? { header: twipsToPt(header) } : {},
105
+ ...footer !== void 0 ? { footer: twipsToPt(footer) } : {}
104
106
  };
105
107
  } else if (poIs(child, "w:headerReference")) pushHeaderFooter(child, headers);
106
108
  else if (poIs(child, "w:footerReference")) pushHeaderFooter(child, footers);
@@ -126,26 +128,26 @@ function pushHeaderFooter(node, list) {
126
128
  relationshipId: rId
127
129
  });
128
130
  }
129
- function parseHeaderFooter(xml, resolveColor = defaultColorResolver) {
131
+ function parseHeaderFooter(xml, ctx = DEFAULT_PARSE_CONTEXT) {
130
132
  const root = parser.parse(decoder.decode(xml)).find((n) => poIs(n, "w:hdr") || poIs(n, "w:ftr"));
131
133
  if (!root) return [];
132
- return parseBodyElements(poChildren(root), resolveColor);
134
+ return parseBodyElements(poChildren(root), ctx);
133
135
  }
134
- function parseBodyElements(children, resolveColor = defaultColorResolver) {
136
+ function parseBodyElements(children, ctx = DEFAULT_PARSE_CONTEXT) {
135
137
  const out = [];
136
138
  for (const child of children) if (poIs(child, "w:p")) {
137
- const drawing = tryExtractDrawingFromParagraph(child, resolveColor);
139
+ const drawing = tryExtractDrawingFromParagraph(child, ctx);
138
140
  out.push(drawing ?? {
139
141
  kind: "paragraph",
140
- paragraph: parseParagraph(child)
142
+ paragraph: parseParagraph(child, ctx)
141
143
  });
142
144
  } else if (poIs(child, "w:tbl")) out.push({
143
145
  kind: "table",
144
- table: parseTable(child)
146
+ table: parseTable(child, ctx)
145
147
  });
146
148
  return out;
147
149
  }
148
- function tryExtractDrawingFromParagraph(p, resolveColor) {
150
+ function tryExtractDrawingFromParagraph(p, ctx) {
149
151
  let drawing;
150
152
  let hasText = false;
151
153
  for (const child of poChildren(p)) {
@@ -156,27 +158,30 @@ function tryExtractDrawingFromParagraph(p, resolveColor) {
156
158
  else if (poIs(runChild, "w:tab") || poIs(runChild, "w:br") || poIs(runChild, "w:noBreakHyphen")) hasText = true;
157
159
  }
158
160
  if (!drawing || hasText) return null;
159
- const parseBody = (children) => parseBodyElements(children, resolveColor);
160
- const content = parseDrawing(drawing, resolveColor, parseBody);
161
+ const parseBody = (children) => parseBodyElements(children, ctx);
162
+ const content = parseDrawing(drawing, ctx.resolveColor, parseBody);
161
163
  if (!content) return null;
162
164
  const pPrNode = poChildren(p).find((c) => poIs(c, "w:pPr"));
163
165
  const paragraphProperties = pPrNode ? parseParagraphProperties(poElementToFlat(pPrNode)) : {};
164
- if (content.kind === "image") return {
165
- kind: "image",
166
- image: {
167
- imageId: content.imageId,
168
- widthEmu: content.widthEmu,
169
- heightEmu: content.heightEmu,
170
- paragraphProperties,
171
- ...content.altText ? { altText: content.altText } : {}
172
- }
173
- };
166
+ if (content.kind === "image") {
167
+ const resource = ctx.resolveImage?.(content.imageId);
168
+ return {
169
+ kind: "image",
170
+ image: {
171
+ ...resource ? { resource } : {},
172
+ width: content.width,
173
+ height: content.height,
174
+ paragraphProperties,
175
+ ...content.altText ? { altText: content.altText } : {}
176
+ }
177
+ };
178
+ }
174
179
  if (content.kind === "chart") return {
175
180
  kind: "chart",
176
181
  chart: {
177
182
  chartRelId: content.chartRelId,
178
- widthEmu: content.widthEmu,
179
- heightEmu: content.heightEmu,
183
+ width: content.width,
184
+ height: content.height,
180
185
  paragraphProperties,
181
186
  ...content.altText ? { altText: content.altText } : {}
182
187
  }
@@ -190,7 +195,7 @@ function tryExtractDrawingFromParagraph(p, resolveColor) {
190
195
  }
191
196
  };
192
197
  }
193
- function parseParagraph(p) {
198
+ function parseParagraph(p, ctx) {
194
199
  const pPr = poChildren(p).find((c) => poIs(c, "w:pPr"));
195
200
  let properties = parseParagraphProperties(pPr ? poElementToFlat(pPr) : void 0);
196
201
  const mathPara = poChildren(p).find((c) => poIs(c, "m:oMathPara"));
@@ -204,17 +209,17 @@ function parseParagraph(p) {
204
209
  };
205
210
  }
206
211
  const runs = [];
207
- collectRuns(p, runs);
212
+ collectRuns(p, runs, ctx);
208
213
  return {
209
214
  properties,
210
215
  runs
211
216
  };
212
217
  }
213
- function collectRuns(container, out) {
218
+ function collectRuns(container, out, ctx) {
214
219
  for (const child of poChildren(container)) {
215
220
  if (poIs(child, "w:pPr")) continue;
216
221
  if (poIs(child, "w:r")) {
217
- out.push(parseRun(child));
222
+ out.push(parseRun(child, ctx));
218
223
  continue;
219
224
  }
220
225
  if (poIs(child, "m:oMath")) {
@@ -234,10 +239,10 @@ function collectRuns(container, out) {
234
239
  continue;
235
240
  }
236
241
  const tag = elementTag(child);
237
- if (tag && RUN_CONTAINER_TAGS.has(tag)) collectRuns(child, out);
242
+ if (tag && RUN_CONTAINER_TAGS.has(tag)) collectRuns(child, out, ctx);
238
243
  }
239
244
  }
240
- function parseRun(r) {
245
+ function parseRun(r, ctx) {
241
246
  const rPr = poChildren(r).find((c) => poIs(c, "w:rPr"));
242
247
  const properties = parseRunProperties(rPr ? poElementToFlat(rPr) : void 0);
243
248
  let text = "";
@@ -253,11 +258,14 @@ function parseRun(r) {
253
258
  else if (poIs(child, "w:softHyphen")) text += "­";
254
259
  else if (poIs(child, "w:drawing")) {
255
260
  const content = parseDrawing(child, defaultColorResolver);
256
- if (content && content.kind === "image") inlineImage = {
257
- imageId: content.imageId,
258
- widthEmu: content.widthEmu,
259
- heightEmu: content.heightEmu
260
- };
261
+ if (content && content.kind === "image") {
262
+ const resource = ctx.resolveImage?.(content.imageId);
263
+ inlineImage = {
264
+ ...resource ? { resource } : {},
265
+ width: content.width,
266
+ height: content.height
267
+ };
268
+ }
261
269
  }
262
270
  }
263
271
  return {
@@ -271,4 +279,4 @@ function elementTag(node) {
271
279
  for (const key of Object.keys(node)) if (key !== ":@" && key !== "#text") return key;
272
280
  }
273
281
  //#endregion
274
- export { EMPTY_SECTION, parseBodyElements, parseDocument, parseHeaderFooter, parseSections };
282
+ export { DEFAULT_PARSE_CONTEXT, EMPTY_SECTION, parseBodyElements, parseDocument, parseHeaderFooter, parseSections };
@@ -0,0 +1,4 @@
1
+ import { DocumentReader, ReadResult } from '../core/ir/adapters.js';
2
+ import { FlowDoc } from '../core/ir/flow.js';
3
+ export declare function readDocx(docx: Uint8Array): ReadResult<FlowDoc>;
4
+ export declare const docxReader: DocumentReader<FlowDoc>;
@@ -0,0 +1,190 @@
1
+ import { ResourceStore } from "../core/ir/resources.js";
2
+ import { FEATURES } from "../core/ir/features.js";
3
+ import { EMPTY_STYLE_SHEET } from "../core/style-cascade/resolver.js";
4
+ import "../core/style-cascade/index.js";
5
+ import { bytesInclude } from "../core/bytes.js";
6
+ import { DEFAULT_THEME_PALETTE, makeColorResolver } from "../core/drawingml/colors.js";
7
+ import { parseChart } from "../core/drawingml/chart-parser.js";
8
+ import { parseTheme } from "../core/drawingml/theme-parser.js";
9
+ import { OpcPackage } from "../core/opc/package.js";
10
+ import { parseCoreProperties } from "../core/opc/core-properties.js";
11
+ import "../core/opc/index.js";
12
+ import { EMPTY_SECTION, parseDocument, parseHeaderFooter, parseSections } from "./document-parser.js";
13
+ import { parseStyles } from "./styles-parser.js";
14
+ import { loadEmbeddedFonts } from "./font-table.js";
15
+ import { EMPTY_NUMBERING, parseNumbering } from "./numbering-parser.js";
16
+ import { EMPTY_SETTINGS, parseSettings } from "./settings-parser.js";
17
+ import "./index.js";
18
+ //#region src/word/docx-reader.ts
19
+ var STYLES_PART = "word/styles.xml";
20
+ var NUMBERING_PART = "word/numbering.xml";
21
+ var SETTINGS_PART = "word/settings.xml";
22
+ var CORE_PROPS_PART = "docProps/core.xml";
23
+ var MAIN_DOCUMENT_PART = "word/document.xml";
24
+ var REL_IMAGE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
25
+ var REL_CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
26
+ var REL_THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
27
+ var REL_HEADER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
28
+ var REL_FOOTER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
29
+ var THEME_PART = "word/theme/theme1.xml";
30
+ function readDocx(docx) {
31
+ const pkg = OpcPackage.open(docx);
32
+ const main = pkg.getMainDocument();
33
+ const resolveColor = buildColorResolver(pkg);
34
+ const resources = new ResourceStore();
35
+ const ctx = {
36
+ resolveColor,
37
+ resolveImage: makeImageResolver(pkg, resources)
38
+ };
39
+ const body = parseDocument(main.data, ctx);
40
+ const rawSections = parseSections(main.data);
41
+ const stylesData = pkg.getPart(STYLES_PART);
42
+ const styles = stylesData ? parseStyles(stylesData) : EMPTY_STYLE_SHEET;
43
+ const numberingData = pkg.getPart(NUMBERING_PART);
44
+ const numbering = numberingData ? parseNumbering(numberingData) : EMPTY_NUMBERING;
45
+ const settingsData = pkg.getPart(SETTINGS_PART);
46
+ const settings = settingsData ? parseSettings(settingsData) : EMPTY_SETTINGS;
47
+ const sections = rawSections.length > 0 ? rawSections.map((s) => ({
48
+ ...s,
49
+ properties: settings.evenAndOddHeaders ? {
50
+ ...s.properties,
51
+ evenAndOddHeaders: true
52
+ } : s.properties
53
+ })) : [{
54
+ properties: settings.evenAndOddHeaders ? {
55
+ ...EMPTY_SECTION,
56
+ evenAndOddHeaders: true
57
+ } : EMPTY_SECTION,
58
+ endIndex: body.length
59
+ }];
60
+ const headersFooters = loadHeadersFootersForSections(pkg, sections, ctx, resources);
61
+ const charts = loadCharts(pkg, resolveColor);
62
+ const embeddedFonts = loadEmbeddedFonts(pkg);
63
+ const coreData = pkg.getPart(CORE_PROPS_PART);
64
+ const info = infoFromCore(coreData ? parseCoreProperties(coreData) : void 0);
65
+ const language = detectDocxLanguage(stylesData, main.data);
66
+ return {
67
+ doc: {
68
+ kind: "flow",
69
+ body,
70
+ sections,
71
+ styles,
72
+ numbering,
73
+ headersFooters,
74
+ charts,
75
+ resources,
76
+ ...embeddedFonts.size > 0 ? { embeddedFonts } : {},
77
+ ...info ? { info } : {},
78
+ ...language ? { language } : {}
79
+ },
80
+ losses: []
81
+ };
82
+ }
83
+ var docxReader = {
84
+ id: "docx",
85
+ produces: "flow",
86
+ supports: new Set([
87
+ FEATURES.text,
88
+ FEATURES.tables,
89
+ FEATURES.tablesNested,
90
+ FEATURES.lists,
91
+ FEATURES.sections,
92
+ FEATURES.headersFooters,
93
+ FEATURES.images,
94
+ FEATURES.shapes,
95
+ FEATURES.charts,
96
+ FEATURES.math,
97
+ FEATURES.rtl,
98
+ FEATURES.trackedChanges,
99
+ FEATURES.fontsEmbedding
100
+ ]),
101
+ sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && bytesInclude(bytes, "word/document.xml"),
102
+ read: (bytes) => readDocx(bytes)
103
+ };
104
+ function infoFromCore(core) {
105
+ if (!core) return void 0;
106
+ return {
107
+ ...core.title ? { title: core.title } : {},
108
+ ...core.creator ? { author: core.creator } : {},
109
+ ...core.subject ? { subject: core.subject } : {},
110
+ ...core.keywords ? { keywords: core.keywords } : {},
111
+ ...core.created ? { creationDate: core.created } : {},
112
+ ...core.modified ? { modificationDate: core.modified } : {}
113
+ };
114
+ }
115
+ function makeImageResolver(pkg, store, partName = MAIN_DOCUMENT_PART) {
116
+ const byRelId = /* @__PURE__ */ new Map();
117
+ for (const rel of pkg.getPartRelationships(partName)) {
118
+ if (rel.type !== REL_IMAGE) continue;
119
+ const resolved = pkg.resolveRelatedPart(partName, rel);
120
+ if (resolved) byRelId.set(rel.id, resolved.data);
121
+ }
122
+ const cache = /* @__PURE__ */ new Map();
123
+ return (relId) => {
124
+ if (cache.has(relId)) return cache.get(relId);
125
+ const bytes = byRelId.get(relId);
126
+ const id = bytes ? store.put(bytes) : void 0;
127
+ cache.set(relId, id);
128
+ return id;
129
+ };
130
+ }
131
+ function loadCharts(pkg, resolveColor) {
132
+ const out = /* @__PURE__ */ new Map();
133
+ for (const rel of pkg.getPartRelationships(MAIN_DOCUMENT_PART)) {
134
+ if (rel.type !== REL_CHART) continue;
135
+ const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
136
+ if (!resolved) continue;
137
+ const chart = parseChart(resolved.data, resolveColor);
138
+ if (chart) out.set(rel.id, chart);
139
+ }
140
+ return out;
141
+ }
142
+ function buildColorResolver(pkg) {
143
+ const themeData = loadTheme(pkg);
144
+ if (!themeData) return makeColorResolver(DEFAULT_THEME_PALETTE);
145
+ const palette = new Map(DEFAULT_THEME_PALETTE);
146
+ for (const [slot, hex] of parseTheme(themeData)) palette.set(slot, hex);
147
+ return makeColorResolver(palette);
148
+ }
149
+ function loadTheme(pkg) {
150
+ for (const rel of pkg.getPartRelationships(MAIN_DOCUMENT_PART)) {
151
+ if (rel.type !== REL_THEME) continue;
152
+ const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
153
+ if (resolved) return resolved.data;
154
+ }
155
+ return pkg.getPart(THEME_PART);
156
+ }
157
+ function loadHeadersFootersForSections(pkg, sections, ctx, store) {
158
+ const wanted = /* @__PURE__ */ new Set();
159
+ for (const s of sections) {
160
+ for (const h of s.properties.headers) wanted.add(h.relationshipId);
161
+ for (const f of s.properties.footers) wanted.add(f.relationshipId);
162
+ }
163
+ if (wanted.size === 0) return /* @__PURE__ */ new Map();
164
+ const rels = pkg.getPartRelationships(MAIN_DOCUMENT_PART);
165
+ if (rels.length === 0) return /* @__PURE__ */ new Map();
166
+ const out = /* @__PURE__ */ new Map();
167
+ for (const rel of rels) {
168
+ if (!wanted.has(rel.id)) continue;
169
+ if (rel.type !== REL_HEADER && rel.type !== REL_FOOTER) continue;
170
+ const resolved = pkg.resolveRelatedPart(MAIN_DOCUMENT_PART, rel);
171
+ if (!resolved) continue;
172
+ const hfCtx = {
173
+ resolveColor: ctx.resolveColor,
174
+ resolveImage: makeImageResolver(pkg, store, resolved.path)
175
+ };
176
+ out.set(rel.id, parseHeaderFooter(resolved.data, hfCtx));
177
+ }
178
+ return out;
179
+ }
180
+ function detectDocxLanguage(stylesData, documentData) {
181
+ const re = /<w:lang\b[^>]*\bw:val="([^"]+)"/;
182
+ const decoder = new TextDecoder();
183
+ for (const data of [stylesData, documentData]) {
184
+ if (!data) continue;
185
+ const m = re.exec(decoder.decode(data));
186
+ if (m?.[1]) return m[1];
187
+ }
188
+ }
189
+ //#endregion
190
+ export { docxReader, readDocx };
@@ -0,0 +1,34 @@
1
+ import { FontBytesByVariant, FontRegistry } from '../core/font/index.js';
2
+ import { FamilyKey, FetchLike } from '../core/fonts/index.js';
3
+ import { SignatureOptions, StyledRenderOptions } from '../pdf/index.js';
4
+ export interface ConvertDocxOptions extends Omit<StyledRenderOptions, 'registry' | 'styles'> {
5
+ readonly fontBytes?: Uint8Array;
6
+ readonly fonts?: FontBytesByVariant;
7
+ readonly fontFamily?: string;
8
+ readonly fontFetch?: FetchLike;
9
+ readonly embedSource?: boolean;
10
+ readonly signature?: SignatureOptions;
11
+ }
12
+ /**
13
+ * Synchronous one-shot conversion (requires `fonts`/`fontBytes`, no network).
14
+ *
15
+ * Internal since 1.0 — see the async variant above.
16
+ */
17
+ export declare function convertDocxToPdfSync(docx: Uint8Array, options: ConvertDocxOptions): Uint8Array;
18
+ export declare function detectDocxFamilyKeys(docx: Uint8Array): Set<FamilyKey>;
19
+ /**
20
+ * One-shot .docx → PDF (auto-downloads a substitute font set when the caller
21
+ * supplies none; zero network with `fonts`/`fontBytes`).
22
+ *
23
+ * Internal since 1.0 — the public entry is `Ream.parse(bytes).convert('pdf')`;
24
+ * the createConverter facade and the test suite drive this directly.
25
+ */
26
+ export declare function convertDocxToPdf(docx: Uint8Array, options?: ConvertDocxOptions): Promise<Uint8Array>;
27
+ export declare function resolveDocxAutoFonts(docx: Uint8Array, options?: {
28
+ readonly fontFamily?: string;
29
+ readonly fontFetch?: FetchLike;
30
+ }): Promise<{
31
+ fonts: FontBytesByVariant;
32
+ registriesByFamily?: Map<FamilyKey, FontRegistry>;
33
+ }>;
34
+ export declare function detectDocxFontFamily(docx: Uint8Array): string | undefined;