@jackuait/blok 0.10.0-beta.4 → 0.10.0-beta.6

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 (355) hide show
  1. package/dist/blok.mjs +3 -3
  2. package/dist/chunks/{blok-D_0qAdUd.mjs → blok-BdlR_lX6.mjs} +2073 -2034
  3. package/dist/chunks/chunk-Byubey_H.mjs +20 -0
  4. package/dist/chunks/{constants-DxSXr7kd.mjs → constants-Cp8O0UfP.mjs} +524 -550
  5. package/dist/chunks/default-DIfXCS2E.mjs +4 -0
  6. package/dist/chunks/{i18next-G6FKbZqA.mjs → i18next-KNC_XV5x.mjs} +1 -1
  7. package/dist/chunks/{i18next-loader-CwNimni3.mjs → i18next-loader-oDO9ZKUV.mjs} +2 -2
  8. package/dist/chunks/katex-NjLaA6AJ.mjs +22026 -0
  9. package/dist/chunks/{lightweight-i18n-DWCdzAw0.mjs → lightweight-i18n-DTySD6f6.mjs} +16 -18
  10. package/dist/chunks/mdast-util-math-yS0EygZV.mjs +151 -0
  11. package/dist/{messages-DVQNjdPk.mjs → chunks/messages-5ArOv8cj.mjs} +3 -17
  12. package/dist/chunks/{messages-Czny5pPT2.mjs → messages-876bKyUj2.mjs} +3 -17
  13. package/dist/{messages-JhoVMjfX2.mjs → chunks/messages-9l49jauY.mjs} +3 -17
  14. package/dist/{messages-D3cAcyzj.mjs → chunks/messages-B5aAzExz.mjs} +3 -17
  15. package/dist/chunks/{messages-CmrMwBv3.mjs → messages-B5fKJXd6.mjs} +3 -17
  16. package/dist/chunks/{messages-DBpXyvRe2.mjs → messages-B9N__q552.mjs} +3 -17
  17. package/dist/{messages-CVcQD-9u.mjs → chunks/messages-BAP2OAQk.mjs} +3 -17
  18. package/dist/chunks/{messages-R2W_rGOo2.mjs → messages-BDXl53cy2.mjs} +3 -17
  19. package/dist/{messages-CM5fsPo02.mjs → chunks/messages-BGCQCeWd.mjs} +3 -17
  20. package/dist/{messages-DtrSrdfE2.mjs → chunks/messages-BHhbHLoq.mjs} +3 -17
  21. package/dist/{messages-C6Y4Jv2N.mjs → chunks/messages-BMq9k_lI.mjs} +3 -17
  22. package/dist/{messages-DjJQoYvP2.mjs → chunks/messages-BXSXk3oS2.mjs} +3 -17
  23. package/dist/{messages-pgPcitDH.mjs → chunks/messages-BXn9Vzbx2.mjs} +3 -17
  24. package/dist/chunks/{messages-DR09nkcZ.mjs → messages-BaoJwsEZ.mjs} +3 -17
  25. package/dist/{messages-CdlsTFB1.mjs → chunks/messages-BbfLRqLh2.mjs} +3 -17
  26. package/dist/{messages-BvgTQLf72.mjs → chunks/messages-BhcYsC_M2.mjs} +3 -17
  27. package/dist/chunks/{messages-Cdx4QMR1.mjs → messages-BlO_37l_.mjs} +3 -17
  28. package/dist/{messages--S8_taOd2.mjs → chunks/messages-BlcRm2I3.mjs} +3 -17
  29. package/dist/{messages-DbxbxUiK2.mjs → chunks/messages-Btr121zI2.mjs} +3 -17
  30. package/dist/chunks/{messages-p4byLfvR.mjs → messages-BxBID_0B.mjs} +3 -17
  31. package/dist/chunks/{messages-Cs9XBt4T.mjs → messages-ByAqzAhB.mjs} +3 -17
  32. package/dist/chunks/{messages-JQKFJo7C.mjs → messages-C-jA6Rf7.mjs} +3 -17
  33. package/dist/{messages-BAcH6PtT2.mjs → chunks/messages-C5aCWL7B.mjs} +3 -17
  34. package/dist/{messages-BCG_evLg.mjs → chunks/messages-CF_PfacZ.mjs} +3 -17
  35. package/dist/{messages-B-4fku2H2.mjs → chunks/messages-CKRJDX0K2.mjs} +3 -17
  36. package/dist/chunks/{messages-CrMfiGu5.mjs → messages-CL3mCbi6.mjs} +3 -17
  37. package/dist/chunks/{messages-BnznaKEP2.mjs → messages-CNEJxD8q2.mjs} +3 -17
  38. package/dist/{messages-hTpeKUaW.mjs → chunks/messages-CZ5Sbf8U.mjs} +3 -17
  39. package/dist/chunks/{messages-CljStrYi.mjs → messages-CcyIKgGU.mjs} +3 -17
  40. package/dist/{messages-Dcyrzdxa2.mjs → chunks/messages-CdzF0Hvl.mjs} +3 -17
  41. package/dist/chunks/{messages-IDEUsFhQ2.mjs → messages-CgedvWCf.mjs} +3 -17
  42. package/dist/chunks/{messages-CmXADeab2.mjs → messages-CjVPwkVy.mjs} +3 -17
  43. package/dist/chunks/{messages-wLSVQbsA2.mjs → messages-CnQydQJd2.mjs} +3 -17
  44. package/dist/chunks/{messages-BS1nOvZ-.mjs → messages-CqgEz7C5.mjs} +3 -17
  45. package/dist/{messages-BCuTVHBV.mjs → chunks/messages-CvlMT1e62.mjs} +3 -17
  46. package/dist/{messages-CYX48nfg.mjs → chunks/messages-CyxDkx8a.mjs} +3 -17
  47. package/dist/chunks/{messages-ClRHDxzh.mjs → messages-D7n_wJK7.mjs} +3 -17
  48. package/dist/chunks/{messages-Dplnp19q.mjs → messages-D8-N0FmU.mjs} +3 -17
  49. package/dist/chunks/{messages-DAVsuDWh2.mjs → messages-D8dKkyII2.mjs} +3 -17
  50. package/dist/chunks/{messages-B3s2vra72.mjs → messages-DGD6BiGd.mjs} +3 -17
  51. package/dist/chunks/{messages-DHCVA7XQ.mjs → messages-DJO0ERQT.mjs} +3 -17
  52. package/dist/chunks/{messages-B7MIRzCa2.mjs → messages-DMyRdafk2.mjs} +3 -17
  53. package/dist/chunks/{messages-C-b6tPad2.mjs → messages-DN-194c32.mjs} +3 -17
  54. package/dist/chunks/{messages-BW_7lfqG2.mjs → messages-DQ5ng0_t2.mjs} +3 -17
  55. package/dist/{messages-DUBHHfEt.mjs → chunks/messages-DRv4g-IA.mjs} +3 -17
  56. package/dist/chunks/{messages-xfjdrZmx.mjs → messages-DSO2U-ul.mjs} +3 -17
  57. package/dist/{messages-CgzbJ8_l2.mjs → chunks/messages-DUGEqDEG.mjs} +3 -17
  58. package/dist/{messages-DA-o8X3A.mjs → chunks/messages-DVKifYlq.mjs} +3 -17
  59. package/dist/{messages-tsHpMdDT2.mjs → chunks/messages-DWD0ry9x.mjs} +3 -17
  60. package/dist/{messages-Dddxv8-f2.mjs → chunks/messages-DYizZHT2.mjs} +3 -17
  61. package/dist/chunks/{messages-Csvm4mtA.mjs → messages-DZwCufSb.mjs} +3 -17
  62. package/dist/{messages-BJ7BuFZi.mjs → chunks/messages-DdmWzF5M.mjs} +3 -17
  63. package/dist/{messages-Bo_FUvVH.mjs → chunks/messages-DgEGJECT.mjs} +3 -17
  64. package/dist/chunks/{messages-Bpda_3PM2.mjs → messages-Dgng6KN8.mjs} +3 -17
  65. package/dist/{messages-CBzd_x7H.mjs → chunks/messages-DkTxBa1V.mjs} +3 -17
  66. package/dist/{messages-Bio7KYsr2.mjs → chunks/messages-DnJHflSh.mjs} +3 -17
  67. package/dist/{messages-CjmSrt1D.mjs → chunks/messages-DopbvJlg.mjs} +3 -17
  68. package/dist/{messages-DIRha_gg2.mjs → chunks/messages-Dux1S0-D2.mjs} +3 -17
  69. package/dist/chunks/{messages-1Raf1IK82.mjs → messages-Dw2rmKMi2.mjs} +3 -17
  70. package/dist/chunks/{messages-D5IgUbBD2.mjs → messages-Dz3UhEco2.mjs} +3 -17
  71. package/dist/{messages-C6OJvnJg2.mjs → chunks/messages-FYl9woii2.mjs} +3 -17
  72. package/dist/{messages-BBvDbp62.mjs → chunks/messages-Jps5Tc77.mjs} +3 -17
  73. package/dist/chunks/{messages-Dfpi8pDY.mjs → messages-NJsvFwJj.mjs} +3 -17
  74. package/dist/chunks/{messages-DPykxECP2.mjs → messages-SSDr5fGF2.mjs} +3 -17
  75. package/dist/{messages-BXI3qIos.mjs → chunks/messages-bmwto4UV.mjs} +3 -17
  76. package/dist/{messages-CBdQ3XP9.mjs → chunks/messages-vN4T4r67.mjs} +3 -17
  77. package/dist/{messages-tK67CBqn.mjs → chunks/messages-yszqJukE.mjs} +3 -17
  78. package/dist/chunks/micromark-extension-math-CCEGWpdz.mjs +169 -0
  79. package/dist/chunks/micromark-factory-space-WwmyBO_J.mjs +36 -0
  80. package/dist/chunks/{notifier-Butv4Dvo.mjs → notifier-BOwxj_Ok.mjs} +1 -1
  81. package/dist/chunks/{objectSpread2-BY4mgzrQ.mjs → objectSpread2-CWwMYL_U.mjs} +1 -1
  82. package/dist/chunks/{tools-DVZ3zU40.mjs → tools-DGOsJbHH.mjs} +1816 -2916
  83. package/dist/full.mjs +14 -14
  84. package/dist/locales.mjs +82 -84
  85. package/dist/markdown.mjs +3962 -0
  86. package/dist/{messages-DqyqEw1_.mjs → messages--cUQf9JX.mjs} +3 -17
  87. package/dist/{messages-BtxaN-xx.mjs → messages-12_eyAo-.mjs} +3 -17
  88. package/dist/{chunks/messages-LxumrNue2.mjs → messages-B3Yhiycb2.mjs} +3 -17
  89. package/dist/{chunks/messages-Cqc-6rfh2.mjs → messages-B4lhNMKm2.mjs} +3 -17
  90. package/dist/{chunks/messages-B0ffBqzr.mjs → messages-BOE2mzCj2.mjs} +3 -17
  91. package/dist/{chunks/messages-BaPZuLjN.mjs → messages-BPL7riv-.mjs} +3 -17
  92. package/dist/{messages-DD5pW0zJ.mjs → messages-BYQ769S5.mjs} +3 -17
  93. package/dist/{chunks/messages-C11byid72.mjs → messages-B_sKqaeK.mjs} +3 -17
  94. package/dist/{messages-BmNaAyKS.mjs → messages-Bdk4ocMI.mjs} +3 -17
  95. package/dist/{chunks/messages-6mikOS4D2.mjs → messages-BeI2HORe2.mjs} +3 -17
  96. package/dist/{chunks/messages-u2yxkNTE2.mjs → messages-Bug6Du35.mjs} +3 -17
  97. package/dist/{messages-eTourT12.mjs → messages-C2veeQpU.mjs} +3 -17
  98. package/dist/{messages-BokEflKa.mjs → messages-C5Uufygq.mjs} +3 -17
  99. package/dist/{chunks/messages-BPog17132.mjs → messages-C8f1I5EQ2.mjs} +3 -17
  100. package/dist/{chunks/messages-ID1PHnMv.mjs → messages-CBPiFbEf2.mjs} +3 -17
  101. package/dist/{messages-DZEcrbmH.mjs → messages-CByBLxWk.mjs} +3 -17
  102. package/dist/{chunks/messages-BgVEGd4c.mjs → messages-CD8K1g_t2.mjs} +3 -17
  103. package/dist/{messages-Dkg99bfr2.mjs → messages-CEEzfqMO2.mjs} +3 -17
  104. package/dist/{messages-DV9e1DW7.mjs → messages-CNNcKuGH.mjs} +3 -17
  105. package/dist/{messages-C30Vz-UZ2.mjs → messages-CSl0Wla62.mjs} +3 -17
  106. package/dist/{messages-fLi0P2dP.mjs → messages-CUzBNjnc.mjs} +3 -17
  107. package/dist/{chunks/messages-DJA6fb_P2.mjs → messages-CWEL1WDy2.mjs} +3 -17
  108. package/dist/{messages-BcFQFcJ92.mjs → messages-C_HmWyXc2.mjs} +3 -17
  109. package/dist/{chunks/messages-CpzO7KRA.mjs → messages-Cb3wXGnc.mjs} +3 -17
  110. package/dist/{messages-C5XPUD9T2.mjs → messages-Cd23UgLV2.mjs} +3 -17
  111. package/dist/{chunks/messages-DSjXen8E.mjs → messages-Cg1CF4pw.mjs} +3 -17
  112. package/dist/{messages-i4S6q64n2.mjs → messages-CgEDVri-2.mjs} +3 -17
  113. package/dist/{messages-CHJ5SOZI.mjs → messages-ChTWmxS8.mjs} +3 -17
  114. package/dist/{messages-BVKZK-3t.mjs → messages-Cho2VTAX.mjs} +3 -17
  115. package/dist/{chunks/messages-d0Ky6QjR.mjs → messages-CkySRhtd2.mjs} +3 -17
  116. package/dist/{chunks/messages-C1OqT_nL.mjs → messages-Clsh86WQ.mjs} +3 -17
  117. package/dist/{chunks/messages-BrFl5773.mjs → messages-CsiGzUSP2.mjs} +3 -17
  118. package/dist/{messages-BKjqW08U.mjs → messages-Cv-DKlZd.mjs} +3 -17
  119. package/dist/{messages-BGsDZTQp2.mjs → messages-CvvbLyTy2.mjs} +3 -17
  120. package/dist/{chunks/messages-DA7Zk-Cy.mjs → messages-CwCEcbWG.mjs} +3 -17
  121. package/dist/{chunks/messages-DQ5AyNCU.mjs → messages-D38h5XlF.mjs} +3 -17
  122. package/dist/{chunks/messages-DC7TX-YT.mjs → messages-D7juvhHp.mjs} +3 -17
  123. package/dist/{chunks/messages-BdnSVKOw.mjs → messages-D8WvwU42.mjs} +3 -17
  124. package/dist/{chunks/messages-Df87zXXG.mjs → messages-DACg1XAu.mjs} +3 -17
  125. package/dist/{messages-BBq0M604.mjs → messages-DIKCwGog.mjs} +3 -17
  126. package/dist/{messages-Ccd587Yn.mjs → messages-DJU4YLij.mjs} +3 -17
  127. package/dist/{chunks/messages-Dm4YVlrm.mjs → messages-DQN1y6E9.mjs} +3 -17
  128. package/dist/{messages-CqkRG9mH.mjs → messages-DRU_IgoW.mjs} +3 -17
  129. package/dist/{chunks/messages-DT7fRpCy.mjs → messages-DbZsJAff.mjs} +3 -17
  130. package/dist/{messages-upqrRZQH2.mjs → messages-Dg2CDXZi2.mjs} +3 -17
  131. package/dist/{messages-DJKLtW7u.mjs → messages-Dj79y02X.mjs} +3 -17
  132. package/dist/{chunks/messages-Ct7AMBS82.mjs → messages-DjWfVYHS2.mjs} +3 -17
  133. package/dist/{chunks/messages-B2pW6jO_.mjs → messages-DkvQ-6HC2.mjs} +3 -17
  134. package/dist/{chunks/messages-ZJ0b1C3a.mjs → messages-DnhEzmXJ2.mjs} +3 -17
  135. package/dist/{chunks/messages-BgsPQXfP.mjs → messages-DqJTZbwt.mjs} +3 -17
  136. package/dist/{chunks/messages-DUDgFEEe2.mjs → messages-Dq_v7slw2.mjs} +3 -17
  137. package/dist/{chunks/messages-CyNsByCY.mjs → messages-En8LDjUB.mjs} +3 -17
  138. package/dist/{chunks/messages-FHrCEJmY2.mjs → messages-JK9Okzsy2.mjs} +3 -17
  139. package/dist/{messages-DnatBKPm.mjs → messages-KSxF8eib.mjs} +3 -17
  140. package/dist/{chunks/messages-DD7BI6BK.mjs → messages-KbYSpNrE.mjs} +3 -17
  141. package/dist/{messages-BvgXeMSL2.mjs → messages-KqWQKmIu2.mjs} +3 -17
  142. package/dist/{messages-BSe3QDnQ.mjs → messages-PvMdmlxI.mjs} +3 -17
  143. package/dist/{chunks/messages-DJkIeapn.mjs → messages-So3SHdIc2.mjs} +3 -17
  144. package/dist/{messages-BywbKcPC.mjs → messages-X80Nh0ib.mjs} +3 -17
  145. package/dist/{messages-DOTJ2NvJ.mjs → messages-hrSlVSHp.mjs} +3 -17
  146. package/dist/{messages-DJT4Bt_02.mjs → messages-mipkPgwQ2.mjs} +3 -17
  147. package/dist/{messages-xEI8gEDK.mjs → messages-nOe1gJYu.mjs} +3 -17
  148. package/dist/{messages-Bk984gRE2.mjs → messages-rbox5gSb2.mjs} +3 -17
  149. package/dist/{chunks/messages-CgRvtOEY.mjs → messages-uCsQjz7M.mjs} +3 -17
  150. package/dist/{chunks/messages-BbdNugdi.mjs → messages-vcoib5Ga.mjs} +3 -17
  151. package/dist/{chunks/messages-CvfKofOP.mjs → messages-vptt-pVF.mjs} +3 -17
  152. package/dist/{chunks/messages-BkCjgGxc.mjs → messages-x353UCBI.mjs} +3 -17
  153. package/dist/react.mjs +3 -3
  154. package/dist/tools.mjs +3 -3
  155. package/dist/vendor.LICENSE.txt +1622 -182
  156. package/package.json +15 -2
  157. package/src/components/blocks.ts +26 -1
  158. package/src/components/i18n/locales/am/messages.json +3 -17
  159. package/src/components/i18n/locales/ar/messages.json +3 -17
  160. package/src/components/i18n/locales/az/messages.json +3 -17
  161. package/src/components/i18n/locales/bg/messages.json +3 -17
  162. package/src/components/i18n/locales/bn/messages.json +3 -17
  163. package/src/components/i18n/locales/bs/messages.json +3 -17
  164. package/src/components/i18n/locales/cs/messages.json +3 -17
  165. package/src/components/i18n/locales/da/messages.json +3 -17
  166. package/src/components/i18n/locales/de/messages.json +3 -17
  167. package/src/components/i18n/locales/dv/messages.json +3 -17
  168. package/src/components/i18n/locales/el/messages.json +3 -17
  169. package/src/components/i18n/locales/en/messages.json +15 -17
  170. package/src/components/i18n/locales/es/messages.json +3 -17
  171. package/src/components/i18n/locales/et/messages.json +3 -17
  172. package/src/components/i18n/locales/fa/messages.json +3 -17
  173. package/src/components/i18n/locales/fi/messages.json +3 -17
  174. package/src/components/i18n/locales/fil/messages.json +3 -17
  175. package/src/components/i18n/locales/fr/messages.json +3 -17
  176. package/src/components/i18n/locales/gu/messages.json +3 -17
  177. package/src/components/i18n/locales/he/messages.json +3 -17
  178. package/src/components/i18n/locales/hi/messages.json +3 -17
  179. package/src/components/i18n/locales/hr/messages.json +3 -17
  180. package/src/components/i18n/locales/hu/messages.json +3 -17
  181. package/src/components/i18n/locales/hy/messages.json +3 -17
  182. package/src/components/i18n/locales/id/messages.json +3 -17
  183. package/src/components/i18n/locales/it/messages.json +3 -17
  184. package/src/components/i18n/locales/ja/messages.json +3 -17
  185. package/src/components/i18n/locales/ka/messages.json +3 -17
  186. package/src/components/i18n/locales/km/messages.json +3 -17
  187. package/src/components/i18n/locales/kn/messages.json +3 -17
  188. package/src/components/i18n/locales/ko/messages.json +3 -17
  189. package/src/components/i18n/locales/ku/messages.json +3 -17
  190. package/src/components/i18n/locales/lo/messages.json +3 -17
  191. package/src/components/i18n/locales/lt/messages.json +3 -17
  192. package/src/components/i18n/locales/lv/messages.json +3 -17
  193. package/src/components/i18n/locales/mk/messages.json +3 -17
  194. package/src/components/i18n/locales/ml/messages.json +3 -17
  195. package/src/components/i18n/locales/mn/messages.json +3 -17
  196. package/src/components/i18n/locales/mr/messages.json +3 -17
  197. package/src/components/i18n/locales/ms/messages.json +3 -17
  198. package/src/components/i18n/locales/my/messages.json +3 -17
  199. package/src/components/i18n/locales/ne/messages.json +3 -17
  200. package/src/components/i18n/locales/nl/messages.json +3 -17
  201. package/src/components/i18n/locales/no/messages.json +3 -17
  202. package/src/components/i18n/locales/pa/messages.json +3 -17
  203. package/src/components/i18n/locales/pl/messages.json +3 -17
  204. package/src/components/i18n/locales/ps/messages.json +3 -17
  205. package/src/components/i18n/locales/pt/messages.json +3 -17
  206. package/src/components/i18n/locales/ro/messages.json +3 -17
  207. package/src/components/i18n/locales/ru/messages.json +3 -17
  208. package/src/components/i18n/locales/sd/messages.json +3 -17
  209. package/src/components/i18n/locales/si/messages.json +3 -17
  210. package/src/components/i18n/locales/sk/messages.json +3 -17
  211. package/src/components/i18n/locales/sl/messages.json +3 -17
  212. package/src/components/i18n/locales/sq/messages.json +3 -17
  213. package/src/components/i18n/locales/sr/messages.json +3 -17
  214. package/src/components/i18n/locales/sv/messages.json +3 -17
  215. package/src/components/i18n/locales/sw/messages.json +3 -17
  216. package/src/components/i18n/locales/ta/messages.json +3 -17
  217. package/src/components/i18n/locales/te/messages.json +3 -17
  218. package/src/components/i18n/locales/th/messages.json +3 -17
  219. package/src/components/i18n/locales/tr/messages.json +3 -17
  220. package/src/components/i18n/locales/ug/messages.json +3 -17
  221. package/src/components/i18n/locales/uk/messages.json +3 -17
  222. package/src/components/i18n/locales/ur/messages.json +3 -17
  223. package/src/components/i18n/locales/vi/messages.json +3 -17
  224. package/src/components/i18n/locales/yi/messages.json +3 -17
  225. package/src/components/i18n/locales/zh/messages.json +3 -17
  226. package/src/components/icons/index.ts +30 -56
  227. package/src/components/inline-tools/inline-tool-code.ts +399 -0
  228. package/src/components/modules/api/blocks.ts +17 -0
  229. package/src/components/modules/api/tools.ts +0 -19
  230. package/src/components/modules/blockEvents/composers/blockSelectionKeys.ts +20 -3
  231. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +5 -5
  232. package/src/components/modules/blockManager/blockManager.ts +0 -11
  233. package/src/components/modules/blockManager/event-binder.ts +1 -12
  234. package/src/components/modules/paste/handlers/html-handler.ts +13 -10
  235. package/src/components/modules/paste/handlers/index.ts +1 -0
  236. package/src/components/modules/paste/index.ts +6 -0
  237. package/src/components/modules/themeManager.ts +1 -3
  238. package/src/components/modules/toolbar/blockSettings.ts +1 -0
  239. package/src/components/modules/toolbar/inline/index.ts +3 -0
  240. package/src/components/modules/uiControllers/controllers/keyboard.ts +0 -29
  241. package/src/components/modules/uiControllers/controllers/selection.ts +2 -14
  242. package/src/components/ui/toolbox.ts +1 -0
  243. package/src/components/utils/popover/popover-position.ts +2 -4
  244. package/src/markdown/index.ts +63 -0
  245. package/src/markdown/markdown-handler.ts +110 -0
  246. package/src/markdown/mdast-to-blocks.ts +418 -0
  247. package/src/markdown/phrasing-to-html.ts +60 -0
  248. package/src/markdown/types.ts +42 -0
  249. package/src/styles/main.css +0 -1139
  250. package/src/tools/callout/index.ts +24 -0
  251. package/src/tools/code/code-keyboard.ts +135 -0
  252. package/src/tools/code/constants.ts +73 -0
  253. package/src/tools/code/dom-builder.ts +146 -0
  254. package/src/tools/code/index.ts +322 -0
  255. package/src/tools/code/katex-loader.ts +50 -0
  256. package/src/tools/code/language-picker.ts +241 -0
  257. package/src/tools/divider/index.ts +9 -1
  258. package/src/tools/index.ts +4 -2
  259. package/src/tools/list/block-operations.ts +3 -1
  260. package/src/tools/list/depth-validator.ts +4 -7
  261. package/src/tools/list/dom-builder.ts +5 -3
  262. package/src/tools/list/index.ts +21 -3
  263. package/src/tools/list/list-helpers.ts +9 -2
  264. package/src/tools/list/list-keyboard.ts +56 -14
  265. package/src/tools/list/list-lifecycle.ts +3 -1
  266. package/src/tools/list/marker-calculator.ts +37 -0
  267. package/src/tools/list/ordered-marker-manager.ts +4 -2
  268. package/src/tools/table/index.ts +2 -2
  269. package/src/tools/table/table-cell-clipboard.ts +1 -1
  270. package/types/api/tools.d.ts +0 -18
  271. package/types/markdown.d.ts +2 -0
  272. package/types/tools/code.d.ts +11 -0
  273. package/src/tools/database/database-backend-sync.ts +0 -101
  274. package/src/tools/database/database-board-view.ts +0 -301
  275. package/src/tools/database/database-card-drag.ts +0 -306
  276. package/src/tools/database/database-card-drawer.ts +0 -546
  277. package/src/tools/database/database-column-controls.ts +0 -46
  278. package/src/tools/database/database-column-drag.ts +0 -262
  279. package/src/tools/database/database-keyboard.ts +0 -35
  280. package/src/tools/database/database-list-row-drag.ts +0 -245
  281. package/src/tools/database/database-list-view.ts +0 -333
  282. package/src/tools/database/database-model.ts +0 -246
  283. package/src/tools/database/database-property-type-popover.ts +0 -108
  284. package/src/tools/database/database-tab-bar.ts +0 -532
  285. package/src/tools/database/database-view-popover.ts +0 -109
  286. package/src/tools/database/database-view-renderer.ts +0 -25
  287. package/src/tools/database/index.ts +0 -948
  288. package/src/tools/database/types.ts +0 -144
  289. /package/dist/chunks/{am-CHDDMHkd.mjs → am-CS-JjQ0N.mjs} +0 -0
  290. /package/dist/chunks/{ar-DoqfNqut.mjs → ar-Dt4XzR5U.mjs} +0 -0
  291. /package/dist/chunks/{az-C34P9iEa.mjs → az-CaDTXby8.mjs} +0 -0
  292. /package/dist/chunks/{bg-jroXLY8Y.mjs → bg-D1pLog-R.mjs} +0 -0
  293. /package/dist/chunks/{bn-BRI-WqxY.mjs → bn-Db_ae60m.mjs} +0 -0
  294. /package/dist/chunks/{bs-CCGUpNHu.mjs → bs-DJTg1R9e.mjs} +0 -0
  295. /package/dist/chunks/{cs-D5qZOGuc.mjs → cs-_Gc21gSL.mjs} +0 -0
  296. /package/dist/chunks/{da-DrJ7W37K.mjs → da-xDB8uhCd.mjs} +0 -0
  297. /package/dist/chunks/{de-BW6-kp2c.mjs → de-B6gVjh1Z.mjs} +0 -0
  298. /package/dist/chunks/{el-C-Vc_Otu.mjs → el-ClbRSnOs.mjs} +0 -0
  299. /package/dist/chunks/{es-B6fI5K9i.mjs → es-CuY9rnLK.mjs} +0 -0
  300. /package/dist/chunks/{et-BhVlZ-Yz.mjs → et-BLu5lDVc.mjs} +0 -0
  301. /package/dist/chunks/{fa-D55Ijdqa.mjs → fa-P3gnrZH8.mjs} +0 -0
  302. /package/dist/chunks/{fi-jNLjhKUQ.mjs → fi-B8PVHLjq.mjs} +0 -0
  303. /package/dist/chunks/{fil-DYd0T5aX.mjs → fil-B9JII5iF.mjs} +0 -0
  304. /package/dist/chunks/{fr-yxy5xWw_.mjs → fr-BWLDZdcc.mjs} +0 -0
  305. /package/dist/chunks/{gu-CcY_LJe7.mjs → gu-BH3R_s4c.mjs} +0 -0
  306. /package/dist/chunks/{he-DL9s7wNw.mjs → he-CCmeCVR_.mjs} +0 -0
  307. /package/dist/chunks/{hi-C8eGXgw5.mjs → hi-BBav00DN.mjs} +0 -0
  308. /package/dist/chunks/{hr-DLpybOhU.mjs → hr-B5ZX0r9G.mjs} +0 -0
  309. /package/dist/chunks/{hu-BkT0gT00.mjs → hu-1jgDa3YU.mjs} +0 -0
  310. /package/dist/chunks/{hy-CVFDCp2S.mjs → hy-LX4Kp2PE.mjs} +0 -0
  311. /package/dist/chunks/{id-0P4W9Az0.mjs → id-CcG40D1H.mjs} +0 -0
  312. /package/dist/chunks/{it-mLY6_uoW.mjs → it-Cb8_K72W.mjs} +0 -0
  313. /package/dist/chunks/{ja-7RkeRNWG.mjs → ja-ipCH91mv.mjs} +0 -0
  314. /package/dist/chunks/{ka-C7Lx-Qsh.mjs → ka-BRvREIgq.mjs} +0 -0
  315. /package/dist/chunks/{km-Q8udaraH.mjs → km-BJwVw7Fg.mjs} +0 -0
  316. /package/dist/chunks/{kn-BiETM-iq.mjs → kn-BPgUazCC.mjs} +0 -0
  317. /package/dist/chunks/{ko-tiB80pF1.mjs → ko-CQLzxe7k.mjs} +0 -0
  318. /package/dist/chunks/{ku-CY-OABkR.mjs → ku-BHhHu8Iz.mjs} +0 -0
  319. /package/dist/chunks/{lo-CTBhEnyk.mjs → lo-DsTgYblY.mjs} +0 -0
  320. /package/dist/chunks/{lt-BHKHEtqK.mjs → lt-CDzHJm71.mjs} +0 -0
  321. /package/dist/chunks/{lv-DWxgtfUg.mjs → lv-MLLIAnIX.mjs} +0 -0
  322. /package/dist/chunks/{mk-BjookGdx.mjs → mk-DQdmUquZ.mjs} +0 -0
  323. /package/dist/chunks/{ml-L-NnZcp9.mjs → ml-DqehZnra.mjs} +0 -0
  324. /package/dist/chunks/{mn-OMWi7Hl_.mjs → mn-4cFkKFjW.mjs} +0 -0
  325. /package/dist/chunks/{mr-B6JPzITo.mjs → mr-DWiztOP4.mjs} +0 -0
  326. /package/dist/chunks/{ms-CG3S-sPB.mjs → ms-BSz-iSnc.mjs} +0 -0
  327. /package/dist/chunks/{my-BLAmGfhT.mjs → my-DbtbM1MW.mjs} +0 -0
  328. /package/dist/chunks/{native-BPcABu9z.mjs → native-CzYG0YgY.mjs} +0 -0
  329. /package/dist/chunks/{ne-D1JHLfYw.mjs → ne-CqALWw_f.mjs} +0 -0
  330. /package/dist/chunks/{nl-Ca7Q8FnY.mjs → nl-D_ra6RvH.mjs} +0 -0
  331. /package/dist/chunks/{no-Coxcohcz.mjs → no-Cg_kz_jl.mjs} +0 -0
  332. /package/dist/chunks/{pa-CCaXqpaI.mjs → pa-NLAsNqwY.mjs} +0 -0
  333. /package/dist/chunks/{pl-Cl_fAZ84.mjs → pl-NHKp4YDg.mjs} +0 -0
  334. /package/dist/chunks/{ps-WD5qGAWy.mjs → ps-D1zEqNeg.mjs} +0 -0
  335. /package/dist/chunks/{pt-C4zvLfvq.mjs → pt-DBtqbUEB.mjs} +0 -0
  336. /package/dist/chunks/{ro-DbefHcmM.mjs → ro-lqr63ai5.mjs} +0 -0
  337. /package/dist/chunks/{ru-uU1J14jd.mjs → ru-BycNnDyN.mjs} +0 -0
  338. /package/dist/chunks/{sd-DKu368Ip.mjs → sd-DpHpIN9Z.mjs} +0 -0
  339. /package/dist/chunks/{si-BsJCiPkZ.mjs → si-BwiwaC7N.mjs} +0 -0
  340. /package/dist/chunks/{sk-CD-a3SN6.mjs → sk-CqRHT2Gp.mjs} +0 -0
  341. /package/dist/chunks/{sl-CXhrPJe_.mjs → sl-DA348uQ_.mjs} +0 -0
  342. /package/dist/chunks/{sq-CTctCoFQ.mjs → sq-D7JNgve1.mjs} +0 -0
  343. /package/dist/chunks/{sr-BZkhBwXj.mjs → sr-D8RK6Kwp.mjs} +0 -0
  344. /package/dist/chunks/{sv-NmRZb_xi.mjs → sv-dwgT67ZG.mjs} +0 -0
  345. /package/dist/chunks/{sw-Be5ik3H6.mjs → sw-ZRRJnkem.mjs} +0 -0
  346. /package/dist/chunks/{ta-DsXh6neL.mjs → ta-5x4L5Krl.mjs} +0 -0
  347. /package/dist/chunks/{te-CwpCbM8M.mjs → te-BZpEimwA.mjs} +0 -0
  348. /package/dist/chunks/{th-CcZ15OLk.mjs → th-Bhr-33kv.mjs} +0 -0
  349. /package/dist/chunks/{tr-q3bTgvhW.mjs → tr-6tSNKGNB.mjs} +0 -0
  350. /package/dist/chunks/{tw-DmW6-pCY.mjs → tw-CqxBf-1Y.mjs} +0 -0
  351. /package/dist/chunks/{ug-919EhLsL.mjs → ug-_e-jvr2b.mjs} +0 -0
  352. /package/dist/chunks/{uk-aNMEzd0Y.mjs → uk-DooSc2Ja.mjs} +0 -0
  353. /package/dist/chunks/{ur-BwQI77sh.mjs → ur-rb-krkIO.mjs} +0 -0
  354. /package/dist/chunks/{vi-Dxq806-F.mjs → vi-CQkLn2AQ.mjs} +0 -0
  355. /package/dist/chunks/{zh-BcHuy1Ti.mjs → zh-CXQ40Q2_.mjs} +0 -0
