@fiduswriter/editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +22 -0
  3. package/dist/bibliography/tools.js +53 -0
  4. package/dist/bibliography/tools.js.map +1 -0
  5. package/dist/citations/index.js +339 -0
  6. package/dist/citations/index.js.map +1 -0
  7. package/dist/citations/render.js +47 -0
  8. package/dist/citations/render.js.map +1 -0
  9. package/dist/clipboard/copy/index.js +2 -0
  10. package/dist/clipboard/copy/index.js.map +1 -0
  11. package/dist/clipboard/copy/schema.js +54 -0
  12. package/dist/clipboard/copy/schema.js.map +1 -0
  13. package/dist/clipboard/copy/serializers.js +132 -0
  14. package/dist/clipboard/copy/serializers.js.map +1 -0
  15. package/dist/clipboard/paste/fidus_writer.js +45 -0
  16. package/dist/clipboard/paste/fidus_writer.js.map +1 -0
  17. package/dist/clipboard/paste/general.js +76 -0
  18. package/dist/clipboard/paste/general.js.map +1 -0
  19. package/dist/clipboard/paste/google_docs.js +24 -0
  20. package/dist/clipboard/paste/google_docs.js.map +1 -0
  21. package/dist/clipboard/paste/html.js +68 -0
  22. package/dist/clipboard/paste/html.js.map +1 -0
  23. package/dist/clipboard/paste/index.js +3 -0
  24. package/dist/clipboard/paste/index.js.map +1 -0
  25. package/dist/clipboard/paste/libreoffice_writer.js +27 -0
  26. package/dist/clipboard/paste/libreoffice_writer.js.map +1 -0
  27. package/dist/clipboard/paste/microsoft_word.js +79 -0
  28. package/dist/clipboard/paste/microsoft_word.js.map +1 -0
  29. package/dist/clipboard/paste/text.js +41 -0
  30. package/dist/clipboard/paste/text.js.map +1 -0
  31. package/dist/collab/chat.js +154 -0
  32. package/dist/collab/chat.js.map +1 -0
  33. package/dist/collab/colors.js +62 -0
  34. package/dist/collab/colors.js.map +1 -0
  35. package/dist/collab/doc.js +1090 -0
  36. package/dist/collab/doc.js.map +1 -0
  37. package/dist/collab/index.js +75 -0
  38. package/dist/collab/index.js.map +1 -0
  39. package/dist/collab/merge/changeset.js +90 -0
  40. package/dist/collab/merge/changeset.js.map +1 -0
  41. package/dist/collab/merge/editor.js +708 -0
  42. package/dist/collab/merge/editor.js.map +1 -0
  43. package/dist/collab/merge/footnotes.js +149 -0
  44. package/dist/collab/merge/footnotes.js.map +1 -0
  45. package/dist/collab/merge/index.js +270 -0
  46. package/dist/collab/merge/index.js.map +1 -0
  47. package/dist/collab/merge/recreate_transform.js +259 -0
  48. package/dist/collab/merge/recreate_transform.js.map +1 -0
  49. package/dist/collab/merge/schema.js +117 -0
  50. package/dist/collab/merge/schema.js.map +1 -0
  51. package/dist/collab/merge/state_plugins/action.js +138 -0
  52. package/dist/collab/merge/state_plugins/action.js.map +1 -0
  53. package/dist/collab/merge/state_plugins/clipboard.js +32 -0
  54. package/dist/collab/merge/state_plugins/clipboard.js.map +1 -0
  55. package/dist/collab/merge/state_plugins/diff.js +541 -0
  56. package/dist/collab/merge/state_plugins/diff.js.map +1 -0
  57. package/dist/collab/merge/state_plugins/index.js +3 -0
  58. package/dist/collab/merge/state_plugins/index.js.map +1 -0
  59. package/dist/collab/merge/tools.js +175 -0
  60. package/dist/collab/merge/tools.js.map +1 -0
  61. package/dist/collab/templates.js +10 -0
  62. package/dist/collab/templates.js.map +1 -0
  63. package/dist/comments/comment.js +17 -0
  64. package/dist/comments/comment.js.map +1 -0
  65. package/dist/comments/editors/answer.js +43 -0
  66. package/dist/comments/editors/answer.js.map +1 -0
  67. package/dist/comments/editors/comment.js +278 -0
  68. package/dist/comments/editors/comment.js.map +1 -0
  69. package/dist/comments/editors/index.js +4 -0
  70. package/dist/comments/editors/index.js.map +1 -0
  71. package/dist/comments/editors/notify.js +13 -0
  72. package/dist/comments/editors/notify.js.map +1 -0
  73. package/dist/comments/editors/schema.js +60 -0
  74. package/dist/comments/editors/schema.js.map +1 -0
  75. package/dist/comments/index.js +11 -0
  76. package/dist/comments/index.js.map +1 -0
  77. package/dist/comments/interactions.js +379 -0
  78. package/dist/comments/interactions.js.map +1 -0
  79. package/dist/comments/store.js +438 -0
  80. package/dist/comments/store.js.map +1 -0
  81. package/dist/contacts/add_dialog.js +88 -0
  82. package/dist/contacts/add_dialog.js.map +1 -0
  83. package/dist/contacts/templates.js +23 -0
  84. package/dist/contacts/templates.js.map +1 -0
  85. package/dist/copyright_dialog/index.js +148 -0
  86. package/dist/copyright_dialog/index.js.map +1 -0
  87. package/dist/copyright_dialog/templates.js +48 -0
  88. package/dist/copyright_dialog/templates.js.map +1 -0
  89. package/dist/databases/bibliography.js +162 -0
  90. package/dist/databases/bibliography.js.map +1 -0
  91. package/dist/databases/images.js +260 -0
  92. package/dist/databases/images.js.map +1 -0
  93. package/dist/databases/index.js +55 -0
  94. package/dist/databases/index.js.map +1 -0
  95. package/dist/dialogs/citation.js +321 -0
  96. package/dist/dialogs/citation.js.map +1 -0
  97. package/dist/dialogs/code_block.js +192 -0
  98. package/dist/dialogs/code_block.js.map +1 -0
  99. package/dist/dialogs/contributor.js +132 -0
  100. package/dist/dialogs/contributor.js.map +1 -0
  101. package/dist/dialogs/figure.js +378 -0
  102. package/dist/dialogs/figure.js.map +1 -0
  103. package/dist/dialogs/index.js +11 -0
  104. package/dist/dialogs/index.js.map +1 -0
  105. package/dist/dialogs/language.js +47 -0
  106. package/dist/dialogs/language.js.map +1 -0
  107. package/dist/dialogs/link.js +243 -0
  108. package/dist/dialogs/link.js.map +1 -0
  109. package/dist/dialogs/math.js +121 -0
  110. package/dist/dialogs/math.js.map +1 -0
  111. package/dist/dialogs/ordered_list.js +67 -0
  112. package/dist/dialogs/ordered_list.js.map +1 -0
  113. package/dist/dialogs/revision.js +36 -0
  114. package/dist/dialogs/revision.js.map +1 -0
  115. package/dist/dialogs/subsup.js +109 -0
  116. package/dist/dialogs/subsup.js.map +1 -0
  117. package/dist/dialogs/table.js +217 -0
  118. package/dist/dialogs/table.js.map +1 -0
  119. package/dist/dialogs/templates.js +366 -0
  120. package/dist/dialogs/templates.js.map +1 -0
  121. package/dist/document_template/exporter.js +83 -0
  122. package/dist/document_template/exporter.js.map +1 -0
  123. package/dist/document_template/index.js +327 -0
  124. package/dist/document_template/index.js.map +1 -0
  125. package/dist/documents/access_rights/index.js +532 -0
  126. package/dist/documents/access_rights/index.js.map +1 -0
  127. package/dist/documents/access_rights/templates.js +150 -0
  128. package/dist/documents/access_rights/templates.js.map +1 -0
  129. package/dist/e2ee/encryptor.js +201 -0
  130. package/dist/e2ee/encryptor.js.map +1 -0
  131. package/dist/e2ee/key-manager.js +171 -0
  132. package/dist/e2ee/key-manager.js.map +1 -0
  133. package/dist/e2ee/passphrase-crypto.js +365 -0
  134. package/dist/e2ee/passphrase-crypto.js.map +1 -0
  135. package/dist/e2ee/passphrase-dialog.js +548 -0
  136. package/dist/e2ee/passphrase-dialog.js.map +1 -0
  137. package/dist/e2ee/passphrase-manager.js +350 -0
  138. package/dist/e2ee/passphrase-manager.js.map +1 -0
  139. package/dist/e2ee/password-dialog.js +552 -0
  140. package/dist/e2ee/password-dialog.js.map +1 -0
  141. package/dist/e2ee/snapshot-manager.js +238 -0
  142. package/dist/e2ee/snapshot-manager.js.map +1 -0
  143. package/dist/exporter/native/copy.js +29 -0
  144. package/dist/exporter/native/copy.js.map +1 -0
  145. package/dist/exporter/native/file.js +19 -0
  146. package/dist/exporter/native/file.js.map +1 -0
  147. package/dist/exporter/native/index.js +4 -0
  148. package/dist/exporter/native/index.js.map +1 -0
  149. package/dist/exporter/native/revision.js +54 -0
  150. package/dist/exporter/native/revision.js.map +1 -0
  151. package/dist/exporter/native/zip.js +2 -0
  152. package/dist/exporter/native/zip.js.map +1 -0
  153. package/dist/footnotes/editor.js +180 -0
  154. package/dist/footnotes/editor.js.map +1 -0
  155. package/dist/footnotes/index.js +15 -0
  156. package/dist/footnotes/index.js.map +1 -0
  157. package/dist/footnotes/layout.js +125 -0
  158. package/dist/footnotes/layout.js.map +1 -0
  159. package/dist/footnotes/state_plugins/access_rights.js +25 -0
  160. package/dist/footnotes/state_plugins/access_rights.js.map +1 -0
  161. package/dist/footnotes/state_plugins/index.js +2 -0
  162. package/dist/footnotes/state_plugins/index.js.map +1 -0
  163. package/dist/images/edit_dialog/edit_dialog/index.js +186 -0
  164. package/dist/images/edit_dialog/edit_dialog/index.js.map +1 -0
  165. package/dist/images/edit_dialog/edit_dialog/model.js +152 -0
  166. package/dist/images/edit_dialog/edit_dialog/model.js.map +1 -0
  167. package/dist/images/edit_dialog/edit_dialog/templates.js +33 -0
  168. package/dist/images/edit_dialog/edit_dialog/templates.js.map +1 -0
  169. package/dist/images/edit_dialog/model.js +6 -0
  170. package/dist/images/edit_dialog/model.js.map +1 -0
  171. package/dist/images/selection_dialog/index.js +149 -0
  172. package/dist/images/selection_dialog/index.js.map +1 -0
  173. package/dist/index.js +1002 -0
  174. package/dist/index.js.map +1 -0
  175. package/dist/keymap.js +73 -0
  176. package/dist/keymap.js.map +1 -0
  177. package/dist/marginboxes/index.js +674 -0
  178. package/dist/marginboxes/index.js.map +1 -0
  179. package/dist/marginboxes/templates.js +447 -0
  180. package/dist/marginboxes/templates.js.map +1 -0
  181. package/dist/menus/code_block/index.js +2 -0
  182. package/dist/menus/code_block/index.js.map +1 -0
  183. package/dist/menus/code_block/model.js +49 -0
  184. package/dist/menus/code_block/model.js.map +1 -0
  185. package/dist/menus/figure/index.js +3 -0
  186. package/dist/menus/figure/index.js.map +1 -0
  187. package/dist/menus/figure/model.js +80 -0
  188. package/dist/menus/figure/model.js.map +1 -0
  189. package/dist/menus/figure/utils.js +6 -0
  190. package/dist/menus/figure/utils.js.map +1 -0
  191. package/dist/menus/headerbar/index.js +3 -0
  192. package/dist/menus/headerbar/index.js.map +1 -0
  193. package/dist/menus/headerbar/model.js +743 -0
  194. package/dist/menus/headerbar/model.js.map +1 -0
  195. package/dist/menus/headerbar/view.js +579 -0
  196. package/dist/menus/headerbar/view.js.map +1 -0
  197. package/dist/menus/image/index.js +2 -0
  198. package/dist/menus/image/index.js.map +1 -0
  199. package/dist/menus/image/model.js +32 -0
  200. package/dist/menus/image/model.js.map +1 -0
  201. package/dist/menus/index.js +10 -0
  202. package/dist/menus/index.js.map +1 -0
  203. package/dist/menus/navigator/index.js +2 -0
  204. package/dist/menus/navigator/index.js.map +1 -0
  205. package/dist/menus/navigator/model.js +29 -0
  206. package/dist/menus/navigator/model.js.map +1 -0
  207. package/dist/menus/ordered_list/index.js +2 -0
  208. package/dist/menus/ordered_list/index.js.map +1 -0
  209. package/dist/menus/ordered_list/model.js +17 -0
  210. package/dist/menus/ordered_list/model.js.map +1 -0
  211. package/dist/menus/selection/index.js +3 -0
  212. package/dist/menus/selection/index.js.map +1 -0
  213. package/dist/menus/selection/model.js +108 -0
  214. package/dist/menus/selection/model.js.map +1 -0
  215. package/dist/menus/selection/view.js +125 -0
  216. package/dist/menus/selection/view.js.map +1 -0
  217. package/dist/menus/table/index.js +2 -0
  218. package/dist/menus/table/index.js.map +1 -0
  219. package/dist/menus/table/model.js +319 -0
  220. package/dist/menus/table/model.js.map +1 -0
  221. package/dist/menus/toolbar/index.js +3 -0
  222. package/dist/menus/toolbar/index.js.map +1 -0
  223. package/dist/menus/toolbar/model.js +747 -0
  224. package/dist/menus/toolbar/model.js.map +1 -0
  225. package/dist/menus/toolbar/view.js +314 -0
  226. package/dist/menus/toolbar/view.js.map +1 -0
  227. package/dist/navigator/index.js +435 -0
  228. package/dist/navigator/index.js.map +1 -0
  229. package/dist/no_collab_save/index.js +169 -0
  230. package/dist/no_collab_save/index.js.map +1 -0
  231. package/dist/plugins/citation_dialog/index.js +2 -0
  232. package/dist/plugins/citation_dialog/index.js.map +1 -0
  233. package/dist/plugins/editor/index.js +2 -0
  234. package/dist/plugins/editor/index.js.map +1 -0
  235. package/dist/state_plugins/access_rights.js +30 -0
  236. package/dist/state_plugins/access_rights.js.map +1 -0
  237. package/dist/state_plugins/citation_render.js +78 -0
  238. package/dist/state_plugins/citation_render.js.map +1 -0
  239. package/dist/state_plugins/clipboard.js +217 -0
  240. package/dist/state_plugins/clipboard.js.map +1 -0
  241. package/dist/state_plugins/code_block.js +165 -0
  242. package/dist/state_plugins/code_block.js.map +1 -0
  243. package/dist/state_plugins/collab_carets.js +115 -0
  244. package/dist/state_plugins/collab_carets.js.map +1 -0
  245. package/dist/state_plugins/comments.js +197 -0
  246. package/dist/state_plugins/comments.js.map +1 -0
  247. package/dist/state_plugins/contributor_input/add_button.js +101 -0
  248. package/dist/state_plugins/contributor_input/add_button.js.map +1 -0
  249. package/dist/state_plugins/contributor_input/dropup.js +273 -0
  250. package/dist/state_plugins/contributor_input/dropup.js.map +1 -0
  251. package/dist/state_plugins/contributor_input/helpers.js +23 -0
  252. package/dist/state_plugins/contributor_input/helpers.js.map +1 -0
  253. package/dist/state_plugins/contributor_input/index.js +3 -0
  254. package/dist/state_plugins/contributor_input/index.js.map +1 -0
  255. package/dist/state_plugins/contributor_input/node_view.js +76 -0
  256. package/dist/state_plugins/contributor_input/node_view.js.map +1 -0
  257. package/dist/state_plugins/contributor_input/plugin.js +236 -0
  258. package/dist/state_plugins/contributor_input/plugin.js.map +1 -0
  259. package/dist/state_plugins/document_template.js +213 -0
  260. package/dist/state_plugins/document_template.js.map +1 -0
  261. package/dist/state_plugins/figure.js +90 -0
  262. package/dist/state_plugins/figure.js.map +1 -0
  263. package/dist/state_plugins/footnote_markers.js +187 -0
  264. package/dist/state_plugins/footnote_markers.js.map +1 -0
  265. package/dist/state_plugins/headerbar.js +10 -0
  266. package/dist/state_plugins/headerbar.js.map +1 -0
  267. package/dist/state_plugins/index.js +27 -0
  268. package/dist/state_plugins/index.js.map +1 -0
  269. package/dist/state_plugins/inline_math.js +719 -0
  270. package/dist/state_plugins/inline_math.js.map +1 -0
  271. package/dist/state_plugins/inline_reference/dropup.js +182 -0
  272. package/dist/state_plugins/inline_reference/dropup.js.map +1 -0
  273. package/dist/state_plugins/inline_reference/index.js +2 -0
  274. package/dist/state_plugins/inline_reference/index.js.map +1 -0
  275. package/dist/state_plugins/inline_reference/plugin.js +1134 -0
  276. package/dist/state_plugins/inline_reference/plugin.js.map +1 -0
  277. package/dist/state_plugins/jump_hidden_nodes.js +47 -0
  278. package/dist/state_plugins/jump_hidden_nodes.js.map +1 -0
  279. package/dist/state_plugins/links.js +622 -0
  280. package/dist/state_plugins/links.js.map +1 -0
  281. package/dist/state_plugins/marginboxes.js +13 -0
  282. package/dist/state_plugins/marginboxes.js.map +1 -0
  283. package/dist/state_plugins/ordered_list_menu.js +72 -0
  284. package/dist/state_plugins/ordered_list_menu.js.map +1 -0
  285. package/dist/state_plugins/placeholders.js +98 -0
  286. package/dist/state_plugins/placeholders.js.map +1 -0
  287. package/dist/state_plugins/search.js +212 -0
  288. package/dist/state_plugins/search.js.map +1 -0
  289. package/dist/state_plugins/selection_menu.js +10 -0
  290. package/dist/state_plugins/selection_menu.js.map +1 -0
  291. package/dist/state_plugins/settings.js +191 -0
  292. package/dist/state_plugins/settings.js.map +1 -0
  293. package/dist/state_plugins/table.js +104 -0
  294. package/dist/state_plugins/table.js.map +1 -0
  295. package/dist/state_plugins/tag_input/helpers.js +55 -0
  296. package/dist/state_plugins/tag_input/helpers.js.map +1 -0
  297. package/dist/state_plugins/tag_input/index.js +3 -0
  298. package/dist/state_plugins/tag_input/index.js.map +1 -0
  299. package/dist/state_plugins/tag_input/node_view.js +77 -0
  300. package/dist/state_plugins/tag_input/node_view.js.map +1 -0
  301. package/dist/state_plugins/tag_input/plugin.js +199 -0
  302. package/dist/state_plugins/tag_input/plugin.js.map +1 -0
  303. package/dist/state_plugins/tag_input/tag_editor.js +159 -0
  304. package/dist/state_plugins/tag_input/tag_editor.js.map +1 -0
  305. package/dist/state_plugins/tag_input/tag_editor_plugins.js +61 -0
  306. package/dist/state_plugins/tag_input/tag_editor_plugins.js.map +1 -0
  307. package/dist/state_plugins/toc_render.js +142 -0
  308. package/dist/state_plugins/toc_render.js.map +1 -0
  309. package/dist/state_plugins/toolbar.js +10 -0
  310. package/dist/state_plugins/toolbar.js.map +1 -0
  311. package/dist/state_plugins/track/find_selected_changes.js +82 -0
  312. package/dist/state_plugins/track/find_selected_changes.js.map +1 -0
  313. package/dist/state_plugins/track/helpers.js +67 -0
  314. package/dist/state_plugins/track/helpers.js.map +1 -0
  315. package/dist/state_plugins/track/index.js +3 -0
  316. package/dist/state_plugins/track/index.js.map +1 -0
  317. package/dist/state_plugins/track/plugin.js +114 -0
  318. package/dist/state_plugins/track/plugin.js.map +1 -0
  319. package/dist/tools/index.js +4 -0
  320. package/dist/tools/index.js.map +1 -0
  321. package/dist/tools/key_bindings/index.js +20 -0
  322. package/dist/tools/key_bindings/index.js.map +1 -0
  323. package/dist/tools/key_bindings/templates.js +68 -0
  324. package/dist/tools/key_bindings/templates.js.map +1 -0
  325. package/dist/tools/search_replace/index.js +275 -0
  326. package/dist/tools/search_replace/index.js.map +1 -0
  327. package/dist/tools/search_replace/templates.js +18 -0
  328. package/dist/tools/search_replace/templates.js.map +1 -0
  329. package/dist/tools/word_count/index.js +40 -0
  330. package/dist/tools/word_count/index.js.map +1 -0
  331. package/dist/tools/word_count/templates.js +27 -0
  332. package/dist/tools/word_count/templates.js.map +1 -0
  333. package/dist/track/accept.js +66 -0
  334. package/dist/track/accept.js.map +1 -0
  335. package/dist/track/accept_all.js +51 -0
  336. package/dist/track/accept_all.js.map +1 -0
  337. package/dist/track/accept_all_no_insertions.js +63 -0
  338. package/dist/track/accept_all_no_insertions.js.map +1 -0
  339. package/dist/track/amend_transaction.js +390 -0
  340. package/dist/track/amend_transaction.js.map +1 -0
  341. package/dist/track/delete.js +62 -0
  342. package/dist/track/delete.js.map +1 -0
  343. package/dist/track/index.js +6 -0
  344. package/dist/track/index.js.map +1 -0
  345. package/dist/track/mod.js +86 -0
  346. package/dist/track/mod.js.map +1 -0
  347. package/dist/track/reject.js +67 -0
  348. package/dist/track/reject.js.map +1 -0
  349. package/dist/track/reject_all.js +56 -0
  350. package/dist/track/reject_all.js.map +1 -0
  351. package/package.json +80 -0
  352. package/src/bibliography/tools.js +58 -0
  353. package/src/citations/index.js +443 -0
  354. package/src/citations/render.js +68 -0
  355. package/src/clipboard/copy/index.js +1 -0
  356. package/src/clipboard/copy/schema.js +62 -0
  357. package/src/clipboard/copy/serializers.js +179 -0
  358. package/src/clipboard/paste/fidus_writer.js +55 -0
  359. package/src/clipboard/paste/general.js +80 -0
  360. package/src/clipboard/paste/google_docs.js +26 -0
  361. package/src/clipboard/paste/html.js +76 -0
  362. package/src/clipboard/paste/index.js +2 -0
  363. package/src/clipboard/paste/libreoffice_writer.js +32 -0
  364. package/src/clipboard/paste/microsoft_word.js +87 -0
  365. package/src/clipboard/paste/text.js +58 -0
  366. package/src/collab/chat.js +195 -0
  367. package/src/collab/colors.js +67 -0
  368. package/src/collab/doc.js +1436 -0
  369. package/src/collab/index.js +81 -0
  370. package/src/collab/merge/changeset.js +103 -0
  371. package/src/collab/merge/editor.js +1065 -0
  372. package/src/collab/merge/footnotes.js +175 -0
  373. package/src/collab/merge/index.js +401 -0
  374. package/src/collab/merge/recreate_transform.js +326 -0
  375. package/src/collab/merge/schema.js +135 -0
  376. package/src/collab/merge/state_plugins/action.js +171 -0
  377. package/src/collab/merge/state_plugins/clipboard.js +32 -0
  378. package/src/collab/merge/state_plugins/diff.js +780 -0
  379. package/src/collab/merge/state_plugins/index.js +2 -0
  380. package/src/collab/merge/tools.js +217 -0
  381. package/src/collab/templates.js +10 -0
  382. package/src/comments/comment.js +29 -0
  383. package/src/comments/editors/answer.js +55 -0
  384. package/src/comments/editors/comment.js +318 -0
  385. package/src/comments/editors/index.js +4 -0
  386. package/src/comments/editors/notify.js +13 -0
  387. package/src/comments/editors/schema.js +65 -0
  388. package/src/comments/index.js +11 -0
  389. package/src/comments/interactions.js +465 -0
  390. package/src/comments/store.js +513 -0
  391. package/src/contacts/add_dialog.js +110 -0
  392. package/src/contacts/templates.js +28 -0
  393. package/src/copyright_dialog/index.js +179 -0
  394. package/src/copyright_dialog/templates.js +56 -0
  395. package/src/databases/bibliography.js +179 -0
  396. package/src/databases/images.js +320 -0
  397. package/src/databases/index.js +69 -0
  398. package/src/dialogs/citation.js +428 -0
  399. package/src/dialogs/code_block.js +242 -0
  400. package/src/dialogs/contributor.js +173 -0
  401. package/src/dialogs/figure.js +479 -0
  402. package/src/dialogs/index.js +10 -0
  403. package/src/dialogs/language.js +58 -0
  404. package/src/dialogs/link.js +358 -0
  405. package/src/dialogs/math.js +148 -0
  406. package/src/dialogs/ordered_list.js +84 -0
  407. package/src/dialogs/revision.js +43 -0
  408. package/src/dialogs/subsup.js +116 -0
  409. package/src/dialogs/table.js +258 -0
  410. package/src/dialogs/templates.js +426 -0
  411. package/src/document_template/exporter.js +97 -0
  412. package/src/document_template/index.js +483 -0
  413. package/src/documents/access_rights/index.js +693 -0
  414. package/src/documents/access_rights/templates.js +178 -0
  415. package/src/e2ee/encryptor.js +228 -0
  416. package/src/e2ee/key-manager.js +202 -0
  417. package/src/e2ee/passphrase-crypto.js +606 -0
  418. package/src/e2ee/passphrase-dialog.js +655 -0
  419. package/src/e2ee/passphrase-manager.js +502 -0
  420. package/src/e2ee/password-dialog.js +652 -0
  421. package/src/e2ee/snapshot-manager.js +305 -0
  422. package/src/exporter/native/copy.js +54 -0
  423. package/src/exporter/native/file.js +37 -0
  424. package/src/exporter/native/index.js +3 -0
  425. package/src/exporter/native/revision.js +86 -0
  426. package/src/exporter/native/zip.js +1 -0
  427. package/src/footnotes/editor.js +227 -0
  428. package/src/footnotes/index.js +16 -0
  429. package/src/footnotes/layout.js +190 -0
  430. package/src/footnotes/state_plugins/access_rights.js +39 -0
  431. package/src/footnotes/state_plugins/index.js +1 -0
  432. package/src/images/edit_dialog/edit_dialog/index.js +222 -0
  433. package/src/images/edit_dialog/edit_dialog/model.js +183 -0
  434. package/src/images/edit_dialog/edit_dialog/templates.js +41 -0
  435. package/src/images/edit_dialog/model.js +5 -0
  436. package/src/images/selection_dialog/index.js +176 -0
  437. package/src/index.js +1252 -0
  438. package/src/keymap.js +102 -0
  439. package/src/marginboxes/index.js +946 -0
  440. package/src/marginboxes/templates.js +573 -0
  441. package/src/menus/code_block/index.js +1 -0
  442. package/src/menus/code_block/model.js +52 -0
  443. package/src/menus/figure/index.js +2 -0
  444. package/src/menus/figure/model.js +91 -0
  445. package/src/menus/figure/utils.js +5 -0
  446. package/src/menus/headerbar/index.js +2 -0
  447. package/src/menus/headerbar/model.js +1077 -0
  448. package/src/menus/headerbar/view.js +675 -0
  449. package/src/menus/image/index.js +1 -0
  450. package/src/menus/image/model.js +32 -0
  451. package/src/menus/index.js +9 -0
  452. package/src/menus/navigator/index.js +1 -0
  453. package/src/menus/navigator/model.js +28 -0
  454. package/src/menus/ordered_list/index.js +1 -0
  455. package/src/menus/ordered_list/model.js +19 -0
  456. package/src/menus/selection/index.js +2 -0
  457. package/src/menus/selection/model.js +134 -0
  458. package/src/menus/selection/view.js +154 -0
  459. package/src/menus/table/index.js +1 -0
  460. package/src/menus/table/model.js +414 -0
  461. package/src/menus/toolbar/index.js +2 -0
  462. package/src/menus/toolbar/model.js +920 -0
  463. package/src/menus/toolbar/view.js +354 -0
  464. package/src/navigator/index.js +515 -0
  465. package/src/no_collab_save/index.js +209 -0
  466. package/src/plugins/citation_dialog/index.js +1 -0
  467. package/src/plugins/editor/index.js +1 -0
  468. package/src/state_plugins/access_rights.js +47 -0
  469. package/src/state_plugins/citation_render.js +88 -0
  470. package/src/state_plugins/clipboard.js +289 -0
  471. package/src/state_plugins/code_block.js +201 -0
  472. package/src/state_plugins/collab_carets.js +152 -0
  473. package/src/state_plugins/comments.js +259 -0
  474. package/src/state_plugins/contributor_input/add_button.js +134 -0
  475. package/src/state_plugins/contributor_input/dropup.js +318 -0
  476. package/src/state_plugins/contributor_input/helpers.js +24 -0
  477. package/src/state_plugins/contributor_input/index.js +2 -0
  478. package/src/state_plugins/contributor_input/node_view.js +86 -0
  479. package/src/state_plugins/contributor_input/plugin.js +318 -0
  480. package/src/state_plugins/document_template.js +315 -0
  481. package/src/state_plugins/figure.js +108 -0
  482. package/src/state_plugins/footnote_markers.js +238 -0
  483. package/src/state_plugins/headerbar.js +12 -0
  484. package/src/state_plugins/index.js +73 -0
  485. package/src/state_plugins/inline_math.js +918 -0
  486. package/src/state_plugins/inline_reference/dropup.js +208 -0
  487. package/src/state_plugins/inline_reference/index.js +5 -0
  488. package/src/state_plugins/inline_reference/plugin.js +1429 -0
  489. package/src/state_plugins/jump_hidden_nodes.js +58 -0
  490. package/src/state_plugins/links.js +830 -0
  491. package/src/state_plugins/marginboxes.js +14 -0
  492. package/src/state_plugins/ordered_list_menu.js +84 -0
  493. package/src/state_plugins/placeholders.js +123 -0
  494. package/src/state_plugins/search.js +251 -0
  495. package/src/state_plugins/selection_menu.js +12 -0
  496. package/src/state_plugins/settings.js +223 -0
  497. package/src/state_plugins/table.js +127 -0
  498. package/src/state_plugins/tag_input/helpers.js +69 -0
  499. package/src/state_plugins/tag_input/index.js +2 -0
  500. package/src/state_plugins/tag_input/node_view.js +85 -0
  501. package/src/state_plugins/tag_input/plugin.js +278 -0
  502. package/src/state_plugins/tag_input/tag_editor.js +202 -0
  503. package/src/state_plugins/tag_input/tag_editor_plugins.js +74 -0
  504. package/src/state_plugins/toc_render.js +160 -0
  505. package/src/state_plugins/toolbar.js +12 -0
  506. package/src/state_plugins/track/find_selected_changes.js +107 -0
  507. package/src/state_plugins/track/helpers.js +108 -0
  508. package/src/state_plugins/track/index.js +6 -0
  509. package/src/state_plugins/track/plugin.js +140 -0
  510. package/src/tools/index.js +3 -0
  511. package/src/tools/key_bindings/index.js +21 -0
  512. package/src/tools/key_bindings/templates.js +68 -0
  513. package/src/tools/search_replace/index.js +421 -0
  514. package/src/tools/search_replace/templates.js +19 -0
  515. package/src/tools/word_count/index.js +59 -0
  516. package/src/tools/word_count/templates.js +34 -0
  517. package/src/track/accept.js +102 -0
  518. package/src/track/accept_all.js +103 -0
  519. package/src/track/accept_all_no_insertions.js +102 -0
  520. package/src/track/amend_transaction.js +562 -0
  521. package/src/track/delete.js +92 -0
  522. package/src/track/index.js +8 -0
  523. package/src/track/mod.js +116 -0
  524. package/src/track/reject.js +116 -0
  525. package/src/track/reject_all.js +121 -0
