@fiduswriter/document 0.1.0-alpha.3 → 0.1.0-alpha.5

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 (582) hide show
  1. package/README.md +22 -1
  2. package/dist/bibliography/common.d.ts +10 -0
  3. package/dist/bibliography/common.d.ts.map +1 -0
  4. package/dist/bibliography/common.js +86 -0
  5. package/dist/bibliography/common.js.map +1 -0
  6. package/dist/bibliography/csl_bib.d.ts +3 -0
  7. package/dist/bibliography/csl_bib.d.ts.map +1 -0
  8. package/dist/bibliography/csl_bib.js +131 -0
  9. package/dist/bibliography/csl_bib.js.map +1 -0
  10. package/dist/citations/citeproc_sys.d.ts +12 -0
  11. package/dist/citations/citeproc_sys.d.ts.map +1 -0
  12. package/dist/citations/citeproc_sys.js +48 -0
  13. package/dist/citations/citeproc_sys.js.map +1 -0
  14. package/dist/citations/format.d.ts +40 -0
  15. package/dist/citations/format.d.ts.map +1 -0
  16. package/dist/citations/format.js +186 -0
  17. package/dist/citations/format.js.map +1 -0
  18. package/dist/editor/e2ee/encryptor.d.ts +123 -0
  19. package/dist/editor/e2ee/encryptor.d.ts.map +1 -0
  20. package/dist/editor/e2ee/encryptor.js +201 -0
  21. package/dist/editor/e2ee/encryptor.js.map +1 -0
  22. package/dist/exporter/docx/citations.d.ts +31 -0
  23. package/dist/exporter/docx/citations.d.ts.map +1 -0
  24. package/dist/exporter/docx/citations.js +171 -0
  25. package/dist/exporter/docx/citations.js.map +1 -0
  26. package/dist/exporter/docx/comments.d.ts +22 -0
  27. package/dist/exporter/docx/comments.d.ts.map +1 -0
  28. package/dist/exporter/docx/comments.js +170 -0
  29. package/dist/exporter/docx/comments.js.map +1 -0
  30. package/dist/exporter/docx/footnotes.d.ts +47 -0
  31. package/dist/exporter/docx/footnotes.d.ts.map +1 -0
  32. package/dist/exporter/docx/footnotes.js +216 -0
  33. package/dist/exporter/docx/footnotes.js.map +1 -0
  34. package/dist/exporter/docx/images.d.ts +25 -0
  35. package/dist/exporter/docx/images.d.ts.map +1 -0
  36. package/dist/exporter/docx/images.js +101 -0
  37. package/dist/exporter/docx/images.js.map +1 -0
  38. package/dist/exporter/docx/index.d.ts +16 -0
  39. package/dist/exporter/docx/index.d.ts.map +1 -0
  40. package/dist/exporter/docx/index.js +115 -0
  41. package/dist/exporter/docx/index.js.map +1 -0
  42. package/dist/exporter/docx/lists.d.ts +38 -0
  43. package/dist/exporter/docx/lists.d.ts.map +1 -0
  44. package/dist/exporter/docx/lists.js +276 -0
  45. package/dist/exporter/docx/lists.js.map +1 -0
  46. package/dist/exporter/docx/math.d.ts +13 -0
  47. package/dist/exporter/docx/math.d.ts.map +1 -0
  48. package/dist/exporter/docx/math.js +59 -0
  49. package/dist/exporter/docx/math.js.map +1 -0
  50. package/dist/exporter/docx/metadata.d.ts +17 -0
  51. package/dist/exporter/docx/metadata.d.ts.map +1 -0
  52. package/dist/exporter/docx/metadata.js +272 -0
  53. package/dist/exporter/docx/metadata.js.map +1 -0
  54. package/dist/exporter/docx/rels.d.ts +27 -0
  55. package/dist/exporter/docx/rels.d.ts.map +1 -0
  56. package/dist/exporter/docx/rels.js +183 -0
  57. package/dist/exporter/docx/rels.js.map +1 -0
  58. package/dist/exporter/docx/render.d.ts +22 -0
  59. package/dist/exporter/docx/render.d.ts.map +1 -0
  60. package/dist/exporter/docx/render.js +780 -0
  61. package/dist/exporter/docx/render.js.map +1 -0
  62. package/dist/exporter/docx/richtext.d.ts +25 -0
  63. package/dist/exporter/docx/richtext.d.ts.map +1 -0
  64. package/dist/exporter/docx/richtext.js +1070 -0
  65. package/dist/exporter/docx/richtext.js.map +1 -0
  66. package/dist/exporter/docx/tables.d.ts +16 -0
  67. package/dist/exporter/docx/tables.d.ts.map +1 -0
  68. package/dist/exporter/docx/tables.js +115 -0
  69. package/dist/exporter/docx/tables.js.map +1 -0
  70. package/dist/exporter/docx/tools.d.ts +4 -0
  71. package/dist/exporter/docx/tools.d.ts.map +1 -0
  72. package/dist/exporter/docx/tools.js +48 -0
  73. package/dist/exporter/docx/tools.js.map +1 -0
  74. package/dist/exporter/epub/index.d.ts +19 -0
  75. package/dist/exporter/epub/index.d.ts.map +1 -0
  76. package/dist/exporter/epub/index.js +109 -0
  77. package/dist/exporter/epub/index.js.map +1 -0
  78. package/dist/exporter/epub/templates.d.ts +63 -0
  79. package/dist/exporter/epub/templates.d.ts.map +1 -0
  80. package/dist/exporter/epub/templates.js +95 -0
  81. package/dist/exporter/epub/templates.js.map +1 -0
  82. package/dist/exporter/epub/tools.d.ts +13 -0
  83. package/dist/exporter/epub/tools.d.ts.map +1 -0
  84. package/{src → dist}/exporter/epub/tools.js +32 -46
  85. package/dist/exporter/epub/tools.js.map +1 -0
  86. package/dist/exporter/html/citations.d.ts +29 -0
  87. package/dist/exporter/html/citations.d.ts.map +1 -0
  88. package/dist/exporter/html/citations.js +110 -0
  89. package/dist/exporter/html/citations.js.map +1 -0
  90. package/dist/exporter/html/convert.d.ts +50 -0
  91. package/dist/exporter/html/convert.d.ts.map +1 -0
  92. package/dist/exporter/html/convert.js +750 -0
  93. package/dist/exporter/html/convert.js.map +1 -0
  94. package/dist/exporter/html/index.d.ts +64 -0
  95. package/dist/exporter/html/index.d.ts.map +1 -0
  96. package/dist/exporter/html/index.js +154 -0
  97. package/dist/exporter/html/index.js.map +1 -0
  98. package/dist/exporter/html/templates.d.ts +24 -0
  99. package/dist/exporter/html/templates.d.ts.map +1 -0
  100. package/dist/exporter/html/templates.js +21 -0
  101. package/dist/exporter/html/templates.js.map +1 -0
  102. package/dist/exporter/html/tools.d.ts +2 -0
  103. package/dist/exporter/html/tools.d.ts.map +1 -0
  104. package/dist/exporter/html/tools.js +49 -0
  105. package/dist/exporter/html/tools.js.map +1 -0
  106. package/dist/exporter/jats/bibliography.d.ts +3 -0
  107. package/dist/exporter/jats/bibliography.d.ts.map +1 -0
  108. package/dist/exporter/jats/bibliography.js +158 -0
  109. package/dist/exporter/jats/bibliography.js.map +1 -0
  110. package/dist/exporter/jats/citations.d.ts +16 -0
  111. package/dist/exporter/jats/citations.d.ts.map +1 -0
  112. package/dist/exporter/jats/citations.js +105 -0
  113. package/dist/exporter/jats/citations.js.map +1 -0
  114. package/dist/exporter/jats/convert.d.ts +41 -0
  115. package/dist/exporter/jats/convert.d.ts.map +1 -0
  116. package/dist/exporter/jats/convert.js +816 -0
  117. package/dist/exporter/jats/convert.js.map +1 -0
  118. package/dist/exporter/jats/index.d.ts +25 -0
  119. package/dist/exporter/jats/index.d.ts.map +1 -0
  120. package/dist/exporter/jats/index.js +82 -0
  121. package/dist/exporter/jats/index.js.map +1 -0
  122. package/dist/exporter/jats/templates.d.ts +18 -0
  123. package/dist/exporter/jats/templates.d.ts.map +1 -0
  124. package/dist/exporter/jats/templates.js +25 -0
  125. package/dist/exporter/jats/templates.js.map +1 -0
  126. package/dist/exporter/jats/text.d.ts +4 -0
  127. package/dist/exporter/jats/text.d.ts.map +1 -0
  128. package/dist/exporter/jats/text.js +72 -0
  129. package/dist/exporter/jats/text.js.map +1 -0
  130. package/dist/exporter/latex/convert.d.ts +24 -0
  131. package/dist/exporter/latex/convert.d.ts.map +1 -0
  132. package/dist/exporter/latex/convert.js +881 -0
  133. package/dist/exporter/latex/convert.js.map +1 -0
  134. package/dist/exporter/latex/escape_latex.d.ts +2 -0
  135. package/dist/exporter/latex/escape_latex.d.ts.map +1 -0
  136. package/dist/exporter/latex/escape_latex.js +20 -0
  137. package/dist/exporter/latex/escape_latex.js.map +1 -0
  138. package/dist/exporter/latex/index.d.ts +24 -0
  139. package/dist/exporter/latex/index.d.ts.map +1 -0
  140. package/dist/exporter/latex/index.js +67 -0
  141. package/dist/exporter/latex/index.js.map +1 -0
  142. package/dist/exporter/latex/readme.d.ts +2 -0
  143. package/dist/exporter/latex/readme.d.ts.map +1 -0
  144. package/dist/exporter/latex/readme.js +23 -0
  145. package/dist/exporter/latex/readme.js.map +1 -0
  146. package/dist/exporter/native/copy.d.ts +30 -0
  147. package/dist/exporter/native/copy.d.ts.map +1 -0
  148. package/dist/exporter/native/copy.js +151 -0
  149. package/dist/exporter/native/copy.js.map +1 -0
  150. package/dist/exporter/native/file.d.ts +12 -0
  151. package/dist/exporter/native/file.d.ts.map +1 -0
  152. package/dist/exporter/native/file.js +38 -0
  153. package/dist/exporter/native/file.js.map +1 -0
  154. package/dist/exporter/native/index.d.ts +5 -0
  155. package/dist/exporter/native/index.d.ts.map +1 -0
  156. package/dist/exporter/native/index.js +5 -0
  157. package/dist/exporter/native/index.js.map +1 -0
  158. package/dist/exporter/native/revision.d.ts +18 -0
  159. package/dist/exporter/native/revision.d.ts.map +1 -0
  160. package/dist/exporter/native/revision.js +39 -0
  161. package/dist/exporter/native/revision.js.map +1 -0
  162. package/dist/exporter/native/shrink.d.ts +36 -0
  163. package/dist/exporter/native/shrink.d.ts.map +1 -0
  164. package/dist/exporter/native/shrink.js +124 -0
  165. package/dist/exporter/native/shrink.js.map +1 -0
  166. package/dist/exporter/native/zip.d.ts +25 -0
  167. package/dist/exporter/native/zip.d.ts.map +1 -0
  168. package/dist/exporter/native/zip.js +56 -0
  169. package/dist/exporter/native/zip.js.map +1 -0
  170. package/dist/exporter/odt/citations.d.ts +21 -0
  171. package/dist/exporter/odt/citations.d.ts.map +1 -0
  172. package/dist/exporter/odt/citations.js +104 -0
  173. package/dist/exporter/odt/citations.js.map +1 -0
  174. package/dist/exporter/odt/footnotes.d.ts +31 -0
  175. package/dist/exporter/odt/footnotes.d.ts.map +1 -0
  176. package/dist/exporter/odt/footnotes.js +129 -0
  177. package/dist/exporter/odt/footnotes.js.map +1 -0
  178. package/dist/exporter/odt/images.d.ts +25 -0
  179. package/dist/exporter/odt/images.d.ts.map +1 -0
  180. package/dist/exporter/odt/images.js +106 -0
  181. package/dist/exporter/odt/images.js.map +1 -0
  182. package/dist/exporter/odt/index.d.ts +17 -0
  183. package/dist/exporter/odt/index.d.ts.map +1 -0
  184. package/dist/exporter/odt/index.js +108 -0
  185. package/dist/exporter/odt/index.js.map +1 -0
  186. package/dist/exporter/odt/math.d.ts +15 -0
  187. package/dist/exporter/odt/math.d.ts.map +1 -0
  188. package/dist/exporter/odt/math.js +71 -0
  189. package/dist/exporter/odt/math.js.map +1 -0
  190. package/dist/exporter/odt/metadata.d.ts +18 -0
  191. package/dist/exporter/odt/metadata.d.ts.map +1 -0
  192. package/dist/exporter/odt/metadata.js +224 -0
  193. package/dist/exporter/odt/metadata.js.map +1 -0
  194. package/dist/exporter/odt/render.d.ts +26 -0
  195. package/dist/exporter/odt/render.d.ts.map +1 -0
  196. package/dist/exporter/odt/render.js +651 -0
  197. package/dist/exporter/odt/render.js.map +1 -0
  198. package/dist/exporter/odt/richtext.d.ts +22 -0
  199. package/dist/exporter/odt/richtext.d.ts.map +1 -0
  200. package/dist/exporter/odt/richtext.js +743 -0
  201. package/dist/exporter/odt/richtext.js.map +1 -0
  202. package/dist/exporter/odt/styles.d.ts +41 -0
  203. package/dist/exporter/odt/styles.d.ts.map +1 -0
  204. package/dist/exporter/odt/styles.js +370 -0
  205. package/dist/exporter/odt/styles.js.map +1 -0
  206. package/dist/exporter/odt/track.d.ts +18 -0
  207. package/dist/exporter/odt/track.d.ts.map +1 -0
  208. package/dist/exporter/odt/track.js +66 -0
  209. package/dist/exporter/odt/track.js.map +1 -0
  210. package/dist/exporter/pandoc/citations.d.ts +23 -0
  211. package/dist/exporter/pandoc/citations.d.ts.map +1 -0
  212. package/dist/exporter/pandoc/citations.js +99 -0
  213. package/dist/exporter/pandoc/citations.js.map +1 -0
  214. package/dist/exporter/pandoc/convert.d.ts +19 -0
  215. package/dist/exporter/pandoc/convert.d.ts.map +1 -0
  216. package/dist/exporter/pandoc/convert.js +886 -0
  217. package/dist/exporter/pandoc/convert.js.map +1 -0
  218. package/dist/exporter/pandoc/index.d.ts +25 -0
  219. package/dist/exporter/pandoc/index.d.ts.map +1 -0
  220. package/dist/exporter/pandoc/index.js +79 -0
  221. package/dist/exporter/pandoc/index.js.map +1 -0
  222. package/dist/exporter/pandoc/readme.d.ts +2 -0
  223. package/dist/exporter/pandoc/readme.d.ts.map +1 -0
  224. package/dist/exporter/pandoc/readme.js +8 -0
  225. package/dist/exporter/pandoc/readme.js.map +1 -0
  226. package/dist/exporter/pandoc/tools.d.ts +22 -0
  227. package/dist/exporter/pandoc/tools.d.ts.map +1 -0
  228. package/dist/exporter/pandoc/tools.js +52 -0
  229. package/dist/exporter/pandoc/tools.js.map +1 -0
  230. package/dist/exporter/print/index.d.ts +20 -0
  231. package/dist/exporter/print/index.d.ts.map +1 -0
  232. package/dist/exporter/print/index.js +142 -0
  233. package/dist/exporter/print/index.js.map +1 -0
  234. package/dist/exporter/tools/doc_content.d.ts +6 -0
  235. package/dist/exporter/tools/doc_content.d.ts.map +1 -0
  236. package/dist/exporter/tools/doc_content.js +130 -0
  237. package/dist/exporter/tools/doc_content.js.map +1 -0
  238. package/dist/exporter/tools/file.d.ts +2 -0
  239. package/dist/exporter/tools/file.d.ts.map +1 -0
  240. package/dist/exporter/tools/file.js +10 -0
  241. package/dist/exporter/tools/file.js.map +1 -0
  242. package/dist/exporter/tools/json.d.ts +7 -0
  243. package/dist/exporter/tools/json.d.ts.map +1 -0
  244. package/dist/exporter/tools/json.js +82 -0
  245. package/dist/exporter/tools/json.js.map +1 -0
  246. package/dist/exporter/tools/svg.d.ts +8 -0
  247. package/dist/exporter/tools/svg.d.ts.map +1 -0
  248. package/dist/exporter/tools/svg.js +26 -0
  249. package/dist/exporter/tools/svg.js.map +1 -0
  250. package/dist/exporter/tools/xml.d.ts +42 -0
  251. package/dist/exporter/tools/xml.d.ts.map +1 -0
  252. package/dist/exporter/tools/xml.js +467 -0
  253. package/dist/exporter/tools/xml.js.map +1 -0
  254. package/dist/exporter/tools/xml_zip.d.ts +21 -0
  255. package/dist/exporter/tools/xml_zip.d.ts.map +1 -0
  256. package/dist/exporter/tools/xml_zip.js +92 -0
  257. package/dist/exporter/tools/xml_zip.js.map +1 -0
  258. package/dist/exporter/tools/zip.d.ts +35 -0
  259. package/dist/exporter/tools/zip.d.ts.map +1 -0
  260. package/dist/exporter/tools/zip.js +78 -0
  261. package/dist/exporter/tools/zip.js.map +1 -0
  262. package/dist/exporter/tools/zotero_csl.d.ts +23 -0
  263. package/dist/exporter/tools/zotero_csl.d.ts.map +1 -0
  264. package/dist/exporter/tools/zotero_csl.js +78 -0
  265. package/dist/exporter/tools/zotero_csl.js.map +1 -0
  266. package/dist/importer/citations.d.ts +28 -0
  267. package/dist/importer/citations.d.ts.map +1 -0
  268. package/dist/importer/citations.js +68 -0
  269. package/dist/importer/citations.js.map +1 -0
  270. package/dist/importer/docx/citations.d.ts +43 -0
  271. package/dist/importer/docx/citations.d.ts.map +1 -0
  272. package/dist/importer/docx/citations.js +81 -0
  273. package/dist/importer/docx/citations.js.map +1 -0
  274. package/dist/importer/docx/convert.d.ts +150 -0
  275. package/dist/importer/docx/convert.d.ts.map +1 -0
  276. package/dist/importer/docx/convert.js +1243 -0
  277. package/dist/importer/docx/convert.js.map +1 -0
  278. package/dist/importer/docx/helpers.d.ts +2 -0
  279. package/dist/importer/docx/helpers.d.ts.map +1 -0
  280. package/dist/importer/docx/helpers.js +10 -0
  281. package/dist/importer/docx/helpers.js.map +1 -0
  282. package/dist/importer/docx/index.d.ts +27 -0
  283. package/dist/importer/docx/index.d.ts.map +1 -0
  284. package/dist/importer/docx/index.js +77 -0
  285. package/dist/importer/docx/index.js.map +1 -0
  286. package/dist/importer/docx/omml2mathml.d.ts +6 -0
  287. package/dist/importer/docx/omml2mathml.d.ts.map +1 -0
  288. package/dist/importer/docx/omml2mathml.js +1146 -0
  289. package/dist/importer/docx/omml2mathml.js.map +1 -0
  290. package/dist/importer/docx/parse.d.ts +96 -0
  291. package/dist/importer/docx/parse.d.ts.map +1 -0
  292. package/dist/importer/docx/parse.js +681 -0
  293. package/dist/importer/docx/parse.js.map +1 -0
  294. package/dist/importer/native/extract_template.d.ts +6 -0
  295. package/dist/importer/native/extract_template.d.ts.map +1 -0
  296. package/dist/importer/native/extract_template.js +80 -0
  297. package/dist/importer/native/extract_template.js.map +1 -0
  298. package/dist/importer/native/file.d.ts +37 -0
  299. package/dist/importer/native/file.d.ts.map +1 -0
  300. package/dist/importer/native/file.js +162 -0
  301. package/dist/importer/native/file.js.map +1 -0
  302. package/dist/importer/native/get_images.d.ts +21 -0
  303. package/dist/importer/native/get_images.d.ts.map +1 -0
  304. package/dist/importer/native/get_images.js +58 -0
  305. package/dist/importer/native/get_images.js.map +1 -0
  306. package/dist/importer/native/importer.d.ts +41 -0
  307. package/dist/importer/native/importer.d.ts.map +1 -0
  308. package/dist/importer/native/importer.js +170 -0
  309. package/dist/importer/native/importer.js.map +1 -0
  310. package/dist/importer/native/index.d.ts +7 -0
  311. package/dist/importer/native/index.d.ts.map +1 -0
  312. package/dist/importer/native/index.js +7 -0
  313. package/dist/importer/native/index.js.map +1 -0
  314. package/dist/importer/native/update.d.ts +7 -0
  315. package/dist/importer/native/update.d.ts.map +1 -0
  316. package/dist/importer/native/update.js +27 -0
  317. package/dist/importer/native/update.js.map +1 -0
  318. package/dist/importer/native/update_template.d.ts +12 -0
  319. package/dist/importer/native/update_template.d.ts.map +1 -0
  320. package/dist/importer/native/update_template.js +19 -0
  321. package/dist/importer/native/update_template.js.map +1 -0
  322. package/dist/importer/odt/citations.d.ts +27 -0
  323. package/dist/importer/odt/citations.d.ts.map +1 -0
  324. package/dist/importer/odt/citations.js +57 -0
  325. package/dist/importer/odt/citations.js.map +1 -0
  326. package/dist/importer/odt/convert.d.ts +146 -0
  327. package/dist/importer/odt/convert.d.ts.map +1 -0
  328. package/dist/importer/odt/convert.js +1530 -0
  329. package/dist/importer/odt/convert.js.map +1 -0
  330. package/dist/importer/odt/index.d.ts +30 -0
  331. package/dist/importer/odt/index.d.ts.map +1 -0
  332. package/dist/importer/odt/index.js +124 -0
  333. package/dist/importer/odt/index.js.map +1 -0
  334. package/dist/importer/pandoc/convert.d.ts +32 -0
  335. package/dist/importer/pandoc/convert.d.ts.map +1 -0
  336. package/dist/importer/pandoc/convert.js +790 -0
  337. package/dist/importer/pandoc/convert.js.map +1 -0
  338. package/dist/importer/pandoc/helpers.d.ts +5 -0
  339. package/dist/importer/pandoc/helpers.d.ts.map +1 -0
  340. package/dist/importer/pandoc/helpers.js +73 -0
  341. package/dist/importer/pandoc/helpers.js.map +1 -0
  342. package/dist/importer/pandoc/index.d.ts +31 -0
  343. package/dist/importer/pandoc/index.d.ts.map +1 -0
  344. package/dist/importer/pandoc/index.js +114 -0
  345. package/dist/importer/pandoc/index.js.map +1 -0
  346. package/dist/importer/registry.d.ts +21 -0
  347. package/dist/importer/registry.d.ts.map +1 -0
  348. package/dist/importer/registry.js +41 -0
  349. package/dist/importer/registry.js.map +1 -0
  350. package/dist/importer/zip_analyzer.d.ts +31 -0
  351. package/dist/importer/zip_analyzer.d.ts.map +1 -0
  352. package/dist/importer/zip_analyzer.js +89 -0
  353. package/dist/importer/zip_analyzer.js.map +1 -0
  354. package/dist/index.d.ts +2 -0
  355. package/dist/index.d.ts.map +1 -0
  356. package/dist/index.js +2 -0
  357. package/dist/index.js.map +1 -0
  358. package/dist/mathlive/opf_includes.d.ts +2 -0
  359. package/dist/mathlive/opf_includes.d.ts.map +1 -0
  360. package/dist/mathlive/opf_includes.js +25 -0
  361. package/dist/mathlive/opf_includes.js.map +1 -0
  362. package/dist/schema/common/annotate.d.ts +47 -0
  363. package/dist/schema/common/annotate.d.ts.map +1 -0
  364. package/dist/schema/common/annotate.js +75 -0
  365. package/dist/schema/common/annotate.js.map +1 -0
  366. package/dist/schema/common/base.d.ts +91 -0
  367. package/dist/schema/common/base.d.ts.map +1 -0
  368. package/dist/schema/common/base.js +109 -0
  369. package/dist/schema/common/base.js.map +1 -0
  370. package/dist/schema/common/citation.d.ts +30 -0
  371. package/dist/schema/common/citation.d.ts.map +1 -0
  372. package/dist/schema/common/citation.js +61 -0
  373. package/dist/schema/common/citation.js.map +1 -0
  374. package/dist/schema/common/equation.d.ts +17 -0
  375. package/dist/schema/common/equation.d.ts.map +1 -0
  376. package/dist/schema/common/equation.js +32 -0
  377. package/dist/schema/common/equation.js.map +1 -0
  378. package/dist/schema/common/figure.d.ts +87 -0
  379. package/dist/schema/common/figure.d.ts.map +1 -0
  380. package/dist/schema/common/figure.js +178 -0
  381. package/dist/schema/common/figure.js.map +1 -0
  382. package/dist/schema/common/heading.d.ts +9 -0
  383. package/dist/schema/common/heading.d.ts.map +1 -0
  384. package/dist/schema/common/heading.js +41 -0
  385. package/dist/schema/common/heading.js.map +1 -0
  386. package/dist/schema/common/index.d.ts +11 -0
  387. package/dist/schema/common/index.d.ts.map +1 -0
  388. package/dist/schema/common/index.js +11 -0
  389. package/dist/schema/common/index.js.map +1 -0
  390. package/dist/schema/common/list.d.ts +63 -0
  391. package/dist/schema/common/list.d.ts.map +1 -0
  392. package/dist/schema/common/list.js +92 -0
  393. package/dist/schema/common/list.js.map +1 -0
  394. package/dist/schema/common/reference.d.ts +70 -0
  395. package/dist/schema/common/reference.d.ts.map +1 -0
  396. package/dist/schema/common/reference.js +97 -0
  397. package/dist/schema/common/reference.js.map +1 -0
  398. package/dist/schema/common/table.d.ts +76 -0
  399. package/dist/schema/common/table.d.ts.map +1 -0
  400. package/dist/schema/common/table.js +86 -0
  401. package/dist/schema/common/table.js.map +1 -0
  402. package/dist/schema/common/track.d.ts +117 -0
  403. package/dist/schema/common/track.d.ts.map +1 -0
  404. package/{src → dist}/schema/common/track.js +44 -49
  405. package/dist/schema/common/track.js.map +1 -0
  406. package/dist/schema/const.d.ts +3 -0
  407. package/dist/schema/const.d.ts.map +1 -0
  408. package/{src → dist}/schema/const.js +3 -3
  409. package/dist/schema/const.js.map +1 -0
  410. package/dist/schema/convert.d.ts +3 -0
  411. package/dist/schema/convert.d.ts.map +1 -0
  412. package/dist/schema/convert.js +1215 -0
  413. package/dist/schema/convert.js.map +1 -0
  414. package/dist/schema/document/content.d.ts +110 -0
  415. package/dist/schema/document/content.d.ts.map +1 -0
  416. package/dist/schema/document/content.js +177 -0
  417. package/dist/schema/document/content.js.map +1 -0
  418. package/dist/schema/document/index.d.ts +795 -0
  419. package/dist/schema/document/index.d.ts.map +1 -0
  420. package/dist/schema/document/index.js +68 -0
  421. package/dist/schema/document/index.js.map +1 -0
  422. package/dist/schema/document/structure.d.ts +164 -0
  423. package/dist/schema/document/structure.d.ts.map +1 -0
  424. package/dist/schema/document/structure.js +445 -0
  425. package/dist/schema/document/structure.js.map +1 -0
  426. package/dist/schema/export.d.ts +7 -0
  427. package/dist/schema/export.d.ts.map +1 -0
  428. package/dist/schema/export.js +17 -0
  429. package/dist/schema/export.js.map +1 -0
  430. package/dist/schema/footnotes.d.ts +454 -0
  431. package/dist/schema/footnotes.d.ts.map +1 -0
  432. package/dist/schema/footnotes.js +90 -0
  433. package/dist/schema/footnotes.js.map +1 -0
  434. package/dist/schema/footnotes_convert.d.ts +5 -0
  435. package/dist/schema/footnotes_convert.d.ts.map +1 -0
  436. package/dist/schema/footnotes_convert.js +30 -0
  437. package/dist/schema/footnotes_convert.js.map +1 -0
  438. package/dist/schema/i18n.d.ts +55 -0
  439. package/dist/schema/i18n.d.ts.map +1 -0
  440. package/{src → dist}/schema/i18n.js +14 -23
  441. package/dist/schema/i18n.js.map +1 -0
  442. package/dist/schema/index.d.ts +6 -0
  443. package/dist/schema/index.d.ts.map +1 -0
  444. package/dist/schema/index.js +6 -0
  445. package/dist/schema/index.js.map +1 -0
  446. package/dist/schema/mini_json.d.ts +4 -0
  447. package/dist/schema/mini_json.d.ts.map +1 -0
  448. package/{src → dist}/schema/mini_json.js +19 -28
  449. package/dist/schema/mini_json.js.map +1 -0
  450. package/dist/schema/text.d.ts +3 -0
  451. package/dist/schema/text.d.ts.map +1 -0
  452. package/dist/schema/text.js +23 -0
  453. package/dist/schema/text.js.map +1 -0
  454. package/dist/types.d.ts +281 -0
  455. package/dist/types.d.ts.map +1 -0
  456. package/dist/types.js +9 -0
  457. package/dist/types.js.map +1 -0
  458. package/package.json +51 -16
  459. package/scripts/export-schema.js +1 -1
  460. package/src/bibliography/{common.js → common.ts} +15 -12
  461. package/src/bibliography/{csl_bib.js → csl_bib.ts} +16 -15
  462. package/src/citations/{citeproc_sys.js → citeproc_sys.ts} +26 -6
  463. package/src/citations/{format.js → format.ts} +80 -24
  464. package/src/editor/e2ee/{encryptor.js → encryptor.ts} +76 -44
  465. package/src/exporter/docx/{citations.js → citations.ts} +51 -23
  466. package/src/exporter/docx/{comments.js → comments.ts} +69 -26
  467. package/src/exporter/docx/{footnotes.js → footnotes.ts} +81 -42
  468. package/src/exporter/docx/images.ts +128 -0
  469. package/src/exporter/docx/{index.js → index.ts} +48 -25
  470. package/src/exporter/docx/{lists.js → lists.ts} +89 -46
  471. package/src/exporter/docx/{math.js → math.ts} +29 -9
  472. package/src/exporter/docx/{metadata.js → metadata.ts} +78 -42
  473. package/src/exporter/docx/{rels.js → rels.ts} +71 -50
  474. package/src/exporter/docx/{render.js → render.ts} +124 -87
  475. package/src/exporter/docx/{richtext.js → richtext.ts} +107 -84
  476. package/src/exporter/docx/{tables.js → tables.ts} +33 -23
  477. package/src/exporter/docx/{tools.js → tools.ts} +4 -3
  478. package/src/exporter/epub/{index.js → index.ts} +44 -15
  479. package/src/exporter/epub/{templates.js → templates.ts} +71 -7
  480. package/src/exporter/epub/tools.ts +102 -0
  481. package/src/exporter/html/{citations.js → citations.ts} +79 -31
  482. package/src/exporter/html/{convert.js → convert.ts} +118 -71
  483. package/src/exporter/html/{index.js → index.ts} +63 -29
  484. package/src/exporter/html/{templates.js → templates.ts} +22 -2
  485. package/src/exporter/html/{tools.js → tools.ts} +9 -6
  486. package/src/exporter/jats/bibliography.ts +199 -0
  487. package/src/exporter/jats/{citations.js → citations.ts} +56 -20
  488. package/src/exporter/jats/{convert.js → convert.ts} +72 -53
  489. package/src/exporter/jats/index.ts +132 -0
  490. package/src/exporter/jats/{templates.js → templates.ts} +19 -3
  491. package/src/exporter/jats/{text.js → text.ts} +8 -6
  492. package/src/exporter/latex/{convert.js → convert.ts} +160 -125
  493. package/src/exporter/latex/{escape_latex.js → escape_latex.ts} +1 -1
  494. package/src/exporter/latex/{index.js → index.ts} +27 -12
  495. package/src/exporter/latex/{readme.js → readme.ts} +2 -2
  496. package/src/exporter/native/copy.ts +231 -0
  497. package/src/exporter/native/file.ts +65 -0
  498. package/src/exporter/native/index.ts +4 -0
  499. package/src/exporter/native/revision.ts +76 -0
  500. package/src/exporter/native/{shrink.js → shrink.ts} +64 -29
  501. package/src/exporter/native/zip.ts +85 -0
  502. package/src/exporter/odt/{citations.js → citations.ts} +35 -15
  503. package/src/exporter/odt/{footnotes.js → footnotes.ts} +53 -30
  504. package/src/exporter/odt/images.ts +135 -0
  505. package/src/exporter/odt/{index.js → index.ts} +49 -27
  506. package/src/exporter/odt/{math.js → math.ts} +38 -9
  507. package/src/exporter/odt/{metadata.js → metadata.ts} +54 -29
  508. package/src/exporter/odt/{render.js → render.ts} +89 -60
  509. package/src/exporter/odt/{richtext.js → richtext.ts} +102 -72
  510. package/src/exporter/odt/{styles.js → styles.ts} +98 -66
  511. package/src/exporter/odt/{track.js → track.ts} +22 -6
  512. package/src/exporter/pandoc/{citations.js → citations.ts} +31 -15
  513. package/src/exporter/pandoc/{convert.js → convert.ts} +98 -79
  514. package/src/exporter/pandoc/{index.js → index.ts} +36 -13
  515. package/src/exporter/pandoc/{readme.js → readme.ts} +0 -1
  516. package/src/exporter/pandoc/{tools.js → tools.ts} +28 -5
  517. package/src/exporter/print/{index.js → index.ts} +38 -19
  518. package/src/exporter/tools/{doc_content.js → doc_content.ts} +34 -24
  519. package/src/exporter/tools/{file.js → file.ts} +1 -1
  520. package/src/exporter/tools/{json.js → json.ts} +30 -19
  521. package/src/exporter/tools/{svg.js → svg.ts} +9 -3
  522. package/src/exporter/tools/{xml.js → xml.ts} +187 -138
  523. package/src/exporter/tools/{xml_zip.js → xml_zip.ts} +19 -11
  524. package/src/exporter/tools/{zip.js → zip.ts} +35 -11
  525. package/src/exporter/tools/{zotero_csl.js → zotero_csl.ts} +35 -18
  526. package/src/global.d.ts +13 -0
  527. package/src/importer/citations.ts +116 -0
  528. package/src/importer/docx/{citations.js → citations.ts} +22 -37
  529. package/src/importer/docx/{convert.js → convert.ts} +176 -141
  530. package/src/importer/docx/{helpers.js → helpers.ts} +1 -1
  531. package/src/importer/docx/index.ts +124 -0
  532. package/src/importer/docx/{omml2mathml.js → omml2mathml.ts} +154 -176
  533. package/src/importer/docx/{parse.js → parse.ts} +103 -81
  534. package/src/importer/native/extract_template.ts +83 -0
  535. package/src/importer/native/file.ts +282 -0
  536. package/src/importer/native/get_images.ts +82 -0
  537. package/src/importer/native/importer.ts +244 -0
  538. package/src/importer/native/index.ts +6 -0
  539. package/src/importer/native/{update.js → update.ts} +13 -5
  540. package/src/importer/native/update_template.ts +32 -0
  541. package/src/importer/odt/{citations.js → citations.ts} +17 -29
  542. package/src/importer/odt/{convert.js → convert.ts} +261 -237
  543. package/src/importer/odt/index.ts +202 -0
  544. package/src/importer/pandoc/{convert.js → convert.ts} +116 -94
  545. package/src/importer/pandoc/{helpers.js → helpers.ts} +24 -12
  546. package/src/importer/pandoc/index.ts +171 -0
  547. package/src/importer/registry.ts +69 -0
  548. package/src/importer/{zip_analyzer.js → zip_analyzer.ts} +44 -18
  549. package/src/mathlive/{opf_includes.js → opf_includes.ts} +1 -1
  550. package/src/modules.d.ts +40 -0
  551. package/src/schema/common/{annotate.js → annotate.ts} +10 -8
  552. package/src/schema/common/{base.js → base.ts} +12 -10
  553. package/src/schema/common/{citation.js → citation.ts} +17 -8
  554. package/src/schema/common/{equation.js → equation.ts} +6 -4
  555. package/src/schema/common/{figure.js → figure.ts} +43 -23
  556. package/src/schema/common/{heading.js → heading.ts} +7 -5
  557. package/src/schema/common/{list.js → list.ts} +15 -13
  558. package/src/schema/common/{reference.js → reference.ts} +14 -12
  559. package/src/schema/common/{table.js → table.ts} +16 -14
  560. package/src/schema/common/track.ts +201 -0
  561. package/src/schema/const.ts +58 -0
  562. package/src/schema/{convert.js → convert.ts} +6 -2
  563. package/src/schema/document/{content.js → content.ts} +22 -20
  564. package/src/schema/document/{structure.js → structure.ts} +15 -9
  565. package/src/schema/{export.js → export.ts} +4 -2
  566. package/src/schema/{footnotes.js → footnotes.ts} +11 -8
  567. package/src/schema/{footnotes_convert.js → footnotes_convert.ts} +11 -8
  568. package/src/schema/i18n.ts +601 -0
  569. package/src/schema/mini_json.ts +60 -0
  570. package/src/schema/{text.js → text.ts} +6 -2
  571. package/src/types.ts +314 -0
  572. package/jest.config.js +0 -24
  573. package/src/exporter/docx/images.js +0 -101
  574. package/src/exporter/jats/bibliography.js +0 -183
  575. package/src/exporter/jats/index.js +0 -92
  576. package/src/exporter/odt/images.js +0 -115
  577. package/src/importer/citations.js +0 -129
  578. package/src/importer/native/get_images.js +0 -76
  579. /package/src/{index.js → index.ts} +0 -0
  580. /package/src/schema/common/{index.js → index.ts} +0 -0
  581. /package/src/schema/document/{index.js → index.ts} +0 -0
  582. /package/src/schema/{index.js → index.ts} +0 -0
