@vc-shell/framework 1.1.44 → 1.1.46

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 (453) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/core/plugins/modularity/loader.ts +150 -74
  3. package/core/services/app-bar-mobile-buttons-service.ts +1 -1
  4. package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
  5. package/dist/core/services/app-bar-mobile-buttons-service.d.ts +1 -1
  6. package/dist/core/services/app-bar-mobile-buttons-service.d.ts.map +1 -1
  7. package/dist/framework.js +33355 -295
  8. package/dist/index.css +1 -9
  9. package/dist/index.d.ts +0 -4
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/locales/de.json +0 -84
  12. package/dist/locales/en.json +0 -84
  13. package/dist/shared/components/blade-navigation/components/vc-blade-navigation/_internal/vc-mobile-back-button.vue.d.ts.map +1 -1
  14. package/dist/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.d.ts +1 -1
  15. package/dist/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.d.ts.map +1 -1
  16. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -1
  17. package/dist/shared/components/change-password-button/change-password-button.vue.d.ts.map +1 -1
  18. package/dist/shared/components/logout-button/logout-button.vue.d.ts.map +1 -1
  19. package/dist/shared/components/settings-menu-item/settings-menu-item.vue.d.ts.map +1 -1
  20. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +2 -2
  21. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +6 -6
  22. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/dist/ui/components/atoms/vc-hint/vc-hint.vue.d.ts.map +1 -1
  25. package/dist/ui/components/atoms/vc-icon/icons/MenuBurgerIcon.vue.d.ts.map +1 -1
  26. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts +0 -26
  27. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts.map +1 -1
  28. package/dist/ui/components/atoms/vc-icon/vc-bootstrap-icon.vue.d.ts.map +1 -1
  29. package/dist/ui/components/atoms/vc-icon/vc-fontawesome-icon.vue.d.ts.map +1 -1
  30. package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
  31. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts +0 -5
  32. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts.map +1 -1
  33. package/dist/ui/components/atoms/vc-icon/vc-material-icon.vue.d.ts +0 -20
  34. package/dist/ui/components/atoms/vc-icon/vc-material-icon.vue.d.ts.map +1 -1
  35. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  36. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue.d.ts +36 -0
  37. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue.d.ts.map +1 -0
  38. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue.d.ts +17 -0
  39. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue.d.ts.map +1 -0
  40. package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts +16 -2381
  41. package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts.map +1 -1
  42. package/dist/ui/components/molecules/vc-form/vc-form.vue.d.ts.map +1 -1
  43. package/dist/ui/components/molecules/vc-input-currency/vc-input-currency.vue.d.ts +1 -1
  44. package/dist/ui/components/molecules/vc-input-currency/vc-input-currency.vue.d.ts.map +1 -1
  45. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts +1 -1
  46. package/dist/ui/components/molecules/vc-pagination/vc-pagination.vue.d.ts.map +1 -1
  47. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue.d.ts.map +1 -1
  48. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
  49. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
  50. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  51. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
  52. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue.d.ts.map +1 -1
  53. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue.d.ts.map +1 -1
  54. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  55. package/dist/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts +2 -2
  56. package/dist/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts +2 -2
  57. package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts.map +1 -1
  58. package/dist/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue.d.ts.map +1 -1
  59. package/dist/vendor-boolbase-Cp9L0GAZ.js +25 -0
  60. package/dist/vendor-cheerio-HN9zIPZn.js +3135 -0
  61. package/dist/vendor-cheerio-select-5Ry0HvBq.js +306 -0
  62. package/dist/vendor-core-js-l0sNRNKZ.js +1 -0
  63. package/dist/vendor-css-select-DRIZ9kfZ.js +966 -0
  64. package/dist/vendor-css-what-DuPJ1HEF.js +448 -0
  65. package/dist/vendor-cypress-signalr-mock-BKdBJpdt.js +778 -0
  66. package/dist/vendor-date-fns-515YWkk-.js +6724 -0
  67. package/dist/vendor-dom-serializer-nQMsqjYW.js +286 -0
  68. package/dist/vendor-dom7-CJLPMwy5.js +941 -0
  69. package/dist/vendor-domelementtype-CjSzQey5.js +53 -0
  70. package/dist/vendor-domhandler-9z8cS16a.js +484 -0
  71. package/dist/vendor-dompurify-CRFzu7ib.js +1336 -0
  72. package/dist/vendor-domutils-Bc-Opz-v.js +981 -0
  73. package/dist/vendor-entities-Bfsx4xOQ.js +636 -0
  74. package/dist/vendor-floating-ui-core-wV8u8QP4.js +511 -0
  75. package/dist/vendor-floating-ui-dom-DDnRPs17.js +706 -0
  76. package/dist/vendor-floating-ui-utils-OMIFy1QU.js +296 -0
  77. package/dist/vendor-floating-ui-vue-D-tCDAMm.js +167 -0
  78. package/dist/vendor-fontsource-plus-jakarta-sans.css +1 -0
  79. package/dist/vendor-headlessui-vue-CY9FRgTb.js +83 -0
  80. package/dist/vendor-htmlparser2-B1dhFPOs.js +1426 -0
  81. package/dist/vendor-iconify-vue-DfRGgyNu.js +1840 -0
  82. package/dist/vendor-intlify-core-base-BuknsFQe.js +1876 -0
  83. package/dist/vendor-intlify-message-compiler-CuOQDWx1.js +1508 -0
  84. package/dist/vendor-intlify-shared-Cz4YRMuC.js +241 -0
  85. package/dist/vendor-iso-639-1-BJCk9DvE.js +819 -0
  86. package/dist/vendor-linkify-it-CKUf4vsc.js +830 -0
  87. package/dist/vendor-linkifyjs-BfyGgbCh.js +1756 -0
  88. package/dist/vendor-lodash-es-BySUOlwf.js +18333 -0
  89. package/dist/vendor-markdown-it-D-apazHa.js +6000 -0
  90. package/dist/vendor-markdown-it-task-lists-rxMVH6Ku.js +131 -0
  91. package/dist/vendor-mdurl-BNh2CCgT.js +537 -0
  92. package/dist/vendor-microsoft-applicationinsights-analytics-js-kG3lLg8X.js +1275 -0
  93. package/dist/vendor-microsoft-applicationinsights-cfgsync-js-C0uQkiQq.js +591 -0
  94. package/dist/vendor-microsoft-applicationinsights-channel-js-Dyd_PXA3.js +2153 -0
  95. package/dist/vendor-microsoft-applicationinsights-common-CfmP1_Qr.js +2470 -0
  96. package/dist/vendor-microsoft-applicationinsights-core-js-Cq4YSEvZ.js +6589 -0
  97. package/dist/vendor-microsoft-applicationinsights-dependencies-js-C56OBFr4.js +1510 -0
  98. package/dist/vendor-microsoft-applicationinsights-properties-js-CBJTBawx.js +761 -0
  99. package/dist/vendor-microsoft-applicationinsights-shims-CX8sJgar.js +70 -0
  100. package/dist/vendor-microsoft-applicationinsights-web-pim2ri-g.js +667 -0
  101. package/dist/vendor-microsoft-dynamicproto-js-CFBBUu9p.js +520 -0
  102. package/dist/vendor-microsoft-signalr-dUnlRsGm.js +3339 -0
  103. package/dist/vendor-moment-Mki5YqAR.js +5679 -0
  104. package/dist/vendor-nevware21-ts-async-CLMApQ9E.js +395 -0
  105. package/dist/vendor-nevware21-ts-utils-e8v8Jty3.js +1160 -0
  106. package/dist/vendor-normalize-css.css +1 -0
  107. package/dist/vendor-nth-check-Bx8TxtJt.js +157 -0
  108. package/dist/vendor-orderedmap-dGG6uMFJ.js +137 -0
  109. package/dist/vendor-parse5-Bt2NhSzR.js +8432 -0
  110. package/dist/vendor-parse5-htmlparser2-tree-adapter-BUUtKzf8.js +216 -0
  111. package/dist/vendor-popperjs-core-Cr2byIky.js +1790 -0
  112. package/dist/vendor-prettier-B4PaeWRQ.js +98 -0
  113. package/dist/vendor-prosemirror-commands-BH9lWGpW.js +561 -0
  114. package/dist/vendor-prosemirror-dropcursor-CeyPcxrA.js +146 -0
  115. package/dist/vendor-prosemirror-gapcursor-U8UoUJII.js +236 -0
  116. package/dist/vendor-prosemirror-history-BDaJkvNx.js +414 -0
  117. package/dist/vendor-prosemirror-keymap-BbWvIWmH.js +128 -0
  118. package/dist/vendor-prosemirror-markdown-gB0PXBbz.js +866 -0
  119. package/dist/vendor-prosemirror-model-BZu3WVcD.js +3463 -0
  120. package/dist/vendor-prosemirror-schema-list-Bl9NpKA7.js +158 -0
  121. package/dist/vendor-prosemirror-state-BvL9Pxph.js +1003 -0
  122. package/dist/vendor-prosemirror-tables-17qAnviK.js +2159 -0
  123. package/dist/vendor-prosemirror-transform-CE9VV3qg.js +2156 -0
  124. package/dist/vendor-prosemirror-view-CU2WTHT7.js +5811 -0
  125. package/dist/vendor-punycode-js-iAs5RxMf.js +441 -0
  126. package/dist/vendor-rope-sequence-BdXDKoGt.js +207 -0
  127. package/dist/vendor-semver-CVLMK-S4.js +2702 -0
  128. package/dist/vendor-ssr-window-s6OpKa3O.js +150 -0
  129. package/dist/vendor-swiper-CdiyNHVt.js +5679 -0
  130. package/dist/vendor-swiper.css +1 -0
  131. package/dist/vendor-tanstack-virtual-core-l0sNRNKZ.js +1 -0
  132. package/dist/vendor-tanstack-vue-virtual-l0sNRNKZ.js +1 -0
  133. package/dist/vendor-tippy-js-DWFe2TfK.js +1647 -0
  134. package/dist/vendor-tiptap-core-NfwGfaQk.js +4910 -0
  135. package/dist/vendor-tiptap-extension-blockquote-jmWBTtsI.js +57 -0
  136. package/dist/vendor-tiptap-extension-bold-p5frh4ak.js +97 -0
  137. package/dist/vendor-tiptap-extension-bubble-menu-KUhZSfrs.js +218 -0
  138. package/dist/vendor-tiptap-extension-bullet-list-COmZRoSB.js +73 -0
  139. package/dist/vendor-tiptap-extension-code-block-DyTARZss.js +221 -0
  140. package/dist/vendor-tiptap-extension-code-jVv6CXpX.js +75 -0
  141. package/dist/vendor-tiptap-extension-document-DssuotYs.js +13 -0
  142. package/dist/vendor-tiptap-extension-dropcursor-BoO0Qv91.js +26 -0
  143. package/dist/vendor-tiptap-extension-floating-menu-CrO8CN5w.js +165 -0
  144. package/dist/vendor-tiptap-extension-gapcursor-KpsWEoMD.js +30 -0
  145. package/dist/vendor-tiptap-extension-hard-break-ldOzhSvf.js +68 -0
  146. package/dist/vendor-tiptap-extension-heading-CKz2llX0.js +77 -0
  147. package/dist/vendor-tiptap-extension-history-DeKZ2VQ9.js +48 -0
  148. package/dist/vendor-tiptap-extension-horizontal-rule-CAjWRyDS.js +92 -0
  149. package/dist/vendor-tiptap-extension-image-ZagcEYuk.js +76 -0
  150. package/dist/vendor-tiptap-extension-italic-CM4xdznY.js +96 -0
  151. package/dist/vendor-tiptap-extension-link-Z-AMC4Ri.js +414 -0
  152. package/dist/vendor-tiptap-extension-list-item-BJi5QpXc.js +37 -0
  153. package/dist/vendor-tiptap-extension-ordered-list-C_TMrfBE.js +97 -0
  154. package/dist/vendor-tiptap-extension-paragraph-CQw0E0Au.js +39 -0
  155. package/dist/vendor-tiptap-extension-placeholder-BBNVKfa_.js +66 -0
  156. package/dist/vendor-tiptap-extension-strike-DUyMYX1Z.js +79 -0
  157. package/dist/vendor-tiptap-extension-table-cell-CoDIMPA5.js +47 -0
  158. package/dist/vendor-tiptap-extension-table-header-DvbGHnmw.js +47 -0
  159. package/dist/vendor-tiptap-extension-table-row-D1uqN5Aj.js +26 -0
  160. package/dist/vendor-tiptap-extension-table-tKS4MOM4.js +354 -0
  161. package/dist/vendor-tiptap-extension-text-DtRBhKB2.js +12 -0
  162. package/dist/vendor-tiptap-extension-underline-DqaSFp_P.js +50 -0
  163. package/dist/vendor-tiptap-markdown-7-PCADTU.js +1017 -0
  164. package/dist/vendor-tiptap-pm-l0sNRNKZ.js +1 -0
  165. package/dist/vendor-tiptap-starter-kit-CDSV_Zuu.js +88 -0
  166. package/dist/vendor-tiptap-vue-3-DZg2fjq_.js +268 -0
  167. package/dist/vendor-truncate-html-3qQY0Djo.js +196 -0
  168. package/dist/vendor-uc-micro-jjt6LQ65.js +23 -0
  169. package/dist/vendor-vee-validate-i18n-v_gHjRmD.js +154 -0
  170. package/dist/vendor-vee-validate-rules-DzV3VY3N.js +536 -0
  171. package/dist/vendor-vue-currency-input-DGAkEFBO.js +545 -0
  172. package/dist/vendor-vue-demi-l0sNRNKZ.js +1 -0
  173. package/dist/vendor-vue-devtools-api-DXYR8qBG.js +169 -0
  174. package/dist/vendor-vue-i18n-Co752uk3.js +1897 -0
  175. package/dist/vendor-vue3-application-insights-CYWFCr_J.js +119 -0
  176. package/dist/vendor-vue3-touch-events-BJEAiSa3.js +416 -0
  177. package/dist/vendor-vuepic-vue-datepicker-BSWXRSiu.js +5019 -0
  178. package/dist/vendor-vuepic-vue-datepicker.css +1 -0
  179. package/dist/vendor-vueuse-components-l1bL12mE.js +339 -0
  180. package/dist/vendor-vueuse-core-DGcJOmwG.js +7743 -0
  181. package/dist/vendor-vueuse-shared-_mOXsFuM.js +1568 -0
  182. package/dist/vendor-w3c-keyname-BOm2dtJm.js +121 -0
  183. package/package.json +22 -11
  184. package/shared/components/blade-navigation/components/vc-blade-navigation/_internal/vc-mobile-back-button.vue +3 -3
  185. package/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.ts +2 -1
  186. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +1 -0
  187. package/shared/components/change-password-button/change-password-button.vue +1 -2
  188. package/shared/components/logout-button/logout-button.vue +1 -2
  189. package/shared/components/notifications/components/notification-container/index.ts +1 -1
  190. package/shared/components/notifications/core/notification.ts +1 -1
  191. package/shared/components/settings-menu-item/settings-menu-item.vue +1 -0
  192. package/shared/components/sidebar/sidebar.vue +2 -2
  193. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +2 -1
  194. package/ui/components/atoms/vc-hint/vc-hint.vue +2 -0
  195. package/ui/components/atoms/vc-icon/composables/use-icon.ts +1 -1
  196. package/ui/components/atoms/vc-icon/icons/MenuBurgerIcon.vue +18 -14
  197. package/ui/components/atoms/vc-icon/icons/index.ts +1 -27
  198. package/ui/components/atoms/vc-icon/vc-bootstrap-icon.vue +7 -11
  199. package/ui/components/atoms/vc-icon/vc-fontawesome-icon.vue +37 -31
  200. package/ui/components/atoms/vc-icon/vc-icon-examples.vue +1 -1
  201. package/ui/components/atoms/vc-icon/vc-icon.stories.ts +4 -5
  202. package/ui/components/atoms/vc-icon/vc-icon.vue +43 -186
  203. package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +22 -70
  204. package/ui/components/atoms/vc-icon/vc-material-icon.vue +28 -59
  205. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +2 -3
  206. package/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue +103 -0
  207. package/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue +252 -0
  208. package/ui/components/molecules/vc-editor/vc-editor.stories.ts +1 -4
  209. package/ui/components/molecules/vc-editor/vc-editor.vue +666 -360
  210. package/ui/components/molecules/vc-form/vc-form.vue +7 -5
  211. package/ui/components/molecules/vc-input/vc-input.vue +1 -1
  212. package/ui/components/molecules/vc-pagination/vc-pagination.vue +4 -17
  213. package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarMobileActions.vue +1 -1
  214. package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue +1 -3
  215. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +1 -4
  216. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +1 -3
  217. package/ui/components/organisms/vc-app/vc-app.backupsb.ts +214 -214
  218. package/ui/components/organisms/vc-app/vc-app.vue +3 -5
  219. package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +3 -10
  220. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/mobile/vc-blade-toolbar-mobile.vue +1 -1
  221. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue +2 -2
  222. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue +2 -2
  223. package/ui/components/organisms/vc-blade/vc-blade.vue +4 -5
  224. package/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue +1 -3
  225. package/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue +1 -2
  226. package/ui/components/organisms/vc-table/composables/useTableState.ts +5 -5
  227. package/dist/apl-B2DGVGxc.js +0 -76
  228. package/dist/asciiarmor-2LVJmxlE.js +0 -34
  229. package/dist/asn1-jKiBa2Ya.js +0 -95
  230. package/dist/asterisk-DS281yxp.js +0 -271
  231. package/dist/brainfuck-C_p9pTT8.js +0 -34
  232. package/dist/clike-DGTaUp48.js +0 -620
  233. package/dist/clojure-CCKyeQKf.js +0 -800
  234. package/dist/cmake-CuaCgAKt.js +0 -28
  235. package/dist/cobol-BlTKFDRj.js +0 -72
  236. package/dist/coffeescript-BVCvwO8I.js +0 -179
  237. package/dist/commonlisp-D_kxz07b.js +0 -75
  238. package/dist/crystal-D309uH6_.js +0 -217
  239. package/dist/css-BkF-NPzE.js +0 -1553
  240. package/dist/cypher-BMq4Fwjl.js +0 -68
  241. package/dist/d-BZcgY6La.js +0 -127
  242. package/dist/diff-Cg9d_RX2.js +0 -18
  243. package/dist/dockerfile-DIy8NleC.js +0 -194
  244. package/dist/dtd-CtLokQ-U.js +0 -84
  245. package/dist/dylan-QYeExnWK.js +0 -234
  246. package/dist/ebnf-DUPDuY4r.js +0 -78
  247. package/dist/ecl-CiXN-g_D.js +0 -121
  248. package/dist/eiffel-yQhjl4T1.js +0 -110
  249. package/dist/elm-CNT9vbN0.js +0 -108
  250. package/dist/erlang-CFOYdy9e.js +0 -487
  251. package/dist/factor-DDOC7X6P.js +0 -65
  252. package/dist/fcl-CPC2WYrI.js +0 -103
  253. package/dist/forth-BmxRyE9S.js +0 -60
  254. package/dist/fortran-9bvPyrOW.js +0 -442
  255. package/dist/gas-cpmYfFX2.js +0 -183
  256. package/dist/gherkin-CJuwpceU.js +0 -34
  257. package/dist/groovy-DZeT_VM-.js +0 -146
  258. package/dist/haskell-Bvt3Qq1t.js +0 -375
  259. package/dist/haxe-70NVW1pR.js +0 -359
  260. package/dist/http-D9LttvKF.js +0 -44
  261. package/dist/idl-B6TRFYjl.js +0 -947
  262. package/dist/index-4DWvmoYg.js +0 -71
  263. package/dist/index-52o7mJaX.js +0 -156
  264. package/dist/index-B0KatioT.js +0 -98
  265. package/dist/index-BP3W8zuk.js +0 -268
  266. package/dist/index-BykT5L1A.js +0 -148134
  267. package/dist/index-CfXo9hsG.js +0 -75
  268. package/dist/index-Ch37pBUt.js +0 -308
  269. package/dist/index-D2KGkAYT.js +0 -93
  270. package/dist/index-D83zQom_.js +0 -58
  271. package/dist/index-DuQrVLbu.js +0 -134
  272. package/dist/index-_fdMid5h.js +0 -288
  273. package/dist/index-a1wO-owY.js +0 -545
  274. package/dist/index-crMpNSFe.js +0 -611
  275. package/dist/index-dmBRpHHY.js +0 -137
  276. package/dist/index-kBdB14Fz.js +0 -341
  277. package/dist/index-uBhy41le.js +0 -249
  278. package/dist/index-zZrijNsr.js +0 -299
  279. package/dist/javascript-C2yteZeJ.js +0 -691
  280. package/dist/jinja2-DnB6dQmV.js +0 -154
  281. package/dist/julia-DpvXAuO6.js +0 -241
  282. package/dist/livescript-CanGTf8u.js +0 -272
  283. package/dist/lua-XplVlWi_.js +0 -217
  284. package/dist/mathematica-jaRHnSxC.js +0 -35
  285. package/dist/mbox-BctzC1hL.js +0 -76
  286. package/dist/mirc-CFBPAOaF.js +0 -72
  287. package/dist/mllike-BSnXJBGA.js +0 -272
  288. package/dist/modelica-vUgVs--1.js +0 -93
  289. package/dist/mscgen-Cpl0NYLN.js +0 -104
  290. package/dist/mumps-CQoS1kWX.js +0 -25
  291. package/dist/nginx-zDPm3Z74.js +0 -89
  292. package/dist/nsis-fePjrhq7.js +0 -62
  293. package/dist/ntriples-CsNjv2QF.js +0 -79
  294. package/dist/octave-C8PmmSRH.js +0 -143
  295. package/dist/oz-Ce8aN8oE.js +0 -151
  296. package/dist/pascal-De0D6mP7.js +0 -77
  297. package/dist/perl-B4bSCe1C.js +0 -915
  298. package/dist/pig-D24Z8EXi.js +0 -54
  299. package/dist/powershell-DkYVfTzP.js +0 -249
  300. package/dist/properties-Dn9wna3M.js +0 -26
  301. package/dist/protobuf-BPIjwpzm.js +0 -49
  302. package/dist/pug-CwAQJzGR.js +0 -248
  303. package/dist/puppet-nyd4dhjf.js +0 -45
  304. package/dist/python-BkR3uSy8.js +0 -313
  305. package/dist/q-DXjKs-tC.js +0 -83
  306. package/dist/r-LKEuhEGI.js +0 -104
  307. package/dist/rpm-IznJm2Xc.js +0 -57
  308. package/dist/ruby-CcYfvIk6.js +0 -228
  309. package/dist/sas-7E8yHoCW.js +0 -105
  310. package/dist/scheme-DjibxsNh.js +0 -124
  311. package/dist/shared/modules/dynamic/components/fields/storybook/common/args.d.ts +0 -113
  312. package/dist/shared/modules/dynamic/components/fields/storybook/common/args.d.ts.map +0 -1
  313. package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts +0 -3
  314. package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts.map +0 -1
  315. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts +0 -102
  316. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts.map +0 -1
  317. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.d.ts +0 -4
  318. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.d.ts.map +0 -1
  319. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.d.ts +0 -3
  320. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.d.ts.map +0 -1
  321. package/dist/shell-C0C2sNA_.js +0 -182
  322. package/dist/sieve-Bwz7vjP5.js +0 -72
  323. package/dist/simple-mode-B0dvCdAA.js +0 -89
  324. package/dist/smalltalk-Bhddl2pB.js +0 -48
  325. package/dist/solr-BNlsLglM.js +0 -41
  326. package/dist/sparql-FarWu_Gb.js +0 -197
  327. package/dist/spreadsheet-C-cy4P5N.js +0 -49
  328. package/dist/sql-CfG5lQ3l.js +0 -282
  329. package/dist/stex-Du4h4KAU.js +0 -129
  330. package/dist/stylus-CAdqWld3.js +0 -250
  331. package/dist/swift-DSxqR9R6.js +0 -230
  332. package/dist/tcl-xfoLljhY.js +0 -81
  333. package/dist/textile-D1AWE-pc.js +0 -295
  334. package/dist/tiddlywiki-5wqsXtSk.js +0 -155
  335. package/dist/tiki-__Kn3CeS.js +0 -181
  336. package/dist/toml-BHiuTcfn.js +0 -49
  337. package/dist/troff-D2UO-fKf.js +0 -35
  338. package/dist/ttcn-Bsa4sfRm.js +0 -123
  339. package/dist/ttcn-cfg-Bac_acMi.js +0 -88
  340. package/dist/turtle-xwJUxoPV.js +0 -80
  341. package/dist/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue.d.ts +0 -7
  342. package/dist/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue.d.ts.map +0 -1
  343. package/dist/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue.d.ts +0 -7
  344. package/dist/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue.d.ts.map +0 -1
  345. package/dist/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue.d.ts +0 -7
  346. package/dist/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue.d.ts.map +0 -1
  347. package/dist/ui/components/atoms/vc-icon/icons/BellIcon.vue.d.ts +0 -7
  348. package/dist/ui/components/atoms/vc-icon/icons/BellIcon.vue.d.ts.map +0 -1
  349. package/dist/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue.d.ts +0 -7
  350. package/dist/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue.d.ts.map +0 -1
  351. package/dist/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue.d.ts +0 -7
  352. package/dist/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue.d.ts.map +0 -1
  353. package/dist/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue.d.ts +0 -7
  354. package/dist/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue.d.ts.map +0 -1
  355. package/dist/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue.d.ts +0 -7
  356. package/dist/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue.d.ts.map +0 -1
  357. package/dist/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue.d.ts +0 -7
  358. package/dist/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue.d.ts.map +0 -1
  359. package/dist/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue.d.ts +0 -7
  360. package/dist/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue.d.ts.map +0 -1
  361. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue.d.ts +0 -7
  362. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue.d.ts.map +0 -1
  363. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue.d.ts +0 -7
  364. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue.d.ts.map +0 -1
  365. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts +0 -7
  366. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts.map +0 -1
  367. package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts +0 -7
  368. package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts.map +0 -1
  369. package/dist/ui/components/atoms/vc-icon/icons/LogoutIcon.vue.d.ts +0 -7
  370. package/dist/ui/components/atoms/vc-icon/icons/LogoutIcon.vue.d.ts.map +0 -1
  371. package/dist/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue.d.ts +0 -7
  372. package/dist/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue.d.ts.map +0 -1
  373. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts +0 -7
  374. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts.map +0 -1
  375. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts +0 -7
  376. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts.map +0 -1
  377. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts +0 -7
  378. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts.map +0 -1
  379. package/dist/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue.d.ts +0 -7
  380. package/dist/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue.d.ts.map +0 -1
  381. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts +0 -7
  382. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts.map +0 -1
  383. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts +0 -7
  384. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts.map +0 -1
  385. package/dist/ui/components/atoms/vc-icon/icons/SearchIcon.vue.d.ts +0 -7
  386. package/dist/ui/components/atoms/vc-icon/icons/SearchIcon.vue.d.ts.map +0 -1
  387. package/dist/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue.d.ts +0 -7
  388. package/dist/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue.d.ts.map +0 -1
  389. package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts +0 -7
  390. package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts.map +0 -1
  391. package/dist/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue.d.ts +0 -7
  392. package/dist/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue.d.ts.map +0 -1
  393. package/dist/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue.d.ts +0 -7
  394. package/dist/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue.d.ts.map +0 -1
  395. package/dist/vb-c2kQGd6-.js +0 -74
  396. package/dist/vbscript-1f_Dhg5H.js +0 -324
  397. package/dist/velocity-DJd0pTTC.js +0 -96
  398. package/dist/verilog-CiS1jyi5.js +0 -262
  399. package/dist/vhdl-T9HkrbI2.js +0 -106
  400. package/dist/webidl-CjfDENEo.js +0 -155
  401. package/dist/xquery-BUQdORAS.js +0 -422
  402. package/dist/yacas-C0absKBh.js +0 -73
  403. package/dist/z80-Pki2zAjW.js +0 -61
  404. package/shared/modules/dynamic/components/fields/storybook/Button.stories.ts +0 -186
  405. package/shared/modules/dynamic/components/fields/storybook/Card.stories.ts +0 -175
  406. package/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.ts +0 -185
  407. package/shared/modules/dynamic/components/fields/storybook/ContentField.stories.ts +0 -245
  408. package/shared/modules/dynamic/components/fields/storybook/EditorField.stories.ts +0 -192
  409. package/shared/modules/dynamic/components/fields/storybook/Fieldset.stories.ts +0 -347
  410. package/shared/modules/dynamic/components/fields/storybook/GalleryField.stories.ts +0 -239
  411. package/shared/modules/dynamic/components/fields/storybook/ImageField.stories.ts +0 -186
  412. package/shared/modules/dynamic/components/fields/storybook/InputCurrency.stories.ts +0 -281
  413. package/shared/modules/dynamic/components/fields/storybook/InputField.stories.ts +0 -312
  414. package/shared/modules/dynamic/components/fields/storybook/MultivalueField.stories.ts +0 -361
  415. package/shared/modules/dynamic/components/fields/storybook/RadioButtonGroup.stories.ts +0 -224
  416. package/shared/modules/dynamic/components/fields/storybook/RatingField.stories.ts +0 -131
  417. package/shared/modules/dynamic/components/fields/storybook/SelectField.stories.ts +0 -666
  418. package/shared/modules/dynamic/components/fields/storybook/StatusField.stories.ts +0 -202
  419. package/shared/modules/dynamic/components/fields/storybook/SwitchField.stories.ts +0 -178
  420. package/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.ts +0 -203
  421. package/shared/modules/dynamic/components/fields/storybook/VideoField.stories.ts +0 -92
  422. package/shared/modules/dynamic/components/fields/storybook/common/args.ts +0 -130
  423. package/shared/modules/dynamic/components/fields/storybook/common/templates.ts +0 -8
  424. package/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.ts +0 -54
  425. package/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.ts +0 -16
  426. package/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.ts +0 -41
  427. package/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue +0 -15
  428. package/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue +0 -20
  429. package/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue +0 -13
  430. package/ui/components/atoms/vc-icon/icons/BellIcon.vue +0 -14
  431. package/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue +0 -13
  432. package/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue +0 -13
  433. package/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue +0 -13
  434. package/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue +0 -13
  435. package/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue +0 -16
  436. package/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue +0 -20
  437. package/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue +0 -14
  438. package/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue +0 -14
  439. package/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue +0 -27
  440. package/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue +0 -22
  441. package/ui/components/atoms/vc-icon/icons/LogoutIcon.vue +0 -13
  442. package/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue +0 -14
  443. package/ui/components/atoms/vc-icon/icons/OffersIcon.vue +0 -23
  444. package/ui/components/atoms/vc-icon/icons/OrdersIcon.vue +0 -19
  445. package/ui/components/atoms/vc-icon/icons/PeopleIcon.vue +0 -21
  446. package/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue +0 -20
  447. package/ui/components/atoms/vc-icon/icons/ProductsIcon.vue +0 -23
  448. package/ui/components/atoms/vc-icon/icons/ProfileIcon.vue +0 -18
  449. package/ui/components/atoms/vc-icon/icons/SearchIcon.vue +0 -14
  450. package/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue +0 -21
  451. package/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue +0 -16
  452. package/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue +0 -26
  453. package/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue +0 -19
