@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,655 @@
1
+ /**
2
+ * Passphrase Dialog - UI for the Personal Passphrase system.
3
+ *
4
+ * Provides dialogs for:
5
+ * 1. Setup passphrase - first-time key generation
6
+ * 2. Enter passphrase - unlock keys from sessionStorage
7
+ * 3. Display recovery key - show recovery key after setup
8
+ * 4. Recover with key - use recovery key to reset passphrase
9
+ */
10
+
11
+ import {Dialog, escapeText} from "fwtoolkit"
12
+ import {passwordStrength, strengthInfo} from "./password-dialog"
13
+
14
+ /**
15
+ * Show a dialog to set up the personal passphrase for the first time.
16
+ *
17
+ * @param {Function} onSetup - Callback called with the passphrase string
18
+ * @returns {Promise<void>}
19
+ */
20
+ export function setupPassphraseDialog(onSetup) {
21
+ return new Promise(resolve => {
22
+ const dialogId = "e2ee-setup-passphrase"
23
+
24
+ const body = `
25
+ <div class="e2ee-password-dialog">
26
+ <p>${gettext("Set up a personal encryption passphrase. This passphrase will unlock all your encrypted documents — you will not need separate passwords for each document.")}</p>
27
+ <p class="e2ee-password-hint"><strong>${gettext("Important:")}</strong> ${gettext("This passphrase is separate from your login password. If you lose it, your encrypted documents cannot be recovered.")}</p>
28
+ <div class="e2ee-password-field">
29
+ <label for="e2ee-passphrase-input">${gettext("Passphrase")}</label>
30
+ <input type="password" id="e2ee-passphrase-input" class="e2ee-password-input"
31
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
32
+ <button type="button" class="e2ee-toggle-visibility" title="${gettext("Show passphrase")}">
33
+ <i class="fa-solid fa-eye"></i>
34
+ </button>
35
+ </div>
36
+ <div class="e2ee-strength-meter">
37
+ <div class="e2ee-strength-bar" id="e2ee-strength-bar"></div>
38
+ <span class="e2ee-strength-label" id="e2ee-strength-label"></span>
39
+ </div>
40
+ <div class="e2ee-password-field">
41
+ <label for="e2ee-confirm-passphrase-input">${gettext("Confirm passphrase")}</label>
42
+ <input type="password" id="e2ee-confirm-passphrase-input" class="e2ee-password-input"
43
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
44
+ </div>
45
+ <div class="e2ee-password-error" id="e2ee-passphrase-error"></div>
46
+ </div>
47
+ `
48
+
49
+ const buttons = [
50
+ {
51
+ text: gettext("Set Up Encryption"),
52
+ classes: "fw-button fw-dark",
53
+ click: () => {
54
+ const input = document.getElementById(
55
+ "e2ee-passphrase-input"
56
+ )
57
+ const confirmInput = document.getElementById(
58
+ "e2ee-confirm-passphrase-input"
59
+ )
60
+ const errorEl = document.getElementById(
61
+ "e2ee-passphrase-error"
62
+ )
63
+ const passphrase = input ? input.value : ""
64
+ const confirmPassphrase = confirmInput
65
+ ? confirmInput.value
66
+ : ""
67
+
68
+ if (passphrase.length < 8) {
69
+ if (errorEl) {
70
+ errorEl.textContent = gettext(
71
+ "Passphrase must be at least 8 characters long."
72
+ )
73
+ }
74
+ return
75
+ }
76
+
77
+ if (passphrase !== confirmPassphrase) {
78
+ if (errorEl) {
79
+ errorEl.textContent = gettext(
80
+ "Passphrases do not match."
81
+ )
82
+ }
83
+ return
84
+ }
85
+
86
+ dialogInstance.close()
87
+ onSetup(passphrase)
88
+ resolve()
89
+ }
90
+ }
91
+ ]
92
+
93
+ const dialog = {
94
+ title: gettext("Set Up Personal Encryption"),
95
+ id: dialogId,
96
+ body: body,
97
+ buttons: buttons,
98
+ canClose: true,
99
+ width: 450
100
+ }
101
+
102
+ const dialogInstance = new Dialog(dialog)
103
+ dialogInstance.open()
104
+
105
+ // The dialog content is short and should not scroll. Ensure it starts
106
+ // at the top so the explanatory text and title are fully visible.
107
+ requestAnimationFrame(() => {
108
+ const contentEl = document.getElementById(dialogId)
109
+ if (contentEl) {
110
+ contentEl.scrollTop = 0
111
+ }
112
+ })
113
+
114
+ setTimeout(() => {
115
+ const toggleBtns = document.querySelectorAll(
116
+ `#${dialogId} .e2ee-toggle-visibility`
117
+ )
118
+ toggleBtns.forEach(btn => {
119
+ btn.addEventListener("click", () => {
120
+ const input = btn.parentElement.querySelector("input")
121
+ if (input) {
122
+ if (input.type === "password") {
123
+ input.type = "text"
124
+ btn.innerHTML =
125
+ '<i class="fa-solid fa-eye-slash"></i>'
126
+ } else {
127
+ input.type = "password"
128
+ btn.innerHTML = '<i class="fa-solid fa-eye"></i>'
129
+ }
130
+ }
131
+ })
132
+ })
133
+
134
+ const passphraseInput = document.getElementById(
135
+ "e2ee-passphrase-input"
136
+ )
137
+ if (passphraseInput) {
138
+ passphraseInput.addEventListener("input", () => {
139
+ const score = passwordStrength(passphraseInput.value)
140
+ const info = strengthInfo(score)
141
+ const bar = document.getElementById("e2ee-strength-bar")
142
+ const label = document.getElementById("e2ee-strength-label")
143
+ if (bar) {
144
+ bar.className = `e2ee-strength-bar ${info.cssClass}`
145
+ bar.style.width = `${(score + 1) * 25}%`
146
+ }
147
+ if (label) {
148
+ label.textContent = info.label
149
+ label.className = `e2ee-strength-label ${info.cssClass}`
150
+ }
151
+ })
152
+ passphraseInput.dispatchEvent(new Event("input"))
153
+ passphraseInput.focus()
154
+ }
155
+
156
+ const confirmInput = document.getElementById(
157
+ "e2ee-confirm-passphrase-input"
158
+ )
159
+ if (confirmInput) {
160
+ confirmInput.addEventListener("keypress", event => {
161
+ if (event.key === "Enter") {
162
+ event.preventDefault()
163
+ buttons[0].click()
164
+ }
165
+ })
166
+ }
167
+ }, 100)
168
+ })
169
+ }
170
+
171
+ /**
172
+ * Show a dialog to enter the personal passphrase to unlock encryption keys.
173
+ *
174
+ * @param {Function} onUnlock - Callback called with the passphrase string
175
+ * @param {Function} onRecover - Callback when user clicks "Recover with key"
176
+ * @param {Object} [options] - Optional settings
177
+ * @param {string} [options.errorMessage] - Inline error to display
178
+ * @returns {Promise<void>}
179
+ */
180
+ export function enterPassphraseDialog(
181
+ onUnlock,
182
+ onRecover = null,
183
+ options = {}
184
+ ) {
185
+ return new Promise(resolve => {
186
+ const dialogId = "e2ee-enter-passphrase"
187
+ const errorMessage = options.errorMessage || ""
188
+
189
+ const body = `
190
+ <div class="e2ee-password-dialog">
191
+ <p>${gettext("Enter your personal encryption passphrase to unlock your documents.")}</p>
192
+ <div class="e2ee-password-field">
193
+ <label for="e2ee-passphrase-input">${gettext("Passphrase")}</label>
194
+ <input type="password" id="e2ee-passphrase-input" class="e2ee-password-input"
195
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" autofocus />
196
+ <button type="button" class="e2ee-toggle-visibility" title="${gettext("Show passphrase")}">
197
+ <i class="fa-solid fa-eye"></i>
198
+ </button>
199
+ </div>
200
+ <div class="e2ee-password-error" id="e2ee-passphrase-error">${escapeText(errorMessage)}</div>
201
+ </div>
202
+ `
203
+
204
+ const buttons = [
205
+ {
206
+ text: gettext("Unlock"),
207
+ classes: "fw-button fw-dark",
208
+ click: () => {
209
+ const input = document.getElementById(
210
+ "e2ee-passphrase-input"
211
+ )
212
+ const passphrase = input ? input.value : ""
213
+ if (passphrase.length === 0) {
214
+ const errorEl = document.getElementById(
215
+ "e2ee-passphrase-error"
216
+ )
217
+ if (errorEl) {
218
+ errorEl.textContent = gettext(
219
+ "Please enter your passphrase."
220
+ )
221
+ }
222
+ return
223
+ }
224
+ dialogInstance.close()
225
+ onUnlock(passphrase)
226
+ resolve()
227
+ }
228
+ },
229
+ {
230
+ text: gettext("Cancel"),
231
+ classes: "fw-button fw-light",
232
+ click: () => {
233
+ dialogInstance.close()
234
+ resolve()
235
+ }
236
+ }
237
+ ]
238
+
239
+ if (onRecover) {
240
+ buttons.push({
241
+ text: gettext("Recover with key"),
242
+ classes: "fw-button fw-orange",
243
+ click: () => {
244
+ dialogInstance.close()
245
+ onRecover()
246
+ resolve()
247
+ }
248
+ })
249
+ }
250
+
251
+ const dialog = {
252
+ title: gettext("Unlock Encryption"),
253
+ id: dialogId,
254
+ body: body,
255
+ buttons: buttons,
256
+ canClose: true
257
+ }
258
+
259
+ const dialogInstance = new Dialog(dialog)
260
+ dialogInstance.open()
261
+
262
+ setTimeout(() => {
263
+ const toggleBtn = document.querySelector(
264
+ `#${dialogId} .e2ee-toggle-visibility`
265
+ )
266
+ const input = document.getElementById("e2ee-passphrase-input")
267
+ if (toggleBtn && input) {
268
+ toggleBtn.addEventListener("click", () => {
269
+ if (input.type === "password") {
270
+ input.type = "text"
271
+ toggleBtn.innerHTML =
272
+ '<i class="fa-solid fa-eye-slash"></i>'
273
+ toggleBtn.title = gettext("Hide passphrase")
274
+ } else {
275
+ input.type = "password"
276
+ toggleBtn.innerHTML = '<i class="fa-solid fa-eye"></i>'
277
+ toggleBtn.title = gettext("Show passphrase")
278
+ }
279
+ })
280
+ }
281
+
282
+ if (input) {
283
+ input.addEventListener("keypress", event => {
284
+ if (event.key === "Enter") {
285
+ event.preventDefault()
286
+ buttons[0].click()
287
+ }
288
+ })
289
+ input.focus()
290
+ }
291
+ }, 100)
292
+ })
293
+ }
294
+
295
+ /**
296
+ * Show a dialog displaying the recovery key to the user.
297
+ *
298
+ * @param {string} recoveryKey - The recovery key to display
299
+ * @param {Function} onContinue - Callback when user clicks Continue
300
+ * @returns {Promise<void>}
301
+ */
302
+ export function showRecoveryKeyDialog(recoveryKey, onContinue) {
303
+ return new Promise(resolve => {
304
+ const dialogId = "e2ee-recovery-key"
305
+
306
+ const body = `
307
+ <div class="e2ee-password-dialog">
308
+ <p><strong>${gettext("This is your recovery key.")}</strong></p>
309
+ <p>${gettext("Store it somewhere safe (e.g., a password manager, printed copy). If you forget your passphrase, this is the ONLY way to recover your encrypted documents. We cannot recover it for you.")}</p>
310
+ <div class="e2ee-recovery-key-box">
311
+ <code id="e2ee-recovery-key-value">${recoveryKey}</code>
312
+ <button type="button" class="fw-button fw-light" id="e2ee-copy-recovery-key">
313
+ <i class="fa-solid fa-copy"></i> ${gettext("Copy")}
314
+ </button>
315
+ </div>
316
+ <p class="e2ee-password-hint"><strong>${gettext("Copy it now — it will not be shown again.")}</strong></p>
317
+ </div>
318
+ `
319
+
320
+ const buttons = [
321
+ {
322
+ text: gettext("I have saved it"),
323
+ classes: "fw-button fw-dark",
324
+ click: () => {
325
+ dialogInstance.close()
326
+ if (typeof onContinue === "function") {
327
+ onContinue()
328
+ }
329
+ resolve()
330
+ }
331
+ }
332
+ ]
333
+
334
+ const dialog = {
335
+ title: gettext("Recovery Key"),
336
+ id: dialogId,
337
+ body: body,
338
+ buttons: buttons,
339
+ canClose: false
340
+ }
341
+
342
+ const dialogInstance = new Dialog(dialog)
343
+ dialogInstance.open()
344
+
345
+ setTimeout(() => {
346
+ const copyBtn = document.getElementById("e2ee-copy-recovery-key")
347
+ if (copyBtn) {
348
+ copyBtn.addEventListener("click", () => {
349
+ navigator.clipboard.writeText(recoveryKey).then(() => {
350
+ copyBtn.innerHTML = `<i class="fa-solid fa-check"></i> ${gettext("Copied!")}`
351
+ setTimeout(() => {
352
+ copyBtn.innerHTML = `<i class="fa-solid fa-copy"></i> ${gettext("Copy")}`
353
+ }, 2000)
354
+ })
355
+ })
356
+ }
357
+ }, 100)
358
+ })
359
+ }
360
+
361
+ /**
362
+ * Show a dialog to recover encryption keys using the recovery key.
363
+ *
364
+ * @param {Function} onRecover - Callback called with {recoveryKey: string, newPassphrase: string}
365
+ * @returns {Promise<void>}
366
+ */
367
+ export function recoverWithKeyDialog(onRecover) {
368
+ return new Promise(resolve => {
369
+ const dialogId = "e2ee-recover-with-key"
370
+
371
+ const body = `
372
+ <div class="e2ee-password-dialog">
373
+ <p>${gettext("Enter your recovery key and a new passphrase to regain access to your encrypted documents.")}</p>
374
+ <div class="e2ee-password-field">
375
+ <label for="e2ee-recovery-key-input">${gettext("Recovery key")}</label>
376
+ <input type="text" id="e2ee-recovery-key-input" class="e2ee-password-input"
377
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" autofocus />
378
+ </div>
379
+ <div class="e2ee-password-field">
380
+ <label for="e2ee-new-passphrase-input">${gettext("New passphrase")}</label>
381
+ <input type="password" id="e2ee-new-passphrase-input" class="e2ee-password-input"
382
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
383
+ <button type="button" class="e2ee-toggle-visibility" title="${gettext("Show passphrase")}">
384
+ <i class="fa-solid fa-eye"></i>
385
+ </button>
386
+ </div>
387
+ <div class="e2ee-password-field">
388
+ <label for="e2ee-confirm-passphrase-input">${gettext("Confirm new passphrase")}</label>
389
+ <input type="password" id="e2ee-confirm-passphrase-input" class="e2ee-password-input"
390
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
391
+ </div>
392
+ <div class="e2ee-password-error" id="e2ee-recover-error"></div>
393
+ </div>
394
+ `
395
+
396
+ const buttons = [
397
+ {
398
+ text: gettext("Recover"),
399
+ classes: "fw-button fw-dark",
400
+ click: () => {
401
+ const recoveryInput = document.getElementById(
402
+ "e2ee-recovery-key-input"
403
+ )
404
+ const newInput = document.getElementById(
405
+ "e2ee-new-passphrase-input"
406
+ )
407
+ const confirmInput = document.getElementById(
408
+ "e2ee-confirm-passphrase-input"
409
+ )
410
+ const errorEl =
411
+ document.getElementById("e2ee-recover-error")
412
+
413
+ const recoveryKey = recoveryInput
414
+ ? recoveryInput.value.trim()
415
+ : ""
416
+ const newPassphrase = newInput ? newInput.value : ""
417
+ const confirmPassphrase = confirmInput
418
+ ? confirmInput.value
419
+ : ""
420
+
421
+ if (recoveryKey.length === 0) {
422
+ if (errorEl) {
423
+ errorEl.textContent = gettext(
424
+ "Please enter your recovery key."
425
+ )
426
+ }
427
+ return
428
+ }
429
+
430
+ if (newPassphrase.length < 8) {
431
+ if (errorEl) {
432
+ errorEl.textContent = gettext(
433
+ "Passphrase must be at least 8 characters long."
434
+ )
435
+ }
436
+ return
437
+ }
438
+
439
+ if (newPassphrase !== confirmPassphrase) {
440
+ if (errorEl) {
441
+ errorEl.textContent = gettext(
442
+ "Passphrases do not match."
443
+ )
444
+ }
445
+ return
446
+ }
447
+
448
+ dialogInstance.close()
449
+ onRecover({recoveryKey, newPassphrase})
450
+ resolve()
451
+ }
452
+ },
453
+ {
454
+ text: gettext("Cancel"),
455
+ classes: "fw-button fw-light",
456
+ click: () => {
457
+ dialogInstance.close()
458
+ resolve()
459
+ }
460
+ }
461
+ ]
462
+
463
+ const dialog = {
464
+ title: gettext("Recover Encryption"),
465
+ id: dialogId,
466
+ body: body,
467
+ buttons: buttons,
468
+ canClose: true
469
+ }
470
+
471
+ const dialogInstance = new Dialog(dialog)
472
+ dialogInstance.open()
473
+
474
+ setTimeout(() => {
475
+ const toggleBtns = document.querySelectorAll(
476
+ `#${dialogId} .e2ee-toggle-visibility`
477
+ )
478
+ toggleBtns.forEach(btn => {
479
+ btn.addEventListener("click", () => {
480
+ const input = btn.parentElement.querySelector("input")
481
+ if (input) {
482
+ if (input.type === "password") {
483
+ input.type = "text"
484
+ btn.innerHTML =
485
+ '<i class="fa-solid fa-eye-slash"></i>'
486
+ } else {
487
+ input.type = "password"
488
+ btn.innerHTML = '<i class="fa-solid fa-eye"></i>'
489
+ }
490
+ }
491
+ })
492
+ })
493
+
494
+ const confirmInput = document.getElementById(
495
+ "e2ee-confirm-passphrase-input"
496
+ )
497
+ if (confirmInput) {
498
+ confirmInput.addEventListener("keypress", event => {
499
+ if (event.key === "Enter") {
500
+ event.preventDefault()
501
+ buttons[0].click()
502
+ }
503
+ })
504
+ }
505
+ }, 100)
506
+ })
507
+ }
508
+
509
+ /**
510
+ * Show a dialog to change the encryption passphrase.
511
+ *
512
+ * @param {Function} onChange - Callback called with {oldPassphrase: string, newPassphrase: string}
513
+ * @returns {Promise<void>}
514
+ */
515
+ export function changePassphraseDialog(onChange) {
516
+ return new Promise(resolve => {
517
+ const dialogId = "e2ee-change-passphrase"
518
+
519
+ const body = `
520
+ <div class="e2ee-password-dialog">
521
+ <p>${gettext("Enter your current passphrase and a new passphrase to change your encryption password.")}</p>
522
+ <div class="e2ee-password-field">
523
+ <label for="e2ee-old-passphrase-input">${gettext("Current passphrase")}</label>
524
+ <input type="password" id="e2ee-old-passphrase-input" class="e2ee-password-input"
525
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" autofocus />
526
+ <button type="button" class="e2ee-toggle-visibility" title="${gettext("Show passphrase")}">
527
+ <i class="fa-solid fa-eye"></i>
528
+ </button>
529
+ </div>
530
+ <div class="e2ee-password-field">
531
+ <label for="e2ee-new-passphrase-input">${gettext("New passphrase")}</label>
532
+ <input type="password" id="e2ee-new-passphrase-input" class="e2ee-password-input"
533
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
534
+ <button type="button" class="e2ee-toggle-visibility" title="${gettext("Show passphrase")}">
535
+ <i class="fa-solid fa-eye"></i>
536
+ </button>
537
+ </div>
538
+ <div class="e2ee-password-field">
539
+ <label for="e2ee-confirm-new-passphrase-input">${gettext("Confirm new passphrase")}</label>
540
+ <input type="password" id="e2ee-confirm-new-passphrase-input" class="e2ee-password-input"
541
+ autocomplete="off" data-1p-ignore data-lp-ignore data-lpignore="true" data-bwignore data-form-type="other" />
542
+ </div>
543
+ <div class="e2ee-password-error" id="e2ee-change-error"></div>
544
+ </div>
545
+ `
546
+
547
+ const buttons = [
548
+ {
549
+ text: gettext("Change Passphrase"),
550
+ classes: "fw-button fw-dark",
551
+ click: () => {
552
+ const oldInput = document.getElementById(
553
+ "e2ee-old-passphrase-input"
554
+ )
555
+ const newInput = document.getElementById(
556
+ "e2ee-new-passphrase-input"
557
+ )
558
+ const confirmInput = document.getElementById(
559
+ "e2ee-confirm-new-passphrase-input"
560
+ )
561
+ const errorEl = document.getElementById("e2ee-change-error")
562
+
563
+ const oldPassphrase = oldInput ? oldInput.value : ""
564
+ const newPassphrase = newInput ? newInput.value : ""
565
+ const confirmPassphrase = confirmInput
566
+ ? confirmInput.value
567
+ : ""
568
+
569
+ if (oldPassphrase.length === 0) {
570
+ if (errorEl) {
571
+ errorEl.textContent = gettext(
572
+ "Please enter your current passphrase."
573
+ )
574
+ }
575
+ return
576
+ }
577
+
578
+ if (newPassphrase.length < 8) {
579
+ if (errorEl) {
580
+ errorEl.textContent = gettext(
581
+ "Passphrase must be at least 8 characters long."
582
+ )
583
+ }
584
+ return
585
+ }
586
+
587
+ if (newPassphrase !== confirmPassphrase) {
588
+ if (errorEl) {
589
+ errorEl.textContent = gettext(
590
+ "Passphrases do not match."
591
+ )
592
+ }
593
+ return
594
+ }
595
+
596
+ dialogInstance.close()
597
+ onChange({oldPassphrase, newPassphrase})
598
+ resolve()
599
+ }
600
+ },
601
+ {
602
+ text: gettext("Cancel"),
603
+ classes: "fw-button fw-light",
604
+ click: () => {
605
+ dialogInstance.close()
606
+ resolve()
607
+ }
608
+ }
609
+ ]
610
+
611
+ const dialog = {
612
+ title: gettext("Change Encryption Passphrase"),
613
+ id: dialogId,
614
+ body: body,
615
+ buttons: buttons,
616
+ canClose: true
617
+ }
618
+
619
+ const dialogInstance = new Dialog(dialog)
620
+ dialogInstance.open()
621
+
622
+ setTimeout(() => {
623
+ const toggleBtns = document.querySelectorAll(
624
+ `#${dialogId} .e2ee-toggle-visibility`
625
+ )
626
+ toggleBtns.forEach(btn => {
627
+ btn.addEventListener("click", () => {
628
+ const input = btn.parentElement.querySelector("input")
629
+ if (input) {
630
+ if (input.type === "password") {
631
+ input.type = "text"
632
+ btn.innerHTML =
633
+ '<i class="fa-solid fa-eye-slash"></i>'
634
+ } else {
635
+ input.type = "password"
636
+ btn.innerHTML = '<i class="fa-solid fa-eye"></i>'
637
+ }
638
+ }
639
+ })
640
+ })
641
+
642
+ const confirmInput = document.getElementById(
643
+ "e2ee-confirm-new-passphrase-input"
644
+ )
645
+ if (confirmInput) {
646
+ confirmInput.addEventListener("keypress", event => {
647
+ if (event.key === "Enter") {
648
+ event.preventDefault()
649
+ buttons[0].click()
650
+ }
651
+ })
652
+ }
653
+ }, 100)
654
+ })
655
+ }