@@ -0,0 +1,1530 @@
1
+ import { MathMLToLaTeX } from "mathml-to-latex";
2
+ import { xmlDOM } from "../../exporter/tools/xml.js";
3
+ import { randomCommentId, randomFigureId, randomHeadingId, randomListId, randomTableId } from "../../schema/common/index.js";
4
+ import { parseTracks } from "../../schema/common/track.js";
5
+ import { isOdtBibliographyReferenceMark, isOdtBibliographySection, isOdtCitationMark, parseOdtBibliographyMark, parseOdtReferenceMark } from "./citations.js";
6
+ import { gettext } from "fwtoolkit";
7
+ function attr(node, name) {
8
+ if (node && typeof node === "object" && "getAttribute" in node) {
9
+ return String(node.getAttribute(name) || "");
10
+ }
11
+ return "";
12
+ }
13
+ export class OdtConvert {
14
+ importId;
15
+ template;
16
+ bibliography;
17
+ bibDB;
18
+ images;
19
+ styles;
20
+ contentDoc;
21
+ stylesDoc;
22
+ metaDoc;
23
+ manifestDoc;
24
+ tracks;
25
+ comments;
26
+ currentCommentIds;
27
+ currentTracks;
28
+ referenceableObjects;
29
+ constructor(contentXml, stylesXml, metaXml, manifestXml, importId, template, bibliography, bibDb) {
30
+ this.importId = importId;
31
+ this.template = template;
32
+ this.bibliography = bibliography;
33
+ this.bibDB = bibDb;
34
+ this.images = {};
35
+ this.styles = {};
36
+ this.contentDoc = contentXml ? xmlDOM(contentXml) : null;
37
+ this.stylesDoc = stylesXml ? xmlDOM(stylesXml) : null;
38
+ this.metaDoc = metaXml ? xmlDOM(metaXml) : null;
39
+ this.manifestDoc = manifestXml ? xmlDOM(manifestXml) : null;
40
+ this.tracks = {};
41
+ this.comments = {};
42
+ this.currentCommentIds = [];
43
+ this.currentTracks = [];
44
+ this.referenceableObjects = {}; // All objects that can be referenced
45
+ }
46
+ init() {
47
+ this.parseTrackedChanges();
48
+ this.parseStyles();
49
+ this.parseComments();
50
+ this.collectReferenceableObjects(this.contentDoc);
51
+ const content = this.convert();
52
+ return {
53
+ content,
54
+ settings: {
55
+ import_id: this.importId,
56
+ tracked: Object.keys(this.tracks).length > 0,
57
+ language: this.detectLanguage()
58
+ },
59
+ comments: this.comments
60
+ };
61
+ }
62
+ parseTrackedChanges() {
63
+ if (!this.contentDoc) {
64
+ return;
65
+ }
66
+ const trackedChangesEl = this.contentDoc.query("text:tracked-changes");
67
+ if (!trackedChangesEl) {
68
+ return;
69
+ }
70
+ // Tracked deletions are stored in two different ways in FW and ODT.
71
+ // FW: The deleted content stays in place where it was before the deletion,
72
+ // and is marked with a tracked change mark. Megre only occurs after change
73
+ // has been accepted.
74
+ // ODT: The deleted content is removed from the content flow and is replaced by a marker.
75
+ // The removed content is stored in a special section of the document.
76
+ // This method takes all the deleted content and puts it back into the place where
77
+ // it was previously. That way the structure is more similar to the output FW document
78
+ // and is more easily converted.
79
+ const deletions = {};
80
+ const changedRegions = trackedChangesEl.queryAll("text:changed-region");
81
+ changedRegions.forEach((region) => {
82
+ const id = attr(region, "text:id");
83
+ const insertion = region.query("text:insertion");
84
+ const deletion = region.query("text:deletion");
85
+ if (!insertion && !deletion) {
86
+ // Neither insertion or deletion. Must be type unknown to us
87
+ return;
88
+ }
89
+ const changeInfo = region.query("office:change-info");
90
+ if (changeInfo) {
91
+ const track = {
92
+ type: insertion ? "insertion" : "deletion",
93
+ user: 1,
94
+ username: changeInfo.query("dc:creator")?.textContent || "",
95
+ date: Math.floor(new Date(changeInfo.query("dc:date")?.textContent || "").getTime() / 60000)
96
+ };
97
+ if (insertion) {
98
+ track.approved = false;
99
+ }
100
+ this.tracks[id] = track;
101
+ if (deletion) {
102
+ // Store deletion content for later use
103
+ deletions[id] = deletion.children.filter((child) => child.tagName !== "office:change-info");
104
+ }
105
+ }
106
+ });
107
+ // Then find and replace all deletion change markers
108
+ const changeMarkers = this.contentDoc.queryAll("text:change");
109
+ changeMarkers.forEach((marker) => {
110
+ const changeId = attr(marker, "text:change-id");
111
+ const deletion = deletions[changeId];
112
+ if (deletion) {
113
+ if (deletion.length > 0) {
114
+ // Create change-start and change-end elements
115
+ const markerIndex = marker.parentElement.children.indexOf(marker);
116
+ marker.parentElement.insertXMLAt(`<text:change-start text:change-id="${changeId}"/>`, markerIndex);
117
+ marker.parentElement.insertXMLAt(`<text:change-end text:change-id="${changeId}"/>`, markerIndex + 2);
118
+ if (deletion.length === 1) {
119
+ // Single block - just insert the content
120
+ deletion[0].children.forEach((content) => {
121
+ marker.parentElement.insertBefore(content, marker);
122
+ });
123
+ }
124
+ else {
125
+ // Multiple blocks - need to split the paragraph/headline
126
+ const parentElement = marker.parentElement;
127
+ parentElement.splitAtChildElement(marker, deletion[0].children
128
+ ?.map((node) => node.toString())
129
+ .join("") || "", // First block content to be added to current node
130
+ deletion
131
+ .slice(1, -1)
132
+ .map((node) => node.toString())
133
+ .join(""), // Middle blocks
134
+ deletion[deletion.length - 1].toString() // Last block
135
+ );
136
+ }
137
+ }
138
+ // Remove the original change marker
139
+ marker.parentElement.removeChild(marker);
140
+ }
141
+ });
142
+ }
143
+ parseStyles() {
144
+ if (!this.stylesDoc) {
145
+ return;
146
+ }
147
+ const styleNodes = this.stylesDoc.queryAll("style:style");
148
+ styleNodes.forEach((node) => {
149
+ const styleName = attr(node, "style:name");
150
+ this.styles[styleName] = this.parseStyle(node);
151
+ });
152
+ const contentStyleNodes = this.contentDoc.queryAll("style:style");
153
+ contentStyleNodes.forEach((node) => {
154
+ const styleName = attr(node, "style:name");
155
+ this.styles[styleName] = this.parseStyle(node);
156
+ });
157
+ }
158
+ parseStyle(styleNode) {
159
+ const properties = {
160
+ // Basic style information
161
+ parentStyleName: attr(styleNode, "style:parent-style-name"),
162
+ isSection: attr(styleNode, "style:family") === "section" ||
163
+ Boolean(styleNode.query("style:section-properties")),
164
+ title: attr(styleNode, "style:display-name"),
165
+ // Family and name info
166
+ family: attr(styleNode, "style:family"),
167
+ name: attr(styleNode, "style:name"),
168
+ // Heading related
169
+ isHeading: attr(styleNode, "style:family") === "paragraph" &&
170
+ (attr(styleNode, "style:name")
171
+ .toLowerCase()
172
+ .includes("heading") ||
173
+ attr(styleNode, "style:parent-style-name")
174
+ ?.toLowerCase()
175
+ .includes("heading")),
176
+ outlineLevel: attr(styleNode, "text:outline-level"),
177
+ // Text properties
178
+ textProperties: {},
179
+ // Paragraph properties
180
+ paragraphProperties: {},
181
+ // Section properties
182
+ sectionProperties: {}
183
+ };
184
+ // Parse text properties
185
+ const textProperties = styleNode.query("style:text-properties");
186
+ if (textProperties) {
187
+ properties.textProperties = {
188
+ bold: attr(textProperties, "fo:font-weight") === "bold",
189
+ italic: attr(textProperties, "fo:font-style") === "italic",
190
+ fontSize: this.convertLength(attr(textProperties, "fo:font-size")),
191
+ fontFamily: attr(textProperties, "fo:font-family"),
192
+ color: attr(textProperties, "fo:color"),
193
+ backgroundColor: attr(textProperties, "fo:background-color"),
194
+ textDecoration: attr(textProperties, "style:text-underline-style") ||
195
+ attr(textProperties, "style:text-line-through-style"),
196
+ textPosition: attr(textProperties, "style:text-position")
197
+ };
198
+ }
199
+ // Parse paragraph properties
200
+ const paragraphProperties = styleNode.query("style:paragraph-properties");
201
+ if (paragraphProperties) {
202
+ properties.paragraphProperties = {
203
+ marginTop: this.convertLength(attr(paragraphProperties, "fo:margin-top")),
204
+ marginBottom: this.convertLength(attr(paragraphProperties, "fo:margin-bottom")),
205
+ marginLeft: this.convertLength(attr(paragraphProperties, "fo:margin-left")),
206
+ marginRight: this.convertLength(attr(paragraphProperties, "fo:margin-right")),
207
+ textAlign: attr(paragraphProperties, "fo:text-align"),
208
+ lineHeight: attr(paragraphProperties, "fo:line-height"),
209
+ backgroundColor: attr(paragraphProperties, "fo:background-color"),
210
+ padding: this.convertLength(attr(paragraphProperties, "fo:padding")),
211
+ borderStyle: attr(paragraphProperties, "fo:border-style")
212
+ };
213
+ }
214
+ // Parse section properties
215
+ const sectionProperties = styleNode.query("style:section-properties");
216
+ if (sectionProperties) {
217
+ properties.sectionProperties = {
218
+ columnCount: attr(sectionProperties, "fo:column-count"),
219
+ columnGap: this.convertLength(attr(sectionProperties, "fo:column-gap")),
220
+ backgroundColor: attr(sectionProperties, "fo:background-color"),
221
+ margins: {
222
+ top: this.convertLength(attr(sectionProperties, "fo:margin-top")),
223
+ bottom: this.convertLength(attr(sectionProperties, "fo:margin-bottom")),
224
+ left: this.convertLength(attr(sectionProperties, "fo:margin-left")),
225
+ right: this.convertLength(attr(sectionProperties, "fo:margin-right"))
226
+ }
227
+ };
228
+ }
229
+ // Additional table-specific properties
230
+ if (attr(styleNode, "style:family") === "table") {
231
+ properties.tableProperties = {
232
+ align: attr(styleNode, "table:align"),
233
+ width: this.convertLength(attr(styleNode, "style:width")),
234
+ relWidth: attr(styleNode, "style:rel-width")
235
+ };
236
+ }
237
+ return properties;
238
+ }
239
+ convertObject(node, attrs) {
240
+ const mathEl = node.query("math");
241
+ if (mathEl) {
242
+ attrs = Object.assign({
243
+ equation: MathMLToLaTeX.convert(mathEl.innerXML)
244
+ }, attrs);
245
+ return {
246
+ type: "equation",
247
+ attrs
248
+ };
249
+ }
250
+ return null;
251
+ }
252
+ parseComments() {
253
+ if (!this.contentDoc) {
254
+ return;
255
+ }
256
+ const annotations = this.contentDoc.queryAll("office:annotation");
257
+ annotations.forEach((annotation) => {
258
+ const username = annotation.query("dc:creator")?.textContent || "";
259
+ const date = new Date(annotation.query("dc:date")?.textContent || "").getTime();
260
+ const id = (attr(annotation, "office:name") || "")
261
+ .replace(/\D/g, "")
262
+ .slice(0, 9);
263
+ if (id) {
264
+ // main comment
265
+ this.comments[id] = {
266
+ user: 0,
267
+ username,
268
+ date,
269
+ comment: annotation
270
+ .queryAll("text:p")
271
+ .map((par) => this.convertBlockNode(par))
272
+ .filter((par) => par)
273
+ .flat(),
274
+ answers: [],
275
+ resolved: attr(annotation, "loext:resolved") === "true"
276
+ };
277
+ }
278
+ else {
279
+ const parentId = (attr(annotation, "loext:parent-name") || "")
280
+ .replace(/\D/g, "")
281
+ .slice(0, 9);
282
+ if (parentId && this.comments[parentId]) {
283
+ this.comments[parentId].answers.push({
284
+ id: randomCommentId(),
285
+ user: 0,
286
+ username,
287
+ date,
288
+ // drop the frist paragraph. It only contains "Reply to...."
289
+ answer: annotation
290
+ .queryAll("text:p")
291
+ .slice(1)
292
+ .map((par) => this.convertBlockNode(par))
293
+ .filter((par) => par)
294
+ .flat()
295
+ });
296
+ }
297
+ }
298
+ });
299
+ }
300
+ collectReferenceableObjects(node) {
301
+ // Handle heading bookmarks
302
+ const bookmarkStarts = node.queryAll("text:bookmark-start");
303
+ bookmarkStarts.forEach((mark) => {
304
+ const refName = attr(mark, "text:name");
305
+ if (!refName) {
306
+ return;
307
+ }
308
+ // Find the closest heading
309
+ let targetParent = mark.parentElement;
310
+ while (targetParent) {
311
+ if (targetParent.tagName === "text:h") {
312
+ const id = randomHeadingId();
313
+ this.referenceableObjects[refName] = {
314
+ type: "heading",
315
+ id,
316
+ node: targetParent
317
+ };
318
+ break;
319
+ }
320
+ targetParent = targetParent.parentElement;
321
+ }
322
+ });
323
+ // Handle figure sequences
324
+ const sequences = node.queryAll("text:sequence");
325
+ sequences.forEach((sequence) => {
326
+ const refName = attr(sequence, "text:ref-name");
327
+ if (!refName) {
328
+ return;
329
+ }
330
+ // Find the figure container
331
+ let targetParent = sequence.parentElement;
332
+ while (targetParent) {
333
+ if (targetParent.tagName === "draw:frame") {
334
+ const id = randomFigureId();
335
+ this.referenceableObjects[refName] = {
336
+ type: "figure",
337
+ id,
338
+ node: targetParent
339
+ };
340
+ break;
341
+ }
342
+ targetParent = targetParent.parentElement;
343
+ }
344
+ });
345
+ }
346
+ convert() {
347
+ const templateParts = this.template.content.content.slice();
348
+ templateParts.shift();
349
+ const document = {
350
+ type: "doc",
351
+ attrs: {
352
+ import_id: this.importId
353
+ },
354
+ content: []
355
+ };
356
+ // Add title (required first element)
357
+ const title = this.extractTitle();
358
+ if (title.content.length) {
359
+ document.content.push({
360
+ type: "title",
361
+ content: title.content
362
+ });
363
+ }
364
+ else {
365
+ // If no title found, use default title
366
+ document.content.push({
367
+ type: "title",
368
+ content: [
369
+ {
370
+ type: "text",
371
+ text: gettext("Untitled")
372
+ }
373
+ ]
374
+ });
375
+ }
376
+ title.containerNodes.forEach((node) => {
377
+ node.parentElement.removeChild(node);
378
+ });
379
+ document.attrs.title =
380
+ title.content.map((node) => node.textContent).join("") ||
381
+ gettext("Untitled");
382
+ // Get all content sections from the ODT
383
+ const body = this.contentDoc.query("office:text");
384
+ if (!body) {
385
+ return document;
386
+ }
387
+ // Look for metadata sections first (author, abstract, etc.)
388
+ const metadataContent = this.extractMetadata();
389
+ metadataContent.forEach(({ type, attrs, content }) => {
390
+ const templatePart = templateParts.find((part) => part.attrs.metadata === type);
391
+ if (templatePart) {
392
+ document.content.push({
393
+ type: templatePart.type,
394
+ attrs: {
395
+ ...templatePart.attrs,
396
+ ...attrs
397
+ },
398
+ content: content.content
399
+ });
400
+ // Remove paragraphs from content so they are not added to body
401
+ content.containerNodes.forEach((node) => {
402
+ node.parentElement.removeChild(node);
403
+ });
404
+ }
405
+ });
406
+ // Group remaining content by sections based on style names/titles
407
+ const sections = this.groupContentIntoSections(body);
408
+ // Map ODT sections to template parts
409
+ sections.forEach((section) => {
410
+ // Find matching template part
411
+ const templatePart = this.findMatchingTemplatePart(section.title, templateParts);
412
+ if (templatePart) {
413
+ // If template part found, use its configuration
414
+ document.content.push({
415
+ type: "richtext_part",
416
+ attrs: {
417
+ title: templatePart.attrs.title,
418
+ id: templatePart.attrs.id,
419
+ metadata: templatePart.attrs.metadata || undefined,
420
+ marks: templatePart.attrs.marks || [
421
+ "strong",
422
+ "em",
423
+ "link"
424
+ ]
425
+ },
426
+ content: section.content
427
+ });
428
+ }
429
+ });
430
+ // Add remaining content to body section
431
+ const unassignedContent = sections
432
+ .filter((section) => !this.findMatchingTemplatePart(section.title, templateParts))
433
+ .flatMap((section) => section.content);
434
+ if (unassignedContent.length) {
435
+ // Find default body template part
436
+ const bodyTemplatePart = templateParts.find((part) => !part.attrs.metadata && part.type === "richtext_part");
437
+ document.content.push({
438
+ type: "richtext_part",
439
+ attrs: {
440
+ title: bodyTemplatePart?.attrs?.title || "Body",
441
+ id: bodyTemplatePart?.attrs?.id || "body",
442
+ marks: ["strong", "em", "link"]
443
+ },
444
+ content: unassignedContent
445
+ });
446
+ }
447
+ return document;
448
+ }
449
+ extractMetadata() {
450
+ const metadata = [];
451
+ // Try structured contributor data from meta.xml first
452
+ const contributorsByRole = this.extractContributorsFromMeta();
453
+ if (Object.keys(contributorsByRole).length) {
454
+ Object.entries(contributorsByRole).forEach(([role, contributors]) => {
455
+ metadata.push({
456
+ type: role,
457
+ content: { content: contributors, containerNodes: [] }
458
+ });
459
+ });
460
+ }
461
+ else {
462
+ // Fall back to legacy author extraction
463
+ const authors = this.extractAuthors();
464
+ if (authors.content.length) {
465
+ metadata.push({
466
+ type: "authors",
467
+ content: authors
468
+ });
469
+ }
470
+ }
471
+ // Extract abstract if present
472
+ const abstract = this.extractAbstract();
473
+ if (abstract.content.length) {
474
+ metadata.push({
475
+ type: "abstract",
476
+ content: abstract
477
+ });
478
+ }
479
+ // Extract keywords if present
480
+ const keywords = this.extractKeywords();
481
+ if (keywords.content.length) {
482
+ metadata.push({
483
+ type: "keywords",
484
+ content: keywords
485
+ });
486
+ }
487
+ return metadata;
488
+ }
489
+ extractContributorsFromMeta() {
490
+ if (!this.metaDoc) {
491
+ return {};
492
+ }
493
+ const userDefined = this.metaDoc.queryAll("meta:user-defined");
494
+ const contributors = [];
495
+ userDefined.forEach((prop) => {
496
+ const name = attr(prop, "meta:name");
497
+ if (!name || !name.startsWith("fidus_contributor_")) {
498
+ return;
499
+ }
500
+ const match = name.match(/^fidus_contributor_(\d+)_(\w+)$/);
501
+ if (!match) {
502
+ return;
503
+ }
504
+ const num = parseInt(match[1]);
505
+ const field = match[2];
506
+ const value = prop.textContent || "";
507
+ if (!contributors[num - 1]) {
508
+ contributors[num - 1] = {
509
+ type: "contributor",
510
+ attrs: {
511
+ firstname: "",
512
+ lastname: "",
513
+ email: "",
514
+ institution: "",
515
+ id_type: "",
516
+ id_value: "",
517
+ role: ""
518
+ }
519
+ };
520
+ }
521
+ if (field === "role") {
522
+ contributors[num - 1].attrs.role = value;
523
+ }
524
+ else if ([
525
+ "firstname",
526
+ "lastname",
527
+ "email",
528
+ "institution",
529
+ "id_type",
530
+ "id_value"
531
+ ].includes(field)) {
532
+ contributors[num - 1].attrs[field] = value;
533
+ }
534
+ });
535
+ const byRole = {};
536
+ contributors.forEach((contributor) => {
537
+ if (!contributor) {
538
+ return;
539
+ }
540
+ const role = contributor.attrs.role || "authors";
541
+ if (!byRole[role]) {
542
+ byRole[role] = [];
543
+ }
544
+ byRole[role].push(contributor);
545
+ });
546
+ return byRole;
547
+ }
548
+ extractAuthors() {
549
+ const authors = [];
550
+ // Try to find author information in metadata
551
+ const metaAuthors = this.contentDoc.queryAll("meta:user-defined", {
552
+ "meta:name": "author"
553
+ });
554
+ metaAuthors.forEach((authorMeta) => {
555
+ const authorText = authorMeta.textContent;
556
+ const [firstname = "", lastname = ""] = authorText.split(" ", 2);
557
+ authors.push({
558
+ type: "contributor",
559
+ attrs: {
560
+ firstname,
561
+ lastname,
562
+ email: "",
563
+ institution: ""
564
+ }
565
+ });
566
+ });
567
+ if (authors.length) {
568
+ return {
569
+ content: authors,
570
+ containerNodes: metaAuthors
571
+ };
572
+ }
573
+ // Also check for creator in document metadata
574
+ const creator = this.contentDoc.query("meta:creator");
575
+ if (creator) {
576
+ const [firstname = "", lastname = ""] = creator.textContent.split(" ", 2);
577
+ return {
578
+ content: [
579
+ {
580
+ type: "contributor",
581
+ attrs: {
582
+ firstname,
583
+ lastname,
584
+ email: "",
585
+ institution: ""
586
+ }
587
+ }
588
+ ],
589
+ containerNodes: []
590
+ };
591
+ }
592
+ return { content: [], containerNodes: [] };
593
+ }
594
+ extractAbstract() {
595
+ // Look for section titled "Abstract" or with abstract style
596
+ const abstractSection = this.contentDoc.query("text:section", {
597
+ "text:style-name": "Abstract"
598
+ }) ||
599
+ this.contentDoc.query("text:h", {
600
+ "text:outline-level": "1"
601
+ }); // Then check content for "Abstract"
602
+ if (abstractSection &&
603
+ (attr(abstractSection, "text:style-name") === "Abstract" ||
604
+ abstractSection.textContent.includes("Abstract"))) {
605
+ return {
606
+ content: this.convertContainer(abstractSection),
607
+ containerNodes: [abstractSection]
608
+ };
609
+ }
610
+ return {
611
+ content: [],
612
+ containerNodes: []
613
+ };
614
+ }
615
+ extractKeywords() {
616
+ // Look for keywords section or metadata
617
+ const keywordsSection = this.contentDoc.query("text:p", { "text:style-name": "Keywords" }) ||
618
+ this.contentDoc.query("meta:user-defined", {
619
+ "meta:name": "keywords"
620
+ });
621
+ if (keywordsSection) {
622
+ return {
623
+ content: this.convertContainer(keywordsSection),
624
+ containerNodes: [keywordsSection]
625
+ };
626
+ }
627
+ return { content: [], containerNodes: [] };
628
+ }
629
+ findMatchingTemplatePart(sectionTitle, templateParts) {
630
+ if (!sectionTitle) {
631
+ return null;
632
+ }
633
+ // Try exact match first
634
+ let matchingPart = templateParts.find((part) => part.type === "richtext_part" &&
635
+ !part.attrs.metadata &&
636
+ part.attrs.title.toLowerCase() === sectionTitle.toLowerCase());
637
+ if (!matchingPart) {
638
+ // Try fuzzy matching if exact match fails
639
+ matchingPart = templateParts.find((part) => part.type === "richtext_part" &&
640
+ !part.attrs.metadata &&
641
+ this.isSimilarTitle(part.attrs.title, sectionTitle));
642
+ }
643
+ return matchingPart;
644
+ }
645
+ isSimilarTitle(title1, title2) {
646
+ // Remove special characters and extra spaces
647
+ const normalize = (str) => str
648
+ .toLowerCase()
649
+ .replace(/[^a-z0-9]/g, "")
650
+ .trim();
651
+ const normalized1 = normalize(title1);
652
+ const normalized2 = normalize(title2);
653
+ // Check if one string contains the other
654
+ return (normalized1.includes(normalized2) ||
655
+ normalized2.includes(normalized1));
656
+ }
657
+ extractTitle() {
658
+ // First try to find paragraph with Title style
659
+ const titleParagraph = this.contentDoc.query("text:p", {
660
+ "text:style-name": "Title"
661
+ });
662
+ if (titleParagraph) {
663
+ return {
664
+ content: this.convertBlockNode(titleParagraph)?.content || [],
665
+ containerNodes: [titleParagraph]
666
+ };
667
+ }
668
+ // Fall back to first heading
669
+ const titleHeading = this.contentDoc.query("text:h", {
670
+ "text:outline-level": "1"
671
+ });
672
+ if (titleHeading) {
673
+ return {
674
+ content: this.convertBlockNode(titleHeading)?.content || [],
675
+ containerNodes: [titleHeading]
676
+ };
677
+ }
678
+ // Check for other common title style names
679
+ const commonTitleStyles = [
680
+ "title",
681
+ "doctitle",
682
+ "document-title",
683
+ "heading-title"
684
+ ];
685
+ for (const styleName of commonTitleStyles) {
686
+ const titleElement = this.contentDoc.query("text:p", {
687
+ "text:style-name": styleName
688
+ });
689
+ if (titleElement) {
690
+ return {
691
+ content: this.convertBlockNode(titleElement)?.content || [],
692
+ containerNodes: [titleElement]
693
+ };
694
+ }
695
+ }
696
+ // Check style properties for title-like formatting
697
+ const firstParagraph = this.contentDoc.query("text:p");
698
+ if (firstParagraph) {
699
+ const styleName = attr(firstParagraph, "text:style-name");
700
+ const style = this.styles[styleName];
701
+ if (style && this.isTitleStyle(style)) {
702
+ // Remove this node from the document so it's not processed again
703
+ return {
704
+ content: this.convertBlockNode(firstParagraph)?.content || [],
705
+ containerNodes: [firstParagraph]
706
+ };
707
+ }
708
+ }
709
+ return {
710
+ content: [],
711
+ containerNodes: []
712
+ };
713
+ }
714
+ isTitleStyle(style) {
715
+ // Check if style or its parent has characteristics of a title style
716
+ if (!style) {
717
+ return false;
718
+ }
719
+ // Check style name
720
+ if (style.title?.toLowerCase().includes("title")) {
721
+ return true;
722
+ }
723
+ // Check text properties for title-like formatting
724
+ const textProps = style.textProperties;
725
+ if (textProps) {
726
+ // Title usually has larger font size and/or bold weight
727
+ if (textProps.fontSize > 14 || textProps.bold) {
728
+ return true;
729
+ }
730
+ }
731
+ // Check paragraph properties
732
+ const paraProps = style.paragraphProperties;
733
+ if (paraProps) {
734
+ // Titles are often centered and have larger margins
735
+ if (paraProps.textAlign === "center" ||
736
+ (paraProps.marginTop > 0.5 && paraProps.marginBottom > 0.5)) {
737
+ return true;
738
+ }
739
+ }
740
+ // Check parent style if exists
741
+ if (style.parentStyleName) {
742
+ const parentStyle = this.styles[style.parentStyleName];
743
+ return this.isTitleStyle(parentStyle);
744
+ }
745
+ return false;
746
+ }
747
+ getSectionTitle(node, styleName) {
748
+ if (!node || !styleName) {
749
+ return null;
750
+ }
751
+ // For headings, use the text content as section title
752
+ if (node.tagName === "text:h") {
753
+ // Get the heading level
754
+ const level = parseInt(attr(node, "text:outline-level")) || 1;
755
+ // Only use level 1 and 2 headings as section titles
756
+ if (level <= 2) {
757
+ return node.textContent.trim();
758
+ }
759
+ }
760
+ // Check if the style indicates a section title
761
+ const style = this.styles[styleName];
762
+ if (style) {
763
+ // Check for explicit section title style
764
+ if (style.title ||
765
+ styleName.toLowerCase().includes("section") ||
766
+ styleName.toLowerCase().includes("title")) {
767
+ // If it's a styled paragraph, use its content as title
768
+ if (node.tagName === "text:p") {
769
+ return node.textContent.trim();
770
+ }
771
+ }
772
+ // Check if it's a custom section style
773
+ const parentStyle = style.parentStyleName
774
+ ? this.styles[style.parentStyleName]
775
+ : null;
776
+ if (parentStyle?.isSection) {
777
+ return node.textContent.trim();
778
+ }
779
+ }
780
+ // For text:section elements, check for section-name attribute
781
+ if (node.tagName === "text:section") {
782
+ const sectionName = attr(node, "text:name");
783
+ if (sectionName) {
784
+ return this.formatSectionName(sectionName);
785
+ }
786
+ }
787
+ return null;
788
+ }
789
+ formatSectionName(name) {
790
+ // Remove common suffixes
791
+ name = name.replace(/_?(section|part|chapter)$/i, "");
792
+ // Split by underscores or hyphens
793
+ const words = name.split(/[_-]/);
794
+ // Capitalize first letter of each word and join
795
+ return words
796
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
797
+ .join(" ")
798
+ .trim();
799
+ }
800
+ groupContentIntoSections(body) {
801
+ const sections = [];
802
+ let currentSection = {
803
+ title: null,
804
+ content: []
805
+ };
806
+ body.children.forEach((node) => {
807
+ const styleName = attr(node, "text:style-name");
808
+ const title = this.getSectionTitle(node, styleName);
809
+ if (title && this.isHeadingStyle(styleName)) {
810
+ // Start new section
811
+ if (currentSection.content.length) {
812
+ sections.push(currentSection);
813
+ }
814
+ currentSection = {
815
+ title: title,
816
+ content: []
817
+ };
818
+ }
819
+ const converted = [this.convertBlockNode(node)]
820
+ .filter((node) => node)
821
+ .flat();
822
+ converted.forEach((node) => currentSection.content.push(node));
823
+ });
824
+ // Add final section
825
+ if (currentSection.content.length) {
826
+ sections.push(currentSection);
827
+ }
828
+ return sections;
829
+ }
830
+ isCodeBlockStyle(styleName, style) {
831
+ if (!styleName) {
832
+ return false;
833
+ }
834
+ // Check if style name contains preformatted or code indicators
835
+ const lowerStyleName = styleName.toLowerCase();
836
+ if (lowerStyleName.includes("preformatted") ||
837
+ lowerStyleName.includes("code") ||
838
+ styleName === "Preformatted_20_Text") {
839
+ return true;
840
+ }
841
+ // Check if parent style is a code block style
842
+ if (style?.parentStyleName) {
843
+ const parentStyle = this.styles[style.parentStyleName];
844
+ return this.isCodeBlockStyle(style.parentStyleName, parentStyle);
845
+ }
846
+ // Check text properties for monospace fonts
847
+ if (style?.textProperties?.fontFamily) {
848
+ const fontFamily = style.textProperties.fontFamily.toLowerCase();
849
+ const monospacePatterns = [
850
+ "courier",
851
+ "consolas",
852
+ "monaco",
853
+ "menlo",
854
+ "lucida console",
855
+ "liberation mono",
856
+ "dejavu sans mono",
857
+ "bitstream vera sans mono",
858
+ "source code pro",
859
+ "fira code"
860
+ ];
861
+ return monospacePatterns.some((pattern) => fontFamily.includes(pattern));
862
+ }
863
+ return false;
864
+ }
865
+ isHeadingStyle(styleName) {
866
+ if (!styleName) {
867
+ return false;
868
+ }
869
+ const style = this.styles[styleName];
870
+ if (!style) {
871
+ return false;
872
+ }
873
+ // Check multiple indicators that this might be a heading style
874
+ return (
875
+ // Direct heading indicators
876
+ style.isHeading ||
877
+ styleName.toLowerCase().includes("heading") ||
878
+ styleName.toLowerCase().includes("title") ||
879
+ // Check outline level property
880
+ Boolean(style.outlineLevel) ||
881
+ // Check if it's derived from a heading style
882
+ (style.parentStyleName &&
883
+ this.isHeadingStyle(style.parentStyleName)) ||
884
+ // Check specific formatting that's typical for headings
885
+ (style.paragraphProperties &&
886
+ // Larger margins than normal paragraphs
887
+ (style.paragraphProperties.marginTop > 0.3 ||
888
+ style.paragraphProperties.marginBottom > 0.3 ||
889
+ // Different alignment
890
+ style.paragraphProperties.textAlign === "center")) ||
891
+ // Check text properties typical for headings
892
+ (style.textProperties &&
893
+ // Larger font size
894
+ (style.textProperties.fontSize > 12 ||
895
+ // Bold text
896
+ style.textProperties.bold ||
897
+ // Different font family
898
+ style.textProperties.fontFamily)));
899
+ }
900
+ convertContainer(container) {
901
+ return container.children
902
+ .map((node) => this.convertBlockNode(node))
903
+ .filter((node) => node)
904
+ .flat();
905
+ }
906
+ convertBlockNode(node) {
907
+ const track = this.currentTracks.map((track) => ({
908
+ type: track.type,
909
+ user: track.attrs.user,
910
+ username: track.attrs.username,
911
+ date: track.attrs.date
912
+ }));
913
+ const attrs = track.length ? { track } : {};
914
+ switch (node.tagName) {
915
+ case "text:p":
916
+ if (node.children.length === 1 &&
917
+ node.children[0].tagName === "draw:frame") {
918
+ // Paragraph consists of only one figure/image.
919
+ return this.convertImage(node.children[0], attrs);
920
+ }
921
+ return this.convertParagraph(node, attrs);
922
+ case "text:h":
923
+ return this.convertHeading(node, attrs);
924
+ case "text:list":
925
+ return this.convertList(node, attrs);
926
+ case "draw:frame":
927
+ return this.convertImage(node, attrs);
928
+ case "draw:object":
929
+ return this.convertObject(node, attrs);
930
+ case "table:table":
931
+ return this.convertTable(node, attrs);
932
+ case "text:sequence-decls":
933
+ case "office:forms":
934
+ case "text:tracked-changes":
935
+ return null;
936
+ case "text:bibliography":
937
+ // LibreOffice native bibliography — rendered output only,
938
+ // skip entirely in favour of Fidus Writer's own system.
939
+ return null;
940
+ case "text:section": {
941
+ // Skip bibliography sections inserted by citation managers
942
+ // (Zotero: name contains "ZOTERO_BIBL"/"CSL_BIBLIOGRAPHY",
943
+ // JabRef: name is "JR_bib" / "JR_BIB").
944
+ const sectionName = attr(node, "text:name") || "";
945
+ if (isOdtBibliographySection(sectionName)) {
946
+ return null;
947
+ }
948
+ // Other named sections are not bibliographies — fall through
949
+ // to default handling (treat children as block content).
950
+ return this.convertContainer(node);
951
+ }
952
+ default:
953
+ console.warn(`Unsupported block node: ${node.tagName}`);
954
+ return null;
955
+ }
956
+ }
957
+ convertParagraph(node, attrs = {}) {
958
+ const styleName = attr(node, "text:style-name");
959
+ const style = this.styles[styleName];
960
+ // Check if this is a code block (preformatted text)
961
+ if (this.isCodeBlockStyle(styleName, style)) {
962
+ attrs = Object.assign({
963
+ track: [],
964
+ language: "",
965
+ category: "",
966
+ title: "",
967
+ id: ""
968
+ }, attrs);
969
+ return {
970
+ type: "code_block",
971
+ attrs,
972
+ content: this.convertNodeChildren(node)
973
+ };
974
+ }
975
+ // Check if this paragraph is title-like
976
+ if (this.isTitleStyle(style)) {
977
+ attrs = Object.assign({
978
+ id: randomHeadingId()
979
+ }, attrs);
980
+ return {
981
+ type: "heading1",
982
+ attrs,
983
+ content: this.convertNodeChildren(node)
984
+ };
985
+ }
986
+ if (this.isHeadingStyle(styleName)) {
987
+ return this.convertHeading(node, attrs);
988
+ }
989
+ return {
990
+ type: "paragraph",
991
+ attrs,
992
+ content: this.convertNodeChildren(node)
993
+ };
994
+ }
995
+ convertHeading(node, attrs = {}) {
996
+ const level = parseInt(attr(node, "text:outline-level") || "1") || 1;
997
+ // Check for bookmark
998
+ let id = null;
999
+ const bookmarkStart = node.query("text:bookmark-start");
1000
+ if (bookmarkStart) {
1001
+ const refName = attr(bookmarkStart, "text:name");
1002
+ if (refName && this.referenceableObjects[refName]) {
1003
+ id = this.referenceableObjects[refName].id;
1004
+ }
1005
+ }
1006
+ attrs = Object.assign({
1007
+ id: id || randomHeadingId()
1008
+ }, attrs);
1009
+ return {
1010
+ type: `heading${level}`,
1011
+ attrs,
1012
+ content: this.convertNodeChildren(node)
1013
+ };
1014
+ }
1015
+ convertNodeChildren(node, currentStyleMarks = []) {
1016
+ let insideCitationReferenceMark = false;
1017
+ let insideBibliographyReferenceMark = false;
1018
+ return node.children
1019
+ .map((child) => {
1020
+ if (insideBibliographyReferenceMark) {
1021
+ // Swallow all rendered bibliography content until the
1022
+ // closing mark — we have our own bibliography system.
1023
+ if (child.tagName === "text:reference-mark-end") {
1024
+ const name = attr(child, "text:name");
1025
+ if (name && isOdtBibliographyReferenceMark(name)) {
1026
+ insideBibliographyReferenceMark = false;
1027
+ }
1028
+ }
1029
+ return null;
1030
+ }
1031
+ if (insideCitationReferenceMark) {
1032
+ if (child.tagName === "text:reference-mark-end") {
1033
+ // Process citation when we hit the end mark
1034
+ const name = attr(child, "text:name");
1035
+ if (name && isOdtCitationMark(name)) {
1036
+ insideCitationReferenceMark = false;
1037
+ return this.convertCitation(name, currentStyleMarks);
1038
+ }
1039
+ }
1040
+ return null;
1041
+ }
1042
+ switch (child.tagName) {
1043
+ case "text:change-start": {
1044
+ const changeId = attr(child, "text:change-id");
1045
+ const track = this.tracks[changeId];
1046
+ if (track) {
1047
+ const trackMark = {
1048
+ type: track.type,
1049
+ attrs: {
1050
+ user: track.user,
1051
+ username: track.username,
1052
+ date: track.date
1053
+ }
1054
+ };
1055
+ if (track.type === "insertion") {
1056
+ trackMark.attrs.approved = track.approved;
1057
+ }
1058
+ this.currentTracks.push(trackMark);
1059
+ }
1060
+ return null;
1061
+ }
1062
+ case "text:change-end": {
1063
+ const changeId = attr(child, "text:change-id");
1064
+ const track = this.tracks[changeId];
1065
+ if (track) {
1066
+ this.currentTracks = this.currentTracks.filter((mark) => mark.type !== track.type);
1067
+ }
1068
+ return null;
1069
+ }
1070
+ case "#text":
1071
+ return this.convertText(String(child.textContent), currentStyleMarks);
1072
+ case "text:s": // space
1073
+ return this.convertText(" ", currentStyleMarks);
1074
+ case "text:span": {
1075
+ return this.convertSpan(child, currentStyleMarks);
1076
+ }
1077
+ case "text:a":
1078
+ return this.convertLink(child, currentStyleMarks);
1079
+ case "text:note":
1080
+ return this.convertFootnote(child, currentStyleMarks);
1081
+ case "office:annotation":
1082
+ return this.convertAnnotationStart(child);
1083
+ case "office:annotation-end":
1084
+ return this.convertAnnotationEnd(child);
1085
+ case "text:reference-mark-start": {
1086
+ const name = attr(child, "text:name");
1087
+ if (name && isOdtCitationMark(name)) {
1088
+ insideCitationReferenceMark = true;
1089
+ }
1090
+ else if (name &&
1091
+ isOdtBibliographyReferenceMark(name)) {
1092
+ insideBibliographyReferenceMark = true;
1093
+ }
1094
+ return null;
1095
+ }
1096
+ case "text:bibliography-mark":
1097
+ return this.convertBibliographyMark(child, currentStyleMarks);
1098
+ case "text:bookmark-ref":
1099
+ return this.convertHeadingReference(child);
1100
+ case "text:sequence-ref":
1101
+ return this.convertFigureReference(child);
1102
+ case "text:soft-page-break":
1103
+ return null;
1104
+ default:
1105
+ console.warn(`Unsupported inline node: ${child.tagName}`);
1106
+ }
1107
+ })
1108
+ .filter((node) => node)
1109
+ .flat();
1110
+ }
1111
+ getCurrentMarks(currentStyleMarks = []) {
1112
+ const commentMarks = [];
1113
+ // Add comment marks for any active comment IDs
1114
+ this.currentCommentIds.forEach((commentId) => {
1115
+ commentMarks.push({
1116
+ type: "comment",
1117
+ attrs: {
1118
+ id: commentId
1119
+ }
1120
+ });
1121
+ });
1122
+ return [...currentStyleMarks, ...this.currentTracks, ...commentMarks];
1123
+ }
1124
+ convertText(text, currentStyleMarks) {
1125
+ const textNode = {
1126
+ type: "text",
1127
+ text
1128
+ };
1129
+ const marks = this.getCurrentMarks(currentStyleMarks);
1130
+ if (marks.length) {
1131
+ textNode.marks = marks;
1132
+ }
1133
+ return textNode;
1134
+ }
1135
+ convertSpan(node, currentStyleMarks) {
1136
+ const styleName = attr(node, "text:style-name");
1137
+ const style = this.styles[styleName];
1138
+ if (style?.textProperties?.bold) {
1139
+ currentStyleMarks = [...currentStyleMarks, { type: "strong" }];
1140
+ }
1141
+ if (style?.textProperties?.italic) {
1142
+ currentStyleMarks = [...currentStyleMarks, { type: "em" }];
1143
+ }
1144
+ // Handle superscript and subscript
1145
+ if (style?.textProperties?.textPosition) {
1146
+ const position = style.textProperties.textPosition;
1147
+ if (position.includes("super")) {
1148
+ currentStyleMarks = [...currentStyleMarks, { type: "sup" }];
1149
+ }
1150
+ else if (position.includes("sub")) {
1151
+ currentStyleMarks = [...currentStyleMarks, { type: "sub" }];
1152
+ }
1153
+ }
1154
+ // Handle inline code (monospace fonts)
1155
+ if (style?.textProperties?.fontFamily) {
1156
+ const fontFamily = style.textProperties.fontFamily.toLowerCase();
1157
+ const monospacePatterns = [
1158
+ "courier",
1159
+ "consolas",
1160
+ "monaco",
1161
+ "menlo",
1162
+ "lucida console",
1163
+ "liberation mono",
1164
+ "dejavu sans mono",
1165
+ "bitstream vera sans mono",
1166
+ "source code pro",
1167
+ "fira code",
1168
+ "ubuntu mono",
1169
+ "droid sans mono",
1170
+ "monospace"
1171
+ ];
1172
+ const isMonospace = monospacePatterns.some((pattern) => fontFamily.includes(pattern));
1173
+ if (isMonospace) {
1174
+ currentStyleMarks = [...currentStyleMarks, { type: "code" }];
1175
+ }
1176
+ }
1177
+ return this.convertNodeChildren(node, currentStyleMarks);
1178
+ }
1179
+ convertFootnote(node, currentStyleMarks) {
1180
+ const noteBody = node.query("text:note-body");
1181
+ if (!noteBody) {
1182
+ return null;
1183
+ }
1184
+ // Get the first paragraph in the footnote
1185
+ const firstParagraph = noteBody.query("text:p");
1186
+ if (!firstParagraph) {
1187
+ return null;
1188
+ }
1189
+ // Check if this is a citation-only footnote
1190
+ const referenceMarkStart = firstParagraph.query("text:reference-mark-start");
1191
+ const referenceMarkEnd = firstParagraph.query("text:reference-mark-end");
1192
+ const markName = attr(referenceMarkStart, "text:name");
1193
+ if (referenceMarkStart &&
1194
+ referenceMarkEnd &&
1195
+ markName &&
1196
+ isOdtCitationMark(markName) &&
1197
+ // Check that there's no content outside the reference marks
1198
+ firstParagraph.children.every((child) => child.tagName === "text:reference-mark-start" ||
1199
+ child.tagName === "text:reference-mark-end" ||
1200
+ (child.tagName === "text:span" &&
1201
+ child.previousSibling?.tagName ===
1202
+ "text:reference-mark-start" &&
1203
+ child.nextSibling?.tagName ===
1204
+ "text:reference-mark-end"))) {
1205
+ // If it's a citation-only footnote, convert it directly to a citation
1206
+ return this.convertCitation(markName, currentStyleMarks);
1207
+ }
1208
+ // Otherwise, convert as regular footnote
1209
+ return {
1210
+ type: "footnote",
1211
+ attrs: {
1212
+ footnote: this.convertContainer(noteBody)
1213
+ },
1214
+ marks: this.getCurrentMarks(currentStyleMarks)
1215
+ };
1216
+ }
1217
+ convertCitation(markName, currentStyleMarks) {
1218
+ const citationNode = parseOdtReferenceMark(markName, this.bibliography, this.bibDB);
1219
+ if (citationNode) {
1220
+ citationNode.marks = this.getCurrentMarks(currentStyleMarks);
1221
+ return citationNode;
1222
+ }
1223
+ return null;
1224
+ }
1225
+ convertBibliographyMark(bibMarkNode, currentStyleMarks) {
1226
+ const citationNode = parseOdtBibliographyMark(bibMarkNode, this.bibliography);
1227
+ if (citationNode) {
1228
+ citationNode.marks = this.getCurrentMarks(currentStyleMarks);
1229
+ return citationNode;
1230
+ }
1231
+ return null;
1232
+ }
1233
+ convertList(node, attrs) {
1234
+ const listStyle = attr(node, "text:style-name");
1235
+ const isOrdered = this.isOrderedList(listStyle);
1236
+ attrs = Object.assign({
1237
+ id: randomListId()
1238
+ }, attrs);
1239
+ if (isOrdered) {
1240
+ attrs.order = 1;
1241
+ }
1242
+ return {
1243
+ type: isOrdered ? "ordered_list" : "bullet_list",
1244
+ attrs,
1245
+ content: node.queryAll("text:list-item").map((item) => ({
1246
+ type: "list_item",
1247
+ content: this.convertContainer(item)
1248
+ }))
1249
+ };
1250
+ }
1251
+ convertAnnotationStart(node) {
1252
+ const commentId = (attr(node, "office:name") || "")
1253
+ .replace(/\D/g, "")
1254
+ .slice(0, 9);
1255
+ if (commentId && this.comments[commentId]) {
1256
+ this.currentCommentIds.push(commentId);
1257
+ }
1258
+ return null;
1259
+ }
1260
+ convertAnnotationEnd(node) {
1261
+ const commentId = (attr(node, "office:name") || "")
1262
+ .replace(/\D/g, "")
1263
+ .slice(0, 9);
1264
+ if (commentId) {
1265
+ const index = this.currentCommentIds.indexOf(commentId);
1266
+ if (index !== -1) {
1267
+ this.currentCommentIds.splice(index, 1);
1268
+ }
1269
+ }
1270
+ return null;
1271
+ }
1272
+ convertHeadingReference(node) {
1273
+ const refName = attr(node, "text:ref-name");
1274
+ if (!refName || !this.referenceableObjects[refName]) {
1275
+ return null;
1276
+ }
1277
+ const targetObject = this.referenceableObjects[refName];
1278
+ if (targetObject.type !== "heading") {
1279
+ return null;
1280
+ }
1281
+ return {
1282
+ type: "cross_reference",
1283
+ attrs: {
1284
+ id: targetObject.id,
1285
+ title: targetObject.node.textContent
1286
+ }
1287
+ };
1288
+ }
1289
+ convertFigureReference(node) {
1290
+ const refName = attr(node, "text:ref-name");
1291
+ if (!refName || !this.referenceableObjects[refName]) {
1292
+ return null;
1293
+ }
1294
+ const targetObject = this.referenceableObjects[refName];
1295
+ if (targetObject.type !== "figure") {
1296
+ return null;
1297
+ }
1298
+ // Find the caption text within the figure
1299
+ const caption = targetObject.node.query("text:p")?.textContent || "";
1300
+ return {
1301
+ type: "cross_reference",
1302
+ attrs: {
1303
+ id: targetObject.id,
1304
+ title: caption
1305
+ }
1306
+ };
1307
+ }
1308
+ isOrderedList(styleName) {
1309
+ if (!this.stylesDoc) {
1310
+ return false;
1311
+ }
1312
+ const listStyle = this.stylesDoc.query("text:list-style", {
1313
+ "style:name": styleName
1314
+ });
1315
+ return listStyle?.query("text:list-level-style-number") !== null;
1316
+ }
1317
+ convertImage(node, attrs = {}) {
1318
+ const imageElement = node.query("draw:image");
1319
+ if (!imageElement) {
1320
+ return null;
1321
+ }
1322
+ const frame = node.closest("draw:frame");
1323
+ if (!frame) {
1324
+ return null;
1325
+ }
1326
+ const href = attr(imageElement, "xlink:href");
1327
+ if (!href || !href.startsWith("Pictures/")) {
1328
+ return null;
1329
+ }
1330
+ const imageId = Math.floor(Math.random() * 1000000);
1331
+ const width = this.convertLength(attr(node, "svg:width"));
1332
+ const height = this.convertLength(attr(node, "svg:height"));
1333
+ const title = href.split("/").pop();
1334
+ this.images[imageId] = {
1335
+ id: imageId,
1336
+ title,
1337
+ copyright: {
1338
+ holder: false,
1339
+ year: false,
1340
+ freeToRead: true,
1341
+ licenses: []
1342
+ },
1343
+ image: href,
1344
+ file_type: this.getImageFileType(title),
1345
+ file: null,
1346
+ width,
1347
+ height,
1348
+ checksum: 0
1349
+ };
1350
+ // Find sequence element for figure reference
1351
+ const sequence = frame.query("text:sequence");
1352
+ let figureId = null;
1353
+ if (sequence) {
1354
+ const refName = attr(sequence, "text:ref-name");
1355
+ if (refName && this.referenceableObjects[refName]) {
1356
+ figureId = this.referenceableObjects[refName].id;
1357
+ }
1358
+ }
1359
+ const caption = node.query("text:p");
1360
+ const captionContent = caption ? this.convertNodeChildren(caption) : [];
1361
+ attrs = Object.assign({
1362
+ id: figureId || randomFigureId(),
1363
+ aligned: "center",
1364
+ width: Math.min(Math.round((width / 8.5) * 100), 100),
1365
+ caption: Boolean(captionContent.length)
1366
+ }, attrs);
1367
+ const figureCaption = { type: "figure_caption" };
1368
+ if (captionContent.length) {
1369
+ figureCaption.content = captionContent;
1370
+ }
1371
+ return {
1372
+ type: "figure",
1373
+ attrs,
1374
+ content: [
1375
+ {
1376
+ type: "image",
1377
+ attrs: {
1378
+ image: imageId
1379
+ }
1380
+ },
1381
+ figureCaption
1382
+ ]
1383
+ };
1384
+ }
1385
+ getImageFileType(filename) {
1386
+ const ext = filename.split(".").pop().toLowerCase();
1387
+ switch (ext) {
1388
+ case "avif":
1389
+ case "avifs":
1390
+ return "image/avif";
1391
+ case "png":
1392
+ return "image/png";
1393
+ case "jpg":
1394
+ case "jpeg":
1395
+ return "image/jpeg";
1396
+ case "gif":
1397
+ return "image/gif";
1398
+ case "svg":
1399
+ return "image/svg+xml";
1400
+ case "webp":
1401
+ return "image/webp";
1402
+ default:
1403
+ return "image/png"; // Default fallback
1404
+ }
1405
+ }
1406
+ convertLength(length) {
1407
+ if (!length) {
1408
+ return 0;
1409
+ }
1410
+ // Match number and unit
1411
+ const match = length.match(/^(-?\d*\.?\d+)(pt|cm|mm|in|pc|px|%)?$/);
1412
+ if (!match) {
1413
+ return 0;
1414
+ }
1415
+ const [_, value, unit = "pt"] = match;
1416
+ const numValue = parseFloat(value);
1417
+ // Convert to inches first (as base unit)
1418
+ switch (unit) {
1419
+ case "pt": // points
1420
+ return numValue / 72;
1421
+ case "pc": // picas (1 pica = 12 points)
1422
+ return (numValue * 12) / 72;
1423
+ case "cm": // centimeters
1424
+ return numValue / 2.54;
1425
+ case "mm": // millimeters
1426
+ return numValue / 25.4;
1427
+ case "in": // inches
1428
+ return numValue;
1429
+ case "px": // pixels (assuming 96 DPI)
1430
+ return numValue / 96;
1431
+ case "%": // percentage (return as is)
1432
+ return numValue;
1433
+ default:
1434
+ return 0;
1435
+ }
1436
+ }
1437
+ convertTable(node, attrs) {
1438
+ const width = attr(node, "style:rel-width")?.replace("%", "") || "100";
1439
+ const styleName = attr(node, "table:style-name");
1440
+ const style = this.styles[styleName];
1441
+ const aligned = style?.tableProperties.align || "center";
1442
+ attrs = Object.assign({
1443
+ id: randomTableId(),
1444
+ track: parseTracks(attr(node, "text:change-id")),
1445
+ width,
1446
+ aligned,
1447
+ layout: "fixed",
1448
+ category: "none",
1449
+ caption: false
1450
+ }, attrs);
1451
+ return {
1452
+ type: "table",
1453
+ attrs,
1454
+ content: [
1455
+ { type: "table_caption" },
1456
+ {
1457
+ type: "table_body",
1458
+ content: node
1459
+ .queryAll("table:table-row")
1460
+ .map((row) => this.convertTableRow(row))
1461
+ }
1462
+ ]
1463
+ };
1464
+ }
1465
+ convertTableRow(row) {
1466
+ return {
1467
+ type: "table_row",
1468
+ content: row
1469
+ .queryAll(["table:table-cell", "table:covered-table-cell"])
1470
+ .map((cell) => this.convertTableCell(cell))
1471
+ };
1472
+ }
1473
+ convertTableCell(node) {
1474
+ if (node.tagName === "table:covered-table-cell") {
1475
+ return null;
1476
+ }
1477
+ return {
1478
+ type: "table_cell",
1479
+ attrs: {
1480
+ colspan: parseInt(attr(node, "table:number-columns-spanned")) || 1,
1481
+ rowspan: parseInt(attr(node, "table:number-rows-spanned")) ||
1482
+ 1,
1483
+ track: parseTracks(attr(node, "text:change-id"))
1484
+ },
1485
+ content: this.convertContainer(node)
1486
+ };
1487
+ }
1488
+ convertLink(node, currentStyleMarks) {
1489
+ const href = attr(node, "xlink:href");
1490
+ currentStyleMarks = currentStyleMarks.concat([
1491
+ { type: "link", attrs: { href } }
1492
+ ]);
1493
+ return this.convertNodeChildren(node, currentStyleMarks);
1494
+ }
1495
+ detectLanguage() {
1496
+ // Try to detect document language in following order:
1497
+ // 1. From document content
1498
+ // 2. From document styles
1499
+ // 3. Default to "en-US"
1500
+ // Check content language
1501
+ if (this.contentDoc) {
1502
+ const langAttr = attr(this.contentDoc, "office:default-language") ||
1503
+ attr(this.contentDoc, "dc:language");
1504
+ if (langAttr) {
1505
+ return langAttr;
1506
+ }
1507
+ const firstParagraph = this.contentDoc.query("text:p");
1508
+ if (firstParagraph) {
1509
+ const paraLang = attr(firstParagraph, "xml:lang");
1510
+ if (paraLang) {
1511
+ return paraLang;
1512
+ }
1513
+ }
1514
+ }
1515
+ // Check styles language
1516
+ if (this.stylesDoc) {
1517
+ const defaultStyle = this.stylesDoc.query("style:default-style");
1518
+ if (defaultStyle) {
1519
+ const styleLang = attr(defaultStyle, "fo:language") ||
1520
+ attr(defaultStyle, "style:language-complex");
1521
+ if (styleLang) {
1522
+ return styleLang;
1523
+ }
1524
+ }
1525
+ }
1526
+ // Default to "en-US"
1527
+ return "en-US";
1528
+ }
1529
+ }
1530
+ //# sourceMappingURL=convert.js.map