smartrte-core 0.2.0 → 1.0.0-beta.1

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 (329) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +23 -0
  3. package/dist/command.d.ts +8 -8
  4. package/dist/editor.d.ts +32 -0
  5. package/dist/editor.js +121 -0
  6. package/dist/foundation/annotations/index.d.ts +2 -0
  7. package/dist/foundation/annotations/index.js +2 -0
  8. package/dist/foundation/annotations/range.d.ts +54 -0
  9. package/dist/foundation/annotations/range.js +158 -0
  10. package/dist/foundation/annotations/types.d.ts +33 -0
  11. package/dist/foundation/annotations/types.js +1 -0
  12. package/dist/foundation/atom/commands.d.ts +11 -0
  13. package/dist/foundation/atom/commands.js +118 -0
  14. package/dist/foundation/atom/composition.d.ts +8 -0
  15. package/dist/foundation/atom/composition.js +22 -0
  16. package/dist/foundation/atom/declarations.d.ts +2 -0
  17. package/dist/foundation/atom/declarations.js +17 -0
  18. package/dist/foundation/atom/formats.d.ts +21 -0
  19. package/dist/foundation/atom/formats.js +77 -0
  20. package/dist/foundation/atom/index.d.ts +10 -0
  21. package/dist/foundation/atom/index.js +10 -0
  22. package/dist/foundation/atom/lifecycle.d.ts +12 -0
  23. package/dist/foundation/atom/lifecycle.js +41 -0
  24. package/dist/foundation/atom/persistence.d.ts +3 -0
  25. package/dist/foundation/atom/persistence.js +20 -0
  26. package/dist/foundation/atom/plugin.d.ts +20 -0
  27. package/dist/foundation/atom/plugin.js +55 -0
  28. package/dist/foundation/atom/schema.d.ts +3 -0
  29. package/dist/foundation/atom/schema.js +29 -0
  30. package/dist/foundation/atom/security.d.ts +10 -0
  31. package/dist/foundation/atom/security.js +20 -0
  32. package/dist/foundation/atom/selection.d.ts +3 -0
  33. package/dist/foundation/atom/selection.js +4 -0
  34. package/dist/foundation/atom/types.d.ts +47 -0
  35. package/dist/foundation/atom/types.js +1 -0
  36. package/dist/foundation/block/commands.d.ts +17 -0
  37. package/dist/foundation/block/commands.js +197 -0
  38. package/dist/foundation/block/formats.d.ts +33 -0
  39. package/dist/foundation/block/formats.js +57 -0
  40. package/dist/foundation/block/index.d.ts +5 -0
  41. package/dist/foundation/block/index.js +5 -0
  42. package/dist/foundation/block/input.d.ts +19 -0
  43. package/dist/foundation/block/input.js +67 -0
  44. package/dist/foundation/block/plugin.d.ts +26 -0
  45. package/dist/foundation/block/plugin.js +79 -0
  46. package/dist/foundation/block/schema.d.ts +49 -0
  47. package/dist/foundation/block/schema.js +27 -0
  48. package/dist/foundation/block/types.d.ts +40 -0
  49. package/dist/foundation/block/types.js +1 -0
  50. package/dist/foundation/boundaries.d.ts +11 -0
  51. package/dist/foundation/boundaries.js +117 -0
  52. package/dist/foundation/clipboard/detection.d.ts +3 -0
  53. package/dist/foundation/clipboard/detection.js +29 -0
  54. package/dist/foundation/clipboard/diagnostics.d.ts +24 -0
  55. package/dist/foundation/clipboard/diagnostics.js +59 -0
  56. package/dist/foundation/clipboard/index.d.ts +8 -0
  57. package/dist/foundation/clipboard/index.js +8 -0
  58. package/dist/foundation/clipboard/insertion.d.ts +22 -0
  59. package/dist/foundation/clipboard/insertion.js +210 -0
  60. package/dist/foundation/clipboard/normalizers.d.ts +8 -0
  61. package/dist/foundation/clipboard/normalizers.js +229 -0
  62. package/dist/foundation/clipboard/pipeline.d.ts +13 -0
  63. package/dist/foundation/clipboard/pipeline.js +58 -0
  64. package/dist/foundation/clipboard/sanitizer.d.ts +3 -0
  65. package/dist/foundation/clipboard/sanitizer.js +58 -0
  66. package/dist/foundation/clipboard/serialization.d.ts +5 -0
  67. package/dist/foundation/clipboard/serialization.js +33 -0
  68. package/dist/foundation/clipboard/transfer.d.ts +11 -0
  69. package/dist/foundation/clipboard/transfer.js +108 -0
  70. package/dist/foundation/clipboard/types.d.ts +65 -0
  71. package/dist/foundation/clipboard/types.js +1 -0
  72. package/dist/foundation/collab/index.d.ts +3 -0
  73. package/dist/foundation/collab/index.js +3 -0
  74. package/dist/foundation/collab/rebase.d.ts +28 -0
  75. package/dist/foundation/collab/rebase.js +82 -0
  76. package/dist/foundation/collab/transform.d.ts +73 -0
  77. package/dist/foundation/collab/transform.js +251 -0
  78. package/dist/foundation/collab/types.d.ts +52 -0
  79. package/dist/foundation/collab/types.js +1 -0
  80. package/dist/foundation/comments/fromSelection.d.ts +16 -0
  81. package/dist/foundation/comments/fromSelection.js +24 -0
  82. package/dist/foundation/comments/index.d.ts +3 -0
  83. package/dist/foundation/comments/index.js +3 -0
  84. package/dist/foundation/comments/rebase.d.ts +31 -0
  85. package/dist/foundation/comments/rebase.js +43 -0
  86. package/dist/foundation/comments/types.d.ts +37 -0
  87. package/dist/foundation/comments/types.js +1 -0
  88. package/dist/foundation/diff/documentDiff.d.ts +12 -0
  89. package/dist/foundation/diff/documentDiff.js +148 -0
  90. package/dist/foundation/diff/index.d.ts +3 -0
  91. package/dist/foundation/diff/index.js +3 -0
  92. package/dist/foundation/diff/textDiff.d.ts +12 -0
  93. package/dist/foundation/diff/textDiff.js +114 -0
  94. package/dist/foundation/diff/types.d.ts +74 -0
  95. package/dist/foundation/diff/types.js +1 -0
  96. package/dist/foundation/editor.d.ts +138 -0
  97. package/dist/foundation/editor.js +398 -0
  98. package/dist/foundation/formats/codec.d.ts +45 -0
  99. package/dist/foundation/formats/codec.js +1 -0
  100. package/dist/foundation/formats/docx/export.d.ts +4 -0
  101. package/dist/foundation/formats/docx/export.js +285 -0
  102. package/dist/foundation/formats/docx/import.d.ts +9 -0
  103. package/dist/foundation/formats/docx/import.js +37 -0
  104. package/dist/foundation/formats/docx/nestingGuard.d.ts +40 -0
  105. package/dist/foundation/formats/docx/nestingGuard.js +66 -0
  106. package/dist/foundation/formats/docx/portableAtoms.d.ts +4 -0
  107. package/dist/foundation/formats/docx/portableAtoms.js +66 -0
  108. package/dist/foundation/formats/docx/styledImport.d.ts +10 -0
  109. package/dist/foundation/formats/docx/styledImport.js +205 -0
  110. package/dist/foundation/formats/featureCodecs.d.ts +37 -0
  111. package/dist/foundation/formats/featureCodecs.js +69 -0
  112. package/dist/foundation/formats/fidelity.d.ts +31 -0
  113. package/dist/foundation/formats/fidelity.js +123 -0
  114. package/dist/foundation/formats/index.d.ts +7 -0
  115. package/dist/foundation/formats/index.js +7 -0
  116. package/dist/foundation/formats/pdf/format.d.ts +29 -0
  117. package/dist/foundation/formats/pdf/format.js +190 -0
  118. package/dist/foundation/history.d.ts +20 -0
  119. package/dist/foundation/history.js +121 -0
  120. package/dist/foundation/identity.d.ts +8 -0
  121. package/dist/foundation/identity.js +30 -0
  122. package/dist/foundation/index.d.ts +30 -0
  123. package/dist/foundation/index.js +30 -0
  124. package/dist/foundation/list/commands.d.ts +28 -0
  125. package/dist/foundation/list/commands.js +422 -0
  126. package/dist/foundation/list/formats.d.ts +20 -0
  127. package/dist/foundation/list/formats.js +795 -0
  128. package/dist/foundation/list/index.d.ts +8 -0
  129. package/dist/foundation/list/index.js +8 -0
  130. package/dist/foundation/list/input.d.ts +35 -0
  131. package/dist/foundation/list/input.js +320 -0
  132. package/dist/foundation/list/plugin.d.ts +21 -0
  133. package/dist/foundation/list/plugin.js +71 -0
  134. package/dist/foundation/list/presets.d.ts +16 -0
  135. package/dist/foundation/list/presets.js +21 -0
  136. package/dist/foundation/list/schema.d.ts +35 -0
  137. package/dist/foundation/list/schema.js +29 -0
  138. package/dist/foundation/list/shadow.d.ts +54 -0
  139. package/dist/foundation/list/shadow.js +75 -0
  140. package/dist/foundation/list/shadowCorpus.d.ts +10 -0
  141. package/dist/foundation/list/shadowCorpus.js +41 -0
  142. package/dist/foundation/list/types.d.ts +50 -0
  143. package/dist/foundation/list/types.js +1 -0
  144. package/dist/foundation/mapping.d.ts +11 -0
  145. package/dist/foundation/mapping.js +40 -0
  146. package/dist/foundation/marks/canonical.d.ts +9 -0
  147. package/dist/foundation/marks/canonical.js +72 -0
  148. package/dist/foundation/marks/commands.d.ts +21 -0
  149. package/dist/foundation/marks/commands.js +136 -0
  150. package/dist/foundation/marks/dom.d.ts +2 -0
  151. package/dist/foundation/marks/dom.js +46 -0
  152. package/dist/foundation/marks/editor.d.ts +8 -0
  153. package/dist/foundation/marks/editor.js +50 -0
  154. package/dist/foundation/marks/formats.d.ts +37 -0
  155. package/dist/foundation/marks/formats.js +49 -0
  156. package/dist/foundation/marks/hardBreak.d.ts +8 -0
  157. package/dist/foundation/marks/hardBreak.js +80 -0
  158. package/dist/foundation/marks/index.d.ts +11 -0
  159. package/dist/foundation/marks/index.js +11 -0
  160. package/dist/foundation/marks/normalization.d.ts +2 -0
  161. package/dist/foundation/marks/normalization.js +49 -0
  162. package/dist/foundation/marks/plugin.d.ts +14 -0
  163. package/dist/foundation/marks/plugin.js +63 -0
  164. package/dist/foundation/marks/resolveMarkRun.d.ts +8 -0
  165. package/dist/foundation/marks/resolveMarkRun.js +47 -0
  166. package/dist/foundation/marks/schema.d.ts +167 -0
  167. package/dist/foundation/marks/schema.js +50 -0
  168. package/dist/foundation/marks/stored.d.ts +2 -0
  169. package/dist/foundation/marks/stored.js +31 -0
  170. package/dist/foundation/marks/types.d.ts +40 -0
  171. package/dist/foundation/marks/types.js +1 -0
  172. package/dist/foundation/modelDom.d.ts +38 -0
  173. package/dist/foundation/modelDom.js +327 -0
  174. package/dist/foundation/normalization.d.ts +22 -0
  175. package/dist/foundation/normalization.js +132 -0
  176. package/dist/foundation/operations.d.ts +28 -0
  177. package/dist/foundation/operations.js +568 -0
  178. package/dist/foundation/plugin/builtins.d.ts +10 -0
  179. package/dist/foundation/plugin/builtins.js +27 -0
  180. package/dist/foundation/plugin/dispatch.d.ts +33 -0
  181. package/dist/foundation/plugin/dispatch.js +34 -0
  182. package/dist/foundation/plugin/index.d.ts +4 -0
  183. package/dist/foundation/plugin/index.js +4 -0
  184. package/dist/foundation/plugin/registry.d.ts +36 -0
  185. package/dist/foundation/plugin/registry.js +115 -0
  186. package/dist/foundation/plugin/types.d.ts +141 -0
  187. package/dist/foundation/plugin/types.js +13 -0
  188. package/dist/foundation/positions.d.ts +20 -0
  189. package/dist/foundation/positions.js +121 -0
  190. package/dist/foundation/schema.d.ts +57 -0
  191. package/dist/foundation/schema.js +371 -0
  192. package/dist/foundation/schemaBuilder.d.ts +41 -0
  193. package/dist/foundation/schemaBuilder.js +96 -0
  194. package/dist/foundation/scope/index.d.ts +2 -0
  195. package/dist/foundation/scope/index.js +2 -0
  196. package/dist/foundation/scope/resolveScope.d.ts +13 -0
  197. package/dist/foundation/scope/resolveScope.js +860 -0
  198. package/dist/foundation/scope/types.d.ts +122 -0
  199. package/dist/foundation/scope/types.js +1 -0
  200. package/dist/foundation/security/urlPolicy.d.ts +21 -0
  201. package/dist/foundation/security/urlPolicy.js +75 -0
  202. package/dist/foundation/structural/contentTarget.d.ts +21 -0
  203. package/dist/foundation/structural/contentTarget.js +51 -0
  204. package/dist/foundation/structural/index.d.ts +2 -0
  205. package/dist/foundation/structural/index.js +2 -0
  206. package/dist/foundation/structural/move.d.ts +7 -0
  207. package/dist/foundation/structural/move.js +35 -0
  208. package/dist/foundation/suggestions/index.d.ts +3 -0
  209. package/dist/foundation/suggestions/index.js +3 -0
  210. package/dist/foundation/suggestions/inline.d.ts +64 -0
  211. package/dist/foundation/suggestions/inline.js +116 -0
  212. package/dist/foundation/suggestions/structural.d.ts +40 -0
  213. package/dist/foundation/suggestions/structural.js +47 -0
  214. package/dist/foundation/suggestions/types.d.ts +19 -0
  215. package/dist/foundation/suggestions/types.js +1 -0
  216. package/dist/foundation/surface/index.d.ts +3 -0
  217. package/dist/foundation/surface/index.js +3 -0
  218. package/dist/foundation/surface/input.d.ts +127 -0
  219. package/dist/foundation/surface/input.js +1761 -0
  220. package/dist/foundation/surface/renderer.d.ts +84 -0
  221. package/dist/foundation/surface/renderer.js +974 -0
  222. package/dist/foundation/surface/types.d.ts +48 -0
  223. package/dist/foundation/surface/types.js +1 -0
  224. package/dist/foundation/table/commands.d.ts +31 -0
  225. package/dist/foundation/table/commands.js +470 -0
  226. package/dist/foundation/table/formats.d.ts +26 -0
  227. package/dist/foundation/table/formats.js +40 -0
  228. package/dist/foundation/table/grid.d.ts +8 -0
  229. package/dist/foundation/table/grid.js +178 -0
  230. package/dist/foundation/table/index.d.ts +6 -0
  231. package/dist/foundation/table/index.js +6 -0
  232. package/dist/foundation/table/plugin.d.ts +23 -0
  233. package/dist/foundation/table/plugin.js +119 -0
  234. package/dist/foundation/table/schema.d.ts +2 -0
  235. package/dist/foundation/table/schema.js +38 -0
  236. package/dist/foundation/table/selection.d.ts +7 -0
  237. package/dist/foundation/table/selection.js +35 -0
  238. package/dist/foundation/table/types.d.ts +109 -0
  239. package/dist/foundation/table/types.js +1 -0
  240. package/dist/foundation/transactions.d.ts +41 -0
  241. package/dist/foundation/transactions.js +90 -0
  242. package/dist/foundation/types.d.ts +261 -0
  243. package/dist/foundation/types.js +1 -0
  244. package/dist/foundation/versioning/diffVersions.d.ts +5 -0
  245. package/dist/foundation/versioning/diffVersions.js +3 -0
  246. package/dist/foundation/versioning/index.d.ts +2 -0
  247. package/dist/foundation/versioning/index.js +2 -0
  248. package/dist/foundation/versioning/types.d.ts +17 -0
  249. package/dist/foundation/versioning/types.js +1 -0
  250. package/dist/history.d.ts +20 -0
  251. package/dist/history.js +165 -0
  252. package/dist/html/compatibility.js +7 -1
  253. package/dist/index.d.ts +1 -14
  254. package/dist/index.js +9 -14
  255. package/dist/legacy/index.d.ts +45 -0
  256. package/dist/legacy/index.js +45 -0
  257. package/dist/legacyCommands/alignment.d.ts +20 -0
  258. package/dist/{commands → legacyCommands}/alignment.js +17 -0
  259. package/dist/legacyCommands/blocks.d.ts +14 -0
  260. package/dist/legacyCommands/blocks.js +105 -0
  261. package/dist/legacyCommands/checklist.d.ts +11 -0
  262. package/dist/legacyCommands/checklist.js +45 -0
  263. package/dist/legacyCommands/code.d.ts +15 -0
  264. package/dist/{commands → legacyCommands}/code.js +25 -1
  265. package/dist/legacyCommands/formula.d.ts +7 -0
  266. package/dist/legacyCommands/formula.js +67 -0
  267. package/dist/legacyCommands/inlineAtoms.d.ts +7 -0
  268. package/dist/legacyCommands/inlineAtoms.js +58 -0
  269. package/dist/legacyCommands/list.d.ts +38 -0
  270. package/dist/legacyCommands/list.js +477 -0
  271. package/dist/{commands → legacyCommands}/marks.d.ts +3 -0
  272. package/dist/{commands → legacyCommands}/marks.js +45 -11
  273. package/dist/legacyCommands/media.d.ts +31 -0
  274. package/dist/legacyCommands/media.js +205 -0
  275. package/dist/legacyCommands/move.d.ts +14 -0
  276. package/dist/legacyCommands/move.js +91 -0
  277. package/dist/legacyCommands/table.d.ts +91 -0
  278. package/dist/legacyCommands/table.js +547 -0
  279. package/dist/listPresets.d.ts +12 -0
  280. package/dist/listPresets.js +6 -0
  281. package/dist/listScope.d.ts +27 -0
  282. package/dist/listScope.js +104 -0
  283. package/dist/markdown/compatibility.d.ts +2 -0
  284. package/dist/markdown/compatibility.js +94 -2
  285. package/dist/marks.d.ts +5 -5
  286. package/dist/model.d.ts +65 -9
  287. package/dist/plugin.d.ts +15 -0
  288. package/dist/plugin.js +31 -0
  289. package/dist/plugins/alignment.d.ts +3 -0
  290. package/dist/plugins/alignment.js +6 -0
  291. package/dist/plugins/basicFormatting.d.ts +9 -0
  292. package/dist/plugins/basicFormatting.js +24 -0
  293. package/dist/plugins/blockType.d.ts +3 -0
  294. package/dist/plugins/blockType.js +6 -0
  295. package/dist/plugins/blockquote.d.ts +3 -0
  296. package/dist/plugins/blockquote.js +6 -0
  297. package/dist/plugins/checklist.d.ts +3 -0
  298. package/dist/plugins/checklist.js +10 -0
  299. package/dist/plugins/codeBlock.d.ts +3 -0
  300. package/dist/plugins/codeBlock.js +6 -0
  301. package/dist/plugins/formula.d.ts +3 -0
  302. package/dist/plugins/formula.js +9 -0
  303. package/dist/plugins/list.d.ts +3 -0
  304. package/dist/plugins/list.js +10 -0
  305. package/dist/plugins/media.d.ts +3 -0
  306. package/dist/plugins/media.js +12 -0
  307. package/dist/plugins/move.d.ts +3 -0
  308. package/dist/plugins/move.js +9 -0
  309. package/dist/plugins/table.d.ts +3 -0
  310. package/dist/plugins/table.js +22 -0
  311. package/dist/preset.d.ts +12 -0
  312. package/dist/preset.js +40 -0
  313. package/dist/schema.d.ts +22 -0
  314. package/dist/schema.js +333 -0
  315. package/dist/security/urlPolicy.d.ts +1 -17
  316. package/dist/security/urlPolicy.js +3 -69
  317. package/dist/selection.d.ts +1 -1
  318. package/dist/selectionMapping.d.ts +4 -0
  319. package/dist/selectionMapping.js +222 -0
  320. package/dist/table.d.ts +3 -3
  321. package/dist/transaction.d.ts +35 -12
  322. package/dist/transaction.js +174 -28
  323. package/dist/tree.d.ts +8 -2
  324. package/dist/tree.js +44 -0
  325. package/package.json +27 -8
  326. package/dist/commands/alignment.d.ts +0 -18
  327. package/dist/commands/code.d.ts +0 -13
  328. package/dist/commands/list.d.ts +0 -20
  329. package/dist/commands/list.js +0 -52