@@ -78,21 +78,6 @@ export class KeyboardController extends Controller {
78
78
  return;
79
79
  }
80
80
 
81
- const target = event.target;
82
-
83
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
84
- return;
85
- }
86
-
87
- // Skip events from nested editors
88
- if (target instanceof Element) {
89
- const closestEditor = target.closest('[data-blok-testid="blok-editor"]');
90
-
91
- if (closestEditor !== null && closestEditor !== this.Blok.UI.nodes.wrapper) {
92
- return;
93
- }
94
- }
95
-
96
81
  if (KEYS_REQUIRING_CARET_CAPTURE.has(event.key)) {
97
82
  this.Blok.YjsManager.markCaretBeforeChange();
98
83
  }
@@ -104,20 +89,6 @@ export class KeyboardController extends Controller {
104
89
  * @param event - keyboard event
105
90
  */
106
91
  private handleKeydown(event: KeyboardEvent): void {
107
- const target = event.target;
108
-
109
- if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
110
- return;
111
- }
112
-
113
- if (target instanceof Element) {
114
- const closestEditor = target.closest('[data-blok-testid="blok-editor"]');
115
-
116
- if (closestEditor !== null && closestEditor !== this.Blok.UI.nodes.wrapper) {
117
- return;
118
- }
119
- }
120
-
121
92
  const key = event.key ?? '';
122
93
 
123
94
  switch (key) {
@@ -167,22 +167,10 @@ export class SelectionController extends Controller {
167
167
  * @returns true if current block should be updated
168
168
  */
169
169
  private shouldUpdateCurrentBlock(): boolean {
170
- const focusedElement = Selection.anchorElement;
171
-
172
- if (!focusedElement || !this.wrapperElement) {
173
- return false;
174
- }
175
-
176
170
  /**
177
- * Skip updating current block when focus is inside a nested editor instance.
178
- * The closest editor wrapper must match this instance's wrapper.
171
+ * Always update current block when focus moves to a different block.
172
+ * This handles Tab key navigation, programmatic focus, and accessibility tools.
179
173
  */
180
- const closestEditor = focusedElement.closest('[data-blok-testid="blok-editor"]');
181
-
182
- if (closestEditor !== null && closestEditor !== this.wrapperElement) {
183
- return false;
184
- }
185
-
186
174
  return true;
187
175
  }
188
176
  }
@@ -411,6 +411,7 @@ export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
411
411
  const PopoverClass = isMobileScreen() ? PopoverMobile : PopoverDesktop;
412
412
 
413
413
  this.popover = new PopoverClass({
414
+ scopeElement: this.api.ui.nodes.redactor,
414
415
  trigger: this.triggerElement || this.nodes.toolbox,
415
416
  leftAlignElement: this.leftAlignElement,
416
417
  messages: {
@@ -32,9 +32,7 @@ export interface ResolvedPosition {
32
32
 
33
33
  /**
34
34
  * Determines whether the popover should flip to the alternate side.
35
- * Returns true only when the popover fits on the alternate side but not the preferred side.
36
- * When neither side fits, stays on the preferred side so the popover remains adjacent
37
- * to the anchor instead of getting clamped to a distant boundary edge.
35
+ * Returns true when the popover doesn't fit on the preferred side and the alternate side has more (or equal) space.
38
36
  */
39
37
  function shouldFlip(popoverDimension: number, spaceOnPreferred: number, spaceOnAlternate: number): boolean {
40
38
  if (popoverDimension <= spaceOnPreferred) {
@@ -45,7 +43,7 @@ function shouldFlip(popoverDimension: number, spaceOnPreferred: number, spaceOnA
45
43
  return true;
46
44
  }
47
45
 
48
- return false;
46
+ return spaceOnAlternate > spaceOnPreferred;
49
47
  }
50
48
 
51
49
  /**
@@ -0,0 +1,63 @@
1
+ import { fromMarkdown } from 'mdast-util-from-markdown';
2
+ import type { Extension as MdastExtension } from 'mdast-util-from-markdown';
3
+ import { gfm } from 'micromark-extension-gfm';
4
+ import { gfmFromMarkdown } from 'mdast-util-gfm';
5
+ import type { Extension as MicromarkExtension } from 'micromark-util-types';
6
+ import type { OutputBlockData } from '../../types/data-formats/output-data';
7
+ import type { MarkdownImportConfig } from './types';
8
+ import { mdastToBlocks } from './mdast-to-blocks';
9
+
10
+ export type { MarkdownImportConfig, ToolMapEntry } from './types';
11
+
12
+ const MATH_SIGNAL = /\$\$[\s\S]+?\$\$|(?<!\$)\$(?!\$)(?=\S)[^$]+(?<=\S)\$(?!\$)/;
13
+
14
+ /**
15
+ * Lazily load math micromark/mdast extensions only when needed.
16
+ */
17
+ async function loadMathExtensions(): Promise<{
18
+ mathSyntax: MicromarkExtension;
19
+ mathFromMarkdown: MdastExtension;
20
+ }> {
21
+ const [{ math }, { mathFromMarkdown }] = await Promise.all([
22
+ import('micromark-extension-math'),
23
+ import('mdast-util-math'),
24
+ ]);
25
+
26
+ return { mathSyntax: math(), mathFromMarkdown: mathFromMarkdown() };
27
+ }
28
+
29
+ /**
30
+ * Convert a Markdown string to an array of Blok OutputBlockData.
31
+ *
32
+ * @param md - Markdown source string
33
+ * @param config - Optional configuration for tool mapping, GFM, and extensions
34
+ * @returns Array of OutputBlockData ready for `blok.blocks.render()` or `blok.blocks.insertMany()`
35
+ */
36
+ export async function markdownToBlocks(md: string, config: MarkdownImportConfig = {}): Promise<OutputBlockData[]> {
37
+ const enableGfm = config.gfm !== false;
38
+ const hasMath = MATH_SIGNAL.test(md);
39
+
40
+ const extensions = [
41
+ ...(enableGfm ? [gfm()] : []),
42
+ ...(config.extensions ?? []),
43
+ ];
44
+
45
+ const mdastExtensions = [
46
+ ...(enableGfm ? [gfmFromMarkdown()] : []),
47
+ ...(config.mdastExtensions ?? []),
48
+ ];
49
+
50
+ if (hasMath) {
51
+ const { mathSyntax, mathFromMarkdown } = await loadMathExtensions();
52
+
53
+ extensions.push(mathSyntax);
54
+ mdastExtensions.push(mathFromMarkdown);
55
+ }
56
+
57
+ const tree = fromMarkdown(md, {
58
+ extensions,
59
+ mdastExtensions,
60
+ });
61
+
62
+ return mdastToBlocks(tree, config);
63
+ }
@@ -0,0 +1,110 @@
1
+ import type { BlockToolData } from '../../types';
2
+ import type { BlokModules } from '../types-internal/blok-modules';
3
+ import type { SanitizerConfigBuilder } from '../components/modules/paste/sanitizer-config';
4
+ import type { ToolRegistry } from '../components/modules/paste/tool-registry';
5
+ import type { HandlerContext } from '../components/modules/paste/types';
6
+ import type { PasteHandler } from '../components/modules/paste/handlers/base';
7
+ import { BasePasteHandler } from '../components/modules/paste/handlers/base';
8
+ import { Block } from '../components/block';
9
+
10
+ /**
11
+ * Patterns that indicate text is likely Markdown rather than plain text.
12
+ * Each must be unlikely to appear in normal prose.
13
+ */
14
+ const MARKDOWN_SIGNALS: RegExp[] = [
15
+ /^#{1,6}\s/m, // ATX headings: # Heading
16
+ /^```/m, // Fenced code blocks
17
+ /\|\s*---/, // GFM table separator: | --- |
18
+ /^- \[[ x]\]/m, // Task list items: - [ ] or - [x]
19
+ /\[.+?\]\(.+?\)/, // Markdown links: [text](url)
20
+ /\*\*.+?\*\*/, // Bold: **text**
21
+ /!\[/, // Image: ![
22
+ /\$\$[\s\S]+?\$\$/, // Block math: $$...$$
23
+ /(?<!\$)\$(?!\$)(?=\S)[^$]+(?<=\S)\$(?!\$)/, // Inline math: $...$
24
+ ];
25
+
26
+ /**
27
+ * Check if a plain-text string contains strong Markdown signals.
28
+ */
29
+ export function hasMarkdownSignals(text: string): boolean {
30
+ if (!text) {
31
+ return false;
32
+ }
33
+
34
+ return MARKDOWN_SIGNALS.some((pattern) => pattern.test(text));
35
+ }
36
+
37
+ /**
38
+ * Paste handler that detects and converts Markdown text.
39
+ * Priority 30: between TextHandler (10) and HtmlHandler (40).
40
+ * Lazy-loads the converter on first use.
41
+ *
42
+ * Uses BlockManager.insertMany() to insert converted blocks directly,
43
+ * preserving all block data (list depth, table cells, etc.) that
44
+ * would be lost if mapped through the DOM-based paste pipeline.
45
+ */
46
+ export class MarkdownHandler extends BasePasteHandler implements PasteHandler {
47
+ constructor(
48
+ Blok: BlokModules,
49
+ toolRegistry: ToolRegistry,
50
+ sanitizerBuilder: SanitizerConfigBuilder
51
+ ) {
52
+ super(Blok, toolRegistry, sanitizerBuilder);
53
+ }
54
+
55
+ canHandle(data: unknown): number {
56
+ if (typeof data !== 'string' || !data.trim()) {
57
+ return 0;
58
+ }
59
+
60
+ return hasMarkdownSignals(data) ? 30 : 0;
61
+ }
62
+
63
+ async handle(data: unknown, context: HandlerContext): Promise<boolean> {
64
+ if (typeof data !== 'string') {
65
+ return false;
66
+ }
67
+
68
+ const { markdownToBlocks } = await import('./index');
69
+ const outputBlocks = await markdownToBlocks(data);
70
+
71
+ if (!outputBlocks.length) {
72
+ return false;
73
+ }
74
+
75
+ const { BlockManager, Caret } = this.Blok;
76
+
77
+ // Replace empty default block if present
78
+ const currentBlock = BlockManager.currentBlock;
79
+ const shouldReplace = context.canReplaceCurrentBlock && currentBlock !== undefined && currentBlock.isEmpty;
80
+ const insertIndex = shouldReplace
81
+ ? BlockManager.currentBlockIndex
82
+ : BlockManager.currentBlockIndex + 1;
83
+
84
+ // Compose Block instances from OutputBlockData
85
+ const blocksToInsert = outputBlocks.map(({ id, type, data: blockData, parent }) =>
86
+ BlockManager.composeBlock({
87
+ id,
88
+ tool: type,
89
+ data: blockData as BlockToolData,
90
+ parentId: parent,
91
+ })
92
+ );
93
+
94
+ BlockManager.insertMany(blocksToInsert, insertIndex);
95
+
96
+ // Remove the replaced empty block
97
+ if (shouldReplace && currentBlock !== undefined) {
98
+ await BlockManager.removeBlock(currentBlock, false);
99
+ }
100
+
101
+ // Set caret to end of last inserted block
102
+ const lastBlock = blocksToInsert[blocksToInsert.length - 1];
103
+
104
+ if (lastBlock instanceof Block) {
105
+ Caret.setToBlock(lastBlock, Caret.positions.END);
106
+ }
107
+
108
+ return true;
109
+ }
110
+ }
@@ -0,0 +1,418 @@
1
+ import type { Root, Nodes, List, ListItem, PhrasingContent, Table, Blockquote, RootContent } from 'mdast';
2
+ import type { OutputBlockData } from '../../types/data-formats/output-data';
3
+ import type { MarkdownImportConfig } from './types';
4
+ import { phrasingToHtml } from './phrasing-to-html';
5
+
6
+ /**
7
+ * Creates a scoped ID generator. Each call to mdastToBlocks gets a fresh generator.
8
+ */
9
+ function createIdGenerator(): () => string {
10
+ const prefix = `md-${Date.now().toString(36)}`;
11
+ const state = { counter: 0 };
12
+
13
+ return () => `${prefix}-${(state.counter++).toString(36)}`;
14
+ }
15
+
16
+ /**
17
+ * Convert an mdast tree to an array of Blok OutputBlockData.
18
+ */
19
+ export function mdastToBlocks(tree: Root, config: MarkdownImportConfig = {}): OutputBlockData[] {
20
+ const generateId = createIdGenerator();
21
+
22
+ return convertNodes(tree.children, config, 0, generateId);
23
+ }
24
+
25
+ function convertNodes(
26
+ nodes: RootContent[],
27
+ config: MarkdownImportConfig,
28
+ listDepth: number,
29
+ generateId: () => string,
30
+ ): OutputBlockData[] {
31
+ const blocks: OutputBlockData[] = [];
32
+
33
+ for (const node of nodes) {
34
+ const result = convertNode(node, config, listDepth, generateId);
35
+
36
+ if (result) {
37
+ blocks.push(...result);
38
+ }
39
+ }
40
+
41
+ return blocks;
42
+ }
43
+
44
+ function convertNode(
45
+ node: RootContent,
46
+ config: MarkdownImportConfig,
47
+ listDepth: number,
48
+ generateId: () => string,
49
+ ): OutputBlockData[] | null {
50
+ // 1. Check toolMap first
51
+ if (config.toolMap?.[node.type]) {
52
+ return handleToolMap(node, config, generateId);
53
+ }
54
+
55
+ // 2. Built-in handlers
56
+ const builtInResult = handleBuiltInNode(node, config, listDepth, generateId);
57
+
58
+ if (builtInResult !== undefined) {
59
+ return builtInResult;
60
+ }
61
+
62
+ // 3. onUnknownNode hook
63
+ if (config.onUnknownNode) {
64
+ return tryOnUnknownNode(config.onUnknownNode, node);
65
+ }
66
+
67
+ // 4. Fallback: extract any text content as paragraph
68
+ if ('value' in node && typeof node.value === 'string') {
69
+ return [makeParagraph(escapeHtml(node.value), generateId)];
70
+ }
71
+
72
+ return null;
73
+ }
74
+
75
+ /**
76
+ * Handle built-in node types. Returns undefined if node type is not built-in.
77
+ */
78
+ function handleBuiltInNode(
79
+ node: RootContent,
80
+ config: MarkdownImportConfig,
81
+ listDepth: number,
82
+ generateId: () => string,
83
+ ): OutputBlockData[] | null | undefined {
84
+ if (node.type === 'paragraph') {
85
+ return handleParagraph(node.children as Array<{ type: string; value?: string; children?: unknown[] }>, generateId);
86
+ }
87
+
88
+ if (node.type === 'heading') {
89
+ return [makeBlock('header', { text: phrasingToHtml(node.children), level: node.depth }, generateId)];
90
+ }
91
+
92
+ if (node.type === 'thematicBreak') {
93
+ return [makeBlock('divider', {}, generateId)];
94
+ }
95
+
96
+ if (node.type === 'list') {
97
+ return handleList(node, config, listDepth, generateId);
98
+ }
99
+
100
+ if (node.type === 'blockquote') {
101
+ return handleBlockquote(node, generateId);
102
+ }
103
+
104
+ if (node.type === 'table') {
105
+ return handleTable(node, generateId);
106
+ }
107
+
108
+ if (node.type === 'code') {
109
+ return [makeBlock('code', {
110
+ code: node.value,
111
+ language: node.lang ?? 'plain text',
112
+ }, generateId)];
113
+ }
114
+
115
+ if (node.type === 'math') {
116
+ return [makeBlock('code', { code: node.value, language: 'latex' }, generateId)];
117
+ }
118
+
119
+ if (node.type === 'html') {
120
+ return handleFallback(node, config, escapeHtml(node.value), generateId);
121
+ }
122
+
123
+ return undefined;
124
+ }
125
+
126
+ type ParagraphChild = { type: string; value?: string; children?: unknown[] };
127
+
128
+ /**
129
+ * Convert a paragraph's phrasing children to blocks.
130
+ * Splits on inlineMath nodes, emitting each as a latex code block.
131
+ */
132
+ function handleParagraph(children: ParagraphChild[], generateId: () => string): OutputBlockData[] {
133
+ const hasInlineMath = children.some(c => c.type === 'inlineMath');
134
+
135
+ if (!hasInlineMath) {
136
+ return [makeParagraph(phrasingToHtml(children as PhrasingContent[]), generateId)];
137
+ }
138
+
139
+ return splitOnInlineMath(children, generateId);
140
+ }
141
+
142
+ function splitOnInlineMath(children: ParagraphChild[], generateId: () => string): OutputBlockData[] {
143
+ const blocks: OutputBlockData[] = [];
144
+ const segments = groupByInlineMath(children);
145
+
146
+ for (const segment of segments) {
147
+ if (segment.type === 'math') {
148
+ blocks.push(makeBlock('code', { code: segment.value, language: 'latex' }, generateId));
149
+ continue;
150
+ }
151
+
152
+ const text = phrasingToHtml(segment.nodes as PhrasingContent[]).trim();
153
+
154
+ if (text) {
155
+ blocks.push(makeParagraph(text, generateId));
156
+ }
157
+ }
158
+
159
+ return blocks;
160
+ }
161
+
162
+ type MathSegment = { type: 'math'; value: string } | { type: 'text'; nodes: ParagraphChild[] };
163
+
164
+ function groupByInlineMath(children: ParagraphChild[]): MathSegment[] {
165
+ const segments: MathSegment[] = [];
166
+ const textNodes: ParagraphChild[] = [];
167
+
168
+ for (const child of children) {
169
+ if (child.type !== 'inlineMath') {
170
+ textNodes.push(child);
171
+ continue;
172
+ }
173
+
174
+ if (textNodes.length > 0) {
175
+ segments.push({ type: 'text', nodes: [...textNodes] });
176
+ textNodes.length = 0;
177
+ }
178
+
179
+ segments.push({ type: 'math', value: child.value ?? '' });
180
+ }
181
+
182
+ if (textNodes.length > 0) {
183
+ segments.push({ type: 'text', nodes: textNodes });
184
+ }
185
+
186
+ return segments;
187
+ }
188
+
189
+ function tryOnUnknownNode(
190
+ onUnknownNode: (node: Nodes) => OutputBlockData[] | null,
191
+ node: RootContent,
192
+ ): OutputBlockData[] | null {
193
+ try {
194
+ return onUnknownNode(node as Nodes);
195
+ } catch (e) {
196
+ console.warn(`markdownToBlocks: onUnknownNode threw for node type "${node.type}"`, e);
197
+
198
+ return null;
199
+ }
200
+ }
201
+
202
+ function handleToolMap(
203
+ node: RootContent,
204
+ config: MarkdownImportConfig,
205
+ generateId: () => string,
206
+ ): OutputBlockData[] {
207
+ const toolMap = config.toolMap;
208
+
209
+ if (!toolMap) {
210
+ return [];
211
+ }
212
+
213
+ const entry = toolMap[node.type];
214
+
215
+ try {
216
+ const block: OutputBlockData = {
217
+ id: generateId(),
218
+ type: entry.tool,
219
+ data: entry.data(node as Nodes),
220
+ };
221
+
222
+ if (entry.children) {
223
+ const childBlocks = entry.children(
224
+ node as Nodes,
225
+ (childNodes) => convertNodes(childNodes as RootContent[], config, 0, generateId),
226
+ );
227
+
228
+ return [block, ...childBlocks];
229
+ }
230
+
231
+ return [block];
232
+ } catch (e) {
233
+ console.warn(`markdownToBlocks: toolMap handler threw for node type "${node.type}"`, e);
234
+
235
+ return [];
236
+ }
237
+ }
238
+
239
+ function handleList(
240
+ list: List,
241
+ config: MarkdownImportConfig,
242
+ depth: number,
243
+ generateId: () => string,
244
+ ): OutputBlockData[] {
245
+ const blocks: OutputBlockData[] = [];
246
+
247
+ for (const [index, item] of list.children.entries()) {
248
+ blocks.push(...handleListItem(item, list, config, depth, index, generateId));
249
+ }
250
+
251
+ return blocks;
252
+ }
253
+
254
+ function resolveListStyle(isChecklist: boolean, ordered: boolean | null | undefined): string {
255
+ if (isChecklist) {
256
+ return 'checklist';
257
+ }
258
+
259
+ return ordered ? 'ordered' : 'unordered';
260
+ }
261
+
262
+ function handleListItem(
263
+ item: ListItem,
264
+ list: List,
265
+ config: MarkdownImportConfig,
266
+ depth: number,
267
+ index: number,
268
+ generateId: () => string,
269
+ ): OutputBlockData[] {
270
+ const blocks: OutputBlockData[] = [];
271
+ const isChecklist = item.checked !== null && item.checked !== undefined;
272
+ const style = resolveListStyle(isChecklist, list.ordered);
273
+
274
+ // Extract text from the first paragraph child
275
+ const paragraphChild = item.children.find(
276
+ (c): c is Extract<typeof c, { type: 'paragraph' }> => c.type === 'paragraph',
277
+ );
278
+ const text = paragraphChild ? phrasingToHtml(paragraphChild.children) : '';
279
+
280
+ const data: Record<string, unknown> = { text, style, depth };
281
+
282
+ if (isChecklist) {
283
+ data.checked = item.checked;
284
+ }
285
+
286
+ if (list.ordered && index === 0 && list.start !== null && list.start !== undefined && list.start !== 1) {
287
+ data.start = list.start;
288
+ }
289
+
290
+ blocks.push(makeBlock('list', data, generateId));
291
+
292
+ // Process nested lists (increase depth)
293
+ for (const child of item.children) {
294
+ if (child.type === 'list') {
295
+ blocks.push(...handleList(child, config, depth + 1, generateId));
296
+ }
297
+ }
298
+
299
+ return blocks;
300
+ }
301
+
302
+ function handleBlockquote(bq: Blockquote, generateId: () => string): OutputBlockData[] {
303
+ const parts: string[] = [];
304
+
305
+ for (const child of bq.children) {
306
+ if (child.type === 'paragraph') {
307
+ parts.push(phrasingToHtml(child.children));
308
+ continue;
309
+ }
310
+
311
+ if (!('children' in child) || !Array.isArray(child.children)) {
312
+ continue;
313
+ }
314
+
315
+ // For non-paragraph flow content, extract text
316
+ const innerPhrasing = child.children.filter(
317
+ (c): c is PhrasingContent => 'value' in c || 'children' in c,
318
+ );
319
+
320
+ if (innerPhrasing.length > 0) {
321
+ parts.push(phrasingToHtml(innerPhrasing));
322
+ }
323
+ }
324
+
325
+ return [makeBlock('quote', { text: parts.join('<br>'), size: 'default' }, generateId)];
326
+ }
327
+
328
+ function handleTable(table: Table, generateId: () => string): OutputBlockData[] {
329
+ const blocks: OutputBlockData[] = [];
330
+ const tableId = generateId();
331
+ const content: Array<Array<{ blocks: string[] }>> = [];
332
+
333
+ for (const row of table.children) {
334
+ const rowContent = processTableRow(row.children, tableId, blocks, generateId);
335
+
336
+ content.push(rowContent);
337
+ }
338
+
339
+ const tableBlock: OutputBlockData = {
340
+ id: tableId,
341
+ type: 'table',
342
+ data: {
343
+ withHeadings: table.children.length > 1,
344
+ withHeadingColumn: false,
345
+ content,
346
+ },
347
+ };
348
+
349
+ // Table block first, then cell blocks
350
+ return [tableBlock, ...blocks];
351
+ }
352
+
353
+ function processTableRow(
354
+ cells: Table['children'][number]['children'],
355
+ tableId: string,
356
+ blocks: OutputBlockData[],
357
+ generateId: () => string,
358
+ ): Array<{ blocks: string[] }> {
359
+ const rowContent: Array<{ blocks: string[] }> = [];
360
+
361
+ for (const cell of cells) {
362
+ const cellText = phrasingToHtml(cell.children);
363
+ const cellBlockId = generateId();
364
+
365
+ blocks.push({
366
+ id: cellBlockId,
367
+ type: 'paragraph',
368
+ data: { text: cellText },
369
+ parent: tableId,
370
+ });
371
+
372
+ rowContent.push({ blocks: [cellBlockId] });
373
+ }
374
+
375
+ return rowContent;
376
+ }
377
+
378
+ function handleFallback(
379
+ node: RootContent,
380
+ config: MarkdownImportConfig,
381
+ fallbackText: string,
382
+ generateId: () => string,
383
+ ): OutputBlockData[] | null {
384
+ // Try onUnknownNode first for unmapped block types
385
+ if (config.onUnknownNode) {
386
+ const result = tryOnUnknownNode(config.onUnknownNode, node);
387
+
388
+ // null means "skip this node" — respect the caller's decision
389
+ // non-null means the hook handled it
390
+ if (result === null) {
391
+ return null;
392
+ }
393
+
394
+ return result;
395
+ }
396
+
397
+ return [makeParagraph(fallbackText, generateId)];
398
+ }
399
+
400
+ function makeParagraph(text: string, generateId: () => string): OutputBlockData {
401
+ return makeBlock('paragraph', { text }, generateId);
402
+ }
403
+
404
+ function makeBlock(type: string, data: Record<string, unknown>, generateId: () => string): OutputBlockData {
405
+ return {
406
+ id: generateId(),
407
+ type,
408
+ data,
409
+ };
410
+ }
411
+
412
+ function escapeHtml(text: string): string {
413
+ return text
414
+ .replace(/&/g, '&amp;')
415
+ .replace(/</g, '&lt;')
416
+ .replace(/>/g, '&gt;')
417
+ .replace(/"/g, '&quot;');
418
+ }