@@ -0,0 +1,150 @@
1
+ import { avatarTemplate, escapeText } from "fwtoolkit";
2
+ export const peopleTabTemplate = ({ contacts, collaborators }) => `<div id="my-contacts" class="fw-ar-container">
3
+ <h3 class="fw-green-title">${gettext("My contacts")}</h3>
4
+ <table class="fw-data-table">
5
+ <thead class="fw-data-table-header"><tr><th width="337">${gettext("Contacts")}</th></tr></thead>
6
+ <tbody class="fw-data-table-body fw-small">
7
+ ${contactsTemplate({ contacts })}
8
+ </tbody>
9
+ </table>
10
+ </div>
11
+ <span id="add-share-contact" class="fw-button fw-large fw-square fw-light fw-ar-button">
12
+ <i class="fa-solid fa-caret-right"></i>
13
+ </span>
14
+ <div id="share-contact" class="fw-ar-container">
15
+ <h3 class="fw-green-title">${gettext("My collaborators")}</h3>
16
+ <table class="fw-data-table tablesorter">
17
+ <thead class="fw-data-table-header"><tr>
18
+ <th width="217">${gettext("Collaborators")}</th>
19
+ <th width="50" align="center">${gettext("Rights")}</th>
20
+ <th width="50" align="center">${gettext("Delete")}</th>
21
+ </tr></thead>
22
+ <tbody class="fw-data-table-body fw-small">
23
+ ${collaboratorsTemplate({ collaborators })}
24
+ </tbody>
25
+ </table>
26
+ </div>`;
27
+ export const shareLinkTabTemplate = () => `<div id="share-token-list">
28
+ <p class="fw-ar-loading">${gettext("Loading…")}</p>
29
+ </div>
30
+ <button class="fw-button fw-light" id="create-share-token-btn">
31
+ <i class="fa-solid fa-plus"></i>&nbsp;${gettext("Create new share link")}
32
+ </button>`;
33
+ /** The list of active share-link tokens for a single document */
34
+ export const shareTokenListTemplate = ({ tokens }) => {
35
+ if (!tokens.length) {
36
+ return `<p class="fw-ar-no-tokens">${gettext("No active share links yet.")}</p>`;
37
+ }
38
+ return tokens.map(token => shareTokenRowTemplate({ token })).join("");
39
+ };
40
+ /** A single share-link token row */
41
+ export const shareTokenRowTemplate = ({ token }) => {
42
+ const expiry = token.expires_at
43
+ ? escapeText(token.expires_at.slice(0, 10))
44
+ : gettext("never");
45
+ const note = token.note ? escapeText(token.note) : "";
46
+ return `<div class="share-token-row" data-token-id="${token.id}">
47
+ <div class="share-token-meta">
48
+ <span class="share-token-rights fw-bold">${escapeText(token.rights)}</span>
49
+ <span class="share-token-expiry">&nbsp;·&nbsp;${gettext("expires")}: ${expiry}</span>
50
+ ${note ? `<span class="share-token-note">&nbsp;·&nbsp;${note}</span>` : ""}
51
+ </div>
52
+ <div class="share-token-url-row">
53
+ <input class="share-token-url-input" type="text" readonly value="${escapeText(token.share_url)}" />
54
+ <button class="fw-button fw-light copy-share-token-btn" data-url="${escapeText(token.share_url)}" title="${gettext("Copy link")}">
55
+ <i class="fa-solid fa-copy"></i>
56
+ </button>
57
+ <button class="fw-button fw-light revoke-share-token-btn" data-token-id="${token.id}" title="${gettext("Revoke")}">
58
+ <i class="fa-solid fa-trash-alt"></i>
59
+ </button>
60
+ </div>
61
+ </div>`;
62
+ };
63
+ /** Sub-dialog for creating a new share link */
64
+ export const createShareTokenDialogTemplate = (e2ee = false, documentPassword = "") => `<table class="fw-dialog-table">
65
+ <tbody>
66
+ <tr>
67
+ <th><label for="share-token-rights">${gettext("Rights")}</label></th>
68
+ <td class="fw-entry-field">
69
+ <select id="share-token-rights" class="fw-button fw-light fw-large">
70
+ ${e2ee
71
+ ? `<option value="read">${gettext("Read")}</option>
72
+ <option value="read-without-comments">${gettext("Read without comments")}</option>
73
+ <option value="write">${gettext("Write")}</option>`
74
+ : `<option value="read">${gettext("Read")}</option>
75
+ <option value="read-without-comments">${gettext("Read without comments")}</option>
76
+ <option value="review">${gettext("Review")}</option>
77
+ <option value="review-tracked">${gettext("Review tracked")}</option>
78
+ <option value="comment">${gettext("Comment")}</option>
79
+ <option value="write">${gettext("Write")}</option>
80
+ <option value="write-tracked">${gettext("Write tracked")}</option>`}
81
+ </select>
82
+ <div class="fw-select-arrow fa-solid fa-caret-down"></div>
83
+ </td>
84
+ </tr>
85
+ <tr>
86
+ <th><label for="share-token-expires">${gettext("Expires")}</label></th>
87
+ <td class="fw-entry-field">
88
+ <input id="share-token-expires" type="text" class="fw-light" placeholder="${gettext("YYYY-MM-DD or empty")}" pattern="\d{4}-\d{2}-\d{2}" />
89
+ </td>
90
+ </tr>
91
+ <tr>
92
+ <th><label for="share-token-note">${gettext("Note")}</label></th>
93
+ <td class="fw-entry-field">
94
+ <input id="share-token-note" type="text" class="fw-light" placeholder="${gettext('optional label, e.g. "for reviewers"')}"/>
95
+ </td>
96
+ </tr>
97
+ ${e2ee
98
+ ? `<tr>
99
+ <th><label for="share-token-password">${gettext("Document password")}</label></th>
100
+ <td class="fw-entry-field">
101
+ <input id="share-token-password" type="text" class="fw-light" value="${escapeText(documentPassword)}" placeholder="${gettext("Enter the document password to include it in the link")}" autocomplete="off" />
102
+ <p class="e2ee-share-warning">
103
+ <i class="fa-solid fa-exclamation-triangle"></i>
104
+ ${gettext("If you enter the password above, it will be embedded in the link (after #). Anyone with the link can open the document. Only share such links through secure channels.")}
105
+ </p>
106
+ </td>
107
+ </tr>`
108
+ : ""}
109
+ </tbody>
110
+ </table>`;
111
+ /** The template for an individual row in the left hand side list of users (all contacts) of the access rights dialogue. */
112
+ export const contactsTemplate = ({ contacts }) => contacts
113
+ .map(contact => `<tr>
114
+ <td width="337" data-id="${contact.id}" data-type="${contact.type}" class="fw-checkable fw-checkable-td">
115
+ <span>${avatarTemplate({ user: contact })}</span>
116
+ <span class="fw-inline">
117
+ ${contact.type === "userinvite"
118
+ ? `${gettext("Invite")}:&nbsp;`
119
+ : ""}
120
+ ${escapeText(contact.name)}
121
+
122
+ </span>
123
+ </td>
124
+ </tr>`)
125
+ .join("");
126
+ /** The template for the right hand side list of users (the collaborators of the current document) of the access rights dialogue. */
127
+ export const collaboratorsTemplate = ({ collaborators }) => collaborators
128
+ .map(collaborator => `<tr id="collaborator-${collaborator.holder.type}-${collaborator.holder.id}"
129
+ data-type="${collaborator.holder.type}" data-id="${collaborator.holder.id}"
130
+ class="fw-collaborator-tr" data-rights="${collaborator.rights}">
131
+ <td width="215">
132
+ <span>${avatarTemplate({ user: collaborator.holder })}</span>
133
+ <span class="fw-inline">${collaborator.holder.type === "userinvite"
134
+ ? `${gettext("Invite")}: `
135
+ : ""}${escapeText(collaborator.holder.name)}</span>
136
+ </td>
137
+ <td width="50" align="center">
138
+ <div class="fw-inline edit-right-wrapper">
139
+ <i class="fw-icon-access-right icon-access-${collaborator.rights}"></i>
140
+ <i class="fa-solid fa-caret-down edit-right"></i>
141
+ </div>
142
+ </td>
143
+ <td width="50" align="center">
144
+ <span class="delete-collaborator fw-inline" data-rights="delete">
145
+ <i class="fa-solid fa-trash-alt fw-link-text"></i>
146
+ </span>
147
+ </td>
148
+ </tr>`)
149
+ .join("");
150
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/documents/access_rights/templates.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * E2EE Encryptor - Handles encryption and decryption of document content
3
+ * for end-to-end encrypted documents.
4
+ *
5
+ * Uses AES-GCM (256-bit) for all encryption operations. Each encryption
6
+ * operation generates a random 12-byte IV (initialization vector) to
7
+ * ensure that encrypting the same plaintext twice produces different
8
+ * ciphertext.
9
+ *
10
+ * Encrypted data format (Appendix A of the E2EE plan):
11
+ * [IV (12 bytes)][Ciphertext (variable length)][Auth Tag (16 bytes, implicit in AES-GCM)]
12
+ *
13
+ * When stored as a string (e.g., in JSON fields), the entire structure
14
+ * is Base64-encoded.
15
+ */
16
+ export class E2EEEncryptor {
17
+ /**
18
+ * Encrypt a string with AES-GCM.
19
+ *
20
+ * @param {string} plaintext - The plaintext string to encrypt
21
+ * @param {CryptoKey} key - An AES-GCM key (from E2EEKeyManager.deriveKey)
22
+ * @returns {Promise<string>} Base64-encoded string (iv + ciphertext + auth tag)
23
+ */
24
+ static async encrypt(plaintext, key) {
25
+ const iv = crypto.getRandomValues(new Uint8Array(12));
26
+ const encoded = new TextEncoder().encode(plaintext);
27
+ const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, key, encoded);
28
+ // Prepend IV to ciphertext for storage
29
+ const combined = new Uint8Array(iv.length + ciphertext.byteLength);
30
+ combined.set(iv, 0);
31
+ combined.set(new Uint8Array(ciphertext), iv.length);
32
+ return E2EEEncryptor._uint8ArrayToBase64(combined);
33
+ }
34
+ /**
35
+ * Decrypt a Base64-encoded AES-GCM ciphertext.
36
+ *
37
+ * @param {string} ciphertextBase64 - Base64-encoded (iv + ciphertext + auth tag)
38
+ * @param {CryptoKey} key - An AES-GCM key (from E2EEKeyManager.deriveKey)
39
+ * @returns {Promise<string>} The decrypted plaintext string
40
+ */
41
+ static async decrypt(ciphertextBase64, key) {
42
+ const combined = E2EEEncryptor._base64ToUint8Array(ciphertextBase64);
43
+ const iv = combined.slice(0, 12);
44
+ const ciphertext = combined.slice(12);
45
+ const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, key, ciphertext);
46
+ return new TextDecoder().decode(decrypted);
47
+ }
48
+ /**
49
+ * Encrypt a JSON-serializable object.
50
+ *
51
+ * Serializes the object to JSON, then encrypts the JSON string.
52
+ *
53
+ * @param {Object} obj - A JSON-serializable object
54
+ * @param {CryptoKey} key - An AES-GCM key
55
+ * @returns {Promise<string>} Base64-encoded encrypted data
56
+ */
57
+ static encryptObject(obj, key) {
58
+ return E2EEEncryptor.encrypt(JSON.stringify(obj), key);
59
+ }
60
+ /**
61
+ * Decrypt to a JSON-serializable object.
62
+ *
63
+ * Decrypts the Base64-encoded ciphertext, then parses the result as JSON.
64
+ *
65
+ * @param {string} ciphertextBase64 - Base64-encoded encrypted data
66
+ * @param {CryptoKey} key - An AES-GCM key
67
+ * @returns {Promise<Object>} The decrypted and parsed object
68
+ */
69
+ static async decryptObject(ciphertextBase64, key) {
70
+ const plaintext = await E2EEEncryptor.decrypt(ciphertextBase64, key);
71
+ return JSON.parse(plaintext);
72
+ }
73
+ /**
74
+ * Encrypt an ArrayBuffer (for images and other binary data).
75
+ *
76
+ * @param {ArrayBuffer} buffer - The binary data to encrypt
77
+ * @param {CryptoKey} key - An AES-GCM key
78
+ * @returns {Promise<string>} Base64-encoded encrypted data (iv + ciphertext)
79
+ */
80
+ static async encryptBuffer(buffer, key) {
81
+ const iv = crypto.getRandomValues(new Uint8Array(12));
82
+ const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, key, buffer);
83
+ // Prepend IV to ciphertext
84
+ const combined = new Uint8Array(iv.length + ciphertext.byteLength);
85
+ combined.set(iv, 0);
86
+ combined.set(new Uint8Array(ciphertext), iv.length);
87
+ return E2EEEncryptor._uint8ArrayToBase64(combined);
88
+ }
89
+ /**
90
+ * Decrypt to an ArrayBuffer.
91
+ *
92
+ * @param {string} ciphertextBase64 - Base64-encoded encrypted data
93
+ * @param {CryptoKey} key - An AES-GCM key
94
+ * @returns {Promise<ArrayBuffer>} The decrypted binary data
95
+ */
96
+ static decryptBuffer(ciphertextBase64, key) {
97
+ const combined = E2EEEncryptor._base64ToUint8Array(ciphertextBase64);
98
+ const iv = combined.slice(0, 12);
99
+ const ciphertext = combined.slice(12);
100
+ return crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, key, ciphertext);
101
+ }
102
+ /**
103
+ * Encrypt an image File/Blob for upload.
104
+ *
105
+ * Reads the file as an ArrayBuffer, encrypts it, and returns
106
+ * a Blob with application/octet-stream type (since the encrypted
107
+ * data is opaque binary).
108
+ *
109
+ * @param {File|Blob} file - The image file to encrypt
110
+ * @param {CryptoKey} key - An AES-GCM key
111
+ * @returns {Promise<Blob>} An encrypted Blob with type application/octet-stream
112
+ */
113
+ static async encryptImage(file, key) {
114
+ const buffer = await file.arrayBuffer();
115
+ const iv = crypto.getRandomValues(new Uint8Array(12));
116
+ const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, key, buffer);
117
+ // Prepend IV to ciphertext
118
+ const combined = new Uint8Array(iv.length + ciphertext.byteLength);
119
+ combined.set(iv, 0);
120
+ combined.set(new Uint8Array(ciphertext), iv.length);
121
+ return new Blob([combined], { type: "application/octet-stream" });
122
+ }
123
+ /**
124
+ * Decrypt an encrypted image back to an ArrayBuffer.
125
+ *
126
+ * @param {string} ciphertextBase64 - Base64-encoded encrypted image data
127
+ * @param {CryptoKey} key - An AES-GCM key
128
+ * @returns {Promise<ArrayBuffer>} The decrypted image data
129
+ */
130
+ static decryptImage(ciphertextBase64, key) {
131
+ return E2EEEncryptor.decryptBuffer(ciphertextBase64, key);
132
+ }
133
+ /**
134
+ * Decrypt a Base64-encoded ciphertext and return as a Base64 string.
135
+ *
136
+ * Useful for decrypting encrypted images that need to be stored
137
+ * as Base64 data URLs or re-exported.
138
+ *
139
+ * @param {string} ciphertextBase64 - Base64-encoded encrypted data
140
+ * @param {CryptoKey} key - An AES-GCM key
141
+ * @returns {Promise<string>} Base64-encoded decrypted data
142
+ */
143
+ static async decryptBufferToBase64(ciphertextBase64, key) {
144
+ const buffer = await E2EEEncryptor.decryptBuffer(ciphertextBase64, key);
145
+ const bytes = new Uint8Array(buffer);
146
+ let binary = "";
147
+ for (let i = 0; i < bytes.length; i++) {
148
+ binary += String.fromCharCode(bytes[i]);
149
+ }
150
+ return btoa(binary);
151
+ }
152
+ /**
153
+ * Decrypt an encrypted image and return a blob URL for display.
154
+ *
155
+ * Fetches the encrypted image file from the given URL, decrypts it,
156
+ * and creates a temporary object URL that can be used as an img src.
157
+ *
158
+ * @param {string} imageUrl - The URL of the encrypted image file
159
+ * @param {CryptoKey} key - An AES-GCM key
160
+ * @param {string} mimeType - The MIME type of the decrypted image
161
+ * @returns {Promise<string>} A blob URL for the decrypted image
162
+ */
163
+ static async decryptImageToUrl(imageUrl, key, mimeType = "image/png") {
164
+ const response = await fetch(imageUrl);
165
+ const arrayBuffer = await response.arrayBuffer();
166
+ const bytes = new Uint8Array(arrayBuffer);
167
+ let binary = "";
168
+ for (let i = 0; i < bytes.length; i++) {
169
+ binary += String.fromCharCode(bytes[i]);
170
+ }
171
+ const base64 = btoa(binary);
172
+ const decrypted = await E2EEEncryptor.decryptBuffer(base64, key);
173
+ const blob = new Blob([decrypted], { type: mimeType });
174
+ return URL.createObjectURL(blob);
175
+ }
176
+ // --- Private helper methods ---
177
+ /**
178
+ * Convert a Uint8Array to a Base64-encoded string.
179
+ * @private
180
+ */
181
+ static _uint8ArrayToBase64(bytes) {
182
+ let binary = "";
183
+ for (let i = 0; i < bytes.length; i++) {
184
+ binary += String.fromCharCode(bytes[i]);
185
+ }
186
+ return btoa(binary);
187
+ }
188
+ /**
189
+ * Convert a Base64-encoded string to a Uint8Array.
190
+ * @private
191
+ */
192
+ static _base64ToUint8Array(base64) {
193
+ const binary = atob(base64);
194
+ const bytes = new Uint8Array(binary.length);
195
+ for (let i = 0; i < binary.length; i++) {
196
+ bytes[i] = binary.charCodeAt(i);
197
+ }
198
+ return bytes;
199
+ }
200
+ }
201
+ //# sourceMappingURL=encryptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryptor.js","sourceRoot":"","sources":["../../src/e2ee/encryptor.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * E2EE Key Manager - Handles key derivation and salt generation for
3
+ * end-to-end encrypted documents.
4
+ *
5
+ * Uses PBKDF2 with SHA-256 to derive a 256-bit AES-GCM key from a
6
+ * user-supplied password and a server-stored salt. The salt and
7
+ * iteration count are stored on the server as part of the Document
8
+ * model (Document.e2ee_salt and Document.e2ee_iterations),
9
+ * so the user only needs the password to decrypt from any device.
10
+ *
11
+ * The key is marked as non-extractable for security — it cannot be
12
+ * read back from the CryptoKey object once created.
13
+ */
14
+ export class E2EEKeyManager {
15
+ /**
16
+ * Derive an AES-GCM key from a password and salt using PBKDF2.
17
+ *
18
+ * @param {string} password - The user-supplied password
19
+ * @param {Uint8Array} salt - The salt (16 bytes), fetched from the server
20
+ * as part of the document data (get_doc_data or subscribe)
21
+ * @param {number} [iterations=600000] - PBKDF2 iteration count
22
+ * (OWASP 2023 recommendation for PBKDF2-SHA256)
23
+ * @returns {Promise<CryptoKey>} A non-extractable AES-GCM 256-bit key
24
+ */
25
+ static async deriveKey(password, salt, iterations = 600000) {
26
+ const encoder = new TextEncoder();
27
+ const keyMaterial = await crypto.subtle.importKey("raw", encoder.encode(password), "PBKDF2", false, ["deriveKey"]);
28
+ const key = await crypto.subtle.deriveKey({
29
+ name: "PBKDF2",
30
+ salt: salt,
31
+ iterations: iterations,
32
+ hash: "SHA-256"
33
+ }, keyMaterial, { name: "AES-GCM", length: 256 }, true, // extractable — required for sessionStorage caching
34
+ ["encrypt", "decrypt"]);
35
+ return key;
36
+ }
37
+ /**
38
+ * Store an AES-GCM key in sessionStorage for the current browser session.
39
+ * The key is exported as raw bytes and Base64-encoded before storage.
40
+ *
41
+ * @param {number} documentId - The document ID
42
+ * @param {CryptoKey} key - The AES-GCM key to store
43
+ */
44
+ static async storeKeyInSession(documentId, key) {
45
+ const raw = await crypto.subtle.exportKey("raw", key);
46
+ const base64 = btoa(String.fromCharCode(...new Uint8Array(raw)));
47
+ sessionStorage.setItem(`e2ee_key_${documentId}`, base64);
48
+ }
49
+ /**
50
+ * Retrieve an AES-GCM key from sessionStorage.
51
+ *
52
+ * @param {number} documentId - The document ID
53
+ * @returns {Promise<CryptoKey|null>} The imported key, or null if not found
54
+ */
55
+ static getKeyFromSession(documentId) {
56
+ const base64 = sessionStorage.getItem(`e2ee_key_${documentId}`);
57
+ if (!base64) {
58
+ return null;
59
+ }
60
+ const binary = atob(base64);
61
+ const raw = new Uint8Array(binary.length);
62
+ for (let i = 0; i < binary.length; i++) {
63
+ raw[i] = binary.charCodeAt(i);
64
+ }
65
+ return crypto.subtle.importKey("raw", raw, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
66
+ }
67
+ /**
68
+ * Remove a cached key from sessionStorage.
69
+ *
70
+ * @param {number} documentId - The document ID
71
+ */
72
+ static clearKeyFromSession(documentId) {
73
+ sessionStorage.removeItem(`e2ee_key_${documentId}`);
74
+ }
75
+ /**
76
+ * Clear all cached E2EE keys from sessionStorage.
77
+ * Should be called on sign-out or session expiration.
78
+ */
79
+ static clearAllKeysFromSession() {
80
+ for (let i = sessionStorage.length - 1; i >= 0; i--) {
81
+ const key = sessionStorage.key(i);
82
+ if (key && key.startsWith("e2ee_key_")) {
83
+ sessionStorage.removeItem(key);
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Generate a new random salt (16 bytes).
89
+ *
90
+ * Used when creating a new E2EE document or changing the password.
91
+ * The generated salt is sent to the server and stored in
92
+ * Document.e2ee_salt. The salt is not a secret — its purpose
93
+ * is to ensure that two documents with the same password produce
94
+ * different derived keys (preventing rainbow table attacks).
95
+ *
96
+ * @returns {Uint8Array} A 16-byte random salt
97
+ */
98
+ static generateSalt() {
99
+ return crypto.getRandomValues(new Uint8Array(16));
100
+ }
101
+ /**
102
+ * Resolve a document password to an AES-GCM key.
103
+ *
104
+ * If the password is a valid base64/base64url-encoded 32-byte string
105
+ * (43 or 44 characters), it is treated as a raw DEK and imported
106
+ * directly without PBKDF2. Otherwise, the key is derived via PBKDF2.
107
+ *
108
+ * @param {string} password - The document password
109
+ * @param {Uint8Array} salt - The salt (16 bytes)
110
+ * @param {number} [iterations=600000] - PBKDF2 iteration count
111
+ * @returns {Promise<CryptoKey>} The AES-GCM key
112
+ */
113
+ static resolvePasswordToKey(password, salt, iterations = 600000) {
114
+ // Try to interpret as raw base64/base64url DEK first
115
+ if (password.length === 44 || password.length === 43) {
116
+ let decoded = null;
117
+ try {
118
+ decoded = atob(password);
119
+ }
120
+ catch (_e) {
121
+ // Try base64url with padding conversion
122
+ try {
123
+ let base64 = password.replace(/-/g, "+").replace(/_/g, "/");
124
+ while (base64.length % 4) {
125
+ base64 += "=";
126
+ }
127
+ decoded = atob(base64);
128
+ }
129
+ catch (_e2) {
130
+ // Not valid base64url either
131
+ }
132
+ }
133
+ if (decoded && decoded.length === 32) {
134
+ const raw = new Uint8Array(decoded.length);
135
+ for (let i = 0; i < decoded.length; i++) {
136
+ raw[i] = decoded.charCodeAt(i);
137
+ }
138
+ return crypto.subtle.importKey("raw", raw, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
139
+ }
140
+ }
141
+ // Fall back to PBKDF2 derivation
142
+ return E2EEKeyManager.deriveKey(password, salt, iterations);
143
+ }
144
+ /**
145
+ * Store the document password in sessionStorage.
146
+ *
147
+ * @param {number} documentId - The document ID
148
+ * @param {string} password - The document password
149
+ */
150
+ static storePasswordInSession(documentId, password) {
151
+ sessionStorage.setItem(`e2ee_password_${documentId}`, password);
152
+ }
153
+ /**
154
+ * Retrieve the document password from sessionStorage.
155
+ *
156
+ * @param {number} documentId - The document ID
157
+ * @returns {string|null} The password, or null if not found
158
+ */
159
+ static getPasswordFromSession(documentId) {
160
+ return sessionStorage.getItem(`e2ee_password_${documentId}`);
161
+ }
162
+ /**
163
+ * Remove a cached password from sessionStorage.
164
+ *
165
+ * @param {number} documentId - The document ID
166
+ */
167
+ static clearPasswordFromSession(documentId) {
168
+ sessionStorage.removeItem(`e2ee_password_${documentId}`);
169
+ }
170
+ }
171
+ //# sourceMappingURL=key-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-manager.js","sourceRoot":"","sources":["../../src/e2ee/key-manager.js"],"names":[],"mappings":"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"}