@jackuait/blok 0.6.0-beta.0 → 0.6.0-beta.10

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 (286) hide show
  1. package/README.md +16 -169
  2. package/bin/blok.mjs +10 -0
  3. package/dist/blok.mjs +2 -2
  4. package/dist/chunks/{blok-Bu9S3SsR.mjs → blok-Buf0btS7.mjs} +2267 -2024
  5. package/dist/chunks/{i18next-loader-CKuXJ0Av.mjs → i18next-loader-CVf_ZfwA.mjs} +1 -1
  6. package/dist/chunks/{index-jtZaryNw.mjs → index-C6jsfLLp.mjs} +1 -1
  7. package/dist/chunks/{inline-tool-convert-CFjyrH30.mjs → inline-tool-convert-BKKEoOqB.mjs} +710 -570
  8. package/dist/chunks/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  9. package/dist/chunks/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
  10. package/dist/{messages-LvFKBBPa.mjs → chunks/messages-7W4d0DwD.mjs} +15 -1
  11. package/dist/{messages-Bn253WWC.mjs → chunks/messages-9SihnaXQ.mjs} +14 -0
  12. package/dist/{messages-Bf6Y3_GI.mjs → chunks/messages-B1Aww8q7.mjs} +16 -2
  13. package/dist/{messages-pA5TvcAj.mjs → chunks/messages-BB5z9Uba.mjs} +14 -0
  14. package/dist/chunks/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  15. package/dist/chunks/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  16. package/dist/chunks/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  17. package/dist/{messages-B5puUm7R.mjs → chunks/messages-BL0tXcDf.mjs} +15 -1
  18. package/dist/chunks/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
  19. package/dist/{messages-CyDU5lz9.mjs → chunks/messages-BMv4xwIr.mjs} +16 -2
  20. package/dist/chunks/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
  21. package/dist/chunks/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  22. package/dist/chunks/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  23. package/dist/{messages-CXHd9SUK.mjs → chunks/messages-BYyy6Wqf.mjs} +14 -0
  24. package/dist/chunks/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
  25. package/dist/chunks/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  26. package/dist/chunks/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  27. package/dist/chunks/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  28. package/dist/chunks/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  29. package/dist/chunks/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
  30. package/dist/chunks/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  31. package/dist/chunks/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
  32. package/dist/chunks/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  33. package/dist/chunks/messages-CKI54h6O.mjs +62 -0
  34. package/dist/{messages-CrsJ1TEJ.mjs → chunks/messages-CLhcMlTc.mjs} +15 -1
  35. package/dist/{messages-CnvW8Slp.mjs → chunks/messages-CMkNSDTo.mjs} +17 -3
  36. package/dist/{messages-BlpqL8vG.mjs → chunks/messages-CQwpzUFp.mjs} +19 -5
  37. package/dist/chunks/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
  38. package/dist/chunks/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  39. package/dist/chunks/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  40. package/dist/chunks/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  41. package/dist/chunks/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  42. package/dist/{messages-Dg92dXZ5.mjs → chunks/messages-CvGLfqmV.mjs} +14 -0
  43. package/dist/{messages-AHESHJm_.mjs → chunks/messages-CzTufCHu.mjs} +14 -0
  44. package/dist/chunks/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  45. package/dist/chunks/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  46. package/dist/chunks/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  47. package/dist/chunks/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  48. package/dist/chunks/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  49. package/dist/{messages-zSzDzXej.mjs → chunks/messages-DBRw-7Zc.mjs} +16 -2
  50. package/dist/chunks/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  51. package/dist/chunks/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  52. package/dist/{messages-DDLgIPDF.mjs → chunks/messages-DLfR5bMd.mjs} +16 -2
  53. package/dist/{messages-CbhuIWRJ.mjs → chunks/messages-DT4dP5uK.mjs} +15 -1
  54. package/dist/chunks/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  55. package/dist/{messages-BPqWKx5Z.mjs → chunks/messages-Diu6jAaR.mjs} +17 -3
  56. package/dist/{messages-BA0rcTCY.mjs → chunks/messages-DnIhyAJk.mjs} +18 -4
  57. package/dist/chunks/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  58. package/dist/chunks/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  59. package/dist/{messages-CJoBtXU6.mjs → chunks/messages-DqM1LFg5.mjs} +14 -0
  60. package/dist/chunks/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
  61. package/dist/chunks/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  62. package/dist/chunks/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
  63. package/dist/chunks/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  64. package/dist/{messages-DY94ykcE.mjs → chunks/messages-LPVfA-8K.mjs} +14 -0
  65. package/dist/{messages-Cr-RJ7YB.mjs → chunks/messages-O5tQus_0.mjs} +14 -0
  66. package/dist/chunks/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  67. package/dist/chunks/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  68. package/dist/{messages-CUy1vn-b.mjs → chunks/messages-Xq8UmkVs.mjs} +14 -0
  69. package/dist/chunks/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  70. package/dist/chunks/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  71. package/dist/chunks/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  72. package/dist/chunks/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  73. package/dist/chunks/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  74. package/dist/chunks/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  75. package/dist/cli.mjs +50 -0
  76. package/dist/full.mjs +15 -15
  77. package/dist/locales.mjs +102 -88
  78. package/dist/{messages-C5b7hr_E.mjs → messages-1fC8IMyX.mjs} +16 -2
  79. package/dist/{messages-CQj2JU2j.mjs → messages-7QoX8DkW.mjs} +23 -9
  80. package/dist/{chunks/messages-LvFKBBPa.mjs → messages-7W4d0DwD.mjs} +15 -1
  81. package/dist/{chunks/messages-Bn253WWC.mjs → messages-9SihnaXQ.mjs} +14 -0
  82. package/dist/{chunks/messages-Bf6Y3_GI.mjs → messages-B1Aww8q7.mjs} +16 -2
  83. package/dist/{chunks/messages-pA5TvcAj.mjs → messages-BB5z9Uba.mjs} +14 -0
  84. package/dist/{messages-wdqp4610.mjs → messages-BC86qLvI.mjs} +17 -3
  85. package/dist/{messages-o24dK6CU.mjs → messages-BELRf6DU.mjs} +16 -2
  86. package/dist/{messages-CUZ1x1QD.mjs → messages-BFG6Wlgy.mjs} +16 -2
  87. package/dist/{chunks/messages-B5puUm7R.mjs → messages-BL0tXcDf.mjs} +15 -1
  88. package/dist/{messages-zS1AXZ0y.mjs → messages-BMXCuEKO.mjs} +19 -5
  89. package/dist/{chunks/messages-CyDU5lz9.mjs → messages-BMv4xwIr.mjs} +16 -2
  90. package/dist/{messages-BeUhMpsr.mjs → messages-BSbjsyHY.mjs} +25 -11
  91. package/dist/{messages-JGsXAReJ.mjs → messages-BU2nlrLK.mjs} +16 -2
  92. package/dist/{messages-srxrv8Yh.mjs → messages-BWF-zUpY.mjs} +17 -3
  93. package/dist/{chunks/messages-CXHd9SUK.mjs → messages-BYyy6Wqf.mjs} +14 -0
  94. package/dist/{messages-DOlC_Tty.mjs → messages-BdeLo0N9.mjs} +24 -10
  95. package/dist/{messages-B5jGUnOy.mjs → messages-Bmu_S7GM.mjs} +14 -0
  96. package/dist/{messages-BmKCChWZ.mjs → messages-BoJc_p1r.mjs} +14 -0
  97. package/dist/{messages-CvaqJFN-.mjs → messages-BogRq8lt.mjs} +15 -1
  98. package/dist/{messages-NP1myMGI.mjs → messages-BrPFGbM-.mjs} +14 -0
  99. package/dist/{messages-D00OjS2n.mjs → messages-C2htQ_3F.mjs} +24 -10
  100. package/dist/{messages-BiExzWJv.mjs → messages-C99mq906.mjs} +15 -1
  101. package/dist/{messages-CkFT2gle.mjs → messages-C9eaarcK.mjs} +20 -6
  102. package/dist/{messages-BrJHUxQL.mjs → messages-CJdUsQ-c.mjs} +15 -1
  103. package/dist/messages-CKI54h6O.mjs +62 -0
  104. package/dist/{chunks/messages-CrsJ1TEJ.mjs → messages-CLhcMlTc.mjs} +15 -1
  105. package/dist/{chunks/messages-CnvW8Slp.mjs → messages-CMkNSDTo.mjs} +17 -3
  106. package/dist/{chunks/messages-BlpqL8vG.mjs → messages-CQwpzUFp.mjs} +19 -5
  107. package/dist/{messages-Cu08aLS3.mjs → messages-CVw84KdI.mjs} +21 -7
  108. package/dist/{messages-B9Oba7sq.mjs → messages-CY8_RyFE.mjs} +15 -1
  109. package/dist/{messages-B5hdXZwA.mjs → messages-CZygwLwM.mjs} +15 -1
  110. package/dist/{messages-CVeWVKsV.mjs → messages-CnwibSvh.mjs} +14 -0
  111. package/dist/{messages-DbVquYKN.mjs → messages-CqWJcCbY.mjs} +14 -0
  112. package/dist/{chunks/messages-Dg92dXZ5.mjs → messages-CvGLfqmV.mjs} +14 -0
  113. package/dist/{chunks/messages-AHESHJm_.mjs → messages-CzTufCHu.mjs} +14 -0
  114. package/dist/{messages-Cj-t1bdy.mjs → messages-CznZadDf.mjs} +15 -1
  115. package/dist/{messages-DMQIHGRj.mjs → messages-D-ZtY5v0.mjs} +14 -0
  116. package/dist/{messages-rRSHQDCX.mjs → messages-D1Hv8XGo.mjs} +14 -0
  117. package/dist/{messages-0tDXLuyH.mjs → messages-D5C3J9qr.mjs} +15 -1
  118. package/dist/{messages-RvMHb2Ht.mjs → messages-D5iv1Kox.mjs} +16 -2
  119. package/dist/{chunks/messages-zSzDzXej.mjs → messages-DBRw-7Zc.mjs} +16 -2
  120. package/dist/{messages-CeCjVKMW.mjs → messages-DBn76jVV.mjs} +16 -2
  121. package/dist/{messages-C7I_AVH2.mjs → messages-DJDG55Vq.mjs} +16 -2
  122. package/dist/{chunks/messages-DDLgIPDF.mjs → messages-DLfR5bMd.mjs} +16 -2
  123. package/dist/{chunks/messages-CbhuIWRJ.mjs → messages-DT4dP5uK.mjs} +15 -1
  124. package/dist/{messages-B66ZSDCJ.mjs → messages-DhLKYm2j.mjs} +15 -1
  125. package/dist/{chunks/messages-BPqWKx5Z.mjs → messages-Diu6jAaR.mjs} +17 -3
  126. package/dist/{chunks/messages-BA0rcTCY.mjs → messages-DnIhyAJk.mjs} +18 -4
  127. package/dist/{messages-DV6shA9b.mjs → messages-DnXLrlHh.mjs} +14 -0
  128. package/dist/{messages-DcKOuncK.mjs → messages-DprmQg6V.mjs} +16 -2
  129. package/dist/{chunks/messages-CJoBtXU6.mjs → messages-DqM1LFg5.mjs} +14 -0
  130. package/dist/{messages-Cyi2AMmz.mjs → messages-DvFLX36Q.mjs} +25 -11
  131. package/dist/{messages-DnbbyJT3.mjs → messages-Dz9L52ol.mjs} +16 -2
  132. package/dist/{messages-GC2PhgV3.mjs → messages-Dzwxv9v1.mjs} +23 -9
  133. package/dist/{messages-Q4kc_ZtL.mjs → messages-JELdtT6E.mjs} +15 -1
  134. package/dist/{chunks/messages-DY94ykcE.mjs → messages-LPVfA-8K.mjs} +14 -0
  135. package/dist/{chunks/messages-Cr-RJ7YB.mjs → messages-O5tQus_0.mjs} +14 -0
  136. package/dist/{messages-CbMyJSzS.mjs → messages-Q7AO_FLv.mjs} +17 -3
  137. package/dist/{messages-2_xedlYw.mjs → messages-R3hUSvr3.mjs} +15 -1
  138. package/dist/{chunks/messages-CUy1vn-b.mjs → messages-Xq8UmkVs.mjs} +14 -0
  139. package/dist/{messages-BBJgd5jG.mjs → messages-Z9nEU2xK.mjs} +16 -2
  140. package/dist/{messages-Cm9aLHeX.mjs → messages-_ErNTNhk.mjs} +15 -1
  141. package/dist/{messages-JZUhXTuV.mjs → messages-_ncGrKHh.mjs} +16 -2
  142. package/dist/{messages-ftMcCEuO.mjs → messages-kep5wtm4.mjs} +15 -1
  143. package/dist/{messages-DteYq0rv.mjs → messages-uKX8WBaD.mjs} +16 -2
  144. package/dist/{messages-Bdv-IkfG.mjs → messages-w7v1GNaE.mjs} +15 -1
  145. package/dist/tools.mjs +2005 -1267
  146. package/dist/vendor.LICENSE.txt +1 -1
  147. package/package.json +15 -14
  148. package/src/cli/commands/migration.ts +16 -0
  149. package/src/cli/commands/migrationContent.ts +6 -0
  150. package/src/cli/index.ts +47 -0
  151. package/src/cli/utils/output.ts +10 -0
  152. package/src/components/block-tunes/block-tune-delete.ts +3 -2
  153. package/src/components/blocks.ts +23 -6
  154. package/src/components/constants/data-attributes.ts +2 -0
  155. package/src/components/i18n/locales/am/messages.json +15 -1
  156. package/src/components/i18n/locales/ar/messages.json +14 -0
  157. package/src/components/i18n/locales/az/messages.json +14 -0
  158. package/src/components/i18n/locales/bg/messages.json +14 -0
  159. package/src/components/i18n/locales/bn/messages.json +25 -11
  160. package/src/components/i18n/locales/bs/messages.json +15 -1
  161. package/src/components/i18n/locales/cs/messages.json +14 -0
  162. package/src/components/i18n/locales/da/messages.json +14 -0
  163. package/src/components/i18n/locales/de/messages.json +14 -0
  164. package/src/components/i18n/locales/dv/messages.json +15 -1
  165. package/src/components/i18n/locales/el/messages.json +15 -1
  166. package/src/components/i18n/locales/en/messages.json +14 -0
  167. package/src/components/i18n/locales/es/messages.json +14 -0
  168. package/src/components/i18n/locales/et/messages.json +14 -0
  169. package/src/components/i18n/locales/fa/messages.json +15 -1
  170. package/src/components/i18n/locales/fi/messages.json +15 -1
  171. package/src/components/i18n/locales/fil/messages.json +20 -6
  172. package/src/components/i18n/locales/fr/messages.json +15 -1
  173. package/src/components/i18n/locales/gu/messages.json +15 -1
  174. package/src/components/i18n/locales/he/messages.json +14 -0
  175. package/src/components/i18n/locales/hi/messages.json +23 -9
  176. package/src/components/i18n/locales/hr/messages.json +14 -0
  177. package/src/components/i18n/locales/hu/messages.json +14 -0
  178. package/src/components/i18n/locales/hy/messages.json +16 -2
  179. package/src/components/i18n/locales/id/messages.json +19 -5
  180. package/src/components/i18n/locales/it/messages.json +14 -0
  181. package/src/components/i18n/locales/ja/messages.json +14 -0
  182. package/src/components/i18n/locales/ka/messages.json +15 -1
  183. package/src/components/i18n/locales/km/messages.json +16 -2
  184. package/src/components/i18n/locales/kn/messages.json +16 -2
  185. package/src/components/i18n/locales/ko/messages.json +14 -0
  186. package/src/components/i18n/locales/ku/messages.json +16 -2
  187. package/src/components/i18n/locales/lo/messages.json +15 -1
  188. package/src/components/i18n/locales/lt/messages.json +15 -1
  189. package/src/components/i18n/locales/lv/messages.json +15 -1
  190. package/src/components/i18n/locales/mk/messages.json +16 -2
  191. package/src/components/i18n/locales/ml/messages.json +16 -2
  192. package/src/components/i18n/locales/mn/messages.json +16 -2
  193. package/src/components/i18n/locales/mr/messages.json +24 -10
  194. package/src/components/i18n/locales/ms/messages.json +17 -3
  195. package/src/components/i18n/locales/my/messages.json +16 -2
  196. package/src/components/i18n/locales/ne/messages.json +24 -10
  197. package/src/components/i18n/locales/nl/messages.json +15 -1
  198. package/src/components/i18n/locales/no/messages.json +16 -2
  199. package/src/components/i18n/locales/pa/messages.json +15 -1
  200. package/src/components/i18n/locales/pl/messages.json +14 -0
  201. package/src/components/i18n/locales/ps/messages.json +17 -3
  202. package/src/components/i18n/locales/pt/messages.json +14 -0
  203. package/src/components/i18n/locales/ro/messages.json +15 -1
  204. package/src/components/i18n/locales/ru/messages.json +14 -0
  205. package/src/components/i18n/locales/sd/messages.json +16 -2
  206. package/src/components/i18n/locales/si/messages.json +23 -9
  207. package/src/components/i18n/locales/sk/messages.json +15 -1
  208. package/src/components/i18n/locales/sl/messages.json +16 -2
  209. package/src/components/i18n/locales/sq/messages.json +16 -2
  210. package/src/components/i18n/locales/sr/messages.json +16 -2
  211. package/src/components/i18n/locales/sv/messages.json +16 -2
  212. package/src/components/i18n/locales/sw/messages.json +16 -2
  213. package/src/components/i18n/locales/ta/messages.json +21 -7
  214. package/src/components/i18n/locales/te/messages.json +40 -26
  215. package/src/components/i18n/locales/th/messages.json +19 -5
  216. package/src/components/i18n/locales/tr/messages.json +15 -1
  217. package/src/components/i18n/locales/ug/messages.json +16 -2
  218. package/src/components/i18n/locales/uk/messages.json +15 -1
  219. package/src/components/i18n/locales/ur/messages.json +15 -1
  220. package/src/components/i18n/locales/vi/messages.json +25 -11
  221. package/src/components/i18n/locales/yi/messages.json +16 -2
  222. package/src/components/i18n/locales/zh/messages.json +15 -1
  223. package/src/components/icons/index.ts +104 -83
  224. package/src/components/modules/api/blocks.ts +35 -2
  225. package/src/components/modules/api/history.ts +64 -0
  226. package/src/components/modules/api/index.ts +2 -0
  227. package/src/components/modules/api/readonly.ts +11 -1
  228. package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +12 -1
  229. package/src/components/modules/blockManager/blockManager.ts +7 -0
  230. package/src/components/modules/blockManager/operations.ts +3 -2
  231. package/src/components/modules/blockManager/types.ts +3 -1
  232. package/src/components/modules/blockManager/yjs-sync.ts +12 -2
  233. package/src/components/modules/index.ts +3 -0
  234. package/src/components/modules/normalizeInlineImages.ts +263 -0
  235. package/src/components/modules/readonly.ts +11 -0
  236. package/src/components/modules/rectangleSelection.ts +19 -3
  237. package/src/components/modules/saver.ts +7 -3
  238. package/src/components/modules/toolbar/blockSettings.ts +3 -3
  239. package/src/components/modules/toolbar/index.ts +72 -14
  240. package/src/components/modules/toolbar/plus-button.ts +24 -3
  241. package/src/components/modules/toolbar/settings-toggler.ts +3 -5
  242. package/src/components/modules/ui.ts +46 -68
  243. package/src/components/modules/uiControllers/controllers/blockHover.ts +49 -61
  244. package/src/components/modules/uiControllers/controllers/keyboard.ts +17 -11
  245. package/src/components/modules/uiControllers/handlers/click.ts +0 -12
  246. package/src/components/modules/yjs/index.ts +23 -0
  247. package/src/components/ui/toolbox.ts +41 -6
  248. package/src/components/utils/placeholder.ts +16 -0
  249. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +2 -1
  250. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -1
  251. package/src/components/utils/popover/index.ts +1 -0
  252. package/src/components/utils/popover/popover-abstract.ts +11 -1
  253. package/src/components/utils/popover/popover-desktop.ts +27 -8
  254. package/src/components/utils/popover/popover-registry.ts +188 -0
  255. package/src/components/utils/sanitizer.ts +23 -2
  256. package/src/components/utils/tooltip.ts +2 -24
  257. package/src/styles/main.css +22 -0
  258. package/src/tools/paragraph/index.ts +12 -4
  259. package/src/tools/table/data-normalizer.ts +1 -0
  260. package/src/tools/table/index.ts +283 -346
  261. package/src/tools/table/table-add-controls.ts +353 -47
  262. package/src/tools/table/table-cell-blocks.ts +95 -7
  263. package/src/tools/table/table-cell-selection.ts +648 -0
  264. package/src/tools/table/table-core.ts +21 -32
  265. package/src/tools/table/table-grip-visuals.ts +96 -0
  266. package/src/tools/table/table-heading-toggle.ts +127 -0
  267. package/src/tools/table/table-operations.ts +475 -0
  268. package/src/tools/table/table-resize.ts +27 -6
  269. package/src/tools/table/table-restrictions.ts +64 -0
  270. package/src/tools/table/table-row-col-action-handler.ts +190 -0
  271. package/src/tools/table/table-row-col-controls.ts +265 -211
  272. package/src/tools/table/table-row-col-drag.ts +4 -4
  273. package/src/tools/table/table-row-col-popover.ts +225 -0
  274. package/src/tools/table/types.ts +4 -0
  275. package/src/types-internal/blok-modules.d.ts +2 -0
  276. package/types/api/blocks.d.ts +8 -0
  277. package/types/api/history.d.ts +33 -0
  278. package/types/api/index.d.ts +1 -0
  279. package/types/api/readonly.d.ts +12 -2
  280. package/types/index.d.ts +10 -0
  281. package/types/tools/table.d.ts +67 -0
  282. package/types/tools-entry.d.ts +4 -0
  283. package/types/utils/popover/popover-item.d.ts +6 -0
  284. package/types/utils/popover/popover.d.ts +7 -0
  285. package/dist/chunks/messages-CySyfkMU.mjs +0 -48
  286. package/dist/messages-CySyfkMU.mjs +0 -48