@@ -0,0 +1,205 @@
1
+ import JSZip from "jszip";
2
+ import { DOMParser } from "@xmldom/xmldom";
3
+ import { parseFragment, serialize } from "parse5";
4
+ import { parseCanonicalListHtml, serializeCanonicalListHtml } from "../../list/formats.js";
5
+ import { importDocxDocumentWithMammoth } from "./import.js";
6
+ import { restorePortableDocxAtoms } from "./portableAtoms.js";
7
+ const ELEMENT_NODE = 1;
8
+ const isElement = (node) => node.nodeType === ELEMENT_NODE;
9
+ const directChildren = (node) => Array.from(node.childNodes || []).filter(isElement);
10
+ const firstChildByName = (node, localName) => node ? directChildren(node).find((child) => child.localName === localName) : undefined;
11
+ const childrenByName = (node, localName) => node ? directChildren(node).filter((child) => child.localName === localName) : [];
12
+ const docxAttr = (node, name) => {
13
+ if (!node)
14
+ return "";
15
+ return node.getAttribute(`w:${name}`)
16
+ || node.getAttribute(name)
17
+ || node.getAttributeNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", name)
18
+ || "";
19
+ };
20
+ const escapeHtml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
21
+ const docxHexColor = (value) => {
22
+ if (!value || value.toLowerCase() === "auto")
23
+ return "";
24
+ const normalized = value.replace(/[^0-9a-f]/gi, "");
25
+ return normalized.length === 6 ? `#${normalized}` : "";
26
+ };
27
+ const twipsToPt = (value) => {
28
+ if (!value)
29
+ return "";
30
+ const numeric = Number(value);
31
+ return Number.isFinite(numeric) ? `${Math.max(numeric / 20, 0)}pt` : "";
32
+ };
33
+ const halfPointsToPt = (value) => {
34
+ if (!value)
35
+ return "";
36
+ const numeric = Number(value);
37
+ return Number.isFinite(numeric) ? `${Math.max(numeric / 2, 1)}pt` : "";
38
+ };
39
+ const cssRules = (rules) => rules.filter(([, value]) => Boolean(value)).map(([name, value]) => `${name}: ${value}`).join("; ");
40
+ const styleAttr = (style) => style ? ` style="${escapeHtml(style)}"` : "";
41
+ const borderCss = (border) => {
42
+ if (!border)
43
+ return "";
44
+ const value = docxAttr(border, "val");
45
+ if (!value || value === "nil" || value === "none")
46
+ return "";
47
+ const size = Number(docxAttr(border, "sz")) || 4;
48
+ const color = docxHexColor(docxAttr(border, "color")) || "#d1d5db";
49
+ return `${Math.max(size / 8, 0.5)}px solid ${color}`;
50
+ };
51
+ const paragraphStyle = (paragraph) => {
52
+ const properties = firstChildByName(paragraph, "pPr");
53
+ if (!properties)
54
+ return "";
55
+ const spacing = firstChildByName(properties, "spacing");
56
+ const justification = firstChildByName(properties, "jc");
57
+ const indent = firstChildByName(properties, "ind");
58
+ const bottomBorder = firstChildByName(firstChildByName(properties, "pBdr"), "bottom");
59
+ const line = docxAttr(spacing, "line");
60
+ return cssRules([
61
+ ["text-align", docxAttr(justification, "val")],
62
+ ["margin-top", twipsToPt(docxAttr(spacing, "before"))],
63
+ ["margin-bottom", twipsToPt(docxAttr(spacing, "after"))],
64
+ ["margin-left", twipsToPt(docxAttr(indent, "left"))],
65
+ ["text-indent", twipsToPt(docxAttr(indent, "firstLine"))],
66
+ ["line-height", line && docxAttr(spacing, "lineRule") === "auto" ? `${Number(line) / 240}` : ""],
67
+ ["border-bottom", borderCss(bottomBorder)],
68
+ ]);
69
+ };
70
+ const runStyle = (run) => {
71
+ const properties = firstChildByName(run, "rPr");
72
+ if (!properties)
73
+ return "";
74
+ const color = docxHexColor(docxAttr(firstChildByName(properties, "color"), "val"));
75
+ const highlight = docxHexColor(docxAttr(firstChildByName(properties, "highlight"), "val"));
76
+ const shade = docxHexColor(docxAttr(firstChildByName(properties, "shd"), "fill"));
77
+ return cssRules([
78
+ ["font-weight", firstChildByName(properties, "b") ? "700" : ""],
79
+ ["font-style", firstChildByName(properties, "i") ? "italic" : ""],
80
+ ["text-decoration", firstChildByName(properties, "u") ? "underline" : ""],
81
+ ["color", color],
82
+ ["background-color", highlight || shade],
83
+ ["font-size", halfPointsToPt(docxAttr(firstChildByName(properties, "sz"), "val"))],
84
+ ]);
85
+ };
86
+ const runHtml = (run) => {
87
+ const properties = firstChildByName(run, "rPr");
88
+ const verticalAlignment = docxAttr(firstChildByName(properties, "vertAlign"), "val");
89
+ const content = directChildren(run).map((child) => {
90
+ if (child.localName === "t")
91
+ return escapeHtml(child.textContent || "");
92
+ if (child.localName === "tab")
93
+ return "&emsp;";
94
+ if (child.localName === "br")
95
+ return docxAttr(child, "type") === "page" ? '<hr class="srte-docx-page-break">' : "<br>";
96
+ return "";
97
+ }).join("");
98
+ if (!content)
99
+ return "";
100
+ const tag = verticalAlignment === "superscript" ? "sup" : verticalAlignment === "subscript" ? "sub" : "span";
101
+ return `<${tag}${styleAttr(runStyle(run))}>${content}</${tag}>`;
102
+ };
103
+ const paragraphHtml = (paragraph) => {
104
+ const content = childrenByName(paragraph, "r").map(runHtml).join("");
105
+ return `<p${styleAttr(paragraphStyle(paragraph))}>${content || "<br>"}</p>`;
106
+ };
107
+ const cellStyle = (cell) => {
108
+ const properties = firstChildByName(cell, "tcPr");
109
+ const borders = firstChildByName(properties, "tcBorders");
110
+ return cssRules([
111
+ ["width", twipsToPt(docxAttr(firstChildByName(properties, "tcW"), "w"))],
112
+ ["background-color", docxHexColor(docxAttr(firstChildByName(properties, "shd"), "fill"))],
113
+ ["border-top", borderCss(firstChildByName(borders, "top"))],
114
+ ["border-right", borderCss(firstChildByName(borders, "right"))],
115
+ ["border-bottom", borderCss(firstChildByName(borders, "bottom"))],
116
+ ["border-left", borderCss(firstChildByName(borders, "left"))],
117
+ ["padding", "8px"],
118
+ ["vertical-align", "top"],
119
+ ]);
120
+ };
121
+ const tableHtml = (table) => {
122
+ const rows = childrenByName(table, "tr").map((row) => {
123
+ const cells = childrenByName(row, "tc").map((cell) => {
124
+ const content = directChildren(cell)
125
+ .filter((child) => child.localName === "p" || child.localName === "tbl")
126
+ .map((child) => child.localName === "p" ? paragraphHtml(child) : tableHtml(child))
127
+ .join("");
128
+ return `<td${styleAttr(cellStyle(cell))}>${content || "<p><br></p>"}</td>`;
129
+ }).join("");
130
+ return `<tr>${cells}</tr>`;
131
+ }).join("");
132
+ return `<table style="border-collapse: collapse; width: 100%; margin: 12px 0;"><tbody>${rows}</tbody></table>`;
133
+ };
134
+ const styleDeclarations = (attrs) => Object.fromEntries((attrs.find((attr) => attr.name === "style")?.value || "").split(";")
135
+ .map((rule) => rule.split(":").map((part) => part.trim()))
136
+ .filter(([property]) => property));
137
+ /** Defensive baseline styling for any table missing explicit inline styles (e.g. the mammoth fallback path, which produces plain semantic HTML with no inline CSS at all). */
138
+ export const enhanceDocxTables = (html) => {
139
+ const visit = (node) => {
140
+ if (!node.childNodes)
141
+ return node;
142
+ const childNodes = node.childNodes.map((child) => {
143
+ if (child.tagName !== "table" && child.tagName !== "td" && child.tagName !== "th")
144
+ return visit(child);
145
+ const attrs = [...(child.attrs || [])];
146
+ const styleIndex = attrs.findIndex((attr) => attr.name === "style");
147
+ const declarations = styleDeclarations(attrs);
148
+ if (child.tagName === "table") {
149
+ declarations["border-collapse"] || (declarations["border-collapse"] = "collapse");
150
+ declarations.width || (declarations.width = "100%");
151
+ }
152
+ else {
153
+ const hasBorder = ["border", "border-top", "border-right", "border-bottom", "border-left"].some((key) => declarations[key]);
154
+ if (!hasBorder)
155
+ declarations.border = "1px solid #d1d5db";
156
+ declarations.padding || (declarations.padding = "8px");
157
+ declarations["vertical-align"] || (declarations["vertical-align"] = "top");
158
+ }
159
+ const style = Object.entries(declarations).map(([property, value]) => `${property}: ${value}`).join("; ");
160
+ const next = { name: "style", value: style };
161
+ if (styleIndex >= 0)
162
+ attrs[styleIndex] = next;
163
+ else
164
+ attrs.push(next);
165
+ return { ...visit(child), attrs };
166
+ });
167
+ return { ...node, childNodes };
168
+ };
169
+ const fragment = visit(parseFragment(html));
170
+ return serialize(fragment);
171
+ };
172
+ const mammothFallback = async (arrayBuffer) => {
173
+ const document = await importDocxDocumentWithMammoth(arrayBuffer);
174
+ const layoutHtml = enhanceDocxTables(serializeCanonicalListHtml(document, { clean: true }));
175
+ return { document, layoutHtml, source: "mammoth" };
176
+ };
177
+ /** Fidelity: `semantic` for structure, richer visual reproduction than plain mammoth import via inline CSS reconstructed from raw wordprocessingml formatting XML, with graceful fallback to mammoth if that XML is missing or malformed. */
178
+ export const importStyledDocxDocument = async (arrayBuffer) => {
179
+ try {
180
+ const zip = await JSZip.loadAsync(arrayBuffer);
181
+ const documentXml = await zip.file("word/document.xml")?.async("text");
182
+ if (!documentXml)
183
+ return mammothFallback(arrayBuffer);
184
+ const parsed = new DOMParser().parseFromString(documentXml, "text/xml");
185
+ if (!parsed || parsed.getElementsByTagName("parsererror").length)
186
+ return mammothFallback(arrayBuffer);
187
+ const body = Array.from(parsed.getElementsByTagName("*")).find((node) => node.localName === "body");
188
+ if (!body)
189
+ return mammothFallback(arrayBuffer);
190
+ const rawHtml = directChildren(body).filter((node) => node.localName !== "sectPr").map((node) => {
191
+ if (node.localName === "p")
192
+ return paragraphHtml(node);
193
+ if (node.localName === "tbl")
194
+ return tableHtml(node);
195
+ return "";
196
+ }).join("");
197
+ if (!rawHtml.trim())
198
+ return mammothFallback(arrayBuffer);
199
+ const layoutHtml = enhanceDocxTables(restorePortableDocxAtoms(rawHtml));
200
+ return { document: parseCanonicalListHtml(layoutHtml), layoutHtml, source: "wordprocessingml" };
201
+ }
202
+ catch {
203
+ return mammothFallback(arrayBuffer);
204
+ }
205
+ };
@@ -0,0 +1,37 @@
1
+ import type { FeatureFormatCodec } from "./codec.js";
2
+ import { type FidelityFeature } from "./fidelity.js";
3
+ /**
4
+ * The 44 (feature x format) FeatureFormatCodec declarations Phase 9 SS3
5
+ * gate 3 requires. feature/format/fidelity/note are mechanically derived
6
+ * from builtInFormatFidelity (fidelity.ts) - that table is the single
7
+ * source of truth for fidelity claims; this file must never restate a
8
+ * level or note independently of it.
9
+ *
10
+ * parse/serialize are only attached where a genuine single-node function
11
+ * already exists, never a fabricated per-node wrapper around whole-document
12
+ * logic:
13
+ * - atom/formats.ts's atomTo{Html,Markdown,Docx,Pdf} and atomFromHtmlElement
14
+ * operate on one SmartElementNode at a time, so images-media and formulas
15
+ * get real wiring for all four formats (Phase 9).
16
+ * - marks/formats.ts's docxProperties and block/formats.ts's blockToDocxEntry
17
+ * (Phase 11 Tier 2, per docs/PHASE_9_CODEC_REFACTOR_SCOPE.md's recommended
18
+ * marks-then-blocks order) were already genuinely single-node - or, for
19
+ * blocks, extracted from canonicalBlocksToDocx's per-node visit() body
20
+ * with canonicalBlocksToDocx refactored to call the extracted function
21
+ * rather than duplicate it - so inline-marks/colors-fonts-sizes (marks)
22
+ * and headings-alignment/blockquote-code (block) get real DOCX wiring
23
+ * here. No parse direction exists for either (no reverse
24
+ * properties-to-marks/DocxBlock-to-node mapping was ever built), so only
25
+ * `serialize` is attached, matching the general "wire what already exists"
26
+ * rule.
27
+ *
28
+ * HTML/Markdown/PDF for marks and blocks, and every format for lists/tables,
29
+ * remain whole-document walkers (docx/export.ts, pdf/format.ts,
30
+ * list/formats.ts's HTML/Markdown serializers, table's own
31
+ * canonical*To{Docx,Pdf} functions) that resolve every feature together in
32
+ * one pass (see codec.ts's own doc comment) - per the scope doc, HTML/
33
+ * Markdown is deliberately not scheduled ("if at all"), so those cells still
34
+ * carry fidelity metadata only. Closing the rest is tracked in
35
+ * docs/PHASE_9_EXIT_GATES.md's gate 3 entry.
36
+ */
37
+ export declare const builtInFeatureFormatCodecs: readonly FeatureFormatCodec<FidelityFeature>[];
@@ -0,0 +1,69 @@
1
+ import { atomFromHtmlElement, atomToDocx, atomToHtml, atomToMarkdown, atomToPdf } from "../atom/formats.js";
2
+ import { markRunDocxProperties } from "../marks/formats.js";
3
+ import { blockToDocxEntry } from "../block/formats.js";
4
+ import { builtInFormatFidelity } from "./fidelity.js";
5
+ const asAtom = (node) => node;
6
+ /**
7
+ * The 44 (feature x format) FeatureFormatCodec declarations Phase 9 SS3
8
+ * gate 3 requires. feature/format/fidelity/note are mechanically derived
9
+ * from builtInFormatFidelity (fidelity.ts) - that table is the single
10
+ * source of truth for fidelity claims; this file must never restate a
11
+ * level or note independently of it.
12
+ *
13
+ * parse/serialize are only attached where a genuine single-node function
14
+ * already exists, never a fabricated per-node wrapper around whole-document
15
+ * logic:
16
+ * - atom/formats.ts's atomTo{Html,Markdown,Docx,Pdf} and atomFromHtmlElement
17
+ * operate on one SmartElementNode at a time, so images-media and formulas
18
+ * get real wiring for all four formats (Phase 9).
19
+ * - marks/formats.ts's docxProperties and block/formats.ts's blockToDocxEntry
20
+ * (Phase 11 Tier 2, per docs/PHASE_9_CODEC_REFACTOR_SCOPE.md's recommended
21
+ * marks-then-blocks order) were already genuinely single-node - or, for
22
+ * blocks, extracted from canonicalBlocksToDocx's per-node visit() body
23
+ * with canonicalBlocksToDocx refactored to call the extracted function
24
+ * rather than duplicate it - so inline-marks/colors-fonts-sizes (marks)
25
+ * and headings-alignment/blockquote-code (block) get real DOCX wiring
26
+ * here. No parse direction exists for either (no reverse
27
+ * properties-to-marks/DocxBlock-to-node mapping was ever built), so only
28
+ * `serialize` is attached, matching the general "wire what already exists"
29
+ * rule.
30
+ *
31
+ * HTML/Markdown/PDF for marks and blocks, and every format for lists/tables,
32
+ * remain whole-document walkers (docx/export.ts, pdf/format.ts,
33
+ * list/formats.ts's HTML/Markdown serializers, table's own
34
+ * canonical*To{Docx,Pdf} functions) that resolve every feature together in
35
+ * one pass (see codec.ts's own doc comment) - per the scope doc, HTML/
36
+ * Markdown is deliberately not scheduled ("if at all"), so those cells still
37
+ * carry fidelity metadata only. Closing the rest is tracked in
38
+ * docs/PHASE_9_EXIT_GATES.md's gate 3 entry.
39
+ */
40
+ export const builtInFeatureFormatCodecs = builtInFormatFidelity.flatMap((contract) => ["html", "markdown", "docx", "pdf"].map((format) => {
41
+ const capability = contract.formats[format];
42
+ const base = {
43
+ feature: contract.feature,
44
+ format,
45
+ fidelity: capability.level,
46
+ note: capability.note,
47
+ };
48
+ if (contract.feature === "images-media" || contract.feature === "formulas") {
49
+ if (format === "html") {
50
+ return {
51
+ ...base,
52
+ serialize: (node) => atomToHtml(asAtom(node)),
53
+ parse: (input) => atomFromHtmlElement(input),
54
+ };
55
+ }
56
+ if (format === "markdown")
57
+ return { ...base, serialize: (node) => atomToMarkdown(asAtom(node)) };
58
+ if (format === "docx")
59
+ return { ...base, serialize: (node) => atomToDocx(asAtom(node)) };
60
+ return { ...base, serialize: (node) => atomToPdf(asAtom(node)) };
61
+ }
62
+ if (format === "docx" && (contract.feature === "inline-marks" || contract.feature === "colors-fonts-sizes")) {
63
+ return { ...base, serialize: (node) => markRunDocxProperties(node) };
64
+ }
65
+ if (format === "docx" && (contract.feature === "headings-alignment" || contract.feature === "blockquote-code")) {
66
+ return { ...base, serialize: (node) => blockToDocxEntry(asAtom(node)) };
67
+ }
68
+ return base;
69
+ }));
@@ -0,0 +1,31 @@
1
+ import type { FormatFidelityLevel, FormatId } from "./codec.js";
2
+ export type FidelityFormat = FormatId;
3
+ export type FidelityLevel = FormatFidelityLevel;
4
+ export type FidelityFeature = "inline-marks" | "colors-fonts-sizes" | "headings-alignment" | "blockquote-code" | "lists" | "checklists" | "tables" | "links" | "images-media" | "formulas" | "special-characters";
5
+ export interface FormatFidelityCapability {
6
+ level: FidelityLevel;
7
+ note: string;
8
+ }
9
+ export interface FeatureFidelityContract {
10
+ feature: FidelityFeature;
11
+ formats: Record<FidelityFormat, FormatFidelityCapability>;
12
+ }
13
+ /**
14
+ * Public, test-enforced compatibility contract for built-in document
15
+ * formats (Phase 9 SS2.2's fidelity table deliverable).
16
+ *
17
+ * Verification status as of Phase 9 SS3 gate 4 (2026-08-13): every one of
18
+ * the 44 (feature, format) cells below now has a passing round-trip fixture.
19
+ * DOCX cells: packages/core/src/foundation/formats/docx/format.test.ts.
20
+ * PDF cells: packages/core/src/foundation/formats/pdf/format.test.ts,
21
+ * atom/formats.test.ts, marks/formats.test.ts, block/formats.test.ts,
22
+ * list/formats.test.ts. HTML/Markdown cells: list/formats.test.ts,
23
+ * marks/formats.test.ts, block/formats.test.ts, table/formats.test.ts,
24
+ * atom/formats.test.ts. special-characters had zero coverage across all
25
+ * four formats until SS3's gate 4 audit found the gap; see the "Unicode
26
+ * special characters" tests added to each of those files. See also
27
+ * featureCodecs.ts, which declares the actual FeatureFormatCodec per cell
28
+ * gate 3 requires.
29
+ */
30
+ export declare const builtInFormatFidelity: readonly FeatureFidelityContract[];
31
+ export declare const getFormatFidelity: (feature: FidelityFeature, format: FidelityFormat) => FormatFidelityCapability;
@@ -0,0 +1,123 @@
1
+ const capability = (level, note) => ({
2
+ level,
3
+ note,
4
+ });
5
+ /**
6
+ * Public, test-enforced compatibility contract for built-in document
7
+ * formats (Phase 9 SS2.2's fidelity table deliverable).
8
+ *
9
+ * Verification status as of Phase 9 SS3 gate 4 (2026-08-13): every one of
10
+ * the 44 (feature, format) cells below now has a passing round-trip fixture.
11
+ * DOCX cells: packages/core/src/foundation/formats/docx/format.test.ts.
12
+ * PDF cells: packages/core/src/foundation/formats/pdf/format.test.ts,
13
+ * atom/formats.test.ts, marks/formats.test.ts, block/formats.test.ts,
14
+ * list/formats.test.ts. HTML/Markdown cells: list/formats.test.ts,
15
+ * marks/formats.test.ts, block/formats.test.ts, table/formats.test.ts,
16
+ * atom/formats.test.ts. special-characters had zero coverage across all
17
+ * four formats until SS3's gate 4 audit found the gap; see the "Unicode
18
+ * special characters" tests added to each of those files. See also
19
+ * featureCodecs.ts, which declares the actual FeatureFormatCodec per cell
20
+ * gate 3 requires.
21
+ */
22
+ export const builtInFormatFidelity = [
23
+ {
24
+ feature: "inline-marks",
25
+ formats: {
26
+ html: capability("full", "Canonical marks round-trip."),
27
+ markdown: capability("semantic", "Bold, italic, strike, code, and links round-trip; underline is lossy."),
28
+ docx: capability("semantic", "All twelve marks are written as Word run properties on export. On import, mammoth's default HTML conversion recognizes and round-trips bold/italic/code/strike/superscript/subscript/link; underline/textColor/backgroundColor/fontSize/fontFamily are not mapped back without an explicit mammoth style map - text content survives, that specific formatting does not (SS2.1: verified per-mark via a dedicated round-trip fixture, not inferred)."),
29
+ pdf: capability("lossy", "Visual emphasis is inferred from extracted font metadata."),
30
+ },
31
+ },
32
+ {
33
+ feature: "colors-fonts-sizes",
34
+ formats: {
35
+ html: capability("full", "Inline style marks round-trip."),
36
+ markdown: capability("unsupported", "Portable Markdown has no standard representation."),
37
+ docx: capability("semantic", "Colors and sizes are supported; font-family fidelity depends on importer styles."),
38
+ pdf: capability("lossy", "Font size/style are inferred; colors are extraction-dependent."),
39
+ },
40
+ },
41
+ {
42
+ feature: "headings-alignment",
43
+ formats: {
44
+ html: capability("full", "Levels, alignment, and indentation round-trip."),
45
+ markdown: capability("lossy", "Heading levels round-trip; alignment and indentation do not."),
46
+ docx: capability("semantic", "Heading styles (w:pStyle), alignment (w:jc), and indentation (w:ind) are emitted (SS2.1, re-verified)."),
47
+ pdf: capability("lossy", "Levels and alignment are inferred geometrically."),
48
+ },
49
+ },
50
+ {
51
+ feature: "blockquote-code",
52
+ formats: {
53
+ html: capability("full", "Canonical block structure round-trips."),
54
+ markdown: capability("semantic", "Portable blockquote and code syntax round-trip."),
55
+ docx: capability("lossy", "Blockquote is represented as indentation (w:ind), not a native Word quote style; code uses a character-level code mark, not a code paragraph style."),
56
+ pdf: capability("lossy", "Export is visual and import reconstruction is heuristic."),
57
+ },
58
+ },
59
+ {
60
+ feature: "lists",
61
+ formats: {
62
+ html: capability("full", "Nested list structure and styles round-trip."),
63
+ markdown: capability("semantic", "Nested ordered and unordered structure round-trips; custom markers are lossy."),
64
+ docx: capability("semantic", "Nested lists export with native Word numbering definitions (w:numId/w:ilvl) and level metadata; verified for decimal/lower-alpha/disc through 9 levels (SS2.1, re-verified)."),
65
+ pdf: capability("lossy", "List structure is inferred from extracted markers."),
66
+ },
67
+ },
68
+ {
69
+ feature: "checklists",
70
+ formats: {
71
+ html: capability("full", "Checked state uses canonical data attributes."),
72
+ markdown: capability("semantic", "GFM task-list state round-trips."),
73
+ docx: capability("lossy", "Checklist semantics degrade to plain bulleted/numbered list content - checked state is not emitted (SS2.1, re-verified: docx/export.ts's list branch does not read list.attrs.checkable or list_item.attrs.checked)."),
74
+ pdf: capability("lossy", "Checklist semantics are visual only."),
75
+ },
76
+ },
77
+ {
78
+ feature: "tables",
79
+ formats: {
80
+ html: capability("full", "Spans, headers, colors, borders, and dimensions round-trip."),
81
+ markdown: capability("lossy", "GFM tables preserve text but not spans, dimensions, colors, or borders."),
82
+ docx: capability("semantic", "Column spans (gridSpan), row spans (vMerge), header rows, cell background, and borders export via occupancyGridFor (SS2.1, re-verified); per-cell vertical alignment is not yet emitted."),
83
+ pdf: capability("lossy", "Export is visual and import uses column-position heuristics."),
84
+ },
85
+ },
86
+ {
87
+ feature: "links",
88
+ formats: {
89
+ html: capability("full", "Safe href and target semantics round-trip."),
90
+ markdown: capability("semantic", "Href and label round-trip; target metadata is lossy."),
91
+ docx: capability("semantic", "Links export as native external Word hyperlink relationships (w:hyperlink); target=_blank is preserved as w:history (SS2.1, re-verified)."),
92
+ pdf: capability("lossy", "Links are visual text in the current print/export path."),
93
+ },
94
+ },
95
+ {
96
+ feature: "images-media",
97
+ formats: {
98
+ html: capability("semantic", "Images, audio, and video round-trip; host-only metadata may be lossy."),
99
+ markdown: capability("lossy", "Inline and block images round-trip as ![alt](src) (SS2.3: fixed a real silent-data-loss bug - markdownInlineText/markdownBlock's fallback for any atom node was an empty string, deleting images with no trace; images are now routed through atomToMarkdown/parsed back via a real image AST case). Audio and video degrade to a readable [video: url](url) link on export - the link and URL survive, but re-import produces a generic link, not a video/audio atom."),
100
+ docx: capability("semantic", "Data-URL PNG/JPEG/GIF images embed as native Word media relationships; remote or unsupported sources fall back to a portable text marker recovered on import (SS2.1, re-verified). No canonical DOCX projection exists yet for video/audio (block_image only)."),
101
+ pdf: capability("lossy", "Export is visual; semantic media import is unsupported."),
102
+ },
103
+ },
104
+ {
105
+ feature: "formulas",
106
+ formats: {
107
+ html: capability("full", "Formula source is stored canonically (data-smart-formula); displayText is presentation-only and is not preserved by canonical's own HTML round-trip, in any format."),
108
+ markdown: capability("semantic", "Dollar-delimited formula source round-trips: $source$ for inline, $$\\nsource\\n$$ for block (SS2.3: fixed the same silent-data-loss bug as images-media/markdown - formulas were being deleted with no trace on export, and remark's core parser has no math extension so $...$ survived as inert literal text on import even after the export side was fixed; both are now handled via a dedicated post-parse regex split, not a library dependency)."),
109
+ docx: capability("lossy", "Formula source is written inside an <m:oMath> zone as literal LaTeX text, not translated to real OMML (no partial-OMML build, an explicit standing scope decision) - Word will show the raw LaTeX string, not typeset math. A hidden portable-marker text run carries the source for lossless round-trip back through Smart RTE specifically, independent of whether Word renders it usefully (SS2.1: this replaces a stale note that described a since-retired export path, which no longer applies)."),
110
+ pdf: capability("lossy", "Rendered output is visual; source cannot be reconstructed reliably."),
111
+ },
112
+ },
113
+ {
114
+ feature: "special-characters",
115
+ formats: {
116
+ html: capability("full", "Unicode text round-trips."),
117
+ markdown: capability("full", "Unicode text round-trips."),
118
+ docx: capability("full", "Unicode text is emitted as Word text (SS2.1, re-verified)."),
119
+ pdf: capability("semantic", "Depends on font embedding and extractor Unicode maps."),
120
+ },
121
+ },
122
+ ];
123
+ export const getFormatFidelity = (feature, format) => builtInFormatFidelity.find((entry) => entry.feature === feature).formats[format];
@@ -0,0 +1,7 @@
1
+ export * from "./docx/export.js";
2
+ export * from "./docx/import.js";
3
+ export * from "./docx/styledImport.js";
4
+ export * from "./pdf/format.js";
5
+ export * from "./codec.js";
6
+ export * from "./fidelity.js";
7
+ export * from "./featureCodecs.js";
@@ -0,0 +1,7 @@
1
+ export * from "./docx/export.js";
2
+ export * from "./docx/import.js";
3
+ export * from "./docx/styledImport.js";
4
+ export * from "./pdf/format.js";
5
+ export * from "./codec.js";
6
+ export * from "./fidelity.js";
7
+ export * from "./featureCodecs.js";
@@ -0,0 +1,29 @@
1
+ import type { SmartDocument } from "../../types.js";
2
+ export declare const PDF_MEDIA_TYPE = "application/pdf";
3
+ export interface PdfTextItemSnapshot {
4
+ text: string;
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ fontFamily?: string;
10
+ }
11
+ export interface PdfPageSnapshot {
12
+ width: number;
13
+ items: readonly PdfTextItemSnapshot[];
14
+ }
15
+ export interface PdfImportResult {
16
+ document: SmartDocument;
17
+ layoutHtml: string;
18
+ pages: number;
19
+ }
20
+ /**
21
+ * Fidelity: `lossy` for everything - PDF has no structural document model to
22
+ * recover, only positioned text runs. This is a best-effort layout
23
+ * reconstruction (lines -> paragraphs/headings/lists/tables via position
24
+ * heuristics), not a round-trip format. Matches the standing scope decision
25
+ * since Phase 1.
26
+ */
27
+ export declare const reconstructPdfPages: (pages: readonly PdfPageSnapshot[]) => PdfImportResult;
28
+ export declare const importPdfDocument: (arrayBuffer: ArrayBuffer) => Promise<PdfImportResult>;
29
+ export declare const buildPdfPrintDocument: (document: SmartDocument) => string;