@@ -0,0 +1,4910 @@
1
+ import { a as PluginKey, N as NodeSelection, P as Plugin, S as Selection, E as EditorState, T as TextSelection, A as AllSelection } from './vendor-prosemirror-state-BvL9Pxph.js';
2
+ import { f as findWrapping, a as canJoin, T as Transform, c as canSplit, j as joinPoint, l as liftTarget, R as ReplaceStep, b as ReplaceAroundStep } from './vendor-prosemirror-transform-CE9VV3qg.js';
3
+ import { E as EditorView } from './vendor-prosemirror-view-CU2WTHT7.js';
4
+ import { a as keymap } from './vendor-prosemirror-keymap-BbWvIWmH.js';
5
+ import { D as DOMSerializer, F as Fragment, S as Slice, a as Schema, b as Node$1, d as DOMParser } from './vendor-prosemirror-model-BZu3WVcD.js';
6
+ import { w as wrapInList$1, s as sinkListItem$1, l as liftListItem$1 } from './vendor-prosemirror-schema-list-Bl9NpKA7.js';
7
+ import { w as wrapIn$1, s as setBlockType, a as selectTextblockStart$1, b as selectTextblockEnd$1, c as selectParentNode$1, d as selectNodeForward$1, e as selectNodeBackward$1, n as newlineInCode$1, l as liftEmptyBlock$1, f as lift$1, j as joinUp$1, g as joinTextblockForward$1, h as joinTextblockBackward$1, i as joinForward$1, k as joinDown$1, m as joinBackward$1, o as exitCode$1, p as deleteSelection$1, q as createParagraphNear$1 } from './vendor-prosemirror-commands-BH9lWGpW.js';
8
+
9
+ /**
10
+ * Takes a Transaction & Editor State and turns it into a chainable state object
11
+ * @param config The transaction and state to create the chainable state from
12
+ * @returns A chainable Editor state object
13
+ */
14
+ function createChainableState(config) {
15
+ const { state, transaction } = config;
16
+ let { selection } = transaction;
17
+ let { doc } = transaction;
18
+ let { storedMarks } = transaction;
19
+ return {
20
+ ...state,
21
+ apply: state.apply.bind(state),
22
+ applyTransaction: state.applyTransaction.bind(state),
23
+ plugins: state.plugins,
24
+ schema: state.schema,
25
+ reconfigure: state.reconfigure.bind(state),
26
+ toJSON: state.toJSON.bind(state),
27
+ get storedMarks() {
28
+ return storedMarks;
29
+ },
30
+ get selection() {
31
+ return selection;
32
+ },
33
+ get doc() {
34
+ return doc;
35
+ },
36
+ get tr() {
37
+ selection = transaction.selection;
38
+ doc = transaction.doc;
39
+ storedMarks = transaction.storedMarks;
40
+ return transaction;
41
+ },
42
+ };
43
+ }
44
+
45
+ class CommandManager {
46
+ constructor(props) {
47
+ this.editor = props.editor;
48
+ this.rawCommands = this.editor.extensionManager.commands;
49
+ this.customState = props.state;
50
+ }
51
+ get hasCustomState() {
52
+ return !!this.customState;
53
+ }
54
+ get state() {
55
+ return this.customState || this.editor.state;
56
+ }
57
+ get commands() {
58
+ const { rawCommands, editor, state } = this;
59
+ const { view } = editor;
60
+ const { tr } = state;
61
+ const props = this.buildProps(tr);
62
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
63
+ const method = (...args) => {
64
+ const callback = command(...args)(props);
65
+ if (!tr.getMeta('preventDispatch') && !this.hasCustomState) {
66
+ view.dispatch(tr);
67
+ }
68
+ return callback;
69
+ };
70
+ return [name, method];
71
+ }));
72
+ }
73
+ get chain() {
74
+ return () => this.createChain();
75
+ }
76
+ get can() {
77
+ return () => this.createCan();
78
+ }
79
+ createChain(startTr, shouldDispatch = true) {
80
+ const { rawCommands, editor, state } = this;
81
+ const { view } = editor;
82
+ const callbacks = [];
83
+ const hasStartTransaction = !!startTr;
84
+ const tr = startTr || state.tr;
85
+ const run = () => {
86
+ if (!hasStartTransaction
87
+ && shouldDispatch
88
+ && !tr.getMeta('preventDispatch')
89
+ && !this.hasCustomState) {
90
+ view.dispatch(tr);
91
+ }
92
+ return callbacks.every(callback => callback === true);
93
+ };
94
+ const chain = {
95
+ ...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
96
+ const chainedCommand = (...args) => {
97
+ const props = this.buildProps(tr, shouldDispatch);
98
+ const callback = command(...args)(props);
99
+ callbacks.push(callback);
100
+ return chain;
101
+ };
102
+ return [name, chainedCommand];
103
+ })),
104
+ run,
105
+ };
106
+ return chain;
107
+ }
108
+ createCan(startTr) {
109
+ const { rawCommands, state } = this;
110
+ const dispatch = false;
111
+ const tr = startTr || state.tr;
112
+ const props = this.buildProps(tr, dispatch);
113
+ const formattedCommands = Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
114
+ return [name, (...args) => command(...args)({ ...props, dispatch: undefined })];
115
+ }));
116
+ return {
117
+ ...formattedCommands,
118
+ chain: () => this.createChain(tr, dispatch),
119
+ };
120
+ }
121
+ buildProps(tr, shouldDispatch = true) {
122
+ const { rawCommands, editor, state } = this;
123
+ const { view } = editor;
124
+ const props = {
125
+ tr,
126
+ editor,
127
+ view,
128
+ state: createChainableState({
129
+ state,
130
+ transaction: tr,
131
+ }),
132
+ dispatch: shouldDispatch ? () => undefined : undefined,
133
+ chain: () => this.createChain(tr, shouldDispatch),
134
+ can: () => this.createCan(tr),
135
+ get commands() {
136
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
137
+ return [name, (...args) => command(...args)(props)];
138
+ }));
139
+ },
140
+ };
141
+ return props;
142
+ }
143
+ }
144
+
145
+ class EventEmitter {
146
+ constructor() {
147
+ this.callbacks = {};
148
+ }
149
+ on(event, fn) {
150
+ if (!this.callbacks[event]) {
151
+ this.callbacks[event] = [];
152
+ }
153
+ this.callbacks[event].push(fn);
154
+ return this;
155
+ }
156
+ emit(event, ...args) {
157
+ const callbacks = this.callbacks[event];
158
+ if (callbacks) {
159
+ callbacks.forEach(callback => callback.apply(this, args));
160
+ }
161
+ return this;
162
+ }
163
+ off(event, fn) {
164
+ const callbacks = this.callbacks[event];
165
+ if (callbacks) {
166
+ if (fn) {
167
+ this.callbacks[event] = callbacks.filter(callback => callback !== fn);
168
+ }
169
+ else {
170
+ delete this.callbacks[event];
171
+ }
172
+ }
173
+ return this;
174
+ }
175
+ once(event, fn) {
176
+ const onceFn = (...args) => {
177
+ this.off(event, onceFn);
178
+ fn.apply(this, args);
179
+ };
180
+ return this.on(event, onceFn);
181
+ }
182
+ removeAllListeners() {
183
+ this.callbacks = {};
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Returns a field from an extension
189
+ * @param extension The Tiptap extension
190
+ * @param field The field, for example `renderHTML` or `priority`
191
+ * @param context The context object that should be passed as `this` into the function
192
+ * @returns The field value
193
+ */
194
+ function getExtensionField(extension, field, context) {
195
+ if (extension.config[field] === undefined && extension.parent) {
196
+ return getExtensionField(extension.parent, field, context);
197
+ }
198
+ if (typeof extension.config[field] === 'function') {
199
+ const value = extension.config[field].bind({
200
+ ...context,
201
+ parent: extension.parent
202
+ ? getExtensionField(extension.parent, field, context)
203
+ : null,
204
+ });
205
+ return value;
206
+ }
207
+ return extension.config[field];
208
+ }
209
+
210
+ function splitExtensions(extensions) {
211
+ const baseExtensions = extensions.filter(extension => extension.type === 'extension');
212
+ const nodeExtensions = extensions.filter(extension => extension.type === 'node');
213
+ const markExtensions = extensions.filter(extension => extension.type === 'mark');
214
+ return {
215
+ baseExtensions,
216
+ nodeExtensions,
217
+ markExtensions,
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Get a list of all extension attributes defined in `addAttribute` and `addGlobalAttribute`.
223
+ * @param extensions List of extensions
224
+ */
225
+ function getAttributesFromExtensions(extensions) {
226
+ const extensionAttributes = [];
227
+ const { nodeExtensions, markExtensions } = splitExtensions(extensions);
228
+ const nodeAndMarkExtensions = [...nodeExtensions, ...markExtensions];
229
+ const defaultAttribute = {
230
+ default: null,
231
+ rendered: true,
232
+ renderHTML: null,
233
+ parseHTML: null,
234
+ keepOnSplit: true,
235
+ isRequired: false,
236
+ };
237
+ extensions.forEach(extension => {
238
+ const context = {
239
+ name: extension.name,
240
+ options: extension.options,
241
+ storage: extension.storage,
242
+ extensions: nodeAndMarkExtensions,
243
+ };
244
+ const addGlobalAttributes = getExtensionField(extension, 'addGlobalAttributes', context);
245
+ if (!addGlobalAttributes) {
246
+ return;
247
+ }
248
+ const globalAttributes = addGlobalAttributes();
249
+ globalAttributes.forEach(globalAttribute => {
250
+ globalAttribute.types.forEach(type => {
251
+ Object
252
+ .entries(globalAttribute.attributes)
253
+ .forEach(([name, attribute]) => {
254
+ extensionAttributes.push({
255
+ type,
256
+ name,
257
+ attribute: {
258
+ ...defaultAttribute,
259
+ ...attribute,
260
+ },
261
+ });
262
+ });
263
+ });
264
+ });
265
+ });
266
+ nodeAndMarkExtensions.forEach(extension => {
267
+ const context = {
268
+ name: extension.name,
269
+ options: extension.options,
270
+ storage: extension.storage,
271
+ };
272
+ const addAttributes = getExtensionField(extension, 'addAttributes', context);
273
+ if (!addAttributes) {
274
+ return;
275
+ }
276
+ // TODO: remove `as Attributes`
277
+ const attributes = addAttributes();
278
+ Object
279
+ .entries(attributes)
280
+ .forEach(([name, attribute]) => {
281
+ const mergedAttr = {
282
+ ...defaultAttribute,
283
+ ...attribute,
284
+ };
285
+ if (typeof (mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.default) === 'function') {
286
+ mergedAttr.default = mergedAttr.default();
287
+ }
288
+ if ((mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.isRequired) && (mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.default) === undefined) {
289
+ delete mergedAttr.default;
290
+ }
291
+ extensionAttributes.push({
292
+ type: extension.name,
293
+ name,
294
+ attribute: mergedAttr,
295
+ });
296
+ });
297
+ });
298
+ return extensionAttributes;
299
+ }
300
+
301
+ function getNodeType(nameOrType, schema) {
302
+ if (typeof nameOrType === 'string') {
303
+ if (!schema.nodes[nameOrType]) {
304
+ throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
305
+ }
306
+ return schema.nodes[nameOrType];
307
+ }
308
+ return nameOrType;
309
+ }
310
+
311
+ function mergeAttributes(...objects) {
312
+ return objects
313
+ .filter(item => !!item)
314
+ .reduce((items, item) => {
315
+ const mergedAttributes = { ...items };
316
+ Object.entries(item).forEach(([key, value]) => {
317
+ const exists = mergedAttributes[key];
318
+ if (!exists) {
319
+ mergedAttributes[key] = value;
320
+ return;
321
+ }
322
+ if (key === 'class') {
323
+ const valueClasses = value ? String(value).split(' ') : [];
324
+ const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(' ') : [];
325
+ const insertClasses = valueClasses.filter(valueClass => !existingClasses.includes(valueClass));
326
+ mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
327
+ }
328
+ else if (key === 'style') {
329
+ const newStyles = value ? value.split(';').map((style) => style.trim()).filter(Boolean) : [];
330
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(';').map((style) => style.trim()).filter(Boolean) : [];
331
+ const styleMap = new Map();
332
+ existingStyles.forEach(style => {
333
+ const [property, val] = style.split(':').map(part => part.trim());
334
+ styleMap.set(property, val);
335
+ });
336
+ newStyles.forEach(style => {
337
+ const [property, val] = style.split(':').map(part => part.trim());
338
+ styleMap.set(property, val);
339
+ });
340
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join('; ');
341
+ }
342
+ else {
343
+ mergedAttributes[key] = value;
344
+ }
345
+ });
346
+ return mergedAttributes;
347
+ }, {});
348
+ }
349
+
350
+ function getRenderedAttributes(nodeOrMark, extensionAttributes) {
351
+ return extensionAttributes
352
+ .filter(attribute => attribute.type === nodeOrMark.type.name)
353
+ .filter(item => item.attribute.rendered)
354
+ .map(item => {
355
+ if (!item.attribute.renderHTML) {
356
+ return {
357
+ [item.name]: nodeOrMark.attrs[item.name],
358
+ };
359
+ }
360
+ return item.attribute.renderHTML(nodeOrMark.attrs) || {};
361
+ })
362
+ .reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
363
+ }
364
+
365
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
366
+ function isFunction(value) {
367
+ return typeof value === 'function';
368
+ }
369
+
370
+ /**
371
+ * Optionally calls `value` as a function.
372
+ * Otherwise it is returned directly.
373
+ * @param value Function or any value.
374
+ * @param context Optional context to bind to function.
375
+ * @param props Optional props to pass to function.
376
+ */
377
+ function callOrReturn(value, context = undefined, ...props) {
378
+ if (isFunction(value)) {
379
+ if (context) {
380
+ return value.bind(context)(...props);
381
+ }
382
+ return value(...props);
383
+ }
384
+ return value;
385
+ }
386
+
387
+ function isEmptyObject(value = {}) {
388
+ return Object.keys(value).length === 0 && value.constructor === Object;
389
+ }
390
+
391
+ function fromString(value) {
392
+ if (typeof value !== 'string') {
393
+ return value;
394
+ }
395
+ if (value.match(/^[+-]?(?:\d*\.)?\d+$/)) {
396
+ return Number(value);
397
+ }
398
+ if (value === 'true') {
399
+ return true;
400
+ }
401
+ if (value === 'false') {
402
+ return false;
403
+ }
404
+ return value;
405
+ }
406
+
407
+ /**
408
+ * This function merges extension attributes into parserule attributes (`attrs` or `getAttrs`).
409
+ * Cancels when `getAttrs` returned `false`.
410
+ * @param parseRule ProseMirror ParseRule
411
+ * @param extensionAttributes List of attributes to inject
412
+ */
413
+ function injectExtensionAttributesToParseRule(parseRule, extensionAttributes) {
414
+ if ('style' in parseRule) {
415
+ return parseRule;
416
+ }
417
+ return {
418
+ ...parseRule,
419
+ getAttrs: (node) => {
420
+ const oldAttributes = parseRule.getAttrs ? parseRule.getAttrs(node) : parseRule.attrs;
421
+ if (oldAttributes === false) {
422
+ return false;
423
+ }
424
+ const newAttributes = extensionAttributes.reduce((items, item) => {
425
+ const value = item.attribute.parseHTML
426
+ ? item.attribute.parseHTML(node)
427
+ : fromString((node).getAttribute(item.name));
428
+ if (value === null || value === undefined) {
429
+ return items;
430
+ }
431
+ return {
432
+ ...items,
433
+ [item.name]: value,
434
+ };
435
+ }, {});
436
+ return { ...oldAttributes, ...newAttributes };
437
+ },
438
+ };
439
+ }
440
+
441
+ function cleanUpSchemaItem(data) {
442
+ return Object.fromEntries(
443
+ // @ts-ignore
444
+ Object.entries(data).filter(([key, value]) => {
445
+ if (key === 'attrs' && isEmptyObject(value)) {
446
+ return false;
447
+ }
448
+ return value !== null && value !== undefined;
449
+ }));
450
+ }
451
+ /**
452
+ * Creates a new Prosemirror schema based on the given extensions.
453
+ * @param extensions An array of Tiptap extensions
454
+ * @param editor The editor instance
455
+ * @returns A Prosemirror schema
456
+ */
457
+ function getSchemaByResolvedExtensions(extensions, editor) {
458
+ var _a;
459
+ const allAttributes = getAttributesFromExtensions(extensions);
460
+ const { nodeExtensions, markExtensions } = splitExtensions(extensions);
461
+ const topNode = (_a = nodeExtensions.find(extension => getExtensionField(extension, 'topNode'))) === null || _a === void 0 ? void 0 : _a.name;
462
+ const nodes = Object.fromEntries(nodeExtensions.map(extension => {
463
+ const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.name);
464
+ const context = {
465
+ name: extension.name,
466
+ options: extension.options,
467
+ storage: extension.storage,
468
+ editor,
469
+ };
470
+ const extraNodeFields = extensions.reduce((fields, e) => {
471
+ const extendNodeSchema = getExtensionField(e, 'extendNodeSchema', context);
472
+ return {
473
+ ...fields,
474
+ ...(extendNodeSchema ? extendNodeSchema(extension) : {}),
475
+ };
476
+ }, {});
477
+ const schema = cleanUpSchemaItem({
478
+ ...extraNodeFields,
479
+ content: callOrReturn(getExtensionField(extension, 'content', context)),
480
+ marks: callOrReturn(getExtensionField(extension, 'marks', context)),
481
+ group: callOrReturn(getExtensionField(extension, 'group', context)),
482
+ inline: callOrReturn(getExtensionField(extension, 'inline', context)),
483
+ atom: callOrReturn(getExtensionField(extension, 'atom', context)),
484
+ selectable: callOrReturn(getExtensionField(extension, 'selectable', context)),
485
+ draggable: callOrReturn(getExtensionField(extension, 'draggable', context)),
486
+ code: callOrReturn(getExtensionField(extension, 'code', context)),
487
+ whitespace: callOrReturn(getExtensionField(extension, 'whitespace', context)),
488
+ linebreakReplacement: callOrReturn(getExtensionField(extension, 'linebreakReplacement', context)),
489
+ defining: callOrReturn(getExtensionField(extension, 'defining', context)),
490
+ isolating: callOrReturn(getExtensionField(extension, 'isolating', context)),
491
+ attrs: Object.fromEntries(extensionAttributes.map(extensionAttribute => {
492
+ var _a;
493
+ return [extensionAttribute.name, { default: (_a = extensionAttribute === null || extensionAttribute === void 0 ? void 0 : extensionAttribute.attribute) === null || _a === void 0 ? void 0 : _a.default }];
494
+ })),
495
+ });
496
+ const parseHTML = callOrReturn(getExtensionField(extension, 'parseHTML', context));
497
+ if (parseHTML) {
498
+ schema.parseDOM = parseHTML.map(parseRule => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
499
+ }
500
+ const renderHTML = getExtensionField(extension, 'renderHTML', context);
501
+ if (renderHTML) {
502
+ schema.toDOM = node => renderHTML({
503
+ node,
504
+ HTMLAttributes: getRenderedAttributes(node, extensionAttributes),
505
+ });
506
+ }
507
+ const renderText = getExtensionField(extension, 'renderText', context);
508
+ if (renderText) {
509
+ schema.toText = renderText;
510
+ }
511
+ return [extension.name, schema];
512
+ }));
513
+ const marks = Object.fromEntries(markExtensions.map(extension => {
514
+ const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.name);
515
+ const context = {
516
+ name: extension.name,
517
+ options: extension.options,
518
+ storage: extension.storage,
519
+ editor,
520
+ };
521
+ const extraMarkFields = extensions.reduce((fields, e) => {
522
+ const extendMarkSchema = getExtensionField(e, 'extendMarkSchema', context);
523
+ return {
524
+ ...fields,
525
+ ...(extendMarkSchema ? extendMarkSchema(extension) : {}),
526
+ };
527
+ }, {});
528
+ const schema = cleanUpSchemaItem({
529
+ ...extraMarkFields,
530
+ inclusive: callOrReturn(getExtensionField(extension, 'inclusive', context)),
531
+ excludes: callOrReturn(getExtensionField(extension, 'excludes', context)),
532
+ group: callOrReturn(getExtensionField(extension, 'group', context)),
533
+ spanning: callOrReturn(getExtensionField(extension, 'spanning', context)),
534
+ code: callOrReturn(getExtensionField(extension, 'code', context)),
535
+ attrs: Object.fromEntries(extensionAttributes.map(extensionAttribute => {
536
+ var _a;
537
+ return [extensionAttribute.name, { default: (_a = extensionAttribute === null || extensionAttribute === void 0 ? void 0 : extensionAttribute.attribute) === null || _a === void 0 ? void 0 : _a.default }];
538
+ })),
539
+ });
540
+ const parseHTML = callOrReturn(getExtensionField(extension, 'parseHTML', context));
541
+ if (parseHTML) {
542
+ schema.parseDOM = parseHTML.map(parseRule => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
543
+ }
544
+ const renderHTML = getExtensionField(extension, 'renderHTML', context);
545
+ if (renderHTML) {
546
+ schema.toDOM = mark => renderHTML({
547
+ mark,
548
+ HTMLAttributes: getRenderedAttributes(mark, extensionAttributes),
549
+ });
550
+ }
551
+ return [extension.name, schema];
552
+ }));
553
+ return new Schema({
554
+ topNode,
555
+ nodes,
556
+ marks,
557
+ });
558
+ }
559
+
560
+ /**
561
+ * Tries to get a node or mark type by its name.
562
+ * @param name The name of the node or mark type
563
+ * @param schema The Prosemiror schema to search in
564
+ * @returns The node or mark type, or null if it doesn't exist
565
+ */
566
+ function getSchemaTypeByName(name, schema) {
567
+ return schema.nodes[name] || schema.marks[name] || null;
568
+ }
569
+
570
+ function isExtensionRulesEnabled(extension, enabled) {
571
+ if (Array.isArray(enabled)) {
572
+ return enabled.some(enabledExtension => {
573
+ const name = typeof enabledExtension === 'string'
574
+ ? enabledExtension
575
+ : enabledExtension.name;
576
+ return name === extension.name;
577
+ });
578
+ }
579
+ return enabled;
580
+ }
581
+
582
+ function getHTMLFromFragment(fragment, schema) {
583
+ const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
584
+ const temporaryDocument = document.implementation.createHTMLDocument();
585
+ const container = temporaryDocument.createElement('div');
586
+ container.appendChild(documentFragment);
587
+ return container.innerHTML;
588
+ }
589
+
590
+ /**
591
+ * Returns the text content of a resolved prosemirror position
592
+ * @param $from The resolved position to get the text content from
593
+ * @param maxMatch The maximum number of characters to match
594
+ * @returns The text content
595
+ */
596
+ const getTextContentFromNodes = ($from, maxMatch = 500) => {
597
+ let textBefore = '';
598
+ const sliceEndPos = $from.parentOffset;
599
+ $from.parent.nodesBetween(Math.max(0, sliceEndPos - maxMatch), sliceEndPos, (node, pos, parent, index) => {
600
+ var _a, _b;
601
+ const chunk = ((_b = (_a = node.type.spec).toText) === null || _b === void 0 ? void 0 : _b.call(_a, {
602
+ node,
603
+ pos,
604
+ parent,
605
+ index,
606
+ }))
607
+ || node.textContent
608
+ || '%leaf%';
609
+ textBefore += node.isAtom && !node.isText ? chunk : chunk.slice(0, Math.max(0, sliceEndPos - pos));
610
+ });
611
+ return textBefore;
612
+ };
613
+
614
+ function isRegExp(value) {
615
+ return Object.prototype.toString.call(value) === '[object RegExp]';
616
+ }
617
+
618
+ class InputRule {
619
+ constructor(config) {
620
+ this.find = config.find;
621
+ this.handler = config.handler;
622
+ }
623
+ }
624
+ const inputRuleMatcherHandler = (text, find) => {
625
+ if (isRegExp(find)) {
626
+ return find.exec(text);
627
+ }
628
+ const inputRuleMatch = find(text);
629
+ if (!inputRuleMatch) {
630
+ return null;
631
+ }
632
+ const result = [inputRuleMatch.text];
633
+ result.index = inputRuleMatch.index;
634
+ result.input = text;
635
+ result.data = inputRuleMatch.data;
636
+ if (inputRuleMatch.replaceWith) {
637
+ if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
638
+ console.warn('[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".');
639
+ }
640
+ result.push(inputRuleMatch.replaceWith);
641
+ }
642
+ return result;
643
+ };
644
+ function run$1(config) {
645
+ var _a;
646
+ const { editor, from, to, text, rules, plugin, } = config;
647
+ const { view } = editor;
648
+ if (view.composing) {
649
+ return false;
650
+ }
651
+ const $from = view.state.doc.resolve(from);
652
+ if (
653
+ // check for code node
654
+ $from.parent.type.spec.code
655
+ // check for code mark
656
+ || !!((_a = ($from.nodeBefore || $from.nodeAfter)) === null || _a === void 0 ? void 0 : _a.marks.find(mark => mark.type.spec.code))) {
657
+ return false;
658
+ }
659
+ let matched = false;
660
+ const textBefore = getTextContentFromNodes($from) + text;
661
+ rules.forEach(rule => {
662
+ if (matched) {
663
+ return;
664
+ }
665
+ const match = inputRuleMatcherHandler(textBefore, rule.find);
666
+ if (!match) {
667
+ return;
668
+ }
669
+ const tr = view.state.tr;
670
+ const state = createChainableState({
671
+ state: view.state,
672
+ transaction: tr,
673
+ });
674
+ const range = {
675
+ from: from - (match[0].length - text.length),
676
+ to,
677
+ };
678
+ const { commands, chain, can } = new CommandManager({
679
+ editor,
680
+ state,
681
+ });
682
+ const handler = rule.handler({
683
+ state,
684
+ range,
685
+ match,
686
+ commands,
687
+ chain,
688
+ can,
689
+ });
690
+ // stop if there are no changes
691
+ if (handler === null || !tr.steps.length) {
692
+ return;
693
+ }
694
+ // store transform as meta data
695
+ // so we can undo input rules within the `undoInputRules` command
696
+ tr.setMeta(plugin, {
697
+ transform: tr,
698
+ from,
699
+ to,
700
+ text,
701
+ });
702
+ view.dispatch(tr);
703
+ matched = true;
704
+ });
705
+ return matched;
706
+ }
707
+ /**
708
+ * Create an input rules plugin. When enabled, it will cause text
709
+ * input that matches any of the given rules to trigger the rule’s
710
+ * action.
711
+ */
712
+ function inputRulesPlugin(props) {
713
+ const { editor, rules } = props;
714
+ const plugin = new Plugin({
715
+ state: {
716
+ init() {
717
+ return null;
718
+ },
719
+ apply(tr, prev, state) {
720
+ const stored = tr.getMeta(plugin);
721
+ if (stored) {
722
+ return stored;
723
+ }
724
+ // if InputRule is triggered by insertContent()
725
+ const simulatedInputMeta = tr.getMeta('applyInputRules');
726
+ const isSimulatedInput = !!simulatedInputMeta;
727
+ if (isSimulatedInput) {
728
+ setTimeout(() => {
729
+ let { text } = simulatedInputMeta;
730
+ if (typeof text === 'string') {
731
+ text = text;
732
+ }
733
+ else {
734
+ text = getHTMLFromFragment(Fragment.from(text), state.schema);
735
+ }
736
+ const { from } = simulatedInputMeta;
737
+ const to = from + text.length;
738
+ run$1({
739
+ editor,
740
+ from,
741
+ to,
742
+ text,
743
+ rules,
744
+ plugin,
745
+ });
746
+ });
747
+ }
748
+ return tr.selectionSet || tr.docChanged ? null : prev;
749
+ },
750
+ },
751
+ props: {
752
+ handleTextInput(view, from, to, text) {
753
+ return run$1({
754
+ editor,
755
+ from,
756
+ to,
757
+ text,
758
+ rules,
759
+ plugin,
760
+ });
761
+ },
762
+ handleDOMEvents: {
763
+ compositionend: view => {
764
+ setTimeout(() => {
765
+ const { $cursor } = view.state.selection;
766
+ if ($cursor) {
767
+ run$1({
768
+ editor,
769
+ from: $cursor.pos,
770
+ to: $cursor.pos,
771
+ text: '',
772
+ rules,
773
+ plugin,
774
+ });
775
+ }
776
+ });
777
+ return false;
778
+ },
779
+ },
780
+ // add support for input rules to trigger on enter
781
+ // this is useful for example for code blocks
782
+ handleKeyDown(view, event) {
783
+ if (event.key !== 'Enter') {
784
+ return false;
785
+ }
786
+ const { $cursor } = view.state.selection;
787
+ if ($cursor) {
788
+ return run$1({
789
+ editor,
790
+ from: $cursor.pos,
791
+ to: $cursor.pos,
792
+ text: '\n',
793
+ rules,
794
+ plugin,
795
+ });
796
+ }
797
+ return false;
798
+ },
799
+ },
800
+ // @ts-ignore
801
+ isInputRules: true,
802
+ });
803
+ return plugin;
804
+ }
805
+
806
+ // see: https://github.com/mesqueeb/is-what/blob/88d6e4ca92fb2baab6003c54e02eedf4e729e5ab/src/index.ts
807
+ function getType(value) {
808
+ return Object.prototype.toString.call(value).slice(8, -1);
809
+ }
810
+ function isPlainObject(value) {
811
+ if (getType(value) !== 'Object') {
812
+ return false;
813
+ }
814
+ return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
815
+ }
816
+
817
+ function mergeDeep(target, source) {
818
+ const output = { ...target };
819
+ if (isPlainObject(target) && isPlainObject(source)) {
820
+ Object.keys(source).forEach(key => {
821
+ if (isPlainObject(source[key]) && isPlainObject(target[key])) {
822
+ output[key] = mergeDeep(target[key], source[key]);
823
+ }
824
+ else {
825
+ output[key] = source[key];
826
+ }
827
+ });
828
+ }
829
+ return output;
830
+ }
831
+
832
+ /**
833
+ * The Mark class is used to create custom mark extensions.
834
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
835
+ */
836
+ class Mark {
837
+ constructor(config = {}) {
838
+ this.type = 'mark';
839
+ this.name = 'mark';
840
+ this.parent = null;
841
+ this.child = null;
842
+ this.config = {
843
+ name: this.name,
844
+ defaultOptions: {},
845
+ };
846
+ this.config = {
847
+ ...this.config,
848
+ ...config,
849
+ };
850
+ this.name = this.config.name;
851
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
852
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
853
+ }
854
+ // TODO: remove `addOptions` fallback
855
+ this.options = this.config.defaultOptions;
856
+ if (this.config.addOptions) {
857
+ this.options = callOrReturn(getExtensionField(this, 'addOptions', {
858
+ name: this.name,
859
+ }));
860
+ }
861
+ this.storage = callOrReturn(getExtensionField(this, 'addStorage', {
862
+ name: this.name,
863
+ options: this.options,
864
+ })) || {};
865
+ }
866
+ static create(config = {}) {
867
+ return new Mark(config);
868
+ }
869
+ configure(options = {}) {
870
+ // return a new instance so we can use the same extension
871
+ // with different calls of `configure`
872
+ const extension = this.extend({
873
+ ...this.config,
874
+ addOptions: () => {
875
+ return mergeDeep(this.options, options);
876
+ },
877
+ });
878
+ // Always preserve the current name
879
+ extension.name = this.name;
880
+ // Set the parent to be our parent
881
+ extension.parent = this.parent;
882
+ return extension;
883
+ }
884
+ extend(extendedConfig = {}) {
885
+ const extension = new Mark(extendedConfig);
886
+ extension.parent = this;
887
+ this.child = extension;
888
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
889
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
890
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
891
+ }
892
+ extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {
893
+ name: extension.name,
894
+ }));
895
+ extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
896
+ name: extension.name,
897
+ options: extension.options,
898
+ }));
899
+ return extension;
900
+ }
901
+ static handleExit({ editor, mark }) {
902
+ const { tr } = editor.state;
903
+ const currentPos = editor.state.selection.$from;
904
+ const isAtEnd = currentPos.pos === currentPos.end();
905
+ if (isAtEnd) {
906
+ const currentMarks = currentPos.marks();
907
+ const isInMark = !!currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
908
+ if (!isInMark) {
909
+ return false;
910
+ }
911
+ const removeMark = currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
912
+ if (removeMark) {
913
+ tr.removeStoredMark(removeMark);
914
+ }
915
+ tr.insertText(' ', currentPos.pos);
916
+ editor.view.dispatch(tr);
917
+ return true;
918
+ }
919
+ return false;
920
+ }
921
+ }
922
+
923
+ function isNumber(value) {
924
+ return typeof value === 'number';
925
+ }
926
+
927
+ /**
928
+ * Paste rules are used to react to pasted content.
929
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
930
+ */
931
+ class PasteRule {
932
+ constructor(config) {
933
+ this.find = config.find;
934
+ this.handler = config.handler;
935
+ }
936
+ }
937
+ const pasteRuleMatcherHandler = (text, find, event) => {
938
+ if (isRegExp(find)) {
939
+ return [...text.matchAll(find)];
940
+ }
941
+ const matches = find(text, event);
942
+ if (!matches) {
943
+ return [];
944
+ }
945
+ return matches.map(pasteRuleMatch => {
946
+ const result = [pasteRuleMatch.text];
947
+ result.index = pasteRuleMatch.index;
948
+ result.input = text;
949
+ result.data = pasteRuleMatch.data;
950
+ if (pasteRuleMatch.replaceWith) {
951
+ if (!pasteRuleMatch.text.includes(pasteRuleMatch.replaceWith)) {
952
+ console.warn('[tiptap warn]: "pasteRuleMatch.replaceWith" must be part of "pasteRuleMatch.text".');
953
+ }
954
+ result.push(pasteRuleMatch.replaceWith);
955
+ }
956
+ return result;
957
+ });
958
+ };
959
+ function run(config) {
960
+ const { editor, state, from, to, rule, pasteEvent, dropEvent, } = config;
961
+ const { commands, chain, can } = new CommandManager({
962
+ editor,
963
+ state,
964
+ });
965
+ const handlers = [];
966
+ state.doc.nodesBetween(from, to, (node, pos) => {
967
+ if (!node.isTextblock || node.type.spec.code) {
968
+ return;
969
+ }
970
+ const resolvedFrom = Math.max(from, pos);
971
+ const resolvedTo = Math.min(to, pos + node.content.size);
972
+ const textToMatch = node.textBetween(resolvedFrom - pos, resolvedTo - pos, undefined, '\ufffc');
973
+ const matches = pasteRuleMatcherHandler(textToMatch, rule.find, pasteEvent);
974
+ matches.forEach(match => {
975
+ if (match.index === undefined) {
976
+ return;
977
+ }
978
+ const start = resolvedFrom + match.index + 1;
979
+ const end = start + match[0].length;
980
+ const range = {
981
+ from: state.tr.mapping.map(start),
982
+ to: state.tr.mapping.map(end),
983
+ };
984
+ const handler = rule.handler({
985
+ state,
986
+ range,
987
+ match,
988
+ commands,
989
+ chain,
990
+ can,
991
+ pasteEvent,
992
+ dropEvent,
993
+ });
994
+ handlers.push(handler);
995
+ });
996
+ });
997
+ const success = handlers.every(handler => handler !== null);
998
+ return success;
999
+ }
1000
+ // When dragging across editors, must get another editor instance to delete selection content.
1001
+ let tiptapDragFromOtherEditor = null;
1002
+ const createClipboardPasteEvent = (text) => {
1003
+ var _a;
1004
+ const event = new ClipboardEvent('paste', {
1005
+ clipboardData: new DataTransfer(),
1006
+ });
1007
+ (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.setData('text/html', text);
1008
+ return event;
1009
+ };
1010
+ /**
1011
+ * Create an paste rules plugin. When enabled, it will cause pasted
1012
+ * text that matches any of the given rules to trigger the rule’s
1013
+ * action.
1014
+ */
1015
+ function pasteRulesPlugin(props) {
1016
+ const { editor, rules } = props;
1017
+ let dragSourceElement = null;
1018
+ let isPastedFromProseMirror = false;
1019
+ let isDroppedFromProseMirror = false;
1020
+ let pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
1021
+ let dropEvent;
1022
+ try {
1023
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1024
+ }
1025
+ catch {
1026
+ dropEvent = null;
1027
+ }
1028
+ const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
1029
+ const tr = state.tr;
1030
+ const chainableState = createChainableState({
1031
+ state,
1032
+ transaction: tr,
1033
+ });
1034
+ const handler = run({
1035
+ editor,
1036
+ state: chainableState,
1037
+ from: Math.max(from - 1, 0),
1038
+ to: to.b - 1,
1039
+ rule,
1040
+ pasteEvent: pasteEvt,
1041
+ dropEvent,
1042
+ });
1043
+ if (!handler || !tr.steps.length) {
1044
+ return;
1045
+ }
1046
+ try {
1047
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1048
+ }
1049
+ catch {
1050
+ dropEvent = null;
1051
+ }
1052
+ pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
1053
+ return tr;
1054
+ };
1055
+ const plugins = rules.map(rule => {
1056
+ return new Plugin({
1057
+ // we register a global drag handler to track the current drag source element
1058
+ view(view) {
1059
+ const handleDragstart = (event) => {
1060
+ var _a;
1061
+ dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
1062
+ ? view.dom.parentElement
1063
+ : null;
1064
+ if (dragSourceElement) {
1065
+ tiptapDragFromOtherEditor = editor;
1066
+ }
1067
+ };
1068
+ const handleDragend = () => {
1069
+ if (tiptapDragFromOtherEditor) {
1070
+ tiptapDragFromOtherEditor = null;
1071
+ }
1072
+ };
1073
+ window.addEventListener('dragstart', handleDragstart);
1074
+ window.addEventListener('dragend', handleDragend);
1075
+ return {
1076
+ destroy() {
1077
+ window.removeEventListener('dragstart', handleDragstart);
1078
+ window.removeEventListener('dragend', handleDragend);
1079
+ },
1080
+ };
1081
+ },
1082
+ props: {
1083
+ handleDOMEvents: {
1084
+ drop: (view, event) => {
1085
+ isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
1086
+ dropEvent = event;
1087
+ if (!isDroppedFromProseMirror) {
1088
+ const dragFromOtherEditor = tiptapDragFromOtherEditor;
1089
+ if (dragFromOtherEditor === null || dragFromOtherEditor === void 0 ? void 0 : dragFromOtherEditor.isEditable) {
1090
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
1091
+ setTimeout(() => {
1092
+ const selection = dragFromOtherEditor.state.selection;
1093
+ if (selection) {
1094
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
1095
+ }
1096
+ }, 10);
1097
+ }
1098
+ }
1099
+ return false;
1100
+ },
1101
+ paste: (_view, event) => {
1102
+ var _a;
1103
+ const html = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
1104
+ pasteEvent = event;
1105
+ isPastedFromProseMirror = !!(html === null || html === void 0 ? void 0 : html.includes('data-pm-slice'));
1106
+ return false;
1107
+ },
1108
+ },
1109
+ },
1110
+ appendTransaction: (transactions, oldState, state) => {
1111
+ const transaction = transactions[0];
1112
+ const isPaste = transaction.getMeta('uiEvent') === 'paste' && !isPastedFromProseMirror;
1113
+ const isDrop = transaction.getMeta('uiEvent') === 'drop' && !isDroppedFromProseMirror;
1114
+ // if PasteRule is triggered by insertContent()
1115
+ const simulatedPasteMeta = transaction.getMeta('applyPasteRules');
1116
+ const isSimulatedPaste = !!simulatedPasteMeta;
1117
+ if (!isPaste && !isDrop && !isSimulatedPaste) {
1118
+ return;
1119
+ }
1120
+ // Handle simulated paste
1121
+ if (isSimulatedPaste) {
1122
+ let { text } = simulatedPasteMeta;
1123
+ if (typeof text === 'string') {
1124
+ text = text;
1125
+ }
1126
+ else {
1127
+ text = getHTMLFromFragment(Fragment.from(text), state.schema);
1128
+ }
1129
+ const { from } = simulatedPasteMeta;
1130
+ const to = from + text.length;
1131
+ const pasteEvt = createClipboardPasteEvent(text);
1132
+ return processEvent({
1133
+ rule,
1134
+ state,
1135
+ from,
1136
+ to: { b: to },
1137
+ pasteEvt,
1138
+ });
1139
+ }
1140
+ // handle actual paste/drop
1141
+ const from = oldState.doc.content.findDiffStart(state.doc.content);
1142
+ const to = oldState.doc.content.findDiffEnd(state.doc.content);
1143
+ // stop if there is no changed range
1144
+ if (!isNumber(from) || !to || from === to.b) {
1145
+ return;
1146
+ }
1147
+ return processEvent({
1148
+ rule,
1149
+ state,
1150
+ from,
1151
+ to,
1152
+ pasteEvt: pasteEvent,
1153
+ });
1154
+ },
1155
+ });
1156
+ });
1157
+ return plugins;
1158
+ }
1159
+
1160
+ function findDuplicates(items) {
1161
+ const filtered = items.filter((el, index) => items.indexOf(el) !== index);
1162
+ return Array.from(new Set(filtered));
1163
+ }
1164
+
1165
+ class ExtensionManager {
1166
+ constructor(extensions, editor) {
1167
+ this.splittableMarks = [];
1168
+ this.editor = editor;
1169
+ this.extensions = ExtensionManager.resolve(extensions);
1170
+ this.schema = getSchemaByResolvedExtensions(this.extensions, editor);
1171
+ this.setupExtensions();
1172
+ }
1173
+ /**
1174
+ * Returns a flattened and sorted extension list while
1175
+ * also checking for duplicated extensions and warns the user.
1176
+ * @param extensions An array of Tiptap extensions
1177
+ * @returns An flattened and sorted array of Tiptap extensions
1178
+ */
1179
+ static resolve(extensions) {
1180
+ const resolvedExtensions = ExtensionManager.sort(ExtensionManager.flatten(extensions));
1181
+ const duplicatedNames = findDuplicates(resolvedExtensions.map(extension => extension.name));
1182
+ if (duplicatedNames.length) {
1183
+ console.warn(`[tiptap warn]: Duplicate extension names found: [${duplicatedNames
1184
+ .map(item => `'${item}'`)
1185
+ .join(', ')}]. This can lead to issues.`);
1186
+ }
1187
+ return resolvedExtensions;
1188
+ }
1189
+ /**
1190
+ * Create a flattened array of extensions by traversing the `addExtensions` field.
1191
+ * @param extensions An array of Tiptap extensions
1192
+ * @returns A flattened array of Tiptap extensions
1193
+ */
1194
+ static flatten(extensions) {
1195
+ return (extensions
1196
+ .map(extension => {
1197
+ const context = {
1198
+ name: extension.name,
1199
+ options: extension.options,
1200
+ storage: extension.storage,
1201
+ };
1202
+ const addExtensions = getExtensionField(extension, 'addExtensions', context);
1203
+ if (addExtensions) {
1204
+ return [extension, ...this.flatten(addExtensions())];
1205
+ }
1206
+ return extension;
1207
+ })
1208
+ // `Infinity` will break TypeScript so we set a number that is probably high enough
1209
+ .flat(10));
1210
+ }
1211
+ /**
1212
+ * Sort extensions by priority.
1213
+ * @param extensions An array of Tiptap extensions
1214
+ * @returns A sorted array of Tiptap extensions by priority
1215
+ */
1216
+ static sort(extensions) {
1217
+ const defaultPriority = 100;
1218
+ return extensions.sort((a, b) => {
1219
+ const priorityA = getExtensionField(a, 'priority') || defaultPriority;
1220
+ const priorityB = getExtensionField(b, 'priority') || defaultPriority;
1221
+ if (priorityA > priorityB) {
1222
+ return -1;
1223
+ }
1224
+ if (priorityA < priorityB) {
1225
+ return 1;
1226
+ }
1227
+ return 0;
1228
+ });
1229
+ }
1230
+ /**
1231
+ * Get all commands from the extensions.
1232
+ * @returns An object with all commands where the key is the command name and the value is the command function
1233
+ */
1234
+ get commands() {
1235
+ return this.extensions.reduce((commands, extension) => {
1236
+ const context = {
1237
+ name: extension.name,
1238
+ options: extension.options,
1239
+ storage: extension.storage,
1240
+ editor: this.editor,
1241
+ type: getSchemaTypeByName(extension.name, this.schema),
1242
+ };
1243
+ const addCommands = getExtensionField(extension, 'addCommands', context);
1244
+ if (!addCommands) {
1245
+ return commands;
1246
+ }
1247
+ return {
1248
+ ...commands,
1249
+ ...addCommands(),
1250
+ };
1251
+ }, {});
1252
+ }
1253
+ /**
1254
+ * Get all registered Prosemirror plugins from the extensions.
1255
+ * @returns An array of Prosemirror plugins
1256
+ */
1257
+ get plugins() {
1258
+ const { editor } = this;
1259
+ // With ProseMirror, first plugins within an array are executed first.
1260
+ // In Tiptap, we provide the ability to override plugins,
1261
+ // so it feels more natural to run plugins at the end of an array first.
1262
+ // That’s why we have to reverse the `extensions` array and sort again
1263
+ // based on the `priority` option.
1264
+ const extensions = ExtensionManager.sort([...this.extensions].reverse());
1265
+ const inputRules = [];
1266
+ const pasteRules = [];
1267
+ const allPlugins = extensions
1268
+ .map(extension => {
1269
+ const context = {
1270
+ name: extension.name,
1271
+ options: extension.options,
1272
+ storage: extension.storage,
1273
+ editor,
1274
+ type: getSchemaTypeByName(extension.name, this.schema),
1275
+ };
1276
+ const plugins = [];
1277
+ const addKeyboardShortcuts = getExtensionField(extension, 'addKeyboardShortcuts', context);
1278
+ let defaultBindings = {};
1279
+ // bind exit handling
1280
+ if (extension.type === 'mark' && getExtensionField(extension, 'exitable', context)) {
1281
+ defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
1282
+ }
1283
+ if (addKeyboardShortcuts) {
1284
+ const bindings = Object.fromEntries(Object.entries(addKeyboardShortcuts()).map(([shortcut, method]) => {
1285
+ return [shortcut, () => method({ editor })];
1286
+ }));
1287
+ defaultBindings = { ...defaultBindings, ...bindings };
1288
+ }
1289
+ const keyMapPlugin = keymap(defaultBindings);
1290
+ plugins.push(keyMapPlugin);
1291
+ const addInputRules = getExtensionField(extension, 'addInputRules', context);
1292
+ if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
1293
+ inputRules.push(...addInputRules());
1294
+ }
1295
+ const addPasteRules = getExtensionField(extension, 'addPasteRules', context);
1296
+ if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
1297
+ pasteRules.push(...addPasteRules());
1298
+ }
1299
+ const addProseMirrorPlugins = getExtensionField(extension, 'addProseMirrorPlugins', context);
1300
+ if (addProseMirrorPlugins) {
1301
+ const proseMirrorPlugins = addProseMirrorPlugins();
1302
+ plugins.push(...proseMirrorPlugins);
1303
+ }
1304
+ return plugins;
1305
+ })
1306
+ .flat();
1307
+ return [
1308
+ inputRulesPlugin({
1309
+ editor,
1310
+ rules: inputRules,
1311
+ }),
1312
+ ...pasteRulesPlugin({
1313
+ editor,
1314
+ rules: pasteRules,
1315
+ }),
1316
+ ...allPlugins,
1317
+ ];
1318
+ }
1319
+ /**
1320
+ * Get all attributes from the extensions.
1321
+ * @returns An array of attributes
1322
+ */
1323
+ get attributes() {
1324
+ return getAttributesFromExtensions(this.extensions);
1325
+ }
1326
+ /**
1327
+ * Get all node views from the extensions.
1328
+ * @returns An object with all node views where the key is the node name and the value is the node view function
1329
+ */
1330
+ get nodeViews() {
1331
+ const { editor } = this;
1332
+ const { nodeExtensions } = splitExtensions(this.extensions);
1333
+ return Object.fromEntries(nodeExtensions
1334
+ .filter(extension => !!getExtensionField(extension, 'addNodeView'))
1335
+ .map(extension => {
1336
+ const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.name);
1337
+ const context = {
1338
+ name: extension.name,
1339
+ options: extension.options,
1340
+ storage: extension.storage,
1341
+ editor,
1342
+ type: getNodeType(extension.name, this.schema),
1343
+ };
1344
+ const addNodeView = getExtensionField(extension, 'addNodeView', context);
1345
+ if (!addNodeView) {
1346
+ return [];
1347
+ }
1348
+ const nodeview = (node, view, getPos, decorations, innerDecorations) => {
1349
+ const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
1350
+ return addNodeView()({
1351
+ // pass-through
1352
+ node,
1353
+ view,
1354
+ getPos: getPos,
1355
+ decorations,
1356
+ innerDecorations,
1357
+ // tiptap-specific
1358
+ editor,
1359
+ extension,
1360
+ HTMLAttributes,
1361
+ });
1362
+ };
1363
+ return [extension.name, nodeview];
1364
+ }));
1365
+ }
1366
+ /**
1367
+ * Go through all extensions, create extension storages & setup marks
1368
+ * & bind editor event listener.
1369
+ */
1370
+ setupExtensions() {
1371
+ this.extensions.forEach(extension => {
1372
+ var _a;
1373
+ // store extension storage in editor
1374
+ this.editor.extensionStorage[extension.name] = extension.storage;
1375
+ const context = {
1376
+ name: extension.name,
1377
+ options: extension.options,
1378
+ storage: extension.storage,
1379
+ editor: this.editor,
1380
+ type: getSchemaTypeByName(extension.name, this.schema),
1381
+ };
1382
+ if (extension.type === 'mark') {
1383
+ const keepOnSplit = (_a = callOrReturn(getExtensionField(extension, 'keepOnSplit', context))) !== null && _a !== void 0 ? _a : true;
1384
+ if (keepOnSplit) {
1385
+ this.splittableMarks.push(extension.name);
1386
+ }
1387
+ }
1388
+ const onBeforeCreate = getExtensionField(extension, 'onBeforeCreate', context);
1389
+ const onCreate = getExtensionField(extension, 'onCreate', context);
1390
+ const onUpdate = getExtensionField(extension, 'onUpdate', context);
1391
+ const onSelectionUpdate = getExtensionField(extension, 'onSelectionUpdate', context);
1392
+ const onTransaction = getExtensionField(extension, 'onTransaction', context);
1393
+ const onFocus = getExtensionField(extension, 'onFocus', context);
1394
+ const onBlur = getExtensionField(extension, 'onBlur', context);
1395
+ const onDestroy = getExtensionField(extension, 'onDestroy', context);
1396
+ if (onBeforeCreate) {
1397
+ this.editor.on('beforeCreate', onBeforeCreate);
1398
+ }
1399
+ if (onCreate) {
1400
+ this.editor.on('create', onCreate);
1401
+ }
1402
+ if (onUpdate) {
1403
+ this.editor.on('update', onUpdate);
1404
+ }
1405
+ if (onSelectionUpdate) {
1406
+ this.editor.on('selectionUpdate', onSelectionUpdate);
1407
+ }
1408
+ if (onTransaction) {
1409
+ this.editor.on('transaction', onTransaction);
1410
+ }
1411
+ if (onFocus) {
1412
+ this.editor.on('focus', onFocus);
1413
+ }
1414
+ if (onBlur) {
1415
+ this.editor.on('blur', onBlur);
1416
+ }
1417
+ if (onDestroy) {
1418
+ this.editor.on('destroy', onDestroy);
1419
+ }
1420
+ });
1421
+ }
1422
+ }
1423
+
1424
+ /**
1425
+ * The Extension class is the base class for all extensions.
1426
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
1427
+ */
1428
+ class Extension {
1429
+ constructor(config = {}) {
1430
+ this.type = 'extension';
1431
+ this.name = 'extension';
1432
+ this.parent = null;
1433
+ this.child = null;
1434
+ this.config = {
1435
+ name: this.name,
1436
+ defaultOptions: {},
1437
+ };
1438
+ this.config = {
1439
+ ...this.config,
1440
+ ...config,
1441
+ };
1442
+ this.name = this.config.name;
1443
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
1444
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
1445
+ }
1446
+ // TODO: remove `addOptions` fallback
1447
+ this.options = this.config.defaultOptions;
1448
+ if (this.config.addOptions) {
1449
+ this.options = callOrReturn(getExtensionField(this, 'addOptions', {
1450
+ name: this.name,
1451
+ }));
1452
+ }
1453
+ this.storage = callOrReturn(getExtensionField(this, 'addStorage', {
1454
+ name: this.name,
1455
+ options: this.options,
1456
+ })) || {};
1457
+ }
1458
+ static create(config = {}) {
1459
+ return new Extension(config);
1460
+ }
1461
+ configure(options = {}) {
1462
+ // return a new instance so we can use the same extension
1463
+ // with different calls of `configure`
1464
+ const extension = this.extend({
1465
+ ...this.config,
1466
+ addOptions: () => {
1467
+ return mergeDeep(this.options, options);
1468
+ },
1469
+ });
1470
+ // Always preserve the current name
1471
+ extension.name = this.name;
1472
+ // Set the parent to be our parent
1473
+ extension.parent = this.parent;
1474
+ return extension;
1475
+ }
1476
+ extend(extendedConfig = {}) {
1477
+ const extension = new Extension({ ...this.config, ...extendedConfig });
1478
+ extension.parent = this;
1479
+ this.child = extension;
1480
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
1481
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
1482
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
1483
+ }
1484
+ extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {
1485
+ name: extension.name,
1486
+ }));
1487
+ extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
1488
+ name: extension.name,
1489
+ options: extension.options,
1490
+ }));
1491
+ return extension;
1492
+ }
1493
+ }
1494
+
1495
+ /**
1496
+ * Gets the text between two positions in a Prosemirror node
1497
+ * and serializes it using the given text serializers and block separator (see getText)
1498
+ * @param startNode The Prosemirror node to start from
1499
+ * @param range The range of the text to get
1500
+ * @param options Options for the text serializer & block separator
1501
+ * @returns The text between the two positions
1502
+ */
1503
+ function getTextBetween(startNode, range, options) {
1504
+ const { from, to } = range;
1505
+ const { blockSeparator = '\n\n', textSerializers = {} } = options || {};
1506
+ let text = '';
1507
+ startNode.nodesBetween(from, to, (node, pos, parent, index) => {
1508
+ var _a;
1509
+ if (node.isBlock && pos > from) {
1510
+ text += blockSeparator;
1511
+ }
1512
+ const textSerializer = textSerializers === null || textSerializers === void 0 ? void 0 : textSerializers[node.type.name];
1513
+ if (textSerializer) {
1514
+ if (parent) {
1515
+ text += textSerializer({
1516
+ node,
1517
+ pos,
1518
+ parent,
1519
+ index,
1520
+ range,
1521
+ });
1522
+ }
1523
+ // do not descend into child nodes when there exists a serializer
1524
+ return false;
1525
+ }
1526
+ if (node.isText) {
1527
+ text += (_a = node === null || node === void 0 ? void 0 : node.text) === null || _a === void 0 ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos); // eslint-disable-line
1528
+ }
1529
+ });
1530
+ return text;
1531
+ }
1532
+
1533
+ /**
1534
+ * Find text serializers `toText` in a Prosemirror schema
1535
+ * @param schema The Prosemirror schema to search in
1536
+ * @returns A record of text serializers by node name
1537
+ */
1538
+ function getTextSerializersFromSchema(schema) {
1539
+ return Object.fromEntries(Object.entries(schema.nodes)
1540
+ .filter(([, node]) => node.spec.toText)
1541
+ .map(([name, node]) => [name, node.spec.toText]));
1542
+ }
1543
+
1544
+ const ClipboardTextSerializer = Extension.create({
1545
+ name: 'clipboardTextSerializer',
1546
+ addOptions() {
1547
+ return {
1548
+ blockSeparator: undefined,
1549
+ };
1550
+ },
1551
+ addProseMirrorPlugins() {
1552
+ return [
1553
+ new Plugin({
1554
+ key: new PluginKey('clipboardTextSerializer'),
1555
+ props: {
1556
+ clipboardTextSerializer: () => {
1557
+ const { editor } = this;
1558
+ const { state, schema } = editor;
1559
+ const { doc, selection } = state;
1560
+ const { ranges } = selection;
1561
+ const from = Math.min(...ranges.map(range => range.$from.pos));
1562
+ const to = Math.max(...ranges.map(range => range.$to.pos));
1563
+ const textSerializers = getTextSerializersFromSchema(schema);
1564
+ const range = { from, to };
1565
+ return getTextBetween(doc, range, {
1566
+ ...(this.options.blockSeparator !== undefined
1567
+ ? { blockSeparator: this.options.blockSeparator }
1568
+ : {}),
1569
+ textSerializers,
1570
+ });
1571
+ },
1572
+ },
1573
+ }),
1574
+ ];
1575
+ },
1576
+ });
1577
+
1578
+ const blur = () => ({ editor, view }) => {
1579
+ requestAnimationFrame(() => {
1580
+ var _a;
1581
+ if (!editor.isDestroyed) {
1582
+ view.dom.blur();
1583
+ // Browsers should remove the caret on blur but safari does not.
1584
+ // See: https://github.com/ueberdosis/tiptap/issues/2405
1585
+ (_a = window === null || window === void 0 ? void 0 : window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
1586
+ }
1587
+ });
1588
+ return true;
1589
+ };
1590
+
1591
+ const clearContent = (emitUpdate = false) => ({ commands }) => {
1592
+ return commands.setContent('', emitUpdate);
1593
+ };
1594
+
1595
+ const clearNodes = () => ({ state, tr, dispatch }) => {
1596
+ const { selection } = tr;
1597
+ const { ranges } = selection;
1598
+ if (!dispatch) {
1599
+ return true;
1600
+ }
1601
+ ranges.forEach(({ $from, $to }) => {
1602
+ state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
1603
+ if (node.type.isText) {
1604
+ return;
1605
+ }
1606
+ const { doc, mapping } = tr;
1607
+ const $mappedFrom = doc.resolve(mapping.map(pos));
1608
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
1609
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
1610
+ if (!nodeRange) {
1611
+ return;
1612
+ }
1613
+ const targetLiftDepth = liftTarget(nodeRange);
1614
+ if (node.type.isTextblock) {
1615
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
1616
+ tr.setNodeMarkup(nodeRange.start, defaultType);
1617
+ }
1618
+ if (targetLiftDepth || targetLiftDepth === 0) {
1619
+ tr.lift(nodeRange, targetLiftDepth);
1620
+ }
1621
+ });
1622
+ });
1623
+ return true;
1624
+ };
1625
+
1626
+ const command = fn => props => {
1627
+ return fn(props);
1628
+ };
1629
+
1630
+ const createParagraphNear = () => ({ state, dispatch }) => {
1631
+ return createParagraphNear$1(state, dispatch);
1632
+ };
1633
+
1634
+ const cut = (originRange, targetPos) => ({ editor, tr }) => {
1635
+ const { state } = editor;
1636
+ const contentSlice = state.doc.slice(originRange.from, originRange.to);
1637
+ tr.deleteRange(originRange.from, originRange.to);
1638
+ const newPos = tr.mapping.map(targetPos);
1639
+ tr.insert(newPos, contentSlice.content);
1640
+ tr.setSelection(new TextSelection(tr.doc.resolve(newPos - 1)));
1641
+ return true;
1642
+ };
1643
+
1644
+ const deleteCurrentNode = () => ({ tr, dispatch }) => {
1645
+ const { selection } = tr;
1646
+ const currentNode = selection.$anchor.node();
1647
+ // if there is content inside the current node, break out of this command
1648
+ if (currentNode.content.size > 0) {
1649
+ return false;
1650
+ }
1651
+ const $pos = tr.selection.$anchor;
1652
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1653
+ const node = $pos.node(depth);
1654
+ if (node.type === currentNode.type) {
1655
+ if (dispatch) {
1656
+ const from = $pos.before(depth);
1657
+ const to = $pos.after(depth);
1658
+ tr.delete(from, to).scrollIntoView();
1659
+ }
1660
+ return true;
1661
+ }
1662
+ }
1663
+ return false;
1664
+ };
1665
+
1666
+ const deleteNode = typeOrName => ({ tr, state, dispatch }) => {
1667
+ const type = getNodeType(typeOrName, state.schema);
1668
+ const $pos = tr.selection.$anchor;
1669
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1670
+ const node = $pos.node(depth);
1671
+ if (node.type === type) {
1672
+ if (dispatch) {
1673
+ const from = $pos.before(depth);
1674
+ const to = $pos.after(depth);
1675
+ tr.delete(from, to).scrollIntoView();
1676
+ }
1677
+ return true;
1678
+ }
1679
+ }
1680
+ return false;
1681
+ };
1682
+
1683
+ const deleteRange = range => ({ tr, dispatch }) => {
1684
+ const { from, to } = range;
1685
+ if (dispatch) {
1686
+ tr.delete(from, to);
1687
+ }
1688
+ return true;
1689
+ };
1690
+
1691
+ const deleteSelection = () => ({ state, dispatch }) => {
1692
+ return deleteSelection$1(state, dispatch);
1693
+ };
1694
+
1695
+ const enter = () => ({ commands }) => {
1696
+ return commands.keyboardShortcut('Enter');
1697
+ };
1698
+
1699
+ const exitCode = () => ({ state, dispatch }) => {
1700
+ return exitCode$1(state, dispatch);
1701
+ };
1702
+
1703
+ /**
1704
+ * Check if object1 includes object2
1705
+ * @param object1 Object
1706
+ * @param object2 Object
1707
+ */
1708
+ function objectIncludes(object1, object2, options = { strict: true }) {
1709
+ const keys = Object.keys(object2);
1710
+ if (!keys.length) {
1711
+ return true;
1712
+ }
1713
+ return keys.every(key => {
1714
+ if (options.strict) {
1715
+ return object2[key] === object1[key];
1716
+ }
1717
+ if (isRegExp(object2[key])) {
1718
+ return object2[key].test(object1[key]);
1719
+ }
1720
+ return object2[key] === object1[key];
1721
+ });
1722
+ }
1723
+
1724
+ function findMarkInSet(marks, type, attributes = {}) {
1725
+ return marks.find(item => {
1726
+ return (item.type === type
1727
+ && objectIncludes(
1728
+ // Only check equality for the attributes that are provided
1729
+ Object.fromEntries(Object.keys(attributes).map(k => [k, item.attrs[k]])), attributes));
1730
+ });
1731
+ }
1732
+ function isMarkInSet(marks, type, attributes = {}) {
1733
+ return !!findMarkInSet(marks, type, attributes);
1734
+ }
1735
+ /**
1736
+ * Get the range of a mark at a resolved position.
1737
+ */
1738
+ function getMarkRange(
1739
+ /**
1740
+ * The position to get the mark range for.
1741
+ */
1742
+ $pos,
1743
+ /**
1744
+ * The mark type to get the range for.
1745
+ */
1746
+ type,
1747
+ /**
1748
+ * The attributes to match against.
1749
+ * If not provided, only the first mark at the position will be matched.
1750
+ */
1751
+ attributes) {
1752
+ var _a;
1753
+ if (!$pos || !type) {
1754
+ return;
1755
+ }
1756
+ let start = $pos.parent.childAfter($pos.parentOffset);
1757
+ // If the cursor is at the start of a text node that does not have the mark, look backward
1758
+ if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
1759
+ start = $pos.parent.childBefore($pos.parentOffset);
1760
+ }
1761
+ // If there is no text node with the mark even backward, return undefined
1762
+ if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
1763
+ return;
1764
+ }
1765
+ // Default to only matching against the first mark's attributes
1766
+ attributes = attributes || ((_a = start.node.marks[0]) === null || _a === void 0 ? void 0 : _a.attrs);
1767
+ // We now know that the cursor is either at the start, middle or end of a text node with the specified mark
1768
+ // so we can look it up on the targeted mark
1769
+ const mark = findMarkInSet([...start.node.marks], type, attributes);
1770
+ if (!mark) {
1771
+ return;
1772
+ }
1773
+ let startIndex = start.index;
1774
+ let startPos = $pos.start() + start.offset;
1775
+ let endIndex = startIndex + 1;
1776
+ let endPos = startPos + start.node.nodeSize;
1777
+ while (startIndex > 0
1778
+ && isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)) {
1779
+ startIndex -= 1;
1780
+ startPos -= $pos.parent.child(startIndex).nodeSize;
1781
+ }
1782
+ while (endIndex < $pos.parent.childCount
1783
+ && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
1784
+ endPos += $pos.parent.child(endIndex).nodeSize;
1785
+ endIndex += 1;
1786
+ }
1787
+ return {
1788
+ from: startPos,
1789
+ to: endPos,
1790
+ };
1791
+ }
1792
+
1793
+ function getMarkType(nameOrType, schema) {
1794
+ if (typeof nameOrType === 'string') {
1795
+ if (!schema.marks[nameOrType]) {
1796
+ throw Error(`There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`);
1797
+ }
1798
+ return schema.marks[nameOrType];
1799
+ }
1800
+ return nameOrType;
1801
+ }
1802
+
1803
+ const extendMarkRange = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
1804
+ const type = getMarkType(typeOrName, state.schema);
1805
+ const { doc, selection } = tr;
1806
+ const { $from, from, to } = selection;
1807
+ if (dispatch) {
1808
+ const range = getMarkRange($from, type, attributes);
1809
+ if (range && range.from <= from && range.to >= to) {
1810
+ const newSelection = TextSelection.create(doc, range.from, range.to);
1811
+ tr.setSelection(newSelection);
1812
+ }
1813
+ }
1814
+ return true;
1815
+ };
1816
+
1817
+ const first = commands => props => {
1818
+ const items = typeof commands === 'function'
1819
+ ? commands(props)
1820
+ : commands;
1821
+ for (let i = 0; i < items.length; i += 1) {
1822
+ if (items[i](props)) {
1823
+ return true;
1824
+ }
1825
+ }
1826
+ return false;
1827
+ };
1828
+
1829
+ function isTextSelection(value) {
1830
+ return value instanceof TextSelection;
1831
+ }
1832
+
1833
+ function minMax(value = 0, min = 0, max = 0) {
1834
+ return Math.min(Math.max(value, min), max);
1835
+ }
1836
+
1837
+ function resolveFocusPosition(doc, position = null) {
1838
+ if (!position) {
1839
+ return null;
1840
+ }
1841
+ const selectionAtStart = Selection.atStart(doc);
1842
+ const selectionAtEnd = Selection.atEnd(doc);
1843
+ if (position === 'start' || position === true) {
1844
+ return selectionAtStart;
1845
+ }
1846
+ if (position === 'end') {
1847
+ return selectionAtEnd;
1848
+ }
1849
+ const minPos = selectionAtStart.from;
1850
+ const maxPos = selectionAtEnd.to;
1851
+ if (position === 'all') {
1852
+ return TextSelection.create(doc, minMax(0, minPos, maxPos), minMax(doc.content.size, minPos, maxPos));
1853
+ }
1854
+ return TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1855
+ }
1856
+
1857
+ function isAndroid() {
1858
+ return navigator.platform === 'Android' || /android/i.test(navigator.userAgent);
1859
+ }
1860
+
1861
+ function isiOS() {
1862
+ return [
1863
+ 'iPad Simulator',
1864
+ 'iPhone Simulator',
1865
+ 'iPod Simulator',
1866
+ 'iPad',
1867
+ 'iPhone',
1868
+ 'iPod',
1869
+ ].includes(navigator.platform)
1870
+ // iPad on iOS 13 detection
1871
+ || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
1872
+ }
1873
+
1874
+ const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
1875
+ options = {
1876
+ scrollIntoView: true,
1877
+ ...options,
1878
+ };
1879
+ const delayedFocus = () => {
1880
+ // focus within `requestAnimationFrame` breaks focus on iOS and Android
1881
+ // so we have to call this
1882
+ if (isiOS() || isAndroid()) {
1883
+ view.dom.focus();
1884
+ }
1885
+ // For React we have to focus asynchronously. Otherwise wild things happen.
1886
+ // see: https://github.com/ueberdosis/tiptap/issues/1520
1887
+ requestAnimationFrame(() => {
1888
+ if (!editor.isDestroyed) {
1889
+ view.focus();
1890
+ if (options === null || options === void 0 ? void 0 : options.scrollIntoView) {
1891
+ editor.commands.scrollIntoView();
1892
+ }
1893
+ }
1894
+ });
1895
+ };
1896
+ if ((view.hasFocus() && position === null) || position === false) {
1897
+ return true;
1898
+ }
1899
+ // we don’t try to resolve a NodeSelection or CellSelection
1900
+ if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
1901
+ delayedFocus();
1902
+ return true;
1903
+ }
1904
+ // pass through tr.doc instead of editor.state.doc
1905
+ // since transactions could change the editors state before this command has been run
1906
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
1907
+ const isSameSelection = editor.state.selection.eq(selection);
1908
+ if (dispatch) {
1909
+ if (!isSameSelection) {
1910
+ tr.setSelection(selection);
1911
+ }
1912
+ // `tr.setSelection` resets the stored marks
1913
+ // so we’ll restore them if the selection is the same as before
1914
+ if (isSameSelection && tr.storedMarks) {
1915
+ tr.setStoredMarks(tr.storedMarks);
1916
+ }
1917
+ delayedFocus();
1918
+ }
1919
+ return true;
1920
+ };
1921
+
1922
+ const forEach = (items, fn) => props => {
1923
+ return items.every((item, index) => fn(item, { ...props, index }));
1924
+ };
1925
+
1926
+ const insertContent = (value, options) => ({ tr, commands }) => {
1927
+ return commands.insertContentAt({ from: tr.selection.from, to: tr.selection.to }, value, options);
1928
+ };
1929
+
1930
+ const removeWhitespaces = (node) => {
1931
+ const children = node.childNodes;
1932
+ for (let i = children.length - 1; i >= 0; i -= 1) {
1933
+ const child = children[i];
1934
+ if (child.nodeType === 3 && child.nodeValue && /^(\n\s\s|\n)$/.test(child.nodeValue)) {
1935
+ node.removeChild(child);
1936
+ }
1937
+ else if (child.nodeType === 1) {
1938
+ removeWhitespaces(child);
1939
+ }
1940
+ }
1941
+ return node;
1942
+ };
1943
+ function elementFromString(value) {
1944
+ // add a wrapper to preserve leading and trailing whitespace
1945
+ const wrappedValue = `<body>${value}</body>`;
1946
+ const html = new window.DOMParser().parseFromString(wrappedValue, 'text/html').body;
1947
+ return removeWhitespaces(html);
1948
+ }
1949
+
1950
+ /**
1951
+ * Takes a JSON or HTML content and creates a Prosemirror node or fragment from it.
1952
+ * @param content The JSON or HTML content to create the node from
1953
+ * @param schema The Prosemirror schema to use for the node
1954
+ * @param options Options for the parser
1955
+ * @returns The created Prosemirror node or fragment
1956
+ */
1957
+ function createNodeFromContent(content, schema, options) {
1958
+ if (content instanceof Node$1 || content instanceof Fragment) {
1959
+ return content;
1960
+ }
1961
+ options = {
1962
+ slice: true,
1963
+ parseOptions: {},
1964
+ ...options,
1965
+ };
1966
+ const isJSONContent = typeof content === 'object' && content !== null;
1967
+ const isTextContent = typeof content === 'string';
1968
+ if (isJSONContent) {
1969
+ try {
1970
+ const isArrayContent = Array.isArray(content) && content.length > 0;
1971
+ // if the JSON Content is an array of nodes, create a fragment for each node
1972
+ if (isArrayContent) {
1973
+ return Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)));
1974
+ }
1975
+ const node = schema.nodeFromJSON(content);
1976
+ if (options.errorOnInvalidContent) {
1977
+ node.check();
1978
+ }
1979
+ return node;
1980
+ }
1981
+ catch (error) {
1982
+ if (options.errorOnInvalidContent) {
1983
+ throw new Error('[tiptap error]: Invalid JSON content', { cause: error });
1984
+ }
1985
+ console.warn('[tiptap warn]: Invalid content.', 'Passed value:', content, 'Error:', error);
1986
+ return createNodeFromContent('', schema, options);
1987
+ }
1988
+ }
1989
+ if (isTextContent) {
1990
+ // Check for invalid content
1991
+ if (options.errorOnInvalidContent) {
1992
+ let hasInvalidContent = false;
1993
+ let invalidContent = '';
1994
+ // A copy of the current schema with a catch-all node at the end
1995
+ const contentCheckSchema = new Schema({
1996
+ topNode: schema.spec.topNode,
1997
+ marks: schema.spec.marks,
1998
+ // Prosemirror's schemas are executed such that: the last to execute, matches last
1999
+ // This means that we can add a catch-all node at the end of the schema to catch any content that we don't know how to handle
2000
+ nodes: schema.spec.nodes.append({
2001
+ __tiptap__private__unknown__catch__all__node: {
2002
+ content: 'inline*',
2003
+ group: 'block',
2004
+ parseDOM: [
2005
+ {
2006
+ tag: '*',
2007
+ getAttrs: e => {
2008
+ // If this is ever called, we know that the content has something that we don't know how to handle in the schema
2009
+ hasInvalidContent = true;
2010
+ // Try to stringify the element for a more helpful error message
2011
+ invalidContent = typeof e === 'string' ? e : e.outerHTML;
2012
+ return null;
2013
+ },
2014
+ },
2015
+ ],
2016
+ },
2017
+ }),
2018
+ });
2019
+ if (options.slice) {
2020
+ DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
2021
+ }
2022
+ else {
2023
+ DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
2024
+ }
2025
+ if (options.errorOnInvalidContent && hasInvalidContent) {
2026
+ throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
2027
+ }
2028
+ }
2029
+ const parser = DOMParser.fromSchema(schema);
2030
+ if (options.slice) {
2031
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
2032
+ }
2033
+ return parser.parse(elementFromString(content), options.parseOptions);
2034
+ }
2035
+ return createNodeFromContent('', schema, options);
2036
+ }
2037
+
2038
+ // source: https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.js#L466
2039
+ function selectionToInsertionEnd(tr, startLen, bias) {
2040
+ const last = tr.steps.length - 1;
2041
+ if (last < startLen) {
2042
+ return;
2043
+ }
2044
+ const step = tr.steps[last];
2045
+ if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) {
2046
+ return;
2047
+ }
2048
+ const map = tr.mapping.maps[last];
2049
+ let end = 0;
2050
+ map.forEach((_from, _to, _newFrom, newTo) => {
2051
+ if (end === 0) {
2052
+ end = newTo;
2053
+ }
2054
+ });
2055
+ tr.setSelection(Selection.near(tr.doc.resolve(end), bias));
2056
+ }
2057
+
2058
+ const isFragment = (nodeOrFragment) => {
2059
+ return !('type' in nodeOrFragment);
2060
+ };
2061
+ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
2062
+ var _a;
2063
+ if (dispatch) {
2064
+ options = {
2065
+ parseOptions: editor.options.parseOptions,
2066
+ updateSelection: true,
2067
+ applyInputRules: false,
2068
+ applyPasteRules: false,
2069
+ ...options,
2070
+ };
2071
+ let content;
2072
+ const emitContentError = (error) => {
2073
+ editor.emit('contentError', {
2074
+ editor,
2075
+ error,
2076
+ disableCollaboration: () => {
2077
+ if (editor.storage.collaboration) {
2078
+ editor.storage.collaboration.isDisabled = true;
2079
+ }
2080
+ },
2081
+ });
2082
+ };
2083
+ const parseOptions = {
2084
+ preserveWhitespace: 'full',
2085
+ ...options.parseOptions,
2086
+ };
2087
+ // If `emitContentError` is enabled, we want to check the content for errors
2088
+ // but ignore them (do not remove the invalid content from the document)
2089
+ if (!options.errorOnInvalidContent && !editor.options.enableContentCheck && editor.options.emitContentError) {
2090
+ try {
2091
+ createNodeFromContent(value, editor.schema, {
2092
+ parseOptions,
2093
+ errorOnInvalidContent: true,
2094
+ });
2095
+ }
2096
+ catch (e) {
2097
+ emitContentError(e);
2098
+ }
2099
+ }
2100
+ try {
2101
+ content = createNodeFromContent(value, editor.schema, {
2102
+ parseOptions,
2103
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck,
2104
+ });
2105
+ }
2106
+ catch (e) {
2107
+ emitContentError(e);
2108
+ return false;
2109
+ }
2110
+ let { from, to } = typeof position === 'number' ? { from: position, to: position } : { from: position.from, to: position.to };
2111
+ let isOnlyTextContent = true;
2112
+ let isOnlyBlockContent = true;
2113
+ const nodes = isFragment(content) ? content : [content];
2114
+ nodes.forEach(node => {
2115
+ // check if added node is valid
2116
+ node.check();
2117
+ isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
2118
+ isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
2119
+ });
2120
+ // check if we can replace the wrapping node by
2121
+ // the newly inserted content
2122
+ // example:
2123
+ // replace an empty paragraph by an inserted image
2124
+ // instead of inserting the image below the paragraph
2125
+ if (from === to && isOnlyBlockContent) {
2126
+ const { parent } = tr.doc.resolve(from);
2127
+ const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
2128
+ if (isEmptyTextBlock) {
2129
+ from -= 1;
2130
+ to += 1;
2131
+ }
2132
+ }
2133
+ let newContent;
2134
+ // if there is only plain text we have to use `insertText`
2135
+ // because this will keep the current marks
2136
+ if (isOnlyTextContent) {
2137
+ // if value is string, we can use it directly
2138
+ // otherwise if it is an array, we have to join it
2139
+ if (Array.isArray(value)) {
2140
+ newContent = value.map(v => v.text || '').join('');
2141
+ }
2142
+ else if (value instanceof Fragment) {
2143
+ let text = '';
2144
+ value.forEach(node => {
2145
+ if (node.text) {
2146
+ text += node.text;
2147
+ }
2148
+ });
2149
+ newContent = text;
2150
+ }
2151
+ else if (typeof value === 'object' && !!value && !!value.text) {
2152
+ newContent = value.text;
2153
+ }
2154
+ else {
2155
+ newContent = value;
2156
+ }
2157
+ tr.insertText(newContent, from, to);
2158
+ }
2159
+ else {
2160
+ newContent = content;
2161
+ tr.replaceWith(from, to, newContent);
2162
+ }
2163
+ // set cursor at end of inserted content
2164
+ if (options.updateSelection) {
2165
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
2166
+ }
2167
+ if (options.applyInputRules) {
2168
+ tr.setMeta('applyInputRules', { from, text: newContent });
2169
+ }
2170
+ if (options.applyPasteRules) {
2171
+ tr.setMeta('applyPasteRules', { from, text: newContent });
2172
+ }
2173
+ }
2174
+ return true;
2175
+ };
2176
+
2177
+ const joinUp = () => ({ state, dispatch }) => {
2178
+ return joinUp$1(state, dispatch);
2179
+ };
2180
+ const joinDown = () => ({ state, dispatch }) => {
2181
+ return joinDown$1(state, dispatch);
2182
+ };
2183
+ const joinBackward = () => ({ state, dispatch }) => {
2184
+ return joinBackward$1(state, dispatch);
2185
+ };
2186
+ const joinForward = () => ({ state, dispatch }) => {
2187
+ return joinForward$1(state, dispatch);
2188
+ };
2189
+
2190
+ const joinItemBackward = () => ({ state, dispatch, tr, }) => {
2191
+ try {
2192
+ const point = joinPoint(state.doc, state.selection.$from.pos, -1);
2193
+ if (point === null || point === undefined) {
2194
+ return false;
2195
+ }
2196
+ tr.join(point, 2);
2197
+ if (dispatch) {
2198
+ dispatch(tr);
2199
+ }
2200
+ return true;
2201
+ }
2202
+ catch {
2203
+ return false;
2204
+ }
2205
+ };
2206
+
2207
+ const joinItemForward = () => ({ state, dispatch, tr, }) => {
2208
+ try {
2209
+ const point = joinPoint(state.doc, state.selection.$from.pos, +1);
2210
+ if (point === null || point === undefined) {
2211
+ return false;
2212
+ }
2213
+ tr.join(point, 2);
2214
+ if (dispatch) {
2215
+ dispatch(tr);
2216
+ }
2217
+ return true;
2218
+ }
2219
+ catch {
2220
+ return false;
2221
+ }
2222
+ };
2223
+
2224
+ const joinTextblockBackward = () => ({ state, dispatch }) => {
2225
+ return joinTextblockBackward$1(state, dispatch);
2226
+ };
2227
+
2228
+ const joinTextblockForward = () => ({ state, dispatch }) => {
2229
+ return joinTextblockForward$1(state, dispatch);
2230
+ };
2231
+
2232
+ function isMacOS() {
2233
+ return typeof navigator !== 'undefined'
2234
+ ? /Mac/.test(navigator.platform)
2235
+ : false;
2236
+ }
2237
+
2238
+ function normalizeKeyName(name) {
2239
+ const parts = name.split(/-(?!$)/);
2240
+ let result = parts[parts.length - 1];
2241
+ if (result === 'Space') {
2242
+ result = ' ';
2243
+ }
2244
+ let alt;
2245
+ let ctrl;
2246
+ let shift;
2247
+ let meta;
2248
+ for (let i = 0; i < parts.length - 1; i += 1) {
2249
+ const mod = parts[i];
2250
+ if (/^(cmd|meta|m)$/i.test(mod)) {
2251
+ meta = true;
2252
+ }
2253
+ else if (/^a(lt)?$/i.test(mod)) {
2254
+ alt = true;
2255
+ }
2256
+ else if (/^(c|ctrl|control)$/i.test(mod)) {
2257
+ ctrl = true;
2258
+ }
2259
+ else if (/^s(hift)?$/i.test(mod)) {
2260
+ shift = true;
2261
+ }
2262
+ else if (/^mod$/i.test(mod)) {
2263
+ if (isiOS() || isMacOS()) {
2264
+ meta = true;
2265
+ }
2266
+ else {
2267
+ ctrl = true;
2268
+ }
2269
+ }
2270
+ else {
2271
+ throw new Error(`Unrecognized modifier name: ${mod}`);
2272
+ }
2273
+ }
2274
+ if (alt) {
2275
+ result = `Alt-${result}`;
2276
+ }
2277
+ if (ctrl) {
2278
+ result = `Ctrl-${result}`;
2279
+ }
2280
+ if (meta) {
2281
+ result = `Meta-${result}`;
2282
+ }
2283
+ if (shift) {
2284
+ result = `Shift-${result}`;
2285
+ }
2286
+ return result;
2287
+ }
2288
+ const keyboardShortcut = name => ({ editor, view, tr, dispatch, }) => {
2289
+ const keys = normalizeKeyName(name).split(/-(?!$)/);
2290
+ const key = keys.find(item => !['Alt', 'Ctrl', 'Meta', 'Shift'].includes(item));
2291
+ const event = new KeyboardEvent('keydown', {
2292
+ key: key === 'Space'
2293
+ ? ' '
2294
+ : key,
2295
+ altKey: keys.includes('Alt'),
2296
+ ctrlKey: keys.includes('Ctrl'),
2297
+ metaKey: keys.includes('Meta'),
2298
+ shiftKey: keys.includes('Shift'),
2299
+ bubbles: true,
2300
+ cancelable: true,
2301
+ });
2302
+ const capturedTransaction = editor.captureTransaction(() => {
2303
+ view.someProp('handleKeyDown', f => f(view, event));
2304
+ });
2305
+ capturedTransaction === null || capturedTransaction === void 0 ? void 0 : capturedTransaction.steps.forEach(step => {
2306
+ const newStep = step.map(tr.mapping);
2307
+ if (newStep && dispatch) {
2308
+ tr.maybeStep(newStep);
2309
+ }
2310
+ });
2311
+ return true;
2312
+ };
2313
+
2314
+ function isNodeActive(state, typeOrName, attributes = {}) {
2315
+ const { from, to, empty } = state.selection;
2316
+ const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
2317
+ const nodeRanges = [];
2318
+ state.doc.nodesBetween(from, to, (node, pos) => {
2319
+ if (node.isText) {
2320
+ return;
2321
+ }
2322
+ const relativeFrom = Math.max(from, pos);
2323
+ const relativeTo = Math.min(to, pos + node.nodeSize);
2324
+ nodeRanges.push({
2325
+ node,
2326
+ from: relativeFrom,
2327
+ to: relativeTo,
2328
+ });
2329
+ });
2330
+ const selectionRange = to - from;
2331
+ const matchedNodeRanges = nodeRanges
2332
+ .filter(nodeRange => {
2333
+ if (!type) {
2334
+ return true;
2335
+ }
2336
+ return type.name === nodeRange.node.type.name;
2337
+ })
2338
+ .filter(nodeRange => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
2339
+ if (empty) {
2340
+ return !!matchedNodeRanges.length;
2341
+ }
2342
+ const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
2343
+ return range >= selectionRange;
2344
+ }
2345
+
2346
+ const lift = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
2347
+ const type = getNodeType(typeOrName, state.schema);
2348
+ const isActive = isNodeActive(state, type, attributes);
2349
+ if (!isActive) {
2350
+ return false;
2351
+ }
2352
+ return lift$1(state, dispatch);
2353
+ };
2354
+
2355
+ const liftEmptyBlock = () => ({ state, dispatch }) => {
2356
+ return liftEmptyBlock$1(state, dispatch);
2357
+ };
2358
+
2359
+ const liftListItem = typeOrName => ({ state, dispatch }) => {
2360
+ const type = getNodeType(typeOrName, state.schema);
2361
+ return liftListItem$1(type)(state, dispatch);
2362
+ };
2363
+
2364
+ const newlineInCode = () => ({ state, dispatch }) => {
2365
+ return newlineInCode$1(state, dispatch);
2366
+ };
2367
+
2368
+ /**
2369
+ * Get the type of a schema item by its name.
2370
+ * @param name The name of the schema item
2371
+ * @param schema The Prosemiror schema to search in
2372
+ * @returns The type of the schema item (`node` or `mark`), or null if it doesn't exist
2373
+ */
2374
+ function getSchemaTypeNameByName(name, schema) {
2375
+ if (schema.nodes[name]) {
2376
+ return 'node';
2377
+ }
2378
+ if (schema.marks[name]) {
2379
+ return 'mark';
2380
+ }
2381
+ return null;
2382
+ }
2383
+
2384
+ /**
2385
+ * Remove a property or an array of properties from an object
2386
+ * @param obj Object
2387
+ * @param key Key to remove
2388
+ */
2389
+ function deleteProps(obj, propOrProps) {
2390
+ const props = typeof propOrProps === 'string'
2391
+ ? [propOrProps]
2392
+ : propOrProps;
2393
+ return Object
2394
+ .keys(obj)
2395
+ .reduce((newObj, prop) => {
2396
+ if (!props.includes(prop)) {
2397
+ newObj[prop] = obj[prop];
2398
+ }
2399
+ return newObj;
2400
+ }, {});
2401
+ }
2402
+
2403
+ const resetAttributes = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
2404
+ let nodeType = null;
2405
+ let markType = null;
2406
+ const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string' ? typeOrName : typeOrName.name, state.schema);
2407
+ if (!schemaType) {
2408
+ return false;
2409
+ }
2410
+ if (schemaType === 'node') {
2411
+ nodeType = getNodeType(typeOrName, state.schema);
2412
+ }
2413
+ if (schemaType === 'mark') {
2414
+ markType = getMarkType(typeOrName, state.schema);
2415
+ }
2416
+ if (dispatch) {
2417
+ tr.selection.ranges.forEach(range => {
2418
+ state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
2419
+ if (nodeType && nodeType === node.type) {
2420
+ tr.setNodeMarkup(pos, undefined, deleteProps(node.attrs, attributes));
2421
+ }
2422
+ if (markType && node.marks.length) {
2423
+ node.marks.forEach(mark => {
2424
+ if (markType === mark.type) {
2425
+ tr.addMark(pos, pos + node.nodeSize, markType.create(deleteProps(mark.attrs, attributes)));
2426
+ }
2427
+ });
2428
+ }
2429
+ });
2430
+ });
2431
+ }
2432
+ return true;
2433
+ };
2434
+
2435
+ const scrollIntoView = () => ({ tr, dispatch }) => {
2436
+ if (dispatch) {
2437
+ tr.scrollIntoView();
2438
+ }
2439
+ return true;
2440
+ };
2441
+
2442
+ const selectAll = () => ({ tr, dispatch }) => {
2443
+ if (dispatch) {
2444
+ const selection = new AllSelection(tr.doc);
2445
+ tr.setSelection(selection);
2446
+ }
2447
+ return true;
2448
+ };
2449
+
2450
+ const selectNodeBackward = () => ({ state, dispatch }) => {
2451
+ return selectNodeBackward$1(state, dispatch);
2452
+ };
2453
+
2454
+ const selectNodeForward = () => ({ state, dispatch }) => {
2455
+ return selectNodeForward$1(state, dispatch);
2456
+ };
2457
+
2458
+ const selectParentNode = () => ({ state, dispatch }) => {
2459
+ return selectParentNode$1(state, dispatch);
2460
+ };
2461
+
2462
+ // @ts-ignore
2463
+ // TODO: add types to @types/prosemirror-commands
2464
+ const selectTextblockEnd = () => ({ state, dispatch }) => {
2465
+ return selectTextblockEnd$1(state, dispatch);
2466
+ };
2467
+
2468
+ // @ts-ignore
2469
+ // TODO: add types to @types/prosemirror-commands
2470
+ const selectTextblockStart = () => ({ state, dispatch }) => {
2471
+ return selectTextblockStart$1(state, dispatch);
2472
+ };
2473
+
2474
+ /**
2475
+ * Create a new Prosemirror document node from content.
2476
+ * @param content The JSON or HTML content to create the document from
2477
+ * @param schema The Prosemirror schema to use for the document
2478
+ * @param parseOptions Options for the parser
2479
+ * @returns The created Prosemirror document node
2480
+ */
2481
+ function createDocument(content, schema, parseOptions = {}, options = {}) {
2482
+ return createNodeFromContent(content, schema, {
2483
+ slice: false,
2484
+ parseOptions,
2485
+ errorOnInvalidContent: options.errorOnInvalidContent,
2486
+ });
2487
+ }
2488
+
2489
+ const setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ editor, tr, dispatch, commands, }) => {
2490
+ var _a, _b;
2491
+ const { doc } = tr;
2492
+ // This is to keep backward compatibility with the previous behavior
2493
+ // TODO remove this in the next major version
2494
+ if (parseOptions.preserveWhitespace !== 'full') {
2495
+ const document = createDocument(content, editor.schema, parseOptions, {
2496
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck,
2497
+ });
2498
+ if (dispatch) {
2499
+ tr.replaceWith(0, doc.content.size, document).setMeta('preventUpdate', !emitUpdate);
2500
+ }
2501
+ return true;
2502
+ }
2503
+ if (dispatch) {
2504
+ tr.setMeta('preventUpdate', !emitUpdate);
2505
+ }
2506
+ return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
2507
+ parseOptions,
2508
+ errorOnInvalidContent: (_b = options.errorOnInvalidContent) !== null && _b !== void 0 ? _b : editor.options.enableContentCheck,
2509
+ });
2510
+ };
2511
+
2512
+ function getMarkAttributes(state, typeOrName) {
2513
+ const type = getMarkType(typeOrName, state.schema);
2514
+ const { from, to, empty } = state.selection;
2515
+ const marks = [];
2516
+ if (empty) {
2517
+ if (state.storedMarks) {
2518
+ marks.push(...state.storedMarks);
2519
+ }
2520
+ marks.push(...state.selection.$head.marks());
2521
+ }
2522
+ else {
2523
+ state.doc.nodesBetween(from, to, node => {
2524
+ marks.push(...node.marks);
2525
+ });
2526
+ }
2527
+ const mark = marks.find(markItem => markItem.type.name === type.name);
2528
+ if (!mark) {
2529
+ return {};
2530
+ }
2531
+ return { ...mark.attrs };
2532
+ }
2533
+
2534
+ /**
2535
+ * Returns a new `Transform` based on all steps of the passed transactions.
2536
+ * @param oldDoc The Prosemirror node to start from
2537
+ * @param transactions The transactions to combine
2538
+ * @returns A new `Transform` with all steps of the passed transactions
2539
+ */
2540
+ function combineTransactionSteps(oldDoc, transactions) {
2541
+ const transform = new Transform(oldDoc);
2542
+ transactions.forEach(transaction => {
2543
+ transaction.steps.forEach(step => {
2544
+ transform.step(step);
2545
+ });
2546
+ });
2547
+ return transform;
2548
+ }
2549
+
2550
+ /**
2551
+ * Gets the default block type at a given match
2552
+ * @param match The content match to get the default block type from
2553
+ * @returns The default block type or null
2554
+ */
2555
+ function defaultBlockAt(match) {
2556
+ for (let i = 0; i < match.edgeCount; i += 1) {
2557
+ const { type } = match.edge(i);
2558
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
2559
+ return type;
2560
+ }
2561
+ }
2562
+ return null;
2563
+ }
2564
+
2565
+ /**
2566
+ * Same as `findChildren` but searches only within a `range`.
2567
+ * @param node The Prosemirror node to search in
2568
+ * @param range The range to search in
2569
+ * @param predicate The predicate to match
2570
+ * @returns An array of nodes with their positions
2571
+ */
2572
+ function findChildrenInRange(node, range, predicate) {
2573
+ const nodesWithPos = [];
2574
+ // if (range.from === range.to) {
2575
+ // const nodeAt = node.nodeAt(range.from)
2576
+ // if (nodeAt) {
2577
+ // nodesWithPos.push({
2578
+ // node: nodeAt,
2579
+ // pos: range.from,
2580
+ // })
2581
+ // }
2582
+ // }
2583
+ node.nodesBetween(range.from, range.to, (child, pos) => {
2584
+ if (predicate(child)) {
2585
+ nodesWithPos.push({
2586
+ node: child,
2587
+ pos,
2588
+ });
2589
+ }
2590
+ });
2591
+ return nodesWithPos;
2592
+ }
2593
+
2594
+ /**
2595
+ * Finds the closest parent node to a resolved position that matches a predicate.
2596
+ * @param $pos The resolved position to search from
2597
+ * @param predicate The predicate to match
2598
+ * @returns The closest parent node to the resolved position that matches the predicate
2599
+ * @example ```js
2600
+ * findParentNodeClosestToPos($from, node => node.type.name === 'paragraph')
2601
+ * ```
2602
+ */
2603
+ function findParentNodeClosestToPos($pos, predicate) {
2604
+ for (let i = $pos.depth; i > 0; i -= 1) {
2605
+ const node = $pos.node(i);
2606
+ if (predicate(node)) {
2607
+ return {
2608
+ pos: i > 0 ? $pos.before(i) : 0,
2609
+ start: $pos.start(i),
2610
+ depth: i,
2611
+ node,
2612
+ };
2613
+ }
2614
+ }
2615
+ }
2616
+
2617
+ /**
2618
+ * Finds the closest parent node to the current selection that matches a predicate.
2619
+ * @param predicate The predicate to match
2620
+ * @returns A command that finds the closest parent node to the current selection that matches the predicate
2621
+ * @example ```js
2622
+ * findParentNode(node => node.type.name === 'paragraph')
2623
+ * ```
2624
+ */
2625
+ function findParentNode(predicate) {
2626
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2627
+ }
2628
+
2629
+ /**
2630
+ * Gets the text of a Prosemirror node
2631
+ * @param node The Prosemirror node
2632
+ * @param options Options for the text serializer & block separator
2633
+ * @returns The text of the node
2634
+ * @example ```js
2635
+ * const text = getText(node, { blockSeparator: '\n' })
2636
+ * ```
2637
+ */
2638
+ function getText(node, options) {
2639
+ const range = {
2640
+ from: 0,
2641
+ to: node.content.size,
2642
+ };
2643
+ return getTextBetween(node, range, options);
2644
+ }
2645
+
2646
+ function getNodeAttributes(state, typeOrName) {
2647
+ const type = getNodeType(typeOrName, state.schema);
2648
+ const { from, to } = state.selection;
2649
+ const nodes = [];
2650
+ state.doc.nodesBetween(from, to, node => {
2651
+ nodes.push(node);
2652
+ });
2653
+ const node = nodes.reverse().find(nodeItem => nodeItem.type.name === type.name);
2654
+ if (!node) {
2655
+ return {};
2656
+ }
2657
+ return { ...node.attrs };
2658
+ }
2659
+
2660
+ /**
2661
+ * Get node or mark attributes by type or name on the current editor state
2662
+ * @param state The current editor state
2663
+ * @param typeOrName The node or mark type or name
2664
+ * @returns The attributes of the node or mark or an empty object
2665
+ */
2666
+ function getAttributes(state, typeOrName) {
2667
+ const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string' ? typeOrName : typeOrName.name, state.schema);
2668
+ if (schemaType === 'node') {
2669
+ return getNodeAttributes(state, typeOrName);
2670
+ }
2671
+ if (schemaType === 'mark') {
2672
+ return getMarkAttributes(state, typeOrName);
2673
+ }
2674
+ return {};
2675
+ }
2676
+
2677
+ /**
2678
+ * Removes duplicated values within an array.
2679
+ * Supports numbers, strings and objects.
2680
+ */
2681
+ function removeDuplicates(array, by = JSON.stringify) {
2682
+ const seen = {};
2683
+ return array.filter(item => {
2684
+ const key = by(item);
2685
+ return Object.prototype.hasOwnProperty.call(seen, key)
2686
+ ? false
2687
+ : (seen[key] = true);
2688
+ });
2689
+ }
2690
+
2691
+ /**
2692
+ * Removes duplicated ranges and ranges that are
2693
+ * fully captured by other ranges.
2694
+ */
2695
+ function simplifyChangedRanges(changes) {
2696
+ const uniqueChanges = removeDuplicates(changes);
2697
+ return uniqueChanges.length === 1
2698
+ ? uniqueChanges
2699
+ : uniqueChanges.filter((change, index) => {
2700
+ const rest = uniqueChanges.filter((_, i) => i !== index);
2701
+ return !rest.some(otherChange => {
2702
+ return change.oldRange.from >= otherChange.oldRange.from
2703
+ && change.oldRange.to <= otherChange.oldRange.to
2704
+ && change.newRange.from >= otherChange.newRange.from
2705
+ && change.newRange.to <= otherChange.newRange.to;
2706
+ });
2707
+ });
2708
+ }
2709
+ /**
2710
+ * Returns a list of changed ranges
2711
+ * based on the first and last state of all steps.
2712
+ */
2713
+ function getChangedRanges(transform) {
2714
+ const { mapping, steps } = transform;
2715
+ const changes = [];
2716
+ mapping.maps.forEach((stepMap, index) => {
2717
+ const ranges = [];
2718
+ // This accounts for step changes where no range was actually altered
2719
+ // e.g. when setting a mark, node attribute, etc.
2720
+ // @ts-ignore
2721
+ if (!stepMap.ranges.length) {
2722
+ const { from, to } = steps[index];
2723
+ if (from === undefined || to === undefined) {
2724
+ return;
2725
+ }
2726
+ ranges.push({ from, to });
2727
+ }
2728
+ else {
2729
+ stepMap.forEach((from, to) => {
2730
+ ranges.push({ from, to });
2731
+ });
2732
+ }
2733
+ ranges.forEach(({ from, to }) => {
2734
+ const newStart = mapping.slice(index).map(from, -1);
2735
+ const newEnd = mapping.slice(index).map(to);
2736
+ const oldStart = mapping.invert().map(newStart, -1);
2737
+ const oldEnd = mapping.invert().map(newEnd);
2738
+ changes.push({
2739
+ oldRange: {
2740
+ from: oldStart,
2741
+ to: oldEnd,
2742
+ },
2743
+ newRange: {
2744
+ from: newStart,
2745
+ to: newEnd,
2746
+ },
2747
+ });
2748
+ });
2749
+ });
2750
+ return simplifyChangedRanges(changes);
2751
+ }
2752
+
2753
+ function getMarksBetween(from, to, doc) {
2754
+ const marks = [];
2755
+ // get all inclusive marks on empty selection
2756
+ if (from === to) {
2757
+ doc
2758
+ .resolve(from)
2759
+ .marks()
2760
+ .forEach(mark => {
2761
+ const $pos = doc.resolve(from);
2762
+ const range = getMarkRange($pos, mark.type);
2763
+ if (!range) {
2764
+ return;
2765
+ }
2766
+ marks.push({
2767
+ mark,
2768
+ ...range,
2769
+ });
2770
+ });
2771
+ }
2772
+ else {
2773
+ doc.nodesBetween(from, to, (node, pos) => {
2774
+ if (!node || (node === null || node === void 0 ? void 0 : node.nodeSize) === undefined) {
2775
+ return;
2776
+ }
2777
+ marks.push(...node.marks.map(mark => ({
2778
+ from: pos,
2779
+ to: pos + node.nodeSize,
2780
+ mark,
2781
+ })));
2782
+ });
2783
+ }
2784
+ return marks;
2785
+ }
2786
+
2787
+ /**
2788
+ * Return attributes of an extension that should be splitted by keepOnSplit flag
2789
+ * @param extensionAttributes Array of extension attributes
2790
+ * @param typeName The type of the extension
2791
+ * @param attributes The attributes of the extension
2792
+ * @returns The splitted attributes
2793
+ */
2794
+ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2795
+ return Object.fromEntries(Object
2796
+ .entries(attributes)
2797
+ .filter(([name]) => {
2798
+ const extensionAttribute = extensionAttributes.find(item => {
2799
+ return item.type === typeName && item.name === name;
2800
+ });
2801
+ if (!extensionAttribute) {
2802
+ return false;
2803
+ }
2804
+ return extensionAttribute.attribute.keepOnSplit;
2805
+ }));
2806
+ }
2807
+
2808
+ function isMarkActive(state, typeOrName, attributes = {}) {
2809
+ const { empty, ranges } = state.selection;
2810
+ const type = typeOrName ? getMarkType(typeOrName, state.schema) : null;
2811
+ if (empty) {
2812
+ return !!(state.storedMarks || state.selection.$from.marks())
2813
+ .filter(mark => {
2814
+ if (!type) {
2815
+ return true;
2816
+ }
2817
+ return type.name === mark.type.name;
2818
+ })
2819
+ .find(mark => objectIncludes(mark.attrs, attributes, { strict: false }));
2820
+ }
2821
+ let selectionRange = 0;
2822
+ const markRanges = [];
2823
+ ranges.forEach(({ $from, $to }) => {
2824
+ const from = $from.pos;
2825
+ const to = $to.pos;
2826
+ state.doc.nodesBetween(from, to, (node, pos) => {
2827
+ if (!node.isText && !node.marks.length) {
2828
+ return;
2829
+ }
2830
+ const relativeFrom = Math.max(from, pos);
2831
+ const relativeTo = Math.min(to, pos + node.nodeSize);
2832
+ const range = relativeTo - relativeFrom;
2833
+ selectionRange += range;
2834
+ markRanges.push(...node.marks.map(mark => ({
2835
+ mark,
2836
+ from: relativeFrom,
2837
+ to: relativeTo,
2838
+ })));
2839
+ });
2840
+ });
2841
+ if (selectionRange === 0) {
2842
+ return false;
2843
+ }
2844
+ // calculate range of matched mark
2845
+ const matchedRange = markRanges
2846
+ .filter(markRange => {
2847
+ if (!type) {
2848
+ return true;
2849
+ }
2850
+ return type.name === markRange.mark.type.name;
2851
+ })
2852
+ .filter(markRange => objectIncludes(markRange.mark.attrs, attributes, { strict: false }))
2853
+ .reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2854
+ // calculate range of marks that excludes the searched mark
2855
+ // for example `code` doesn’t allow any other marks
2856
+ const excludedRange = markRanges
2857
+ .filter(markRange => {
2858
+ if (!type) {
2859
+ return true;
2860
+ }
2861
+ return markRange.mark.type !== type && markRange.mark.type.excludes(type);
2862
+ })
2863
+ .reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2864
+ // we only include the result of `excludedRange`
2865
+ // if there is a match at all
2866
+ const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
2867
+ return range >= selectionRange;
2868
+ }
2869
+
2870
+ function isActive(state, name, attributes = {}) {
2871
+ if (!name) {
2872
+ return isNodeActive(state, null, attributes) || isMarkActive(state, null, attributes);
2873
+ }
2874
+ const schemaType = getSchemaTypeNameByName(name, state.schema);
2875
+ if (schemaType === 'node') {
2876
+ return isNodeActive(state, name, attributes);
2877
+ }
2878
+ if (schemaType === 'mark') {
2879
+ return isMarkActive(state, name, attributes);
2880
+ }
2881
+ return false;
2882
+ }
2883
+
2884
+ function isList(name, extensions) {
2885
+ const { nodeExtensions } = splitExtensions(extensions);
2886
+ const extension = nodeExtensions.find(item => item.name === name);
2887
+ if (!extension) {
2888
+ return false;
2889
+ }
2890
+ const context = {
2891
+ name: extension.name,
2892
+ options: extension.options,
2893
+ storage: extension.storage,
2894
+ };
2895
+ const group = callOrReturn(getExtensionField(extension, 'group', context));
2896
+ if (typeof group !== 'string') {
2897
+ return false;
2898
+ }
2899
+ return group.split(' ').includes('list');
2900
+ }
2901
+
2902
+ /**
2903
+ * Returns true if the given prosemirror node is empty.
2904
+ */
2905
+ function isNodeEmpty(node, { checkChildren = true, ignoreWhitespace = false, } = {}) {
2906
+ var _a;
2907
+ if (ignoreWhitespace) {
2908
+ if (node.type.name === 'hardBreak') {
2909
+ // Hard breaks are considered empty
2910
+ return true;
2911
+ }
2912
+ if (node.isText) {
2913
+ return /^\s*$/m.test((_a = node.text) !== null && _a !== void 0 ? _a : '');
2914
+ }
2915
+ }
2916
+ if (node.isText) {
2917
+ return !node.text;
2918
+ }
2919
+ if (node.isAtom || node.isLeaf) {
2920
+ return false;
2921
+ }
2922
+ if (node.content.childCount === 0) {
2923
+ return true;
2924
+ }
2925
+ if (checkChildren) {
2926
+ let isContentEmpty = true;
2927
+ node.content.forEach(childNode => {
2928
+ if (isContentEmpty === false) {
2929
+ // Exit early for perf
2930
+ return;
2931
+ }
2932
+ if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
2933
+ isContentEmpty = false;
2934
+ }
2935
+ });
2936
+ return isContentEmpty;
2937
+ }
2938
+ return false;
2939
+ }
2940
+
2941
+ function isNodeSelection(value) {
2942
+ return value instanceof NodeSelection;
2943
+ }
2944
+
2945
+ function posToDOMRect(view, from, to) {
2946
+ const minPos = 0;
2947
+ const maxPos = view.state.doc.content.size;
2948
+ const resolvedFrom = minMax(from, minPos, maxPos);
2949
+ const resolvedEnd = minMax(to, minPos, maxPos);
2950
+ const start = view.coordsAtPos(resolvedFrom);
2951
+ const end = view.coordsAtPos(resolvedEnd, -1);
2952
+ const top = Math.min(start.top, end.top);
2953
+ const bottom = Math.max(start.bottom, end.bottom);
2954
+ const left = Math.min(start.left, end.left);
2955
+ const right = Math.max(start.right, end.right);
2956
+ const width = right - left;
2957
+ const height = bottom - top;
2958
+ const x = left;
2959
+ const y = top;
2960
+ const data = {
2961
+ top,
2962
+ bottom,
2963
+ left,
2964
+ right,
2965
+ width,
2966
+ height,
2967
+ x,
2968
+ y,
2969
+ };
2970
+ return {
2971
+ ...data,
2972
+ toJSON: () => data,
2973
+ };
2974
+ }
2975
+
2976
+ function canSetMark(state, tr, newMarkType) {
2977
+ var _a;
2978
+ const { selection } = tr;
2979
+ let cursor = null;
2980
+ if (isTextSelection(selection)) {
2981
+ cursor = selection.$cursor;
2982
+ }
2983
+ if (cursor) {
2984
+ const currentMarks = (_a = state.storedMarks) !== null && _a !== void 0 ? _a : cursor.marks();
2985
+ // There can be no current marks that exclude the new mark
2986
+ return (!!newMarkType.isInSet(currentMarks)
2987
+ || !currentMarks.some(mark => mark.type.excludes(newMarkType)));
2988
+ }
2989
+ const { ranges } = selection;
2990
+ return ranges.some(({ $from, $to }) => {
2991
+ let someNodeSupportsMark = $from.depth === 0
2992
+ ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType)
2993
+ : false;
2994
+ state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
2995
+ // If we already found a mark that we can enable, return false to bypass the remaining search
2996
+ if (someNodeSupportsMark) {
2997
+ return false;
2998
+ }
2999
+ if (node.isInline) {
3000
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
3001
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks)
3002
+ || !node.marks.some(otherMark => otherMark.type.excludes(newMarkType));
3003
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
3004
+ }
3005
+ return !someNodeSupportsMark;
3006
+ });
3007
+ return someNodeSupportsMark;
3008
+ });
3009
+ }
3010
+ const setMark = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
3011
+ const { selection } = tr;
3012
+ const { empty, ranges } = selection;
3013
+ const type = getMarkType(typeOrName, state.schema);
3014
+ if (dispatch) {
3015
+ if (empty) {
3016
+ const oldAttributes = getMarkAttributes(state, type);
3017
+ tr.addStoredMark(type.create({
3018
+ ...oldAttributes,
3019
+ ...attributes,
3020
+ }));
3021
+ }
3022
+ else {
3023
+ ranges.forEach(range => {
3024
+ const from = range.$from.pos;
3025
+ const to = range.$to.pos;
3026
+ state.doc.nodesBetween(from, to, (node, pos) => {
3027
+ const trimmedFrom = Math.max(pos, from);
3028
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
3029
+ const someHasMark = node.marks.find(mark => mark.type === type);
3030
+ // if there is already a mark of this type
3031
+ // we know that we have to merge its attributes
3032
+ // otherwise we add a fresh new mark
3033
+ if (someHasMark) {
3034
+ node.marks.forEach(mark => {
3035
+ if (type === mark.type) {
3036
+ tr.addMark(trimmedFrom, trimmedTo, type.create({
3037
+ ...mark.attrs,
3038
+ ...attributes,
3039
+ }));
3040
+ }
3041
+ });
3042
+ }
3043
+ else {
3044
+ tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
3045
+ }
3046
+ });
3047
+ });
3048
+ }
3049
+ }
3050
+ return canSetMark(state, tr, type);
3051
+ };
3052
+
3053
+ const setMeta = (key, value) => ({ tr }) => {
3054
+ tr.setMeta(key, value);
3055
+ return true;
3056
+ };
3057
+
3058
+ const setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
3059
+ const type = getNodeType(typeOrName, state.schema);
3060
+ let attributesToCopy;
3061
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3062
+ // only copy attributes if the selection is pointing to a node of the same type
3063
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3064
+ }
3065
+ // TODO: use a fallback like insertContent?
3066
+ if (!type.isTextblock) {
3067
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
3068
+ return false;
3069
+ }
3070
+ return (chain()
3071
+ // try to convert node to default node if needed
3072
+ .command(({ commands }) => {
3073
+ const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state);
3074
+ if (canSetBlock) {
3075
+ return true;
3076
+ }
3077
+ return commands.clearNodes();
3078
+ })
3079
+ .command(({ state: updatedState }) => {
3080
+ return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch);
3081
+ })
3082
+ .run());
3083
+ };
3084
+
3085
+ const setNodeSelection = position => ({ tr, dispatch }) => {
3086
+ if (dispatch) {
3087
+ const { doc } = tr;
3088
+ const from = minMax(position, 0, doc.content.size);
3089
+ const selection = NodeSelection.create(doc, from);
3090
+ tr.setSelection(selection);
3091
+ }
3092
+ return true;
3093
+ };
3094
+
3095
+ const setTextSelection = position => ({ tr, dispatch }) => {
3096
+ if (dispatch) {
3097
+ const { doc } = tr;
3098
+ const { from, to } = typeof position === 'number' ? { from: position, to: position } : position;
3099
+ const minPos = TextSelection.atStart(doc).from;
3100
+ const maxPos = TextSelection.atEnd(doc).to;
3101
+ const resolvedFrom = minMax(from, minPos, maxPos);
3102
+ const resolvedEnd = minMax(to, minPos, maxPos);
3103
+ const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd);
3104
+ tr.setSelection(selection);
3105
+ }
3106
+ return true;
3107
+ };
3108
+
3109
+ const sinkListItem = typeOrName => ({ state, dispatch }) => {
3110
+ const type = getNodeType(typeOrName, state.schema);
3111
+ return sinkListItem$1(type)(state, dispatch);
3112
+ };
3113
+
3114
+ function ensureMarks(state, splittableMarks) {
3115
+ const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
3116
+ if (marks) {
3117
+ const filteredMarks = marks.filter(mark => splittableMarks === null || splittableMarks === void 0 ? void 0 : splittableMarks.includes(mark.type.name));
3118
+ state.tr.ensureMarks(filteredMarks);
3119
+ }
3120
+ }
3121
+ const splitBlock = ({ keepMarks = true } = {}) => ({ tr, state, dispatch, editor, }) => {
3122
+ const { selection, doc } = tr;
3123
+ const { $from, $to } = selection;
3124
+ const extensionAttributes = editor.extensionManager.attributes;
3125
+ const newAttributes = getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs);
3126
+ if (selection instanceof NodeSelection && selection.node.isBlock) {
3127
+ if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
3128
+ return false;
3129
+ }
3130
+ if (dispatch) {
3131
+ if (keepMarks) {
3132
+ ensureMarks(state, editor.extensionManager.splittableMarks);
3133
+ }
3134
+ tr.split($from.pos).scrollIntoView();
3135
+ }
3136
+ return true;
3137
+ }
3138
+ if (!$from.parent.isBlock) {
3139
+ return false;
3140
+ }
3141
+ const atEnd = $to.parentOffset === $to.parent.content.size;
3142
+ const deflt = $from.depth === 0
3143
+ ? undefined
3144
+ : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
3145
+ let types = atEnd && deflt
3146
+ ? [
3147
+ {
3148
+ type: deflt,
3149
+ attrs: newAttributes,
3150
+ },
3151
+ ]
3152
+ : undefined;
3153
+ let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
3154
+ if (!types
3155
+ && !can
3156
+ && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
3157
+ can = true;
3158
+ types = deflt
3159
+ ? [
3160
+ {
3161
+ type: deflt,
3162
+ attrs: newAttributes,
3163
+ },
3164
+ ]
3165
+ : undefined;
3166
+ }
3167
+ if (dispatch) {
3168
+ if (can) {
3169
+ if (selection instanceof TextSelection) {
3170
+ tr.deleteSelection();
3171
+ }
3172
+ tr.split(tr.mapping.map($from.pos), 1, types);
3173
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
3174
+ const first = tr.mapping.map($from.before());
3175
+ const $first = tr.doc.resolve(first);
3176
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
3177
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
3178
+ }
3179
+ }
3180
+ }
3181
+ if (keepMarks) {
3182
+ ensureMarks(state, editor.extensionManager.splittableMarks);
3183
+ }
3184
+ tr.scrollIntoView();
3185
+ }
3186
+ return can;
3187
+ };
3188
+
3189
+ const splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state, dispatch, editor, }) => {
3190
+ var _a;
3191
+ const type = getNodeType(typeOrName, state.schema);
3192
+ const { $from, $to } = state.selection;
3193
+ // @ts-ignore
3194
+ // eslint-disable-next-line
3195
+ const node = state.selection.node;
3196
+ if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) {
3197
+ return false;
3198
+ }
3199
+ const grandParent = $from.node(-1);
3200
+ if (grandParent.type !== type) {
3201
+ return false;
3202
+ }
3203
+ const extensionAttributes = editor.extensionManager.attributes;
3204
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
3205
+ // In an empty block. If this is a nested list, the wrapping
3206
+ // list item should be split. Otherwise, bail out and let next
3207
+ // command handle lifting.
3208
+ if ($from.depth === 2
3209
+ || $from.node(-3).type !== type
3210
+ || $from.index(-2) !== $from.node(-2).childCount - 1) {
3211
+ return false;
3212
+ }
3213
+ if (dispatch) {
3214
+ let wrap = Fragment.empty;
3215
+ // eslint-disable-next-line
3216
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
3217
+ // Build a fragment containing empty versions of the structure
3218
+ // from the outer list item to the parent node of the cursor
3219
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
3220
+ wrap = Fragment.from($from.node(d).copy(wrap));
3221
+ }
3222
+ // eslint-disable-next-line
3223
+ const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
3224
+ // Add a second list item with an empty default start node
3225
+ const newNextTypeAttributes = {
3226
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
3227
+ ...overrideAttrs,
3228
+ };
3229
+ const nextType = ((_a = type.contentMatch.defaultType) === null || _a === void 0 ? void 0 : _a.createAndFill(newNextTypeAttributes)) || undefined;
3230
+ wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType) || undefined));
3231
+ const start = $from.before($from.depth - (depthBefore - 1));
3232
+ tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
3233
+ let sel = -1;
3234
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
3235
+ if (sel > -1) {
3236
+ return false;
3237
+ }
3238
+ if (n.isTextblock && n.content.size === 0) {
3239
+ sel = pos + 1;
3240
+ }
3241
+ });
3242
+ if (sel > -1) {
3243
+ tr.setSelection(TextSelection.near(tr.doc.resolve(sel)));
3244
+ }
3245
+ tr.scrollIntoView();
3246
+ }
3247
+ return true;
3248
+ }
3249
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
3250
+ const newTypeAttributes = {
3251
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
3252
+ ...overrideAttrs,
3253
+ };
3254
+ const newNextTypeAttributes = {
3255
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
3256
+ ...overrideAttrs,
3257
+ };
3258
+ tr.delete($from.pos, $to.pos);
3259
+ const types = nextType
3260
+ ? [
3261
+ { type, attrs: newTypeAttributes },
3262
+ { type: nextType, attrs: newNextTypeAttributes },
3263
+ ]
3264
+ : [{ type, attrs: newTypeAttributes }];
3265
+ if (!canSplit(tr.doc, $from.pos, 2)) {
3266
+ return false;
3267
+ }
3268
+ if (dispatch) {
3269
+ const { selection, storedMarks } = state;
3270
+ const { splittableMarks } = editor.extensionManager;
3271
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks());
3272
+ tr.split($from.pos, 2, types).scrollIntoView();
3273
+ if (!marks || !dispatch) {
3274
+ return true;
3275
+ }
3276
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name));
3277
+ tr.ensureMarks(filteredMarks);
3278
+ }
3279
+ return true;
3280
+ };
3281
+
3282
+ const joinListBackwards = (tr, listType) => {
3283
+ const list = findParentNode(node => node.type === listType)(tr.selection);
3284
+ if (!list) {
3285
+ return true;
3286
+ }
3287
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
3288
+ if (before === undefined) {
3289
+ return true;
3290
+ }
3291
+ const nodeBefore = tr.doc.nodeAt(before);
3292
+ const canJoinBackwards = list.node.type === (nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.type) && canJoin(tr.doc, list.pos);
3293
+ if (!canJoinBackwards) {
3294
+ return true;
3295
+ }
3296
+ tr.join(list.pos);
3297
+ return true;
3298
+ };
3299
+ const joinListForwards = (tr, listType) => {
3300
+ const list = findParentNode(node => node.type === listType)(tr.selection);
3301
+ if (!list) {
3302
+ return true;
3303
+ }
3304
+ const after = tr.doc.resolve(list.start).after(list.depth);
3305
+ if (after === undefined) {
3306
+ return true;
3307
+ }
3308
+ const nodeAfter = tr.doc.nodeAt(after);
3309
+ const canJoinForwards = list.node.type === (nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.type) && canJoin(tr.doc, after);
3310
+ if (!canJoinForwards) {
3311
+ return true;
3312
+ }
3313
+ tr.join(after);
3314
+ return true;
3315
+ };
3316
+ const toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state, dispatch, chain, commands, can, }) => {
3317
+ const { extensions, splittableMarks } = editor.extensionManager;
3318
+ const listType = getNodeType(listTypeOrName, state.schema);
3319
+ const itemType = getNodeType(itemTypeOrName, state.schema);
3320
+ const { selection, storedMarks } = state;
3321
+ const { $from, $to } = selection;
3322
+ const range = $from.blockRange($to);
3323
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks());
3324
+ if (!range) {
3325
+ return false;
3326
+ }
3327
+ const parentList = findParentNode(node => isList(node.type.name, extensions))(selection);
3328
+ if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
3329
+ // remove list
3330
+ if (parentList.node.type === listType) {
3331
+ return commands.liftListItem(itemType);
3332
+ }
3333
+ // change list type
3334
+ if (isList(parentList.node.type.name, extensions)
3335
+ && listType.validContent(parentList.node.content)
3336
+ && dispatch) {
3337
+ return chain()
3338
+ .command(() => {
3339
+ tr.setNodeMarkup(parentList.pos, listType);
3340
+ return true;
3341
+ })
3342
+ .command(() => joinListBackwards(tr, listType))
3343
+ .command(() => joinListForwards(tr, listType))
3344
+ .run();
3345
+ }
3346
+ }
3347
+ if (!keepMarks || !marks || !dispatch) {
3348
+ return chain()
3349
+ // try to convert node to default node if needed
3350
+ .command(() => {
3351
+ const canWrapInList = can().wrapInList(listType, attributes);
3352
+ if (canWrapInList) {
3353
+ return true;
3354
+ }
3355
+ return commands.clearNodes();
3356
+ })
3357
+ .wrapInList(listType, attributes)
3358
+ .command(() => joinListBackwards(tr, listType))
3359
+ .command(() => joinListForwards(tr, listType))
3360
+ .run();
3361
+ }
3362
+ return (chain()
3363
+ // try to convert node to default node if needed
3364
+ .command(() => {
3365
+ const canWrapInList = can().wrapInList(listType, attributes);
3366
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name));
3367
+ tr.ensureMarks(filteredMarks);
3368
+ if (canWrapInList) {
3369
+ return true;
3370
+ }
3371
+ return commands.clearNodes();
3372
+ })
3373
+ .wrapInList(listType, attributes)
3374
+ .command(() => joinListBackwards(tr, listType))
3375
+ .command(() => joinListForwards(tr, listType))
3376
+ .run());
3377
+ };
3378
+
3379
+ const toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
3380
+ const { extendEmptyMarkRange = false } = options;
3381
+ const type = getMarkType(typeOrName, state.schema);
3382
+ const isActive = isMarkActive(state, type, attributes);
3383
+ if (isActive) {
3384
+ return commands.unsetMark(type, { extendEmptyMarkRange });
3385
+ }
3386
+ return commands.setMark(type, attributes);
3387
+ };
3388
+
3389
+ const toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {
3390
+ const type = getNodeType(typeOrName, state.schema);
3391
+ const toggleType = getNodeType(toggleTypeOrName, state.schema);
3392
+ const isActive = isNodeActive(state, type, attributes);
3393
+ let attributesToCopy;
3394
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3395
+ // only copy attributes if the selection is pointing to a node of the same type
3396
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3397
+ }
3398
+ if (isActive) {
3399
+ return commands.setNode(toggleType, attributesToCopy);
3400
+ }
3401
+ // If the node is not active, we want to set the new node type with the given attributes
3402
+ // Copying over the attributes from the current node if the selection is pointing to a node of the same type
3403
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
3404
+ };
3405
+
3406
+ const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
3407
+ const type = getNodeType(typeOrName, state.schema);
3408
+ const isActive = isNodeActive(state, type, attributes);
3409
+ if (isActive) {
3410
+ return commands.lift(type);
3411
+ }
3412
+ return commands.wrapIn(type, attributes);
3413
+ };
3414
+
3415
+ const undoInputRule = () => ({ state, dispatch }) => {
3416
+ const plugins = state.plugins;
3417
+ for (let i = 0; i < plugins.length; i += 1) {
3418
+ const plugin = plugins[i];
3419
+ let undoable;
3420
+ // @ts-ignore
3421
+ // eslint-disable-next-line
3422
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
3423
+ if (dispatch) {
3424
+ const tr = state.tr;
3425
+ const toUndo = undoable.transform;
3426
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
3427
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
3428
+ }
3429
+ if (undoable.text) {
3430
+ const marks = tr.doc.resolve(undoable.from).marks();
3431
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
3432
+ }
3433
+ else {
3434
+ tr.delete(undoable.from, undoable.to);
3435
+ }
3436
+ }
3437
+ return true;
3438
+ }
3439
+ }
3440
+ return false;
3441
+ };
3442
+
3443
+ const unsetAllMarks = () => ({ tr, dispatch }) => {
3444
+ const { selection } = tr;
3445
+ const { empty, ranges } = selection;
3446
+ if (empty) {
3447
+ return true;
3448
+ }
3449
+ if (dispatch) {
3450
+ ranges.forEach(range => {
3451
+ tr.removeMark(range.$from.pos, range.$to.pos);
3452
+ });
3453
+ }
3454
+ return true;
3455
+ };
3456
+
3457
+ const unsetMark = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
3458
+ var _a;
3459
+ const { extendEmptyMarkRange = false } = options;
3460
+ const { selection } = tr;
3461
+ const type = getMarkType(typeOrName, state.schema);
3462
+ const { $from, empty, ranges } = selection;
3463
+ if (!dispatch) {
3464
+ return true;
3465
+ }
3466
+ if (empty && extendEmptyMarkRange) {
3467
+ let { from, to } = selection;
3468
+ const attrs = (_a = $from.marks().find(mark => mark.type === type)) === null || _a === void 0 ? void 0 : _a.attrs;
3469
+ const range = getMarkRange($from, type, attrs);
3470
+ if (range) {
3471
+ from = range.from;
3472
+ to = range.to;
3473
+ }
3474
+ tr.removeMark(from, to, type);
3475
+ }
3476
+ else {
3477
+ ranges.forEach(range => {
3478
+ tr.removeMark(range.$from.pos, range.$to.pos, type);
3479
+ });
3480
+ }
3481
+ tr.removeStoredMark(type);
3482
+ return true;
3483
+ };
3484
+
3485
+ const updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
3486
+ let nodeType = null;
3487
+ let markType = null;
3488
+ const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string' ? typeOrName : typeOrName.name, state.schema);
3489
+ if (!schemaType) {
3490
+ return false;
3491
+ }
3492
+ if (schemaType === 'node') {
3493
+ nodeType = getNodeType(typeOrName, state.schema);
3494
+ }
3495
+ if (schemaType === 'mark') {
3496
+ markType = getMarkType(typeOrName, state.schema);
3497
+ }
3498
+ if (dispatch) {
3499
+ tr.selection.ranges.forEach((range) => {
3500
+ const from = range.$from.pos;
3501
+ const to = range.$to.pos;
3502
+ let lastPos;
3503
+ let lastNode;
3504
+ let trimmedFrom;
3505
+ let trimmedTo;
3506
+ if (tr.selection.empty) {
3507
+ state.doc.nodesBetween(from, to, (node, pos) => {
3508
+ if (nodeType && nodeType === node.type) {
3509
+ trimmedFrom = Math.max(pos, from);
3510
+ trimmedTo = Math.min(pos + node.nodeSize, to);
3511
+ lastPos = pos;
3512
+ lastNode = node;
3513
+ }
3514
+ });
3515
+ }
3516
+ else {
3517
+ state.doc.nodesBetween(from, to, (node, pos) => {
3518
+ if (pos < from && nodeType && nodeType === node.type) {
3519
+ trimmedFrom = Math.max(pos, from);
3520
+ trimmedTo = Math.min(pos + node.nodeSize, to);
3521
+ lastPos = pos;
3522
+ lastNode = node;
3523
+ }
3524
+ if (pos >= from && pos <= to) {
3525
+ if (nodeType && nodeType === node.type) {
3526
+ tr.setNodeMarkup(pos, undefined, {
3527
+ ...node.attrs,
3528
+ ...attributes,
3529
+ });
3530
+ }
3531
+ if (markType && node.marks.length) {
3532
+ node.marks.forEach((mark) => {
3533
+ if (markType === mark.type) {
3534
+ const trimmedFrom2 = Math.max(pos, from);
3535
+ const trimmedTo2 = Math.min(pos + node.nodeSize, to);
3536
+ tr.addMark(trimmedFrom2, trimmedTo2, markType.create({
3537
+ ...mark.attrs,
3538
+ ...attributes,
3539
+ }));
3540
+ }
3541
+ });
3542
+ }
3543
+ }
3544
+ });
3545
+ }
3546
+ if (lastNode) {
3547
+ if (lastPos !== undefined) {
3548
+ tr.setNodeMarkup(lastPos, undefined, {
3549
+ ...lastNode.attrs,
3550
+ ...attributes,
3551
+ });
3552
+ }
3553
+ if (markType && lastNode.marks.length) {
3554
+ lastNode.marks.forEach((mark) => {
3555
+ if (markType === mark.type) {
3556
+ tr.addMark(trimmedFrom, trimmedTo, markType.create({
3557
+ ...mark.attrs,
3558
+ ...attributes,
3559
+ }));
3560
+ }
3561
+ });
3562
+ }
3563
+ }
3564
+ });
3565
+ }
3566
+ return true;
3567
+ };
3568
+
3569
+ const wrapIn = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3570
+ const type = getNodeType(typeOrName, state.schema);
3571
+ return wrapIn$1(type, attributes)(state, dispatch);
3572
+ };
3573
+
3574
+ const wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3575
+ const type = getNodeType(typeOrName, state.schema);
3576
+ return wrapInList$1(type, attributes)(state, dispatch);
3577
+ };
3578
+
3579
+ var commands = /*#__PURE__*/Object.freeze({
3580
+ __proto__: null,
3581
+ blur: blur,
3582
+ clearContent: clearContent,
3583
+ clearNodes: clearNodes,
3584
+ command: command,
3585
+ createParagraphNear: createParagraphNear,
3586
+ cut: cut,
3587
+ deleteCurrentNode: deleteCurrentNode,
3588
+ deleteNode: deleteNode,
3589
+ deleteRange: deleteRange,
3590
+ deleteSelection: deleteSelection,
3591
+ enter: enter,
3592
+ exitCode: exitCode,
3593
+ extendMarkRange: extendMarkRange,
3594
+ first: first,
3595
+ focus: focus,
3596
+ forEach: forEach,
3597
+ insertContent: insertContent,
3598
+ insertContentAt: insertContentAt,
3599
+ joinBackward: joinBackward,
3600
+ joinDown: joinDown,
3601
+ joinForward: joinForward,
3602
+ joinItemBackward: joinItemBackward,
3603
+ joinItemForward: joinItemForward,
3604
+ joinTextblockBackward: joinTextblockBackward,
3605
+ joinTextblockForward: joinTextblockForward,
3606
+ joinUp: joinUp,
3607
+ keyboardShortcut: keyboardShortcut,
3608
+ lift: lift,
3609
+ liftEmptyBlock: liftEmptyBlock,
3610
+ liftListItem: liftListItem,
3611
+ newlineInCode: newlineInCode,
3612
+ resetAttributes: resetAttributes,
3613
+ scrollIntoView: scrollIntoView,
3614
+ selectAll: selectAll,
3615
+ selectNodeBackward: selectNodeBackward,
3616
+ selectNodeForward: selectNodeForward,
3617
+ selectParentNode: selectParentNode,
3618
+ selectTextblockEnd: selectTextblockEnd,
3619
+ selectTextblockStart: selectTextblockStart,
3620
+ setContent: setContent,
3621
+ setMark: setMark,
3622
+ setMeta: setMeta,
3623
+ setNode: setNode,
3624
+ setNodeSelection: setNodeSelection,
3625
+ setTextSelection: setTextSelection,
3626
+ sinkListItem: sinkListItem,
3627
+ splitBlock: splitBlock,
3628
+ splitListItem: splitListItem,
3629
+ toggleList: toggleList,
3630
+ toggleMark: toggleMark,
3631
+ toggleNode: toggleNode,
3632
+ toggleWrap: toggleWrap,
3633
+ undoInputRule: undoInputRule,
3634
+ unsetAllMarks: unsetAllMarks,
3635
+ unsetMark: unsetMark,
3636
+ updateAttributes: updateAttributes,
3637
+ wrapIn: wrapIn,
3638
+ wrapInList: wrapInList
3639
+ });
3640
+
3641
+ const Commands = Extension.create({
3642
+ name: 'commands',
3643
+ addCommands() {
3644
+ return {
3645
+ ...commands,
3646
+ };
3647
+ },
3648
+ });
3649
+
3650
+ const Drop = Extension.create({
3651
+ name: 'drop',
3652
+ addProseMirrorPlugins() {
3653
+ return [
3654
+ new Plugin({
3655
+ key: new PluginKey('tiptapDrop'),
3656
+ props: {
3657
+ handleDrop: (_, e, slice, moved) => {
3658
+ this.editor.emit('drop', {
3659
+ editor: this.editor,
3660
+ event: e,
3661
+ slice,
3662
+ moved,
3663
+ });
3664
+ },
3665
+ },
3666
+ }),
3667
+ ];
3668
+ },
3669
+ });
3670
+
3671
+ const Editable = Extension.create({
3672
+ name: 'editable',
3673
+ addProseMirrorPlugins() {
3674
+ return [
3675
+ new Plugin({
3676
+ key: new PluginKey('editable'),
3677
+ props: {
3678
+ editable: () => this.editor.options.editable,
3679
+ },
3680
+ }),
3681
+ ];
3682
+ },
3683
+ });
3684
+
3685
+ const focusEventsPluginKey = new PluginKey('focusEvents');
3686
+ const FocusEvents = Extension.create({
3687
+ name: 'focusEvents',
3688
+ addProseMirrorPlugins() {
3689
+ const { editor } = this;
3690
+ return [
3691
+ new Plugin({
3692
+ key: focusEventsPluginKey,
3693
+ props: {
3694
+ handleDOMEvents: {
3695
+ focus: (view, event) => {
3696
+ editor.isFocused = true;
3697
+ const transaction = editor.state.tr
3698
+ .setMeta('focus', { event })
3699
+ .setMeta('addToHistory', false);
3700
+ view.dispatch(transaction);
3701
+ return false;
3702
+ },
3703
+ blur: (view, event) => {
3704
+ editor.isFocused = false;
3705
+ const transaction = editor.state.tr
3706
+ .setMeta('blur', { event })
3707
+ .setMeta('addToHistory', false);
3708
+ view.dispatch(transaction);
3709
+ return false;
3710
+ },
3711
+ },
3712
+ },
3713
+ }),
3714
+ ];
3715
+ },
3716
+ });
3717
+
3718
+ const Keymap = Extension.create({
3719
+ name: 'keymap',
3720
+ addKeyboardShortcuts() {
3721
+ const handleBackspace = () => this.editor.commands.first(({ commands }) => [
3722
+ () => commands.undoInputRule(),
3723
+ // maybe convert first text block node to default node
3724
+ () => commands.command(({ tr }) => {
3725
+ const { selection, doc } = tr;
3726
+ const { empty, $anchor } = selection;
3727
+ const { pos, parent } = $anchor;
3728
+ const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
3729
+ const parentIsIsolating = $parentPos.parent.type.spec.isolating;
3730
+ const parentPos = $anchor.pos - $anchor.parentOffset;
3731
+ const isAtStart = (parentIsIsolating && $parentPos.parent.childCount === 1)
3732
+ ? parentPos === $anchor.pos
3733
+ : Selection.atStart(doc).from === pos;
3734
+ if (!empty
3735
+ || !parent.type.isTextblock
3736
+ || parent.textContent.length
3737
+ || !isAtStart
3738
+ || (isAtStart && $anchor.parent.type.name === 'paragraph') // prevent clearNodes when no nodes to clear, otherwise history stack is appended
3739
+ ) {
3740
+ return false;
3741
+ }
3742
+ return commands.clearNodes();
3743
+ }),
3744
+ () => commands.deleteSelection(),
3745
+ () => commands.joinBackward(),
3746
+ () => commands.selectNodeBackward(),
3747
+ ]);
3748
+ const handleDelete = () => this.editor.commands.first(({ commands }) => [
3749
+ () => commands.deleteSelection(),
3750
+ () => commands.deleteCurrentNode(),
3751
+ () => commands.joinForward(),
3752
+ () => commands.selectNodeForward(),
3753
+ ]);
3754
+ const handleEnter = () => this.editor.commands.first(({ commands }) => [
3755
+ () => commands.newlineInCode(),
3756
+ () => commands.createParagraphNear(),
3757
+ () => commands.liftEmptyBlock(),
3758
+ () => commands.splitBlock(),
3759
+ ]);
3760
+ const baseKeymap = {
3761
+ Enter: handleEnter,
3762
+ 'Mod-Enter': () => this.editor.commands.exitCode(),
3763
+ Backspace: handleBackspace,
3764
+ 'Mod-Backspace': handleBackspace,
3765
+ 'Shift-Backspace': handleBackspace,
3766
+ Delete: handleDelete,
3767
+ 'Mod-Delete': handleDelete,
3768
+ 'Mod-a': () => this.editor.commands.selectAll(),
3769
+ };
3770
+ const pcKeymap = {
3771
+ ...baseKeymap,
3772
+ };
3773
+ const macKeymap = {
3774
+ ...baseKeymap,
3775
+ 'Ctrl-h': handleBackspace,
3776
+ 'Alt-Backspace': handleBackspace,
3777
+ 'Ctrl-d': handleDelete,
3778
+ 'Ctrl-Alt-Backspace': handleDelete,
3779
+ 'Alt-Delete': handleDelete,
3780
+ 'Alt-d': handleDelete,
3781
+ 'Ctrl-a': () => this.editor.commands.selectTextblockStart(),
3782
+ 'Ctrl-e': () => this.editor.commands.selectTextblockEnd(),
3783
+ };
3784
+ if (isiOS() || isMacOS()) {
3785
+ return macKeymap;
3786
+ }
3787
+ return pcKeymap;
3788
+ },
3789
+ addProseMirrorPlugins() {
3790
+ return [
3791
+ // With this plugin we check if the whole document was selected and deleted.
3792
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
3793
+ // to a paragraph if necessary.
3794
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
3795
+ // with many other commands.
3796
+ new Plugin({
3797
+ key: new PluginKey('clearDocument'),
3798
+ appendTransaction: (transactions, oldState, newState) => {
3799
+ if (transactions.some(tr => tr.getMeta('composition'))) {
3800
+ return;
3801
+ }
3802
+ const docChanges = transactions.some(transaction => transaction.docChanged)
3803
+ && !oldState.doc.eq(newState.doc);
3804
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3805
+ if (!docChanges || ignoreTr) {
3806
+ return;
3807
+ }
3808
+ const { empty, from, to } = oldState.selection;
3809
+ const allFrom = Selection.atStart(oldState.doc).from;
3810
+ const allEnd = Selection.atEnd(oldState.doc).to;
3811
+ const allWasSelected = from === allFrom && to === allEnd;
3812
+ if (empty || !allWasSelected) {
3813
+ return;
3814
+ }
3815
+ const isEmpty = isNodeEmpty(newState.doc);
3816
+ if (!isEmpty) {
3817
+ return;
3818
+ }
3819
+ const tr = newState.tr;
3820
+ const state = createChainableState({
3821
+ state: newState,
3822
+ transaction: tr,
3823
+ });
3824
+ const { commands } = new CommandManager({
3825
+ editor: this.editor,
3826
+ state,
3827
+ });
3828
+ commands.clearNodes();
3829
+ if (!tr.steps.length) {
3830
+ return;
3831
+ }
3832
+ return tr;
3833
+ },
3834
+ }),
3835
+ ];
3836
+ },
3837
+ });
3838
+
3839
+ const Paste = Extension.create({
3840
+ name: 'paste',
3841
+ addProseMirrorPlugins() {
3842
+ return [
3843
+ new Plugin({
3844
+ key: new PluginKey('tiptapPaste'),
3845
+ props: {
3846
+ handlePaste: (_view, e, slice) => {
3847
+ this.editor.emit('paste', {
3848
+ editor: this.editor,
3849
+ event: e,
3850
+ slice,
3851
+ });
3852
+ },
3853
+ },
3854
+ }),
3855
+ ];
3856
+ },
3857
+ });
3858
+
3859
+ const Tabindex = Extension.create({
3860
+ name: 'tabindex',
3861
+ addProseMirrorPlugins() {
3862
+ return [
3863
+ new Plugin({
3864
+ key: new PluginKey('tabindex'),
3865
+ props: {
3866
+ attributes: () => (this.editor.isEditable ? { tabindex: '0' } : {}),
3867
+ },
3868
+ }),
3869
+ ];
3870
+ },
3871
+ });
3872
+
3873
+ var index = /*#__PURE__*/Object.freeze({
3874
+ __proto__: null,
3875
+ ClipboardTextSerializer: ClipboardTextSerializer,
3876
+ Commands: Commands,
3877
+ Drop: Drop,
3878
+ Editable: Editable,
3879
+ FocusEvents: FocusEvents,
3880
+ Keymap: Keymap,
3881
+ Paste: Paste,
3882
+ Tabindex: Tabindex,
3883
+ focusEventsPluginKey: focusEventsPluginKey
3884
+ });
3885
+
3886
+ class NodePos {
3887
+ get name() {
3888
+ return this.node.type.name;
3889
+ }
3890
+ constructor(pos, editor, isBlock = false, node = null) {
3891
+ this.currentNode = null;
3892
+ this.actualDepth = null;
3893
+ this.isBlock = isBlock;
3894
+ this.resolvedPos = pos;
3895
+ this.editor = editor;
3896
+ this.currentNode = node;
3897
+ }
3898
+ get node() {
3899
+ return this.currentNode || this.resolvedPos.node();
3900
+ }
3901
+ get element() {
3902
+ return this.editor.view.domAtPos(this.pos).node;
3903
+ }
3904
+ get depth() {
3905
+ var _a;
3906
+ return (_a = this.actualDepth) !== null && _a !== void 0 ? _a : this.resolvedPos.depth;
3907
+ }
3908
+ get pos() {
3909
+ return this.resolvedPos.pos;
3910
+ }
3911
+ get content() {
3912
+ return this.node.content;
3913
+ }
3914
+ set content(content) {
3915
+ let from = this.from;
3916
+ let to = this.to;
3917
+ if (this.isBlock) {
3918
+ if (this.content.size === 0) {
3919
+ console.error(`You can’t set content on a block node. Tried to set content on ${this.name} at ${this.pos}`);
3920
+ return;
3921
+ }
3922
+ from = this.from + 1;
3923
+ to = this.to - 1;
3924
+ }
3925
+ this.editor.commands.insertContentAt({ from, to }, content);
3926
+ }
3927
+ get attributes() {
3928
+ return this.node.attrs;
3929
+ }
3930
+ get textContent() {
3931
+ return this.node.textContent;
3932
+ }
3933
+ get size() {
3934
+ return this.node.nodeSize;
3935
+ }
3936
+ get from() {
3937
+ if (this.isBlock) {
3938
+ return this.pos;
3939
+ }
3940
+ return this.resolvedPos.start(this.resolvedPos.depth);
3941
+ }
3942
+ get range() {
3943
+ return {
3944
+ from: this.from,
3945
+ to: this.to,
3946
+ };
3947
+ }
3948
+ get to() {
3949
+ if (this.isBlock) {
3950
+ return this.pos + this.size;
3951
+ }
3952
+ return this.resolvedPos.end(this.resolvedPos.depth) + (this.node.isText ? 0 : 1);
3953
+ }
3954
+ get parent() {
3955
+ if (this.depth === 0) {
3956
+ return null;
3957
+ }
3958
+ const parentPos = this.resolvedPos.start(this.resolvedPos.depth - 1);
3959
+ const $pos = this.resolvedPos.doc.resolve(parentPos);
3960
+ return new NodePos($pos, this.editor);
3961
+ }
3962
+ get before() {
3963
+ let $pos = this.resolvedPos.doc.resolve(this.from - (this.isBlock ? 1 : 2));
3964
+ if ($pos.depth !== this.depth) {
3965
+ $pos = this.resolvedPos.doc.resolve(this.from - 3);
3966
+ }
3967
+ return new NodePos($pos, this.editor);
3968
+ }
3969
+ get after() {
3970
+ let $pos = this.resolvedPos.doc.resolve(this.to + (this.isBlock ? 2 : 1));
3971
+ if ($pos.depth !== this.depth) {
3972
+ $pos = this.resolvedPos.doc.resolve(this.to + 3);
3973
+ }
3974
+ return new NodePos($pos, this.editor);
3975
+ }
3976
+ get children() {
3977
+ const children = [];
3978
+ this.node.content.forEach((node, offset) => {
3979
+ const isBlock = node.isBlock && !node.isTextblock;
3980
+ const isNonTextAtom = node.isAtom && !node.isText;
3981
+ const targetPos = this.pos + offset + (isNonTextAtom ? 0 : 1);
3982
+ // Check if targetPos is within valid document range
3983
+ if (targetPos < 0 || targetPos > this.resolvedPos.doc.nodeSize - 2) {
3984
+ return;
3985
+ }
3986
+ const $pos = this.resolvedPos.doc.resolve(targetPos);
3987
+ if (!isBlock && $pos.depth <= this.depth) {
3988
+ return;
3989
+ }
3990
+ const childNodePos = new NodePos($pos, this.editor, isBlock, isBlock ? node : null);
3991
+ if (isBlock) {
3992
+ childNodePos.actualDepth = this.depth + 1;
3993
+ }
3994
+ children.push(new NodePos($pos, this.editor, isBlock, isBlock ? node : null));
3995
+ });
3996
+ return children;
3997
+ }
3998
+ get firstChild() {
3999
+ return this.children[0] || null;
4000
+ }
4001
+ get lastChild() {
4002
+ const children = this.children;
4003
+ return children[children.length - 1] || null;
4004
+ }
4005
+ closest(selector, attributes = {}) {
4006
+ let node = null;
4007
+ let currentNode = this.parent;
4008
+ while (currentNode && !node) {
4009
+ if (currentNode.node.type.name === selector) {
4010
+ if (Object.keys(attributes).length > 0) ;
4011
+ else {
4012
+ node = currentNode;
4013
+ }
4014
+ }
4015
+ currentNode = currentNode.parent;
4016
+ }
4017
+ return node;
4018
+ }
4019
+ querySelector(selector, attributes = {}) {
4020
+ return this.querySelectorAll(selector, attributes, true)[0] || null;
4021
+ }
4022
+ querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
4023
+ let nodes = [];
4024
+ if (!this.children || this.children.length === 0) {
4025
+ return nodes;
4026
+ }
4027
+ const attrKeys = Object.keys(attributes);
4028
+ /**
4029
+ * Finds all children recursively that match the selector and attributes
4030
+ * If firstItemOnly is true, it will return the first item found
4031
+ */
4032
+ this.children.forEach(childPos => {
4033
+ // If we already found a node and we only want the first item, we dont need to keep going
4034
+ if (firstItemOnly && nodes.length > 0) {
4035
+ return;
4036
+ }
4037
+ if (childPos.node.type.name === selector) {
4038
+ const doesAllAttributesMatch = attrKeys.every(key => attributes[key] === childPos.node.attrs[key]);
4039
+ if (doesAllAttributesMatch) {
4040
+ nodes.push(childPos);
4041
+ }
4042
+ }
4043
+ // If we already found a node and we only want the first item, we can stop here and skip the recursion
4044
+ if (firstItemOnly && nodes.length > 0) {
4045
+ return;
4046
+ }
4047
+ nodes = nodes.concat(childPos.querySelectorAll(selector, attributes, firstItemOnly));
4048
+ });
4049
+ return nodes;
4050
+ }
4051
+ setAttribute(attributes) {
4052
+ const { tr } = this.editor.state;
4053
+ tr.setNodeMarkup(this.from, undefined, {
4054
+ ...this.node.attrs,
4055
+ ...attributes,
4056
+ });
4057
+ this.editor.view.dispatch(tr);
4058
+ }
4059
+ }
4060
+
4061
+ const style = `.ProseMirror {
4062
+ position: relative;
4063
+ }
4064
+
4065
+ .ProseMirror {
4066
+ word-wrap: break-word;
4067
+ white-space: pre-wrap;
4068
+ white-space: break-spaces;
4069
+ -webkit-font-variant-ligatures: none;
4070
+ font-variant-ligatures: none;
4071
+ font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */
4072
+ }
4073
+
4074
+ .ProseMirror [contenteditable="false"] {
4075
+ white-space: normal;
4076
+ }
4077
+
4078
+ .ProseMirror [contenteditable="false"] [contenteditable="true"] {
4079
+ white-space: pre-wrap;
4080
+ }
4081
+
4082
+ .ProseMirror pre {
4083
+ white-space: pre-wrap;
4084
+ }
4085
+
4086
+ img.ProseMirror-separator {
4087
+ display: inline !important;
4088
+ border: none !important;
4089
+ margin: 0 !important;
4090
+ width: 0 !important;
4091
+ height: 0 !important;
4092
+ }
4093
+
4094
+ .ProseMirror-gapcursor {
4095
+ display: none;
4096
+ pointer-events: none;
4097
+ position: absolute;
4098
+ margin: 0;
4099
+ }
4100
+
4101
+ .ProseMirror-gapcursor:after {
4102
+ content: "";
4103
+ display: block;
4104
+ position: absolute;
4105
+ top: -2px;
4106
+ width: 20px;
4107
+ border-top: 1px solid black;
4108
+ animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
4109
+ }
4110
+
4111
+ @keyframes ProseMirror-cursor-blink {
4112
+ to {
4113
+ visibility: hidden;
4114
+ }
4115
+ }
4116
+
4117
+ .ProseMirror-hideselection *::selection {
4118
+ background: transparent;
4119
+ }
4120
+
4121
+ .ProseMirror-hideselection *::-moz-selection {
4122
+ background: transparent;
4123
+ }
4124
+
4125
+ .ProseMirror-hideselection * {
4126
+ caret-color: transparent;
4127
+ }
4128
+
4129
+ .ProseMirror-focused .ProseMirror-gapcursor {
4130
+ display: block;
4131
+ }
4132
+
4133
+ .tippy-box[data-animation=fade][data-state=hidden] {
4134
+ opacity: 0
4135
+ }`;
4136
+
4137
+ function createStyleTag(style, nonce, suffix) {
4138
+ const tiptapStyleTag = document.querySelector(`style[data-tiptap-style${''}]`);
4139
+ if (tiptapStyleTag !== null) {
4140
+ return tiptapStyleTag;
4141
+ }
4142
+ const styleNode = document.createElement('style');
4143
+ if (nonce) {
4144
+ styleNode.setAttribute('nonce', nonce);
4145
+ }
4146
+ styleNode.setAttribute(`data-tiptap-style${''}`, '');
4147
+ styleNode.innerHTML = style;
4148
+ document.getElementsByTagName('head')[0].appendChild(styleNode);
4149
+ return styleNode;
4150
+ }
4151
+
4152
+ let Editor$1 = class Editor extends EventEmitter {
4153
+ constructor(options = {}) {
4154
+ super();
4155
+ this.isFocused = false;
4156
+ /**
4157
+ * The editor is considered initialized after the `create` event has been emitted.
4158
+ */
4159
+ this.isInitialized = false;
4160
+ this.extensionStorage = {};
4161
+ this.options = {
4162
+ element: document.createElement('div'),
4163
+ content: '',
4164
+ injectCSS: true,
4165
+ injectNonce: undefined,
4166
+ extensions: [],
4167
+ autofocus: false,
4168
+ editable: true,
4169
+ editorProps: {},
4170
+ parseOptions: {},
4171
+ coreExtensionOptions: {},
4172
+ enableInputRules: true,
4173
+ enablePasteRules: true,
4174
+ enableCoreExtensions: true,
4175
+ enableContentCheck: false,
4176
+ emitContentError: false,
4177
+ onBeforeCreate: () => null,
4178
+ onCreate: () => null,
4179
+ onUpdate: () => null,
4180
+ onSelectionUpdate: () => null,
4181
+ onTransaction: () => null,
4182
+ onFocus: () => null,
4183
+ onBlur: () => null,
4184
+ onDestroy: () => null,
4185
+ onContentError: ({ error }) => { throw error; },
4186
+ onPaste: () => null,
4187
+ onDrop: () => null,
4188
+ };
4189
+ this.isCapturingTransaction = false;
4190
+ this.capturedTransaction = null;
4191
+ this.setOptions(options);
4192
+ this.createExtensionManager();
4193
+ this.createCommandManager();
4194
+ this.createSchema();
4195
+ this.on('beforeCreate', this.options.onBeforeCreate);
4196
+ this.emit('beforeCreate', { editor: this });
4197
+ this.on('contentError', this.options.onContentError);
4198
+ this.createView();
4199
+ this.injectCSS();
4200
+ this.on('create', this.options.onCreate);
4201
+ this.on('update', this.options.onUpdate);
4202
+ this.on('selectionUpdate', this.options.onSelectionUpdate);
4203
+ this.on('transaction', this.options.onTransaction);
4204
+ this.on('focus', this.options.onFocus);
4205
+ this.on('blur', this.options.onBlur);
4206
+ this.on('destroy', this.options.onDestroy);
4207
+ this.on('drop', ({ event, slice, moved }) => this.options.onDrop(event, slice, moved));
4208
+ this.on('paste', ({ event, slice }) => this.options.onPaste(event, slice));
4209
+ window.setTimeout(() => {
4210
+ if (this.isDestroyed) {
4211
+ return;
4212
+ }
4213
+ this.commands.focus(this.options.autofocus);
4214
+ this.emit('create', { editor: this });
4215
+ this.isInitialized = true;
4216
+ }, 0);
4217
+ }
4218
+ /**
4219
+ * Returns the editor storage.
4220
+ */
4221
+ get storage() {
4222
+ return this.extensionStorage;
4223
+ }
4224
+ /**
4225
+ * An object of all registered commands.
4226
+ */
4227
+ get commands() {
4228
+ return this.commandManager.commands;
4229
+ }
4230
+ /**
4231
+ * Create a command chain to call multiple commands at once.
4232
+ */
4233
+ chain() {
4234
+ return this.commandManager.chain();
4235
+ }
4236
+ /**
4237
+ * Check if a command or a command chain can be executed. Without executing it.
4238
+ */
4239
+ can() {
4240
+ return this.commandManager.can();
4241
+ }
4242
+ /**
4243
+ * Inject CSS styles.
4244
+ */
4245
+ injectCSS() {
4246
+ if (this.options.injectCSS && document) {
4247
+ this.css = createStyleTag(style, this.options.injectNonce);
4248
+ }
4249
+ }
4250
+ /**
4251
+ * Update editor options.
4252
+ *
4253
+ * @param options A list of options
4254
+ */
4255
+ setOptions(options = {}) {
4256
+ this.options = {
4257
+ ...this.options,
4258
+ ...options,
4259
+ };
4260
+ if (!this.view || !this.state || this.isDestroyed) {
4261
+ return;
4262
+ }
4263
+ if (this.options.editorProps) {
4264
+ this.view.setProps(this.options.editorProps);
4265
+ }
4266
+ this.view.updateState(this.state);
4267
+ }
4268
+ /**
4269
+ * Update editable state of the editor.
4270
+ */
4271
+ setEditable(editable, emitUpdate = true) {
4272
+ this.setOptions({ editable });
4273
+ if (emitUpdate) {
4274
+ this.emit('update', { editor: this, transaction: this.state.tr });
4275
+ }
4276
+ }
4277
+ /**
4278
+ * Returns whether the editor is editable.
4279
+ */
4280
+ get isEditable() {
4281
+ // since plugins are applied after creating the view
4282
+ // `editable` is always `true` for one tick.
4283
+ // that’s why we also have to check for `options.editable`
4284
+ return this.options.editable && this.view && this.view.editable;
4285
+ }
4286
+ /**
4287
+ * Returns the editor state.
4288
+ */
4289
+ get state() {
4290
+ return this.view.state;
4291
+ }
4292
+ /**
4293
+ * Register a ProseMirror plugin.
4294
+ *
4295
+ * @param plugin A ProseMirror plugin
4296
+ * @param handlePlugins Control how to merge the plugin into the existing plugins.
4297
+ * @returns The new editor state
4298
+ */
4299
+ registerPlugin(plugin, handlePlugins) {
4300
+ const plugins = isFunction(handlePlugins)
4301
+ ? handlePlugins(plugin, [...this.state.plugins])
4302
+ : [...this.state.plugins, plugin];
4303
+ const state = this.state.reconfigure({ plugins });
4304
+ this.view.updateState(state);
4305
+ return state;
4306
+ }
4307
+ /**
4308
+ * Unregister a ProseMirror plugin.
4309
+ *
4310
+ * @param nameOrPluginKeyToRemove The plugins name
4311
+ * @returns The new editor state or undefined if the editor is destroyed
4312
+ */
4313
+ unregisterPlugin(nameOrPluginKeyToRemove) {
4314
+ if (this.isDestroyed) {
4315
+ return undefined;
4316
+ }
4317
+ const prevPlugins = this.state.plugins;
4318
+ let plugins = prevPlugins;
4319
+ [].concat(nameOrPluginKeyToRemove).forEach(nameOrPluginKey => {
4320
+ // @ts-ignore
4321
+ const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
4322
+ // @ts-ignore
4323
+ plugins = plugins.filter(plugin => !plugin.key.startsWith(name));
4324
+ });
4325
+ if (prevPlugins.length === plugins.length) {
4326
+ // No plugin was removed, so we don’t need to update the state
4327
+ return undefined;
4328
+ }
4329
+ const state = this.state.reconfigure({
4330
+ plugins,
4331
+ });
4332
+ this.view.updateState(state);
4333
+ return state;
4334
+ }
4335
+ /**
4336
+ * Creates an extension manager.
4337
+ */
4338
+ createExtensionManager() {
4339
+ var _a, _b;
4340
+ const coreExtensions = this.options.enableCoreExtensions ? [
4341
+ Editable,
4342
+ ClipboardTextSerializer.configure({
4343
+ blockSeparator: (_b = (_a = this.options.coreExtensionOptions) === null || _a === void 0 ? void 0 : _a.clipboardTextSerializer) === null || _b === void 0 ? void 0 : _b.blockSeparator,
4344
+ }),
4345
+ Commands,
4346
+ FocusEvents,
4347
+ Keymap,
4348
+ Tabindex,
4349
+ Drop,
4350
+ Paste,
4351
+ ].filter(ext => {
4352
+ if (typeof this.options.enableCoreExtensions === 'object') {
4353
+ return this.options.enableCoreExtensions[ext.name] !== false;
4354
+ }
4355
+ return true;
4356
+ }) : [];
4357
+ const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4358
+ return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4359
+ });
4360
+ this.extensionManager = new ExtensionManager(allExtensions, this);
4361
+ }
4362
+ /**
4363
+ * Creates an command manager.
4364
+ */
4365
+ createCommandManager() {
4366
+ this.commandManager = new CommandManager({
4367
+ editor: this,
4368
+ });
4369
+ }
4370
+ /**
4371
+ * Creates a ProseMirror schema.
4372
+ */
4373
+ createSchema() {
4374
+ this.schema = this.extensionManager.schema;
4375
+ }
4376
+ /**
4377
+ * Creates a ProseMirror view.
4378
+ */
4379
+ createView() {
4380
+ var _a;
4381
+ let doc;
4382
+ try {
4383
+ doc = createDocument(this.options.content, this.schema, this.options.parseOptions, { errorOnInvalidContent: this.options.enableContentCheck });
4384
+ }
4385
+ catch (e) {
4386
+ if (!(e instanceof Error) || !['[tiptap error]: Invalid JSON content', '[tiptap error]: Invalid HTML content'].includes(e.message)) {
4387
+ // Not the content error we were expecting
4388
+ throw e;
4389
+ }
4390
+ this.emit('contentError', {
4391
+ editor: this,
4392
+ error: e,
4393
+ disableCollaboration: () => {
4394
+ if (this.storage.collaboration) {
4395
+ this.storage.collaboration.isDisabled = true;
4396
+ }
4397
+ // To avoid syncing back invalid content, reinitialize the extensions without the collaboration extension
4398
+ this.options.extensions = this.options.extensions.filter(extension => extension.name !== 'collaboration');
4399
+ // Restart the initialization process by recreating the extension manager with the new set of extensions
4400
+ this.createExtensionManager();
4401
+ },
4402
+ });
4403
+ // Content is invalid, but attempt to create it anyway, stripping out the invalid parts
4404
+ doc = createDocument(this.options.content, this.schema, this.options.parseOptions, { errorOnInvalidContent: false });
4405
+ }
4406
+ const selection = resolveFocusPosition(doc, this.options.autofocus);
4407
+ this.view = new EditorView(this.options.element, {
4408
+ ...this.options.editorProps,
4409
+ attributes: {
4410
+ // add `role="textbox"` to the editor element
4411
+ role: 'textbox',
4412
+ ...(_a = this.options.editorProps) === null || _a === void 0 ? void 0 : _a.attributes,
4413
+ },
4414
+ dispatchTransaction: this.dispatchTransaction.bind(this),
4415
+ state: EditorState.create({
4416
+ doc,
4417
+ selection: selection || undefined,
4418
+ }),
4419
+ });
4420
+ // `editor.view` is not yet available at this time.
4421
+ // Therefore we will add all plugins and node views directly afterwards.
4422
+ const newState = this.state.reconfigure({
4423
+ plugins: this.extensionManager.plugins,
4424
+ });
4425
+ this.view.updateState(newState);
4426
+ this.createNodeViews();
4427
+ this.prependClass();
4428
+ // Let’s store the editor instance in the DOM element.
4429
+ // So we’ll have access to it for tests.
4430
+ // @ts-ignore
4431
+ const dom = this.view.dom;
4432
+ dom.editor = this;
4433
+ }
4434
+ /**
4435
+ * Creates all node views.
4436
+ */
4437
+ createNodeViews() {
4438
+ if (this.view.isDestroyed) {
4439
+ return;
4440
+ }
4441
+ this.view.setProps({
4442
+ nodeViews: this.extensionManager.nodeViews,
4443
+ });
4444
+ }
4445
+ /**
4446
+ * Prepend class name to element.
4447
+ */
4448
+ prependClass() {
4449
+ this.view.dom.className = `tiptap ${this.view.dom.className}`;
4450
+ }
4451
+ captureTransaction(fn) {
4452
+ this.isCapturingTransaction = true;
4453
+ fn();
4454
+ this.isCapturingTransaction = false;
4455
+ const tr = this.capturedTransaction;
4456
+ this.capturedTransaction = null;
4457
+ return tr;
4458
+ }
4459
+ /**
4460
+ * The callback over which to send transactions (state updates) produced by the view.
4461
+ *
4462
+ * @param transaction An editor state transaction
4463
+ */
4464
+ dispatchTransaction(transaction) {
4465
+ // if the editor / the view of the editor was destroyed
4466
+ // the transaction should not be dispatched as there is no view anymore.
4467
+ if (this.view.isDestroyed) {
4468
+ return;
4469
+ }
4470
+ if (this.isCapturingTransaction) {
4471
+ if (!this.capturedTransaction) {
4472
+ this.capturedTransaction = transaction;
4473
+ return;
4474
+ }
4475
+ transaction.steps.forEach(step => { var _a; return (_a = this.capturedTransaction) === null || _a === void 0 ? void 0 : _a.step(step); });
4476
+ return;
4477
+ }
4478
+ const state = this.state.apply(transaction);
4479
+ const selectionHasChanged = !this.state.selection.eq(state.selection);
4480
+ this.emit('beforeTransaction', {
4481
+ editor: this,
4482
+ transaction,
4483
+ nextState: state,
4484
+ });
4485
+ this.view.updateState(state);
4486
+ this.emit('transaction', {
4487
+ editor: this,
4488
+ transaction,
4489
+ });
4490
+ if (selectionHasChanged) {
4491
+ this.emit('selectionUpdate', {
4492
+ editor: this,
4493
+ transaction,
4494
+ });
4495
+ }
4496
+ const focus = transaction.getMeta('focus');
4497
+ const blur = transaction.getMeta('blur');
4498
+ if (focus) {
4499
+ this.emit('focus', {
4500
+ editor: this,
4501
+ event: focus.event,
4502
+ transaction,
4503
+ });
4504
+ }
4505
+ if (blur) {
4506
+ this.emit('blur', {
4507
+ editor: this,
4508
+ event: blur.event,
4509
+ transaction,
4510
+ });
4511
+ }
4512
+ if (!transaction.docChanged || transaction.getMeta('preventUpdate')) {
4513
+ return;
4514
+ }
4515
+ this.emit('update', {
4516
+ editor: this,
4517
+ transaction,
4518
+ });
4519
+ }
4520
+ /**
4521
+ * Get attributes of the currently selected node or mark.
4522
+ */
4523
+ getAttributes(nameOrType) {
4524
+ return getAttributes(this.state, nameOrType);
4525
+ }
4526
+ isActive(nameOrAttributes, attributesOrUndefined) {
4527
+ const name = typeof nameOrAttributes === 'string' ? nameOrAttributes : null;
4528
+ const attributes = typeof nameOrAttributes === 'string' ? attributesOrUndefined : nameOrAttributes;
4529
+ return isActive(this.state, name, attributes);
4530
+ }
4531
+ /**
4532
+ * Get the document as JSON.
4533
+ */
4534
+ getJSON() {
4535
+ return this.state.doc.toJSON();
4536
+ }
4537
+ /**
4538
+ * Get the document as HTML.
4539
+ */
4540
+ getHTML() {
4541
+ return getHTMLFromFragment(this.state.doc.content, this.schema);
4542
+ }
4543
+ /**
4544
+ * Get the document as text.
4545
+ */
4546
+ getText(options) {
4547
+ const { blockSeparator = '\n\n', textSerializers = {} } = options || {};
4548
+ return getText(this.state.doc, {
4549
+ blockSeparator,
4550
+ textSerializers: {
4551
+ ...getTextSerializersFromSchema(this.schema),
4552
+ ...textSerializers,
4553
+ },
4554
+ });
4555
+ }
4556
+ /**
4557
+ * Check if there is no content.
4558
+ */
4559
+ get isEmpty() {
4560
+ return isNodeEmpty(this.state.doc);
4561
+ }
4562
+ /**
4563
+ * Get the number of characters for the current document.
4564
+ *
4565
+ * @deprecated
4566
+ */
4567
+ getCharacterCount() {
4568
+ console.warn('[tiptap warn]: "editor.getCharacterCount()" is deprecated. Please use "editor.storage.characterCount.characters()" instead.');
4569
+ return this.state.doc.content.size - 2;
4570
+ }
4571
+ /**
4572
+ * Destroy the editor.
4573
+ */
4574
+ destroy() {
4575
+ this.emit('destroy');
4576
+ if (this.view) {
4577
+ // Cleanup our reference to prevent circular references which caused memory leaks
4578
+ // @ts-ignore
4579
+ const dom = this.view.dom;
4580
+ if (dom && dom.editor) {
4581
+ delete dom.editor;
4582
+ }
4583
+ this.view.destroy();
4584
+ }
4585
+ this.removeAllListeners();
4586
+ }
4587
+ /**
4588
+ * Check if the editor is already destroyed.
4589
+ */
4590
+ get isDestroyed() {
4591
+ var _a;
4592
+ // @ts-ignore
4593
+ return !((_a = this.view) === null || _a === void 0 ? void 0 : _a.docView);
4594
+ }
4595
+ $node(selector, attributes) {
4596
+ var _a;
4597
+ return ((_a = this.$doc) === null || _a === void 0 ? void 0 : _a.querySelector(selector, attributes)) || null;
4598
+ }
4599
+ $nodes(selector, attributes) {
4600
+ var _a;
4601
+ return ((_a = this.$doc) === null || _a === void 0 ? void 0 : _a.querySelectorAll(selector, attributes)) || null;
4602
+ }
4603
+ $pos(pos) {
4604
+ const $pos = this.state.doc.resolve(pos);
4605
+ return new NodePos($pos, this);
4606
+ }
4607
+ get $doc() {
4608
+ return this.$pos(0);
4609
+ }
4610
+ };
4611
+
4612
+ /**
4613
+ * Build an input rule that adds a mark when the
4614
+ * matched text is typed into it.
4615
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
4616
+ */
4617
+ function markInputRule(config) {
4618
+ return new InputRule({
4619
+ find: config.find,
4620
+ handler: ({ state, range, match }) => {
4621
+ const attributes = callOrReturn(config.getAttributes, undefined, match);
4622
+ if (attributes === false || attributes === null) {
4623
+ return null;
4624
+ }
4625
+ const { tr } = state;
4626
+ const captureGroup = match[match.length - 1];
4627
+ const fullMatch = match[0];
4628
+ if (captureGroup) {
4629
+ const startSpaces = fullMatch.search(/\S/);
4630
+ const textStart = range.from + fullMatch.indexOf(captureGroup);
4631
+ const textEnd = textStart + captureGroup.length;
4632
+ const excludedMarks = getMarksBetween(range.from, range.to, state.doc)
4633
+ .filter(item => {
4634
+ // @ts-ignore
4635
+ const excluded = item.mark.type.excluded;
4636
+ return excluded.find(type => type === config.type && type !== item.mark.type);
4637
+ })
4638
+ .filter(item => item.to > textStart);
4639
+ if (excludedMarks.length) {
4640
+ return null;
4641
+ }
4642
+ if (textEnd < range.to) {
4643
+ tr.delete(textEnd, range.to);
4644
+ }
4645
+ if (textStart > range.from) {
4646
+ tr.delete(range.from + startSpaces, textStart);
4647
+ }
4648
+ const markEnd = range.from + startSpaces + captureGroup.length;
4649
+ tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
4650
+ tr.removeStoredMark(config.type);
4651
+ }
4652
+ },
4653
+ });
4654
+ }
4655
+
4656
+ /**
4657
+ * Build an input rule that adds a node when the
4658
+ * matched text is typed into it.
4659
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
4660
+ */
4661
+ function nodeInputRule(config) {
4662
+ return new InputRule({
4663
+ find: config.find,
4664
+ handler: ({ state, range, match }) => {
4665
+ const attributes = callOrReturn(config.getAttributes, undefined, match) || {};
4666
+ const { tr } = state;
4667
+ const start = range.from;
4668
+ let end = range.to;
4669
+ const newNode = config.type.create(attributes);
4670
+ if (match[1]) {
4671
+ const offset = match[0].lastIndexOf(match[1]);
4672
+ let matchStart = start + offset;
4673
+ if (matchStart > end) {
4674
+ matchStart = end;
4675
+ }
4676
+ else {
4677
+ end = matchStart + match[1].length;
4678
+ }
4679
+ // insert last typed character
4680
+ const lastChar = match[0][match[0].length - 1];
4681
+ tr.insertText(lastChar, start + match[0].length - 1);
4682
+ // insert node from input rule
4683
+ tr.replaceWith(matchStart, end, newNode);
4684
+ }
4685
+ else if (match[0]) {
4686
+ const insertionStart = config.type.isInline ? start : start - 1;
4687
+ tr.insert(insertionStart, config.type.create(attributes)).delete(tr.mapping.map(start), tr.mapping.map(end));
4688
+ }
4689
+ tr.scrollIntoView();
4690
+ },
4691
+ });
4692
+ }
4693
+
4694
+ /**
4695
+ * Build an input rule that changes the type of a textblock when the
4696
+ * matched text is typed into it. When using a regular expresion you’ll
4697
+ * probably want the regexp to start with `^`, so that the pattern can
4698
+ * only occur at the start of a textblock.
4699
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
4700
+ */
4701
+ function textblockTypeInputRule(config) {
4702
+ return new InputRule({
4703
+ find: config.find,
4704
+ handler: ({ state, range, match }) => {
4705
+ const $start = state.doc.resolve(range.from);
4706
+ const attributes = callOrReturn(config.getAttributes, undefined, match) || {};
4707
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), config.type)) {
4708
+ return null;
4709
+ }
4710
+ state.tr
4711
+ .delete(range.from, range.to)
4712
+ .setBlockType(range.from, range.from, config.type, attributes);
4713
+ },
4714
+ });
4715
+ }
4716
+
4717
+ /**
4718
+ * Build an input rule for automatically wrapping a textblock when a
4719
+ * given string is typed. When using a regular expresion you’ll
4720
+ * probably want the regexp to start with `^`, so that the pattern can
4721
+ * only occur at the start of a textblock.
4722
+ *
4723
+ * `type` is the type of node to wrap in.
4724
+ *
4725
+ * By default, if there’s a node with the same type above the newly
4726
+ * wrapped node, the rule will try to join those
4727
+ * two nodes. You can pass a join predicate, which takes a regular
4728
+ * expression match and the node before the wrapped node, and can
4729
+ * return a boolean to indicate whether a join should happen.
4730
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
4731
+ */
4732
+ function wrappingInputRule(config) {
4733
+ return new InputRule({
4734
+ find: config.find,
4735
+ handler: ({ state, range, match, chain, }) => {
4736
+ const attributes = callOrReturn(config.getAttributes, undefined, match) || {};
4737
+ const tr = state.tr.delete(range.from, range.to);
4738
+ const $start = tr.doc.resolve(range.from);
4739
+ const blockRange = $start.blockRange();
4740
+ const wrapping = blockRange && findWrapping(blockRange, config.type, attributes);
4741
+ if (!wrapping) {
4742
+ return null;
4743
+ }
4744
+ tr.wrap(blockRange, wrapping);
4745
+ if (config.keepMarks && config.editor) {
4746
+ const { selection, storedMarks } = state;
4747
+ const { splittableMarks } = config.editor.extensionManager;
4748
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks());
4749
+ if (marks) {
4750
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name));
4751
+ tr.ensureMarks(filteredMarks);
4752
+ }
4753
+ }
4754
+ if (config.keepAttributes) {
4755
+ /** If the nodeType is `bulletList` or `orderedList` set the `nodeType` as `listItem` */
4756
+ const nodeType = config.type.name === 'bulletList' || config.type.name === 'orderedList' ? 'listItem' : 'taskList';
4757
+ chain().updateAttributes(nodeType, attributes).run();
4758
+ }
4759
+ const before = tr.doc.resolve(range.from - 1).nodeBefore;
4760
+ if (before
4761
+ && before.type === config.type
4762
+ && canJoin(tr.doc, range.from - 1)
4763
+ && (!config.joinPredicate || config.joinPredicate(match, before))) {
4764
+ tr.join(range.from - 1);
4765
+ }
4766
+ },
4767
+ });
4768
+ }
4769
+
4770
+ /**
4771
+ * The Node class is used to create custom node extensions.
4772
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
4773
+ */
4774
+ class Node {
4775
+ constructor(config = {}) {
4776
+ this.type = 'node';
4777
+ this.name = 'node';
4778
+ this.parent = null;
4779
+ this.child = null;
4780
+ this.config = {
4781
+ name: this.name,
4782
+ defaultOptions: {},
4783
+ };
4784
+ this.config = {
4785
+ ...this.config,
4786
+ ...config,
4787
+ };
4788
+ this.name = this.config.name;
4789
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
4790
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
4791
+ }
4792
+ // TODO: remove `addOptions` fallback
4793
+ this.options = this.config.defaultOptions;
4794
+ if (this.config.addOptions) {
4795
+ this.options = callOrReturn(getExtensionField(this, 'addOptions', {
4796
+ name: this.name,
4797
+ }));
4798
+ }
4799
+ this.storage = callOrReturn(getExtensionField(this, 'addStorage', {
4800
+ name: this.name,
4801
+ options: this.options,
4802
+ })) || {};
4803
+ }
4804
+ static create(config = {}) {
4805
+ return new Node(config);
4806
+ }
4807
+ configure(options = {}) {
4808
+ // return a new instance so we can use the same extension
4809
+ // with different calls of `configure`
4810
+ const extension = this.extend({
4811
+ ...this.config,
4812
+ addOptions: () => {
4813
+ return mergeDeep(this.options, options);
4814
+ },
4815
+ });
4816
+ // Always preserve the current name
4817
+ extension.name = this.name;
4818
+ // Set the parent to be our parent
4819
+ extension.parent = this.parent;
4820
+ return extension;
4821
+ }
4822
+ extend(extendedConfig = {}) {
4823
+ const extension = new Node(extendedConfig);
4824
+ extension.parent = this;
4825
+ this.child = extension;
4826
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
4827
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
4828
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
4829
+ }
4830
+ extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {
4831
+ name: extension.name,
4832
+ }));
4833
+ extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
4834
+ name: extension.name,
4835
+ options: extension.options,
4836
+ }));
4837
+ return extension;
4838
+ }
4839
+ }
4840
+
4841
+ /**
4842
+ * Build an paste rule that adds a mark when the
4843
+ * matched text is pasted into it.
4844
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
4845
+ */
4846
+ function markPasteRule(config) {
4847
+ return new PasteRule({
4848
+ find: config.find,
4849
+ handler: ({ state, range, match, pasteEvent, }) => {
4850
+ const attributes = callOrReturn(config.getAttributes, undefined, match, pasteEvent);
4851
+ if (attributes === false || attributes === null) {
4852
+ return null;
4853
+ }
4854
+ const { tr } = state;
4855
+ const captureGroup = match[match.length - 1];
4856
+ const fullMatch = match[0];
4857
+ let markEnd = range.to;
4858
+ if (captureGroup) {
4859
+ const startSpaces = fullMatch.search(/\S/);
4860
+ const textStart = range.from + fullMatch.indexOf(captureGroup);
4861
+ const textEnd = textStart + captureGroup.length;
4862
+ const excludedMarks = getMarksBetween(range.from, range.to, state.doc)
4863
+ .filter(item => {
4864
+ // @ts-ignore
4865
+ const excluded = item.mark.type.excluded;
4866
+ return excluded.find(type => type === config.type && type !== item.mark.type);
4867
+ })
4868
+ .filter(item => item.to > textStart);
4869
+ if (excludedMarks.length) {
4870
+ return null;
4871
+ }
4872
+ if (textEnd < range.to) {
4873
+ tr.delete(textEnd, range.to);
4874
+ }
4875
+ if (textStart > range.from) {
4876
+ tr.delete(range.from + startSpaces, textStart);
4877
+ }
4878
+ markEnd = range.from + startSpaces + captureGroup.length;
4879
+ tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
4880
+ tr.removeStoredMark(config.type);
4881
+ }
4882
+ },
4883
+ });
4884
+ }
4885
+
4886
+ function canInsertNode(state, nodeType) {
4887
+ const { selection } = state;
4888
+ const { $from } = selection;
4889
+ // Special handling for NodeSelection
4890
+ if (selection instanceof NodeSelection) {
4891
+ const index = $from.index();
4892
+ const parent = $from.parent;
4893
+ // Can we replace the selected node with the horizontal rule?
4894
+ return parent.canReplaceWith(index, index + 1, nodeType);
4895
+ }
4896
+ // Default: check if we can insert at the current position
4897
+ let depth = $from.depth;
4898
+ while (depth >= 0) {
4899
+ const index = $from.index(depth);
4900
+ const parent = $from.node(depth);
4901
+ const match = parent.contentMatchAt(index);
4902
+ if (match.matchType(nodeType)) {
4903
+ return true;
4904
+ }
4905
+ depth -= 1;
4906
+ }
4907
+ return false;
4908
+ }
4909
+
4910
+ export { Extension as E, Mark as M, Node as N, markPasteRule as a, markInputRule as b, isNodeSelection as c, getTextSerializersFromSchema as d, callOrReturn as e, getExtensionField as f, getText as g, canInsertNode as h, isTextSelection as i, combineTransactionSteps as j, getChangedRanges as k, findChildrenInRange as l, mergeAttributes as m, nodeInputRule as n, getMarksBetween as o, posToDOMRect as p, getAttributes as q, isNodeEmpty as r, findParentNodeClosestToPos as s, textblockTypeInputRule as t, index as u, getHTMLFromFragment as v, wrappingInputRule as w, Editor$1 as x };