@@ -10,13 +10,14 @@ export const css = {
10
10
  * Note: noHover state is handled via [data-blok-popover-item-no-hover] which disables hover
11
11
  * Priority order: active < hover < focus (focus wins when navigating with keyboard)
12
12
  */
13
- item: 'flex items-center select-none border-none bg-transparent rounded-md p-[var(--item-padding)] text-text-primary mb-px [&[data-blok-popover-item-active]]:bg-icon-active-bg [&[data-blok-popover-item-active]]:text-icon-active-text can-hover:hover:cursor-pointer can-hover:hover:bg-item-hover-bg [&[data-blok-force-hover]]:cursor-pointer [&[data-blok-force-hover]]:bg-item-hover-bg [&[data-blok-focused="true"]]:bg-item-focus-bg [&[data-blok-popover-item-no-hover]]:hover:bg-transparent [&[data-blok-popover-item-no-hover]]:cursor-default',
13
+ item: 'flex items-center select-none border-none bg-transparent rounded-md px-2 py-[var(--item-padding)] text-text-primary mb-px [&[data-blok-popover-item-active]]:bg-icon-active-bg [&[data-blok-popover-item-active]]:text-icon-active-text can-hover:hover:cursor-pointer can-hover:hover:bg-item-hover-bg [&[data-blok-force-hover]]:cursor-pointer [&[data-blok-force-hover]]:bg-item-hover-bg [&[data-blok-focused="true"]]:bg-item-focus-bg [&[data-blok-popover-item-no-hover]]:hover:bg-transparent [&[data-blok-popover-item-no-hover]]:cursor-default can-hover:[&[data-blok-popover-item-destructive]]:hover:text-item-destructive-text can-hover:[&[data-blok-popover-item-destructive]]:hover:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-force-hover]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-force-hover]]:bg-item-destructive-hover-bg [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:text-item-destructive-text [&[data-blok-popover-item-destructive][data-blok-focused="true"]]:bg-item-destructive-hover-bg',
14
14
 
15
15
  /**
16
16
  * Item disabled state
17
17
  */
18
18
  itemDisabled: 'cursor-default pointer-events-none text-text-secondary',
19
19
 
20
+
20
21
  /**
21
22
  * Icon container styles
22
23
  */
@@ -206,6 +206,9 @@ export class PopoverItemDefault extends PopoverItem {
206
206
  if (params.isDisabled) {
207
207
  root.setAttribute(DATA_ATTR.disabled, 'true');
208
208
  }
209
+ if ('isDestructive' in params && params.isDestructive) {
210
+ root.setAttribute(DATA_ATTR.popoverItemDestructive, 'true');
211
+ }
209
212
  if (this.isActive) {
210
213
  root.setAttribute(DATA_ATTR.popoverItemActive, 'true');
211
214
  }
@@ -321,6 +324,8 @@ export class PopoverItemDefault extends PopoverItem {
321
324
 
322
325
  return twMerge(
323
326
  css.item,
327
+ // Asymmetric padding for vertical popovers (better visual balance)
328
+ !isInline && !isNestedInline && 'pl-2 pr-8',
324
329
  isInline && cssInline.item,
325
330
  isNestedInline && cssNestedInline.item,
326
331
  this.params.isDisabled && css.itemDisabled
@@ -335,7 +340,7 @@ export class PopoverItemDefault extends PopoverItem {
335
340
  css.icon,
336
341
  isInline && 'w-auto h-auto [&_svg]:w-icon [&_svg]:h-icon mobile:[&_svg]:w-icon-mobile mobile:[&_svg]:h-icon-mobile',
337
342
  isNestedInline && 'w-toolbox-btn h-toolbox-btn',
338
- iconWithGap && 'mr-2',
343
+ iconWithGap && 'mr-3',
339
344
  iconWithGap && isInline && 'shadow-none bg-transparent !mr-0',
340
345
  iconWithGap && isNestedInline && '!mr-2',
341
346
  isWobbling && 'animate-wobble'
@@ -11,3 +11,4 @@ export { PopoverItemType } from '@/types/utils/popover/popover-item-type';
11
11
  export type Popover = PopoverDesktop | PopoverMobile | PopoverInline;
12
12
 
13
13
  export { PopoverDesktop, PopoverMobile, PopoverInline };
14
+ export { PopoverRegistry } from './popover-registry';
@@ -7,6 +7,7 @@ import { PopoverItemDefault, PopoverItemSeparator, PopoverItemType } from './com
7
7
  import type { PopoverItem, PopoverItemRenderParamsMap , PopoverItemParams } from './components/popover-item';
8
8
  import { PopoverItemHtml } from './components/popover-item/popover-item-html/popover-item-html';
9
9
  import type { SearchInput } from './components/search-input';
10
+ import { PopoverRegistry } from './popover-registry';
10
11
  import { css } from './popover.const';
11
12
 
12
13
  import type { PopoverEventMap, PopoverMessages, PopoverParams, PopoverNodes } from '@/types/utils/popover/popover';
@@ -124,6 +125,13 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
124
125
  if (this.search !== undefined) {
125
126
  this.search.focus();
126
127
  }
128
+
129
+ const { trigger } = this.params;
130
+ const isRootWithTrigger = (this.params.nestingLevel ?? 0) === 0 && trigger !== undefined;
131
+
132
+ if (isRootWithTrigger) {
133
+ PopoverRegistry.instance.register(this, trigger);
134
+ }
127
135
  }
128
136
 
129
137
  /**
@@ -142,6 +150,8 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
142
150
  this.search.clear();
143
151
  }
144
152
 
153
+ PopoverRegistry.instance.unregister(this);
154
+
145
155
  this.emit(PopoverEvent.Closed);
146
156
  }
147
157
 
@@ -414,7 +424,7 @@ export abstract class PopoverAbstract<Nodes extends PopoverNodes = PopoverNodes>
414
424
  popover.setAttribute('data-blok-testid', 'popover');
415
425
 
416
426
  // Set CSS variables
417
- popover.style.setProperty('--width', this.params.width ?? '280px');
427
+ popover.style.setProperty('--width', this.params.width ?? 'auto');
418
428
  popover.style.setProperty('--item-padding', '3px');
419
429
  popover.style.setProperty('--item-height', 'calc(1.25rem + 2 * var(--item-padding))');
420
430
  popover.style.setProperty('--popover-top', 'calc(100% + 0.5rem)');
@@ -217,31 +217,50 @@ export class PopoverDesktop extends PopoverAbstract {
217
217
  this.flipper?.focusItem(0, { skipNextTab: true });
218
218
  }
219
219
 
220
+ /**
221
+ * Updates the popover position dynamically.
222
+ * Used when the trigger position changes or when positioning at caret location.
223
+ * @param position - new DOMRect position for the popover
224
+ */
225
+ public updatePosition(position: DOMRect): void {
226
+ this.params.position = position;
227
+
228
+ // Recalculate and apply position if already shown
229
+ if (this.nodes.popover.hasAttribute('data-blok-popover-opened')) {
230
+ const { top, left } = this.calculatePosition();
231
+
232
+ this.nodes.popover.style.top = `${top}px`;
233
+ this.nodes.popover.style.left = `${left}px`;
234
+ }
235
+ }
236
+
220
237
  /**
221
238
  * Calculates position for the popover
222
239
  */
223
240
  private calculatePosition(): { top: number; left: number } {
224
- if (!this.trigger) {
241
+ // Use provided position if available, otherwise fall back to trigger element
242
+ const rect = this.params.position ?? this.trigger?.getBoundingClientRect();
243
+
244
+ if (!rect) {
225
245
  return {
226
246
  top: 0,
227
247
  left: 0,
228
248
  };
229
249
  }
230
250
 
231
- const triggerRect = this.trigger.getBoundingClientRect();
232
251
  const popoverRect = this.size;
233
252
  const windowWidth = window.innerWidth;
234
253
  const windowHeight = window.innerHeight;
235
254
  const offset = 8;
236
255
 
237
- const initialTop = triggerRect.bottom + offset + window.scrollY;
238
- const shouldFlipTop = (triggerRect.bottom + offset + popoverRect.height > windowHeight + window.scrollY) &&
239
- (triggerRect.top - offset - popoverRect.height > window.scrollY);
240
- const top = shouldFlipTop ? triggerRect.top - offset - popoverRect.height + window.scrollY : initialTop;
256
+ const initialTop = rect.bottom + offset + window.scrollY;
257
+ const shouldFlipTop = (rect.bottom + offset + popoverRect.height > windowHeight + window.scrollY) &&
258
+ (rect.top - offset - popoverRect.height > window.scrollY);
259
+ const top = shouldFlipTop ? rect.top - offset - popoverRect.height + window.scrollY : initialTop;
241
260
 
242
- const initialLeft = triggerRect.left + window.scrollX;
261
+ const initialLeft = rect.left + window.scrollX;
243
262
  const shouldFlipLeft = initialLeft + popoverRect.width > windowWidth + window.scrollX;
244
- const left = shouldFlipLeft ? Math.max(0, triggerRect.right - popoverRect.width + window.scrollX) : initialLeft;
263
+ const left = shouldFlipLeft ? Math.max(0, rect.right - popoverRect.width + window.scrollX) : initialLeft;
245
264
 
246
265
  return {
247
266
  top,
@@ -0,0 +1,188 @@
1
+ import type { PopoverAbstract } from './popover-abstract';
2
+
3
+ /**
4
+ * Entry in the popover registry stack
5
+ */
6
+ interface PopoverRegistryEntry {
7
+ popover: PopoverAbstract;
8
+ triggerElement: HTMLElement;
9
+ }
10
+
11
+ /**
12
+ * Singleton registry that manages open popovers.
13
+ * Enforces mutual exclusion (only one popover open at a time)
14
+ * and handles click-outside-to-close behavior.
15
+ */
16
+ export class PopoverRegistry {
17
+ /**
18
+ * Singleton instance
19
+ */
20
+ private static _instance: PopoverRegistry | null = null;
21
+
22
+ /**
23
+ * Returns the singleton instance, creating it if necessary
24
+ */
25
+ static get instance(): PopoverRegistry {
26
+ if (PopoverRegistry._instance === null) {
27
+ PopoverRegistry._instance = new PopoverRegistry();
28
+ }
29
+
30
+ return PopoverRegistry._instance;
31
+ }
32
+
33
+ /**
34
+ * Resets the singleton for testing purposes.
35
+ * Destroys the existing instance and creates a fresh one.
36
+ */
37
+ static resetForTests(): PopoverRegistry {
38
+ PopoverRegistry._instance?.destroy();
39
+ PopoverRegistry._instance = new PopoverRegistry();
40
+
41
+ return PopoverRegistry._instance;
42
+ }
43
+
44
+ /**
45
+ * Stack of currently registered popover entries
46
+ */
47
+ private stack: PopoverRegistryEntry[] = [];
48
+
49
+ /**
50
+ * Bound reference to the pointerdown handler for add/remove symmetry
51
+ */
52
+ private boundPointerDown: ((e: PointerEvent) => void) | null = null;
53
+
54
+ /**
55
+ * Registers a popover with mutual exclusion.
56
+ * Closes all existing popovers, then adds the new one to the stack.
57
+ * @param popover - the popover instance to register
58
+ * @param triggerElement - the element that triggered this popover
59
+ */
60
+ public register(popover: PopoverAbstract, triggerElement: HTMLElement): void {
61
+ const existingEntries = [...this.stack];
62
+
63
+ for (const entry of existingEntries) {
64
+ if (entry.popover === popover) {
65
+ continue;
66
+ }
67
+ entry.popover.hide();
68
+ this.removeFromStack(entry.popover);
69
+ }
70
+
71
+ this.stack.push({ popover, triggerElement });
72
+ this.ensureDocumentListener();
73
+ }
74
+
75
+ /**
76
+ * Unregisters a popover, removing it from the stack.
77
+ * Removes the document listener if the stack becomes empty.
78
+ * @param popover - the popover instance to unregister
79
+ */
80
+ public unregister(popover: PopoverAbstract): void {
81
+ this.removeFromStack(popover);
82
+
83
+ if (this.stack.length === 0) {
84
+ this.removeDocumentListener();
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Closes the topmost popover on the stack by calling hide().
90
+ * @returns true if a popover was closed, false if the stack was empty
91
+ */
92
+ public closeTopmost(): boolean {
93
+ if (this.stack.length === 0) {
94
+ return false;
95
+ }
96
+
97
+ const topmost = this.stack[this.stack.length - 1];
98
+
99
+ topmost.popover.hide();
100
+
101
+ return true;
102
+ }
103
+
104
+ /**
105
+ * Checks whether any popovers are currently registered
106
+ */
107
+ public hasOpenPopovers(): boolean {
108
+ return this.stack.length > 0;
109
+ }
110
+
111
+ /**
112
+ * Cleans up the registry: removes the document listener and clears the stack
113
+ */
114
+ public destroy(): void {
115
+ this.removeDocumentListener();
116
+ this.stack = [];
117
+ }
118
+
119
+ /**
120
+ * Handles pointerdown events on the document.
121
+ * Walks the stack in reverse (topmost first). For each entry:
122
+ * - If the click target is inside the popover, stop (click is inside).
123
+ * - If the click target is inside the trigger element, stop (click is on trigger).
124
+ * - Otherwise, close the popover by calling hide().
125
+ * @param event - the pointerdown event
126
+ */
127
+ private handleDocumentPointerDown(event: PointerEvent): void {
128
+ const target = event.target;
129
+
130
+ if (!(target instanceof Node)) {
131
+ return;
132
+ }
133
+
134
+ const entriesToClose: PopoverRegistryEntry[] = [];
135
+
136
+ for (const entry of [...this.stack].reverse()) {
137
+ if (entry.popover.hasNode(target)) {
138
+ break;
139
+ }
140
+
141
+ if (entry.triggerElement.contains(target)) {
142
+ break;
143
+ }
144
+
145
+ entriesToClose.push(entry);
146
+ }
147
+
148
+ for (const entry of entriesToClose) {
149
+ entry.popover.hide();
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Lazily adds the pointerdown listener to the document when there are entries in the stack
155
+ */
156
+ private ensureDocumentListener(): void {
157
+ if (this.boundPointerDown !== null) {
158
+ return;
159
+ }
160
+
161
+ this.boundPointerDown = (e: PointerEvent): void => this.handleDocumentPointerDown(e);
162
+ document.addEventListener('pointerdown', this.boundPointerDown);
163
+ }
164
+
165
+ /**
166
+ * Removes the pointerdown listener from the document
167
+ */
168
+ private removeDocumentListener(): void {
169
+ if (this.boundPointerDown === null) {
170
+ return;
171
+ }
172
+
173
+ document.removeEventListener('pointerdown', this.boundPointerDown);
174
+ this.boundPointerDown = null;
175
+ }
176
+
177
+ /**
178
+ * Removes a popover from the stack by reference
179
+ * @param popover - popover to remove
180
+ */
181
+ private removeFromStack(popover: PopoverAbstract): void {
182
+ const index = this.stack.findIndex(entry => entry.popover === popover);
183
+
184
+ if (index !== -1) {
185
+ this.stack.splice(index, 1);
186
+ }
187
+ }
188
+ }
@@ -30,7 +30,7 @@
30
30
  import HTMLJanitor from 'html-janitor';
31
31
 
32
32
  import type { BlockToolData, SanitizerConfig, SanitizerRule } from '../../../types';
33
- import type { TagConfig } from '../../../types/configs/sanitizer-config';
33
+ import type { TagConfig, ToolSanitizerConfig } from '../../../types/configs/sanitizer-config';
34
34
  import type { SavedData } from '../../../types/data-formats';
35
35
  import { deepMerge, isBoolean, isEmpty, isFunction, isObject, isString } from '../utils';
36
36
 
@@ -55,7 +55,7 @@ const UNSAFE_URL_ATTR_FALLBACK_PATTERN =
55
55
  */
56
56
  export const sanitizeBlocks = (
57
57
  blocksData: Array<Pick<SavedData, 'data' | 'tool'>>,
58
- sanitizeConfig: SanitizerConfig | ((toolName: string) => SanitizerConfig | undefined),
58
+ sanitizeConfig: SanitizerConfig | ToolSanitizerConfig | ((toolName: string) => SanitizerConfig | ToolSanitizerConfig | undefined),
59
59
  globalSanitizer: SanitizerConfig = {} as SanitizerConfig
60
60
  ): Array<Pick<SavedData, 'data' | 'tool'>> => {
61
61
  return blocksData.map((block) => {
@@ -400,6 +400,27 @@ const mergeTagRules = (globalRules: SanitizerConfig, fieldRules: SanitizerConfig
400
400
  merged[tag] = cloneTagConfig(globalValue);
401
401
  }
402
402
 
403
+ /**
404
+ * Include tags from field rules that are not present in global rules.
405
+ * Tool-specific sanitize configs should be able to allow tags
406
+ * beyond what the global config defines.
407
+ */
408
+ if (!fieldRules) {
409
+ return merged;
410
+ }
411
+
412
+ for (const tag in fieldRules) {
413
+ if (!Object.prototype.hasOwnProperty.call(fieldRules, tag)) {
414
+ continue;
415
+ }
416
+
417
+ if (Object.prototype.hasOwnProperty.call(merged, tag)) {
418
+ continue;
419
+ }
420
+
421
+ merged[tag] = cloneTagConfig(fieldRules[tag]);
422
+ }
423
+
403
424
  return merged;
404
425
  };
405
426
 
@@ -55,12 +55,6 @@ type CSSTooltipClasses = {
55
55
  tooltip: string | string[];
56
56
  tooltipContent: string | string[];
57
57
  tooltipShown: string | string[];
58
- placement: {
59
- left: string | string[];
60
- bottom: string | string[];
61
- right: string | string[];
62
- top: string | string[];
63
- };
64
58
  };
65
59
 
66
60
  /**
@@ -79,9 +73,7 @@ class Tooltip {
79
73
  'absolute z-overlay top-0 left-0',
80
74
  'bg-tooltip-bg opacity-0',
81
75
  'select-none pointer-events-none',
82
- 'transition-[opacity,transform] duration-[50ms,70ms] ease-in',
83
76
  'rounded-lg shadow-tooltip',
84
- 'will-change-[opacity,top,left]',
85
77
  'before:content-[\'\'] before:absolute before:inset-0 before:bg-tooltip-bg before:-z-10 before:rounded-lg',
86
78
  'mobile:hidden'
87
79
  ).split(' '),
@@ -90,13 +82,7 @@ class Tooltip {
90
82
  'text-tooltip-font text-xs text-center',
91
83
  'tracking-[0.02em] leading-[1em]'
92
84
  ).split(' '),
93
- tooltipShown: ['opacity-100', 'transform-none'],
94
- placement: {
95
- left: ['-translate-x-[5px]'],
96
- bottom: ['translate-y-[5px]'],
97
- right: ['translate-x-[5px]'],
98
- top: ['-translate-y-[5px]'],
99
- },
85
+ tooltipShown: ['opacity-100'],
100
86
  };
101
87
  }
102
88
 
@@ -193,7 +179,7 @@ class Tooltip {
193
179
  marginLeft: 0,
194
180
  marginRight: 0,
195
181
  marginBottom: 0,
196
- delay: 70,
182
+ delay: 0,
197
183
  };
198
184
  const showingOptions = Object.assign(basicOptions, options);
199
185
 
@@ -208,11 +194,6 @@ class Tooltip {
208
194
  return;
209
195
  }
210
196
 
211
- // Flatten the placement classes (each can be a string or array) before removing
212
- const placementClasses = Object.values(this.CSS.placement).flatMap(cls => Array.isArray(cls) ? cls : [cls]);
213
-
214
- this.nodes.wrapper.classList.remove(...placementClasses);
215
-
216
197
  switch (showingOptions.placement) {
217
198
  case 'top':
218
199
  this.placeTop(element, showingOptions);
@@ -503,9 +484,6 @@ class Tooltip {
503
484
  return;
504
485
  }
505
486
 
506
- const classes = Array.isArray(this.CSS.placement[place]) ? this.CSS.placement[place] : [this.CSS.placement[place]];
507
-
508
- this.nodes.wrapper.classList.add(...classes);
509
487
  this.nodes.wrapper.setAttribute('data-blok-placement', place);
510
488
 
511
489
  this.nodes.wrapper.style.left = `${left}px`;
@@ -124,3 +124,25 @@
124
124
  [data-blok-selected="true"] [data-list-style] [role="listitem"] [contenteditable] {
125
125
  @apply select-none;
126
126
  }
127
+
128
+ /**
129
+ * Table cell block wrapper overrides
130
+ * Strip all nested spacing so only the cell's own padding (py-1 px-2) provides spacing.
131
+ * Targets: block wrapper (py/my), .blok-block (py/px), and tool elements (mt/mb).
132
+ */
133
+ [data-blok-table-cell-blocks] > [data-blok-element] {
134
+ @apply py-0 my-0;
135
+ }
136
+
137
+ [data-blok-table-cell-blocks] .blok-block {
138
+ @apply p-0 m-0;
139
+ }
140
+
141
+ /**
142
+ * Table heading styles
143
+ * Applied to first row (heading row) and first column (heading column) cells
144
+ */
145
+ [data-blok-table-heading] [data-blok-table-cell],
146
+ [data-blok-table-heading-col] {
147
+ @apply font-semibold bg-gray-50;
148
+ }
@@ -13,13 +13,13 @@ import type {
13
13
  PasteEvent,
14
14
  ToolboxConfig,
15
15
  ConversionConfig,
16
- SanitizerConfig,
16
+ ToolSanitizerConfig,
17
17
  PasteConfig,
18
18
  } from '../../../types';
19
19
  import { DATA_ATTR } from '../../components/constants';
20
20
  import { IconText } from '../../components/icons';
21
21
  import { stripFakeBackgroundElements } from '../../components/utils';
22
- import { PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
22
+ import { PLACEHOLDER_EMPTY_EDITOR_CLASSES, PLACEHOLDER_FOCUS_ONLY_CLASSES, setupPlaceholder } from '../../components/utils/placeholder';
23
23
  import { twMerge } from '../../components/utils/tw';
24
24
 
25
25
  /**
@@ -239,7 +239,8 @@ export class Paragraph implements BlockTool {
239
239
  div.className = twMerge(
240
240
  this.api.styles.block,
241
241
  Paragraph.WRAPPER_CLASSES,
242
- PLACEHOLDER_FOCUS_ONLY_CLASSES
242
+ PLACEHOLDER_FOCUS_ONLY_CLASSES,
243
+ PLACEHOLDER_EMPTY_EDITOR_CLASSES
243
244
  );
244
245
  div.setAttribute(DATA_ATTR.tool, 'paragraph');
245
246
  div.contentEditable = 'false';
@@ -369,10 +370,17 @@ export class Paragraph implements BlockTool {
369
370
  *
370
371
  * @returns SanitizerConfig
371
372
  */
372
- public static get sanitize(): SanitizerConfig {
373
+ public static get sanitize(): ToolSanitizerConfig {
373
374
  return {
374
375
  text: {
375
376
  br: true,
377
+ img: {
378
+ src: true,
379
+ style: true,
380
+ },
381
+ p: true,
382
+ ul: true,
383
+ li: true,
376
384
  },
377
385
  };
378
386
  }
@@ -25,6 +25,7 @@ export const normalizeTableData = (
25
25
  ): TableData => {
26
26
  return {
27
27
  withHeadings: (data.withHeadings as boolean) ?? defaults?.withHeadings ?? false,
28
+ withHeadingColumn: (data.withHeadingColumn as boolean) ?? false,
28
29
  stretched: (data.stretched as boolean) ?? defaults?.stretched ?? false,
29
30
  content: Array.isArray(data.content) ? data.content as string[][] : [],
30
31
  };