@ckeditor/ckeditor5-core 0.0.0-internal-20241017.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +24 -0
  4. package/dist/accessibility.d.ts +365 -0
  5. package/dist/augmentation.d.ts +14 -0
  6. package/dist/command.d.ts +193 -0
  7. package/dist/commandcollection.d.ts +87 -0
  8. package/dist/context.d.ts +241 -0
  9. package/dist/contextplugin.d.ts +73 -0
  10. package/dist/editingkeystrokehandler.d.ts +60 -0
  11. package/dist/editor/editor.d.ts +524 -0
  12. package/dist/editor/editorconfig.d.ts +992 -0
  13. package/dist/editor/utils/attachtoform.d.ts +19 -0
  14. package/dist/editor/utils/dataapimixin.d.ts +83 -0
  15. package/dist/editor/utils/editorusagedata.d.ts +62 -0
  16. package/dist/editor/utils/elementapimixin.d.ts +39 -0
  17. package/dist/editor/utils/securesourceelement.d.ts +21 -0
  18. package/dist/index-content.css +4 -0
  19. package/dist/index-editor.css +4 -0
  20. package/dist/index.css +4 -0
  21. package/dist/index.d.ts +94 -0
  22. package/dist/index.js +3027 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/multicommand.d.ts +70 -0
  25. package/dist/pendingactions.d.ts +126 -0
  26. package/dist/plugin.d.ts +294 -0
  27. package/dist/plugincollection.d.ts +121 -0
  28. package/dist/translations/af.d.ts +8 -0
  29. package/dist/translations/af.js +5 -0
  30. package/dist/translations/af.umd.js +11 -0
  31. package/dist/translations/ar.d.ts +8 -0
  32. package/dist/translations/ar.js +5 -0
  33. package/dist/translations/ar.umd.js +11 -0
  34. package/dist/translations/ast.d.ts +8 -0
  35. package/dist/translations/ast.js +5 -0
  36. package/dist/translations/ast.umd.js +11 -0
  37. package/dist/translations/az.d.ts +8 -0
  38. package/dist/translations/az.js +5 -0
  39. package/dist/translations/az.umd.js +11 -0
  40. package/dist/translations/bg.d.ts +8 -0
  41. package/dist/translations/bg.js +5 -0
  42. package/dist/translations/bg.umd.js +11 -0
  43. package/dist/translations/bn.d.ts +8 -0
  44. package/dist/translations/bn.js +5 -0
  45. package/dist/translations/bn.umd.js +11 -0
  46. package/dist/translations/bs.d.ts +8 -0
  47. package/dist/translations/bs.js +5 -0
  48. package/dist/translations/bs.umd.js +11 -0
  49. package/dist/translations/ca.d.ts +8 -0
  50. package/dist/translations/ca.js +5 -0
  51. package/dist/translations/ca.umd.js +11 -0
  52. package/dist/translations/cs.d.ts +8 -0
  53. package/dist/translations/cs.js +5 -0
  54. package/dist/translations/cs.umd.js +11 -0
  55. package/dist/translations/da.d.ts +8 -0
  56. package/dist/translations/da.js +5 -0
  57. package/dist/translations/da.umd.js +11 -0
  58. package/dist/translations/de-ch.d.ts +8 -0
  59. package/dist/translations/de-ch.js +5 -0
  60. package/dist/translations/de-ch.umd.js +11 -0
  61. package/dist/translations/de.d.ts +8 -0
  62. package/dist/translations/de.js +5 -0
  63. package/dist/translations/de.umd.js +11 -0
  64. package/dist/translations/el.d.ts +8 -0
  65. package/dist/translations/el.js +5 -0
  66. package/dist/translations/el.umd.js +11 -0
  67. package/dist/translations/en-au.d.ts +8 -0
  68. package/dist/translations/en-au.js +5 -0
  69. package/dist/translations/en-au.umd.js +11 -0
  70. package/dist/translations/en-gb.d.ts +8 -0
  71. package/dist/translations/en-gb.js +5 -0
  72. package/dist/translations/en-gb.umd.js +11 -0
  73. package/dist/translations/en.d.ts +8 -0
  74. package/dist/translations/en.js +5 -0
  75. package/dist/translations/en.umd.js +11 -0
  76. package/dist/translations/eo.d.ts +8 -0
  77. package/dist/translations/eo.js +5 -0
  78. package/dist/translations/eo.umd.js +11 -0
  79. package/dist/translations/es-co.d.ts +8 -0
  80. package/dist/translations/es-co.js +5 -0
  81. package/dist/translations/es-co.umd.js +11 -0
  82. package/dist/translations/es.d.ts +8 -0
  83. package/dist/translations/es.js +5 -0
  84. package/dist/translations/es.umd.js +11 -0
  85. package/dist/translations/et.d.ts +8 -0
  86. package/dist/translations/et.js +5 -0
  87. package/dist/translations/et.umd.js +11 -0
  88. package/dist/translations/eu.d.ts +8 -0
  89. package/dist/translations/eu.js +5 -0
  90. package/dist/translations/eu.umd.js +11 -0
  91. package/dist/translations/fa.d.ts +8 -0
  92. package/dist/translations/fa.js +5 -0
  93. package/dist/translations/fa.umd.js +11 -0
  94. package/dist/translations/fi.d.ts +8 -0
  95. package/dist/translations/fi.js +5 -0
  96. package/dist/translations/fi.umd.js +11 -0
  97. package/dist/translations/fr.d.ts +8 -0
  98. package/dist/translations/fr.js +5 -0
  99. package/dist/translations/fr.umd.js +11 -0
  100. package/dist/translations/gl.d.ts +8 -0
  101. package/dist/translations/gl.js +5 -0
  102. package/dist/translations/gl.umd.js +11 -0
  103. package/dist/translations/gu.d.ts +8 -0
  104. package/dist/translations/gu.js +5 -0
  105. package/dist/translations/gu.umd.js +11 -0
  106. package/dist/translations/he.d.ts +8 -0
  107. package/dist/translations/he.js +5 -0
  108. package/dist/translations/he.umd.js +11 -0
  109. package/dist/translations/hi.d.ts +8 -0
  110. package/dist/translations/hi.js +5 -0
  111. package/dist/translations/hi.umd.js +11 -0
  112. package/dist/translations/hr.d.ts +8 -0
  113. package/dist/translations/hr.js +5 -0
  114. package/dist/translations/hr.umd.js +11 -0
  115. package/dist/translations/hu.d.ts +8 -0
  116. package/dist/translations/hu.js +5 -0
  117. package/dist/translations/hu.umd.js +11 -0
  118. package/dist/translations/hy.d.ts +8 -0
  119. package/dist/translations/hy.js +5 -0
  120. package/dist/translations/hy.umd.js +11 -0
  121. package/dist/translations/id.d.ts +8 -0
  122. package/dist/translations/id.js +5 -0
  123. package/dist/translations/id.umd.js +11 -0
  124. package/dist/translations/it.d.ts +8 -0
  125. package/dist/translations/it.js +5 -0
  126. package/dist/translations/it.umd.js +11 -0
  127. package/dist/translations/ja.d.ts +8 -0
  128. package/dist/translations/ja.js +5 -0
  129. package/dist/translations/ja.umd.js +11 -0
  130. package/dist/translations/jv.d.ts +8 -0
  131. package/dist/translations/jv.js +5 -0
  132. package/dist/translations/jv.umd.js +11 -0
  133. package/dist/translations/km.d.ts +8 -0
  134. package/dist/translations/km.js +5 -0
  135. package/dist/translations/km.umd.js +11 -0
  136. package/dist/translations/kn.d.ts +8 -0
  137. package/dist/translations/kn.js +5 -0
  138. package/dist/translations/kn.umd.js +11 -0
  139. package/dist/translations/ko.d.ts +8 -0
  140. package/dist/translations/ko.js +5 -0
  141. package/dist/translations/ko.umd.js +11 -0
  142. package/dist/translations/ku.d.ts +8 -0
  143. package/dist/translations/ku.js +5 -0
  144. package/dist/translations/ku.umd.js +11 -0
  145. package/dist/translations/lt.d.ts +8 -0
  146. package/dist/translations/lt.js +5 -0
  147. package/dist/translations/lt.umd.js +11 -0
  148. package/dist/translations/lv.d.ts +8 -0
  149. package/dist/translations/lv.js +5 -0
  150. package/dist/translations/lv.umd.js +11 -0
  151. package/dist/translations/ms.d.ts +8 -0
  152. package/dist/translations/ms.js +5 -0
  153. package/dist/translations/ms.umd.js +11 -0
  154. package/dist/translations/nb.d.ts +8 -0
  155. package/dist/translations/nb.js +5 -0
  156. package/dist/translations/nb.umd.js +11 -0
  157. package/dist/translations/ne.d.ts +8 -0
  158. package/dist/translations/ne.js +5 -0
  159. package/dist/translations/ne.umd.js +11 -0
  160. package/dist/translations/nl.d.ts +8 -0
  161. package/dist/translations/nl.js +5 -0
  162. package/dist/translations/nl.umd.js +11 -0
  163. package/dist/translations/no.d.ts +8 -0
  164. package/dist/translations/no.js +5 -0
  165. package/dist/translations/no.umd.js +11 -0
  166. package/dist/translations/oc.d.ts +8 -0
  167. package/dist/translations/oc.js +5 -0
  168. package/dist/translations/oc.umd.js +11 -0
  169. package/dist/translations/pl.d.ts +8 -0
  170. package/dist/translations/pl.js +5 -0
  171. package/dist/translations/pl.umd.js +11 -0
  172. package/dist/translations/pt-br.d.ts +8 -0
  173. package/dist/translations/pt-br.js +5 -0
  174. package/dist/translations/pt-br.umd.js +11 -0
  175. package/dist/translations/pt.d.ts +8 -0
  176. package/dist/translations/pt.js +5 -0
  177. package/dist/translations/pt.umd.js +11 -0
  178. package/dist/translations/ro.d.ts +8 -0
  179. package/dist/translations/ro.js +5 -0
  180. package/dist/translations/ro.umd.js +11 -0
  181. package/dist/translations/ru.d.ts +8 -0
  182. package/dist/translations/ru.js +5 -0
  183. package/dist/translations/ru.umd.js +11 -0
  184. package/dist/translations/si.d.ts +8 -0
  185. package/dist/translations/si.js +5 -0
  186. package/dist/translations/si.umd.js +11 -0
  187. package/dist/translations/sk.d.ts +8 -0
  188. package/dist/translations/sk.js +5 -0
  189. package/dist/translations/sk.umd.js +11 -0
  190. package/dist/translations/sl.d.ts +8 -0
  191. package/dist/translations/sl.js +5 -0
  192. package/dist/translations/sl.umd.js +11 -0
  193. package/dist/translations/sq.d.ts +8 -0
  194. package/dist/translations/sq.js +5 -0
  195. package/dist/translations/sq.umd.js +11 -0
  196. package/dist/translations/sr-latn.d.ts +8 -0
  197. package/dist/translations/sr-latn.js +5 -0
  198. package/dist/translations/sr-latn.umd.js +11 -0
  199. package/dist/translations/sr.d.ts +8 -0
  200. package/dist/translations/sr.js +5 -0
  201. package/dist/translations/sr.umd.js +11 -0
  202. package/dist/translations/sv.d.ts +8 -0
  203. package/dist/translations/sv.js +5 -0
  204. package/dist/translations/sv.umd.js +11 -0
  205. package/dist/translations/th.d.ts +8 -0
  206. package/dist/translations/th.js +5 -0
  207. package/dist/translations/th.umd.js +11 -0
  208. package/dist/translations/ti.d.ts +8 -0
  209. package/dist/translations/ti.js +5 -0
  210. package/dist/translations/ti.umd.js +11 -0
  211. package/dist/translations/tk.d.ts +8 -0
  212. package/dist/translations/tk.js +5 -0
  213. package/dist/translations/tk.umd.js +11 -0
  214. package/dist/translations/tr.d.ts +8 -0
  215. package/dist/translations/tr.js +5 -0
  216. package/dist/translations/tr.umd.js +11 -0
  217. package/dist/translations/tt.d.ts +8 -0
  218. package/dist/translations/tt.js +5 -0
  219. package/dist/translations/tt.umd.js +11 -0
  220. package/dist/translations/ug.d.ts +8 -0
  221. package/dist/translations/ug.js +5 -0
  222. package/dist/translations/ug.umd.js +11 -0
  223. package/dist/translations/uk.d.ts +8 -0
  224. package/dist/translations/uk.js +5 -0
  225. package/dist/translations/uk.umd.js +11 -0
  226. package/dist/translations/ur.d.ts +8 -0
  227. package/dist/translations/ur.js +5 -0
  228. package/dist/translations/ur.umd.js +11 -0
  229. package/dist/translations/uz.d.ts +8 -0
  230. package/dist/translations/uz.js +5 -0
  231. package/dist/translations/uz.umd.js +11 -0
  232. package/dist/translations/vi.d.ts +8 -0
  233. package/dist/translations/vi.js +5 -0
  234. package/dist/translations/vi.umd.js +11 -0
  235. package/dist/translations/zh-cn.d.ts +8 -0
  236. package/dist/translations/zh-cn.js +5 -0
  237. package/dist/translations/zh-cn.umd.js +11 -0
  238. package/dist/translations/zh.d.ts +8 -0
  239. package/dist/translations/zh.js +5 -0
  240. package/dist/translations/zh.umd.js +11 -0
  241. package/dist/typings.d.ts +16 -0
  242. package/lang/contexts.json +31 -0
  243. package/lang/translations/af.po +134 -0
  244. package/lang/translations/ar.po +134 -0
  245. package/lang/translations/ast.po +134 -0
  246. package/lang/translations/az.po +134 -0
  247. package/lang/translations/bg.po +134 -0
  248. package/lang/translations/bn.po +134 -0
  249. package/lang/translations/bs.po +134 -0
  250. package/lang/translations/ca.po +134 -0
  251. package/lang/translations/cs.po +134 -0
  252. package/lang/translations/da.po +134 -0
  253. package/lang/translations/de-ch.po +134 -0
  254. package/lang/translations/de.po +134 -0
  255. package/lang/translations/el.po +134 -0
  256. package/lang/translations/en-au.po +134 -0
  257. package/lang/translations/en-gb.po +134 -0
  258. package/lang/translations/en.po +134 -0
  259. package/lang/translations/eo.po +134 -0
  260. package/lang/translations/es-co.po +134 -0
  261. package/lang/translations/es.po +134 -0
  262. package/lang/translations/et.po +134 -0
  263. package/lang/translations/eu.po +134 -0
  264. package/lang/translations/fa.po +134 -0
  265. package/lang/translations/fi.po +134 -0
  266. package/lang/translations/fr.po +134 -0
  267. package/lang/translations/gl.po +134 -0
  268. package/lang/translations/gu.po +134 -0
  269. package/lang/translations/he.po +134 -0
  270. package/lang/translations/hi.po +134 -0
  271. package/lang/translations/hr.po +134 -0
  272. package/lang/translations/hu.po +134 -0
  273. package/lang/translations/hy.po +134 -0
  274. package/lang/translations/id.po +134 -0
  275. package/lang/translations/it.po +134 -0
  276. package/lang/translations/ja.po +134 -0
  277. package/lang/translations/jv.po +134 -0
  278. package/lang/translations/km.po +134 -0
  279. package/lang/translations/kn.po +134 -0
  280. package/lang/translations/ko.po +134 -0
  281. package/lang/translations/ku.po +134 -0
  282. package/lang/translations/lt.po +134 -0
  283. package/lang/translations/lv.po +134 -0
  284. package/lang/translations/ms.po +134 -0
  285. package/lang/translations/nb.po +134 -0
  286. package/lang/translations/ne.po +134 -0
  287. package/lang/translations/nl.po +134 -0
  288. package/lang/translations/no.po +134 -0
  289. package/lang/translations/oc.po +134 -0
  290. package/lang/translations/pl.po +134 -0
  291. package/lang/translations/pt-br.po +134 -0
  292. package/lang/translations/pt.po +134 -0
  293. package/lang/translations/ro.po +134 -0
  294. package/lang/translations/ru.po +134 -0
  295. package/lang/translations/si.po +134 -0
  296. package/lang/translations/sk.po +134 -0
  297. package/lang/translations/sl.po +134 -0
  298. package/lang/translations/sq.po +134 -0
  299. package/lang/translations/sr-latn.po +134 -0
  300. package/lang/translations/sr.po +134 -0
  301. package/lang/translations/sv.po +134 -0
  302. package/lang/translations/th.po +134 -0
  303. package/lang/translations/ti.po +134 -0
  304. package/lang/translations/tk.po +134 -0
  305. package/lang/translations/tr.po +134 -0
  306. package/lang/translations/tt.po +134 -0
  307. package/lang/translations/ug.po +134 -0
  308. package/lang/translations/uk.po +134 -0
  309. package/lang/translations/ur.po +134 -0
  310. package/lang/translations/uz.po +134 -0
  311. package/lang/translations/vi.po +134 -0
  312. package/lang/translations/zh-cn.po +134 -0
  313. package/lang/translations/zh.po +134 -0
  314. package/package.json +51 -0
  315. package/src/accessibility.d.ts +361 -0
  316. package/src/accessibility.js +325 -0
  317. package/src/augmentation.d.ts +10 -0
  318. package/src/augmentation.js +5 -0
  319. package/src/command.d.ts +189 -0
  320. package/src/command.js +185 -0
  321. package/src/commandcollection.d.ts +83 -0
  322. package/src/commandcollection.js +83 -0
  323. package/src/context.d.ts +237 -0
  324. package/src/context.js +229 -0
  325. package/src/contextplugin.d.ts +69 -0
  326. package/src/contextplugin.js +55 -0
  327. package/src/editingkeystrokehandler.d.ts +56 -0
  328. package/src/editingkeystrokehandler.js +57 -0
  329. package/src/editor/editor.d.ts +520 -0
  330. package/src/editor/editor.js +701 -0
  331. package/src/editor/editorconfig.d.ts +988 -0
  332. package/src/editor/editorconfig.js +5 -0
  333. package/src/editor/utils/attachtoform.d.ts +15 -0
  334. package/src/editor/utils/attachtoform.js +57 -0
  335. package/src/editor/utils/dataapimixin.d.ts +79 -0
  336. package/src/editor/utils/dataapimixin.js +12 -0
  337. package/src/editor/utils/editorusagedata.d.ts +58 -0
  338. package/src/editor/utils/editorusagedata.js +120 -0
  339. package/src/editor/utils/elementapimixin.d.ts +35 -0
  340. package/src/editor/utils/elementapimixin.js +43 -0
  341. package/src/editor/utils/securesourceelement.d.ts +17 -0
  342. package/src/editor/utils/securesourceelement.js +35 -0
  343. package/src/index.d.ts +90 -0
  344. package/src/index.js +147 -0
  345. package/src/multicommand.d.ts +66 -0
  346. package/src/multicommand.js +82 -0
  347. package/src/pendingactions.d.ts +122 -0
  348. package/src/pendingactions.js +123 -0
  349. package/src/plugin.d.ts +290 -0
  350. package/src/plugin.js +118 -0
  351. package/src/plugincollection.d.ts +117 -0
  352. package/src/plugincollection.js +473 -0
  353. package/src/typings.d.ts +12 -0
  354. package/src/typings.js +5 -0
  355. package/theme/icons/align-bottom.svg +1 -0
  356. package/theme/icons/align-center.svg +1 -0
  357. package/theme/icons/align-justify.svg +1 -0
  358. package/theme/icons/align-left.svg +1 -0
  359. package/theme/icons/align-middle.svg +1 -0
  360. package/theme/icons/align-right.svg +1 -0
  361. package/theme/icons/align-top.svg +1 -0
  362. package/theme/icons/bold.svg +1 -0
  363. package/theme/icons/browse-files.svg +1 -0
  364. package/theme/icons/bulletedlist.svg +1 -0
  365. package/theme/icons/cancel.svg +1 -0
  366. package/theme/icons/caption.svg +1 -0
  367. package/theme/icons/check.svg +1 -0
  368. package/theme/icons/codeblock.svg +1 -0
  369. package/theme/icons/cog.svg +1 -0
  370. package/theme/icons/color-palette.svg +1 -0
  371. package/theme/icons/drag-indicator.svg +1 -0
  372. package/theme/icons/eraser.svg +1 -0
  373. package/theme/icons/heading1.svg +1 -0
  374. package/theme/icons/heading2.svg +1 -0
  375. package/theme/icons/heading3.svg +1 -0
  376. package/theme/icons/heading4.svg +1 -0
  377. package/theme/icons/heading5.svg +1 -0
  378. package/theme/icons/heading6.svg +1 -0
  379. package/theme/icons/history.svg +1 -0
  380. package/theme/icons/horizontalline.svg +1 -0
  381. package/theme/icons/html.svg +1 -0
  382. package/theme/icons/image-asset-manager.svg +1 -0
  383. package/theme/icons/image-upload.svg +1 -0
  384. package/theme/icons/image-url.svg +1 -0
  385. package/theme/icons/image.svg +1 -0
  386. package/theme/icons/importexport.svg +1 -0
  387. package/theme/icons/indent.svg +1 -0
  388. package/theme/icons/loupe.svg +1 -0
  389. package/theme/icons/low-vision.svg +1 -0
  390. package/theme/icons/next-arrow.svg +1 -0
  391. package/theme/icons/numberedlist.svg +1 -0
  392. package/theme/icons/object-center.svg +1 -0
  393. package/theme/icons/object-full-width.svg +1 -0
  394. package/theme/icons/object-inline-left.svg +1 -0
  395. package/theme/icons/object-inline-right.svg +1 -0
  396. package/theme/icons/object-inline.svg +1 -0
  397. package/theme/icons/object-left.svg +1 -0
  398. package/theme/icons/object-right.svg +1 -0
  399. package/theme/icons/object-size-custom.svg +1 -0
  400. package/theme/icons/object-size-full.svg +1 -0
  401. package/theme/icons/object-size-large.svg +1 -0
  402. package/theme/icons/object-size-medium.svg +1 -0
  403. package/theme/icons/object-size-small.svg +1 -0
  404. package/theme/icons/outdent.svg +1 -0
  405. package/theme/icons/paragraph.svg +1 -0
  406. package/theme/icons/pencil.svg +1 -0
  407. package/theme/icons/pilcrow.svg +1 -0
  408. package/theme/icons/plus.svg +1 -0
  409. package/theme/icons/previous-arrow.svg +1 -0
  410. package/theme/icons/quote.svg +1 -0
  411. package/theme/icons/redo.svg +1 -0
  412. package/theme/icons/table.svg +1 -0
  413. package/theme/icons/text-alternative.svg +1 -0
  414. package/theme/icons/text.svg +1 -0
  415. package/theme/icons/three-vertical-dots.svg +1 -0
  416. package/theme/icons/todolist.svg +1 -0
  417. package/theme/icons/undo.svg +1 -0
package/dist/index.js ADDED
@@ -0,0 +1,3027 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import { ObservableMixin, insertToPriorityArray, EmitterMixin, CKEditorError, Config, Locale, Collection, KeystrokeHandler, env, global, parseBase64EncodedObject, toArray, crc32, releaseDate, uid, logError, setDataInElement } from '@ckeditor/ckeditor5-utils/dist/index.js';
6
+ import { get, set, isFunction } from 'lodash-es';
7
+ import { Model, StylesProcessor, DataController, EditingController, Conversion } from '@ckeditor/ckeditor5-engine/dist/index.js';
8
+ import { EditorWatchdog, ContextWatchdog } from '@ckeditor/ckeditor5-watchdog/dist/index.js';
9
+
10
+ /**
11
+ * The base class for CKEditor plugin classes.
12
+ */ class Plugin extends /* #__PURE__ */ ObservableMixin() {
13
+ /**
14
+ * The editor instance.
15
+ *
16
+ * Note that most editors implement the {@link module:core/editor/editor~Editor#ui} property.
17
+ * However, editors with an external UI (i.e. Bootstrap-based) or a headless editor may not have this property or
18
+ * throw an error when accessing it.
19
+ *
20
+ * Because of above, to make plugins more universal, it is recommended to split features into:
21
+ * - The "editing" part that uses the {@link module:core/editor/editor~Editor} class without `ui` property.
22
+ * - The "UI" part that uses the {@link module:core/editor/editor~Editor} class and accesses `ui` property.
23
+ */ editor;
24
+ /**
25
+ * Holds identifiers for {@link #forceDisabled} mechanism.
26
+ */ _disableStack = new Set();
27
+ /**
28
+ * @inheritDoc
29
+ */ constructor(editor){
30
+ super();
31
+ this.editor = editor;
32
+ this.set('isEnabled', true);
33
+ }
34
+ /**
35
+ * Disables the plugin.
36
+ *
37
+ * Plugin may be disabled by multiple features or algorithms (at once). When disabling a plugin, unique id should be passed
38
+ * (e.g. feature name). The same identifier should be used when {@link #clearForceDisabled enabling back} the plugin.
39
+ * The plugin becomes enabled only after all features {@link #clearForceDisabled enabled it back}.
40
+ *
41
+ * Disabling and enabling a plugin:
42
+ *
43
+ * ```ts
44
+ * plugin.isEnabled; // -> true
45
+ * plugin.forceDisabled( 'MyFeature' );
46
+ * plugin.isEnabled; // -> false
47
+ * plugin.clearForceDisabled( 'MyFeature' );
48
+ * plugin.isEnabled; // -> true
49
+ * ```
50
+ *
51
+ * Plugin disabled by multiple features:
52
+ *
53
+ * ```ts
54
+ * plugin.forceDisabled( 'MyFeature' );
55
+ * plugin.forceDisabled( 'OtherFeature' );
56
+ * plugin.clearForceDisabled( 'MyFeature' );
57
+ * plugin.isEnabled; // -> false
58
+ * plugin.clearForceDisabled( 'OtherFeature' );
59
+ * plugin.isEnabled; // -> true
60
+ * ```
61
+ *
62
+ * Multiple disabling with the same identifier is redundant:
63
+ *
64
+ * ```ts
65
+ * plugin.forceDisabled( 'MyFeature' );
66
+ * plugin.forceDisabled( 'MyFeature' );
67
+ * plugin.clearForceDisabled( 'MyFeature' );
68
+ * plugin.isEnabled; // -> true
69
+ * ```
70
+ *
71
+ * **Note:** some plugins or algorithms may have more complex logic when it comes to enabling or disabling certain plugins,
72
+ * so the plugin might be still disabled after {@link #clearForceDisabled} was used.
73
+ *
74
+ * @param id Unique identifier for disabling. Use the same id when {@link #clearForceDisabled enabling back} the plugin.
75
+ */ forceDisabled(id) {
76
+ this._disableStack.add(id);
77
+ if (this._disableStack.size == 1) {
78
+ this.on('set:isEnabled', forceDisable$1, {
79
+ priority: 'highest'
80
+ });
81
+ this.isEnabled = false;
82
+ }
83
+ }
84
+ /**
85
+ * Clears forced disable previously set through {@link #forceDisabled}. See {@link #forceDisabled}.
86
+ *
87
+ * @param id Unique identifier, equal to the one passed in {@link #forceDisabled} call.
88
+ */ clearForceDisabled(id) {
89
+ this._disableStack.delete(id);
90
+ if (this._disableStack.size == 0) {
91
+ this.off('set:isEnabled', forceDisable$1);
92
+ this.isEnabled = true;
93
+ }
94
+ }
95
+ /**
96
+ * @inheritDoc
97
+ */ destroy() {
98
+ this.stopListening();
99
+ }
100
+ /**
101
+ * @inheritDoc
102
+ */ static get isContextPlugin() {
103
+ return false;
104
+ }
105
+ /**
106
+ * @inheritDoc
107
+ */ static get isOfficialPlugin() {
108
+ return false;
109
+ }
110
+ /**
111
+ * @inheritDoc
112
+ */ static get isPremiumPlugin() {
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Helper function that forces plugin to be disabled.
118
+ */ function forceDisable$1(evt) {
119
+ evt.return = false;
120
+ evt.stop();
121
+ }
122
+
123
+ /**
124
+ * Base class for the CKEditor commands.
125
+ *
126
+ * Commands are the main way to manipulate the editor contents and state. They are mostly used by UI elements (or by other
127
+ * commands) to make changes in the model. Commands are available in every part of the code that has access to
128
+ * the {@link module:core/editor/editor~Editor editor} instance.
129
+ *
130
+ * Instances of registered commands can be retrieved from {@link module:core/editor/editor~Editor#commands `editor.commands`}.
131
+ * The easiest way to execute a command is through {@link module:core/editor/editor~Editor#execute `editor.execute()`}.
132
+ *
133
+ * By default, commands are disabled when the editor is in the {@link module:core/editor/editor~Editor#isReadOnly read-only} mode
134
+ * but commands with the {@link module:core/command~Command#affectsData `affectsData`} flag set to `false` will not be disabled.
135
+ */ class Command extends /* #__PURE__ */ ObservableMixin() {
136
+ /**
137
+ * The editor on which this command will be used.
138
+ */ editor;
139
+ /**
140
+ * A flag indicating whether a command's `isEnabled` state should be changed depending on where the document
141
+ * selection is placed.
142
+ *
143
+ * By default, it is set to `true`. If the document selection is placed in a
144
+ * {@link module:engine/model/model~Model#canEditAt non-editable} place (such as non-editable root), the command becomes disabled.
145
+ *
146
+ * The flag should be changed to `false` in a concrete command's constructor if the command should not change its `isEnabled`
147
+ * accordingly to the document selection.
148
+ */ _isEnabledBasedOnSelection;
149
+ /**
150
+ * A flag indicating whether a command execution changes the editor data or not.
151
+ *
152
+ * @see #affectsData
153
+ */ _affectsData;
154
+ /**
155
+ * Holds identifiers for {@link #forceDisabled} mechanism.
156
+ */ _disableStack;
157
+ /**
158
+ * Creates a new `Command` instance.
159
+ *
160
+ * @param editor The editor on which this command will be used.
161
+ */ constructor(editor){
162
+ super();
163
+ this.editor = editor;
164
+ this.set('value', undefined);
165
+ this.set('isEnabled', false);
166
+ this._affectsData = true;
167
+ this._isEnabledBasedOnSelection = true;
168
+ this._disableStack = new Set();
169
+ this.decorate('execute');
170
+ // By default, every command is refreshed when changes are applied to the model.
171
+ this.listenTo(this.editor.model.document, 'change', ()=>{
172
+ this.refresh();
173
+ });
174
+ this.listenTo(editor, 'change:isReadOnly', ()=>{
175
+ this.refresh();
176
+ });
177
+ // By default, commands are disabled if the selection is in non-editable place or editor is in read-only mode.
178
+ this.on('set:isEnabled', (evt)=>{
179
+ if (!this.affectsData) {
180
+ return;
181
+ }
182
+ const selection = editor.model.document.selection;
183
+ const selectionInGraveyard = selection.getFirstPosition().root.rootName == '$graveyard';
184
+ const canEditAtSelection = !selectionInGraveyard && editor.model.canEditAt(selection);
185
+ // Disable if editor is read only, or when selection is in a place which cannot be edited.
186
+ //
187
+ // Checking `editor.isReadOnly` is needed for all commands that have `_isEnabledBasedOnSelection == false`.
188
+ // E.g. undo does not base on selection, but affects data and should be disabled when the editor is in read-only mode.
189
+ if (editor.isReadOnly || this._isEnabledBasedOnSelection && !canEditAtSelection) {
190
+ evt.return = false;
191
+ evt.stop();
192
+ }
193
+ }, {
194
+ priority: 'highest'
195
+ });
196
+ this.on('execute', (evt)=>{
197
+ if (!this.isEnabled) {
198
+ evt.stop();
199
+ }
200
+ }, {
201
+ priority: 'high'
202
+ });
203
+ }
204
+ /**
205
+ * A flag indicating whether a command execution changes the editor data or not.
206
+ *
207
+ * Commands with `affectsData` set to `false` will not be automatically disabled in
208
+ * the {@link module:core/editor/editor~Editor#isReadOnly read-only mode} and
209
+ * {@glink features/read-only#related-features other editor modes} with restricted user write permissions.
210
+ *
211
+ * **Note:** You do not have to set it for your every command. It is `true` by default.
212
+ *
213
+ * @default true
214
+ */ get affectsData() {
215
+ return this._affectsData;
216
+ }
217
+ set affectsData(affectsData) {
218
+ this._affectsData = affectsData;
219
+ }
220
+ /**
221
+ * Refreshes the command. The command should update its {@link #isEnabled} and {@link #value} properties
222
+ * in this method.
223
+ *
224
+ * This method is automatically called when
225
+ * {@link module:engine/model/document~Document#event:change any changes are applied to the document}.
226
+ */ refresh() {
227
+ this.isEnabled = true;
228
+ }
229
+ /**
230
+ * Disables the command.
231
+ *
232
+ * Command may be disabled by multiple features or algorithms (at once). When disabling a command, unique id should be passed
233
+ * (e.g. the feature name). The same identifier should be used when {@link #clearForceDisabled enabling back} the command.
234
+ * The command becomes enabled only after all features {@link #clearForceDisabled enabled it back}.
235
+ *
236
+ * Disabling and enabling a command:
237
+ *
238
+ * ```ts
239
+ * command.isEnabled; // -> true
240
+ * command.forceDisabled( 'MyFeature' );
241
+ * command.isEnabled; // -> false
242
+ * command.clearForceDisabled( 'MyFeature' );
243
+ * command.isEnabled; // -> true
244
+ * ```
245
+ *
246
+ * Command disabled by multiple features:
247
+ *
248
+ * ```ts
249
+ * command.forceDisabled( 'MyFeature' );
250
+ * command.forceDisabled( 'OtherFeature' );
251
+ * command.clearForceDisabled( 'MyFeature' );
252
+ * command.isEnabled; // -> false
253
+ * command.clearForceDisabled( 'OtherFeature' );
254
+ * command.isEnabled; // -> true
255
+ * ```
256
+ *
257
+ * Multiple disabling with the same identifier is redundant:
258
+ *
259
+ * ```ts
260
+ * command.forceDisabled( 'MyFeature' );
261
+ * command.forceDisabled( 'MyFeature' );
262
+ * command.clearForceDisabled( 'MyFeature' );
263
+ * command.isEnabled; // -> true
264
+ * ```
265
+ *
266
+ * **Note:** some commands or algorithms may have more complex logic when it comes to enabling or disabling certain commands,
267
+ * so the command might be still disabled after {@link #clearForceDisabled} was used.
268
+ *
269
+ * @param id Unique identifier for disabling. Use the same id when {@link #clearForceDisabled enabling back} the command.
270
+ */ forceDisabled(id) {
271
+ this._disableStack.add(id);
272
+ if (this._disableStack.size == 1) {
273
+ this.on('set:isEnabled', forceDisable, {
274
+ priority: 'highest'
275
+ });
276
+ this.isEnabled = false;
277
+ }
278
+ }
279
+ /**
280
+ * Clears forced disable previously set through {@link #forceDisabled}. See {@link #forceDisabled}.
281
+ *
282
+ * @param id Unique identifier, equal to the one passed in {@link #forceDisabled} call.
283
+ */ clearForceDisabled(id) {
284
+ this._disableStack.delete(id);
285
+ if (this._disableStack.size == 0) {
286
+ this.off('set:isEnabled', forceDisable);
287
+ this.refresh();
288
+ }
289
+ }
290
+ /**
291
+ * Executes the command.
292
+ *
293
+ * A command may accept parameters. They will be passed from {@link module:core/editor/editor~Editor#execute `editor.execute()`}
294
+ * to the command.
295
+ *
296
+ * The `execute()` method will automatically abort when the command is disabled ({@link #isEnabled} is `false`).
297
+ * This behavior is implemented by a high priority listener to the {@link #event:execute} event.
298
+ *
299
+ * In order to see how to disable a command from "outside" see the {@link #isEnabled} documentation.
300
+ *
301
+ * This method may return a value, which would be forwarded all the way down to the
302
+ * {@link module:core/editor/editor~Editor#execute `editor.execute()`}.
303
+ *
304
+ * @fires execute
305
+ */ execute(...args) {
306
+ return undefined;
307
+ }
308
+ /**
309
+ * Destroys the command.
310
+ */ destroy() {
311
+ this.stopListening();
312
+ }
313
+ }
314
+ /**
315
+ * Helper function that forces command to be disabled.
316
+ */ function forceDisable(evt) {
317
+ evt.return = false;
318
+ evt.stop();
319
+ }
320
+
321
+ /**
322
+ * A CKEditor command that aggregates other commands.
323
+ *
324
+ * This command is used to proxy multiple commands. The multi-command is enabled when
325
+ * at least one of its registered child commands is enabled.
326
+ * When executing a multi-command, the first enabled command with highest priority will be executed.
327
+ *
328
+ * ```ts
329
+ * const multiCommand = new MultiCommand( editor );
330
+ *
331
+ * const commandFoo = new Command( editor );
332
+ * const commandBar = new Command( editor );
333
+ *
334
+ * // Register a child command.
335
+ * multiCommand.registerChildCommand( commandFoo );
336
+ * // Register a child command with a low priority.
337
+ * multiCommand.registerChildCommand( commandBar, { priority: 'low' } );
338
+ *
339
+ * // Enable one of the commands.
340
+ * commandBar.isEnabled = true;
341
+ *
342
+ * multiCommand.execute(); // Will execute commandBar.
343
+ * ```
344
+ */ class MultiCommand extends Command {
345
+ /**
346
+ * Registered child commands definitions.
347
+ */ _childCommandsDefinitions = [];
348
+ /**
349
+ * @inheritDoc
350
+ */ refresh() {
351
+ // Override base command refresh(): the command's state is changed when one of child commands changes states.
352
+ }
353
+ /**
354
+ * Executes the first enabled command which has the highest priority of all registered child commands.
355
+ *
356
+ * @returns The value returned by the {@link module:core/command~Command#execute `command.execute()`}.
357
+ */ execute(...args) {
358
+ const command = this._getFirstEnabledCommand();
359
+ return !!command && command.execute(args);
360
+ }
361
+ /**
362
+ * Registers a child command.
363
+ *
364
+ * @param options An object with configuration options.
365
+ * @param options.priority Priority of a command to register.
366
+ */ registerChildCommand(command, options = {}) {
367
+ insertToPriorityArray(this._childCommandsDefinitions, {
368
+ command,
369
+ priority: options.priority || 'normal'
370
+ });
371
+ // Change multi-command enabled state when one of registered commands changes state.
372
+ command.on('change:isEnabled', ()=>this._checkEnabled());
373
+ this._checkEnabled();
374
+ }
375
+ /**
376
+ * Checks if any of child commands is enabled.
377
+ */ _checkEnabled() {
378
+ this.isEnabled = !!this._getFirstEnabledCommand();
379
+ }
380
+ /**
381
+ * Returns a first enabled command with the highest priority or `undefined` if none of them is enabled.
382
+ */ _getFirstEnabledCommand() {
383
+ const commandDefinition = this._childCommandsDefinitions.find(({ command })=>command.isEnabled);
384
+ return commandDefinition && commandDefinition.command;
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Manages a list of CKEditor plugins, including loading, resolving dependencies and initialization.
390
+ */ class PluginCollection extends /* #__PURE__ */ EmitterMixin() {
391
+ _context;
392
+ _plugins = new Map();
393
+ /**
394
+ * A map of plugin constructors that can be retrieved by their names.
395
+ */ _availablePlugins;
396
+ /**
397
+ * Map of {@link module:core/contextplugin~ContextPlugin context plugins} which can be retrieved by their constructors or instances.
398
+ */ _contextPlugins;
399
+ /**
400
+ * Creates an instance of the plugin collection class.
401
+ * Allows loading and initializing plugins and their dependencies.
402
+ * Allows providing a list of already loaded plugins. These plugins will not be destroyed along with this collection.
403
+ *
404
+ * @param availablePlugins Plugins (constructors) which the collection will be able to use
405
+ * when {@link module:core/plugincollection~PluginCollection#init} is used with the plugin names (strings, instead of constructors).
406
+ * Usually, the editor will pass its built-in plugins to the collection so they can later be
407
+ * used in `config.plugins` or `config.removePlugins` by names.
408
+ * @param contextPlugins A list of already initialized plugins represented by a `[ PluginConstructor, pluginInstance ]` pair.
409
+ */ constructor(context, availablePlugins = [], contextPlugins = []){
410
+ super();
411
+ this._context = context;
412
+ this._availablePlugins = new Map();
413
+ for (const PluginConstructor of availablePlugins){
414
+ if (PluginConstructor.pluginName) {
415
+ this._availablePlugins.set(PluginConstructor.pluginName, PluginConstructor);
416
+ }
417
+ }
418
+ this._contextPlugins = new Map();
419
+ for (const [PluginConstructor, pluginInstance] of contextPlugins){
420
+ this._contextPlugins.set(PluginConstructor, pluginInstance);
421
+ this._contextPlugins.set(pluginInstance, PluginConstructor);
422
+ // To make it possible to require a plugin by its name.
423
+ if (PluginConstructor.pluginName) {
424
+ this._availablePlugins.set(PluginConstructor.pluginName, PluginConstructor);
425
+ }
426
+ }
427
+ }
428
+ /**
429
+ * Iterable interface.
430
+ *
431
+ * Returns `[ PluginConstructor, pluginInstance ]` pairs.
432
+ */ *[Symbol.iterator]() {
433
+ for (const entry of this._plugins){
434
+ if (typeof entry[0] == 'function') {
435
+ yield entry;
436
+ }
437
+ }
438
+ }
439
+ /**
440
+ * Gets the plugin instance by its constructor or name.
441
+ *
442
+ * ```ts
443
+ * // Check if 'Clipboard' plugin was loaded.
444
+ * if ( editor.plugins.has( 'ClipboardPipeline' ) ) {
445
+ * // Get clipboard plugin instance
446
+ * const clipboard = editor.plugins.get( 'ClipboardPipeline' );
447
+ *
448
+ * this.listenTo( clipboard, 'inputTransformation', ( evt, data ) => {
449
+ * // Do something on clipboard input.
450
+ * } );
451
+ * }
452
+ * ```
453
+ *
454
+ * **Note**: This method will throw an error if a plugin is not loaded. Use `{@link #has editor.plugins.has()}`
455
+ * to check if a plugin is available.
456
+ *
457
+ * @param key The plugin constructor or {@link module:core/plugin~PluginStaticMembers#pluginName name}.
458
+ */ get(key) {
459
+ const plugin = this._plugins.get(key);
460
+ if (!plugin) {
461
+ let pluginName = key;
462
+ if (typeof key == 'function') {
463
+ pluginName = key.pluginName || key.name;
464
+ }
465
+ /**
466
+ * The plugin is not loaded and could not be obtained.
467
+ *
468
+ * Plugin classes (constructors) need to be provided to the editor and must be loaded before they can be obtained from
469
+ * the plugin collection.
470
+ *
471
+ * **Note**: You can use `{@link module:core/plugincollection~PluginCollection#has editor.plugins.has()}`
472
+ * to check if a plugin was loaded.
473
+ *
474
+ * @error plugincollection-plugin-not-loaded
475
+ * @param plugin The name of the plugin which is not loaded.
476
+ */ throw new CKEditorError('plugincollection-plugin-not-loaded', this._context, {
477
+ plugin: pluginName
478
+ });
479
+ }
480
+ return plugin;
481
+ }
482
+ /**
483
+ * Checks if a plugin is loaded.
484
+ *
485
+ * ```ts
486
+ * // Check if the 'Clipboard' plugin was loaded.
487
+ * if ( editor.plugins.has( 'ClipboardPipeline' ) ) {
488
+ * // Now use the clipboard plugin instance:
489
+ * const clipboard = editor.plugins.get( 'ClipboardPipeline' );
490
+ *
491
+ * // ...
492
+ * }
493
+ * ```
494
+ *
495
+ * @param key The plugin constructor or {@link module:core/plugin~PluginStaticMembers#pluginName name}.
496
+ */ has(key) {
497
+ return this._plugins.has(key);
498
+ }
499
+ /**
500
+ * Initializes a set of plugins and adds them to the collection.
501
+ *
502
+ * @param plugins An array of {@link module:core/plugin~PluginInterface plugin constructors}
503
+ * or {@link module:core/plugin~PluginStaticMembers#pluginName plugin names}.
504
+ * @param pluginsToRemove Names of the plugins or plugin constructors
505
+ * that should not be loaded (despite being specified in the `plugins` array).
506
+ * @param pluginsSubstitutions An array of {@link module:core/plugin~PluginInterface plugin constructors}
507
+ * that will be used to replace plugins of the same names that were passed in `plugins` or that are in their dependency tree.
508
+ * A useful option for replacing built-in plugins while creating tests (for mocking their APIs). Plugins that will be replaced
509
+ * must follow these rules:
510
+ * * The new plugin must be a class.
511
+ * * The new plugin must be named.
512
+ * * Both plugins must not depend on other plugins.
513
+ * @returns A promise which gets resolved once all plugins are loaded and available in the collection.
514
+ */ init(plugins, pluginsToRemove = [], pluginsSubstitutions = []) {
515
+ // Plugin initialization procedure consists of 2 main steps:
516
+ // 1) collecting all available plugin constructors,
517
+ // 2) verification whether all required plugins can be instantiated.
518
+ //
519
+ // In the first step, all plugin constructors, available in the provided `plugins` array and inside
520
+ // plugin's dependencies (from the `Plugin.requires` array), are recursively collected and added to the existing
521
+ // `this._availablePlugins` map, but without any verification at the given moment. Performing the verification
522
+ // at this point (during the plugin constructor searching) would cause false errors to occur, that some plugin
523
+ // is missing but in fact it may be defined further in the array as the dependency of other plugin. After
524
+ // traversing the entire dependency tree, it will be checked if all required "top level" plugins are available.
525
+ //
526
+ // In the second step, the list of plugins that have not been explicitly removed is traversed to get all the
527
+ // plugin constructors to be instantiated in the correct order and to validate against some rules. Finally, if
528
+ // no plugin is missing and no other error has been found, they all will be instantiated.
529
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
530
+ const that = this;
531
+ const context = this._context;
532
+ findAvailablePluginConstructors(plugins);
533
+ validatePlugins(plugins);
534
+ const pluginsToLoad = plugins.filter((plugin)=>!isPluginRemoved(plugin, pluginsToRemove));
535
+ const pluginConstructors = [
536
+ ...getPluginConstructors(pluginsToLoad)
537
+ ];
538
+ substitutePlugins(pluginConstructors, pluginsSubstitutions);
539
+ const pluginInstances = loadPlugins(pluginConstructors);
540
+ return initPlugins(pluginInstances, 'init').then(()=>initPlugins(pluginInstances, 'afterInit')).then(()=>pluginInstances);
541
+ function isPluginConstructor(plugin) {
542
+ return typeof plugin === 'function';
543
+ }
544
+ function isContextPlugin(plugin) {
545
+ return isPluginConstructor(plugin) && !!plugin.isContextPlugin;
546
+ }
547
+ function isPluginRemoved(plugin, pluginsToRemove) {
548
+ return pluginsToRemove.some((removedPlugin)=>{
549
+ if (removedPlugin === plugin) {
550
+ return true;
551
+ }
552
+ if (getPluginName(plugin) === removedPlugin) {
553
+ return true;
554
+ }
555
+ if (getPluginName(removedPlugin) === plugin) {
556
+ return true;
557
+ }
558
+ return false;
559
+ });
560
+ }
561
+ function getPluginName(plugin) {
562
+ return isPluginConstructor(plugin) ? plugin.pluginName || plugin.name : plugin;
563
+ }
564
+ function findAvailablePluginConstructors(plugins, processed = new Set()) {
565
+ plugins.forEach((plugin)=>{
566
+ if (!isPluginConstructor(plugin)) {
567
+ return;
568
+ }
569
+ if (processed.has(plugin)) {
570
+ return;
571
+ }
572
+ processed.add(plugin);
573
+ if (plugin.pluginName && !that._availablePlugins.has(plugin.pluginName)) {
574
+ that._availablePlugins.set(plugin.pluginName, plugin);
575
+ }
576
+ if (plugin.requires) {
577
+ findAvailablePluginConstructors(plugin.requires, processed);
578
+ }
579
+ });
580
+ }
581
+ function getPluginConstructors(plugins, processed = new Set()) {
582
+ return plugins.map((plugin)=>{
583
+ return isPluginConstructor(plugin) ? plugin : that._availablePlugins.get(plugin);
584
+ }).reduce((result, plugin)=>{
585
+ if (processed.has(plugin)) {
586
+ return result;
587
+ }
588
+ processed.add(plugin);
589
+ if (plugin.requires) {
590
+ validatePlugins(plugin.requires, plugin);
591
+ getPluginConstructors(plugin.requires, processed).forEach((plugin)=>result.add(plugin));
592
+ }
593
+ return result.add(plugin);
594
+ }, new Set());
595
+ }
596
+ function validatePlugins(plugins, parentPluginConstructor = null) {
597
+ plugins.map((plugin)=>{
598
+ return isPluginConstructor(plugin) ? plugin : that._availablePlugins.get(plugin) || plugin;
599
+ }).forEach((plugin)=>{
600
+ checkMissingPlugin(plugin, parentPluginConstructor);
601
+ checkContextPlugin(plugin, parentPluginConstructor);
602
+ checkRemovedPlugin(plugin, parentPluginConstructor);
603
+ });
604
+ }
605
+ function checkMissingPlugin(plugin, parentPluginConstructor) {
606
+ if (isPluginConstructor(plugin)) {
607
+ return;
608
+ }
609
+ if (parentPluginConstructor) {
610
+ /**
611
+ * A required "soft" dependency was not found on the plugin list.
612
+ *
613
+ * When configuring the editor, either prior to building (via
614
+ * {@link module:core/editor/editor~Editor.builtinPlugins `Editor.builtinPlugins`}) or when
615
+ * creating a new instance of the editor (e.g. via
616
+ * {@link module:core/editor/editorconfig~EditorConfig#plugins `config.plugins`}), you need to provide
617
+ * some of the dependencies for other plugins that you used.
618
+ *
619
+ * This error is thrown when one of these dependencies was not provided. The name of the missing plugin
620
+ * can be found in `missingPlugin` and the plugin that required it in `requiredBy`.
621
+ *
622
+ * In order to resolve it, you need to import the missing plugin and add it to the
623
+ * current list of plugins (`Editor.builtinPlugins` or `config.plugins`/`config.extraPlugins`).
624
+ *
625
+ * Soft requirements were introduced in version 26.0.0. If you happen to stumble upon this error
626
+ * when upgrading to version 26.0.0, read also the
627
+ * {@glink updating/guides/update-to-26 Migration to 26.0.0} guide.
628
+ *
629
+ * @error plugincollection-soft-required
630
+ * @param missingPlugin The name of the required plugin.
631
+ * @param requiredBy The name of the plugin that requires the other plugin.
632
+ */ throw new CKEditorError('plugincollection-soft-required', context, {
633
+ missingPlugin: plugin,
634
+ requiredBy: getPluginName(parentPluginConstructor)
635
+ });
636
+ }
637
+ /**
638
+ * A plugin is not available and could not be loaded.
639
+ *
640
+ * Plugin classes (constructors) need to be provided to the editor before they can be loaded by name.
641
+ * This is usually done in CKEditor 5 builds by setting the {@link module:core/editor/editor~Editor.builtinPlugins}
642
+ * property.
643
+ *
644
+ * **If you see this warning when using one of the CKEditor 5 Builds},
645
+ * it means that you try to enable a plugin which was not included in that build. This may be due to a typo
646
+ * in the plugin name or simply because that plugin is not a part of this build.
647
+ *
648
+ * Predefined builds are a deprecated solution and we strongly advise
649
+ * {@glink updating/nim-migration/migration-to-new-installation-methods migrating to new installation methods}.
650
+ *
651
+ * **If you see this warning when using one of the editor creators directly** (not a build), then it means
652
+ * that you tried loading plugins by name. However, unlike CKEditor 4, CKEditor 5 does not implement a "plugin loader".
653
+ * This means that CKEditor 5 does not know where to load the plugin modules from. Therefore, you need to
654
+ * provide each plugin through a reference (as a constructor function). Check out the examples in the
655
+ * {@glink getting-started/installation/cloud/quick-start Quick start} guide.
656
+ *
657
+ * @error plugincollection-plugin-not-found
658
+ * @param plugin The name of the plugin which could not be loaded.
659
+ */ throw new CKEditorError('plugincollection-plugin-not-found', context, {
660
+ plugin
661
+ });
662
+ }
663
+ function checkContextPlugin(plugin, parentPluginConstructor) {
664
+ if (!isContextPlugin(parentPluginConstructor)) {
665
+ return;
666
+ }
667
+ if (isContextPlugin(plugin)) {
668
+ return;
669
+ }
670
+ /**
671
+ * If a plugin is a context plugin, all plugins it requires should also be context plugins
672
+ * instead of plugins. In other words, if one plugin can be used in the context,
673
+ * all its requirements should also be ready to be used in the context. Note that the context
674
+ * provides only a part of the API provided by the editor. If one plugin needs a full
675
+ * editor API, all plugins which require it are considered as plugins that need a full
676
+ * editor API.
677
+ *
678
+ * @error plugincollection-context-required
679
+ * @param plugin The name of the required plugin.
680
+ * @param requiredBy The name of the parent plugin.
681
+ */ throw new CKEditorError('plugincollection-context-required', context, {
682
+ plugin: getPluginName(plugin),
683
+ requiredBy: getPluginName(parentPluginConstructor)
684
+ });
685
+ }
686
+ function checkRemovedPlugin(plugin, parentPluginConstructor) {
687
+ if (!parentPluginConstructor) {
688
+ return;
689
+ }
690
+ if (!isPluginRemoved(plugin, pluginsToRemove)) {
691
+ return;
692
+ }
693
+ /**
694
+ * Cannot load a plugin because one of its dependencies is listed in the `removePlugins` option.
695
+ *
696
+ * @error plugincollection-required
697
+ * @param plugin The name of the required plugin.
698
+ * @param requiredBy The name of the parent plugin.
699
+ */ throw new CKEditorError('plugincollection-required', context, {
700
+ plugin: getPluginName(plugin),
701
+ requiredBy: getPluginName(parentPluginConstructor)
702
+ });
703
+ }
704
+ function loadPlugins(pluginConstructors) {
705
+ return pluginConstructors.map((PluginConstructor)=>{
706
+ let pluginInstance = that._contextPlugins.get(PluginConstructor);
707
+ pluginInstance = pluginInstance || new PluginConstructor(context);
708
+ that._add(PluginConstructor, pluginInstance);
709
+ return pluginInstance;
710
+ });
711
+ }
712
+ function initPlugins(pluginInstances, method) {
713
+ return pluginInstances.reduce((promise, plugin)=>{
714
+ if (!plugin[method]) {
715
+ return promise;
716
+ }
717
+ if (that._contextPlugins.has(plugin)) {
718
+ return promise;
719
+ }
720
+ return promise.then(plugin[method].bind(plugin));
721
+ }, Promise.resolve());
722
+ }
723
+ /**
724
+ * Replaces plugin constructors with the specified set of plugins.
725
+ */ function substitutePlugins(pluginConstructors, pluginsSubstitutions) {
726
+ for (const pluginItem of pluginsSubstitutions){
727
+ if (typeof pluginItem != 'function') {
728
+ /**
729
+ * The plugin replacing an existing plugin must be a function.
730
+ *
731
+ * @error plugincollection-replace-plugin-invalid-type
732
+ */ throw new CKEditorError('plugincollection-replace-plugin-invalid-type', null, {
733
+ pluginItem
734
+ });
735
+ }
736
+ const pluginName = pluginItem.pluginName;
737
+ if (!pluginName) {
738
+ /**
739
+ * The plugin replacing an existing plugin must have a name.
740
+ *
741
+ * @error plugincollection-replace-plugin-missing-name
742
+ */ throw new CKEditorError('plugincollection-replace-plugin-missing-name', null, {
743
+ pluginItem
744
+ });
745
+ }
746
+ if (pluginItem.requires && pluginItem.requires.length) {
747
+ /**
748
+ * The plugin replacing an existing plugin cannot depend on other plugins.
749
+ *
750
+ * @error plugincollection-plugin-for-replacing-cannot-have-dependencies
751
+ */ throw new CKEditorError('plugincollection-plugin-for-replacing-cannot-have-dependencies', null, {
752
+ pluginName
753
+ });
754
+ }
755
+ const pluginToReplace = that._availablePlugins.get(pluginName);
756
+ if (!pluginToReplace) {
757
+ /**
758
+ * The replaced plugin does not exist in the
759
+ * {@link module:core/plugincollection~PluginCollection available plugins} collection.
760
+ *
761
+ * @error plugincollection-plugin-for-replacing-not-exist
762
+ */ throw new CKEditorError('plugincollection-plugin-for-replacing-not-exist', null, {
763
+ pluginName
764
+ });
765
+ }
766
+ const indexInPluginConstructors = pluginConstructors.indexOf(pluginToReplace);
767
+ if (indexInPluginConstructors === -1) {
768
+ // The Context feature can substitute plugins as well.
769
+ // It may happen that the editor will be created with the given context, where the plugin for substitute
770
+ // was already replaced. In such a case, we don't want to do it again.
771
+ if (that._contextPlugins.has(pluginToReplace)) {
772
+ return;
773
+ }
774
+ /**
775
+ * The replaced plugin will not be loaded so it cannot be replaced.
776
+ *
777
+ * @error plugincollection-plugin-for-replacing-not-loaded
778
+ */ throw new CKEditorError('plugincollection-plugin-for-replacing-not-loaded', null, {
779
+ pluginName
780
+ });
781
+ }
782
+ if (pluginToReplace.requires && pluginToReplace.requires.length) {
783
+ /**
784
+ * The replaced plugin cannot depend on other plugins.
785
+ *
786
+ * @error plugincollection-replaced-plugin-cannot-have-dependencies
787
+ */ throw new CKEditorError('plugincollection-replaced-plugin-cannot-have-dependencies', null, {
788
+ pluginName
789
+ });
790
+ }
791
+ pluginConstructors.splice(indexInPluginConstructors, 1, pluginItem);
792
+ that._availablePlugins.set(pluginName, pluginItem);
793
+ }
794
+ }
795
+ }
796
+ /**
797
+ * Destroys all loaded plugins.
798
+ */ destroy() {
799
+ const promises = [];
800
+ for (const [, pluginInstance] of this){
801
+ if (typeof pluginInstance.destroy == 'function' && !this._contextPlugins.has(pluginInstance)) {
802
+ promises.push(pluginInstance.destroy());
803
+ }
804
+ }
805
+ return Promise.all(promises);
806
+ }
807
+ /**
808
+ * Adds the plugin to the collection. Exposed mainly for testing purposes.
809
+ *
810
+ * @param PluginConstructor The plugin constructor.
811
+ * @param plugin The instance of the plugin.
812
+ */ _add(PluginConstructor, plugin) {
813
+ this._plugins.set(PluginConstructor, plugin);
814
+ const pluginName = PluginConstructor.pluginName;
815
+ if (!pluginName) {
816
+ return;
817
+ }
818
+ if (this._plugins.has(pluginName)) {
819
+ /**
820
+ * Two plugins with the same {@link module:core/plugin~PluginStaticMembers#pluginName} were loaded.
821
+ * This will lead to runtime conflicts between these plugins.
822
+ *
823
+ * In practice, this warning usually means that new plugins were added to an existing CKEditor 5 build.
824
+ * Plugins should always be added to a source version of the editor (`@ckeditor/ckeditor5-editor-*`),
825
+ * not to an editor imported from one of the `@ckeditor/ckeditor5-build-*` packages.
826
+ *
827
+ * Check your import paths and the list of plugins passed to
828
+ * {@link module:core/editor/editor~Editor.create `Editor.create()`}
829
+ * or specified in {@link module:core/editor/editor~Editor.builtinPlugins `Editor.builtinPlugins`}.
830
+ *
831
+ * Predefined builds are a deprecated solution and we strongly advise
832
+ * {@glink updating/nim-migration/migration-to-new-installation-methods migrating to new installation methods}.
833
+ *
834
+ * The second option is that your `node_modules/` directory contains duplicated versions of the same
835
+ * CKEditor 5 packages. Normally, on clean installations, npm deduplicates packages in `node_modules/`, so
836
+ * it may be enough to call `rm -rf node_modules && npm i`. However, if you installed conflicting versions
837
+ * of some packages, their dependencies may need to be installed in more than one version which may lead to this
838
+ * warning.
839
+ *
840
+ * Technically speaking, this error occurs because after adding a plugin to an existing editor build
841
+ * the dependencies of this plugin are being duplicated.
842
+ * They are already built into that editor build and now get added for the second time as dependencies
843
+ * of the plugin you are installing.
844
+ *
845
+ * @error plugincollection-plugin-name-conflict
846
+ * @param pluginName The duplicated plugin name.
847
+ * @param plugin1 The first plugin constructor.
848
+ * @param plugin2 The second plugin constructor.
849
+ */ throw new CKEditorError('plugincollection-plugin-name-conflict', null, {
850
+ pluginName,
851
+ plugin1: this._plugins.get(pluginName).constructor,
852
+ plugin2: PluginConstructor
853
+ });
854
+ }
855
+ this._plugins.set(pluginName, plugin);
856
+ }
857
+ }
858
+
859
+ /**
860
+ * Provides a common, higher-level environment for solutions that use multiple {@link module:core/editor/editor~Editor editors}
861
+ * or plugins that work outside the editor. Use it instead of {@link module:core/editor/editor~Editor.create `Editor.create()`}
862
+ * in advanced application integrations.
863
+ *
864
+ * All configuration options passed to a context will be used as default options for the editor instances initialized in that context.
865
+ *
866
+ * {@link module:core/contextplugin~ContextPlugin Context plugins} passed to a context instance will be shared among all
867
+ * editor instances initialized in this context. These will be the same plugin instances for all the editors.
868
+ *
869
+ * **Note:** The context can only be initialized with {@link module:core/contextplugin~ContextPlugin context plugins}
870
+ * (e.g. [comments](https://ckeditor.com/collaboration/comments/)). Regular {@link module:core/plugin~Plugin plugins} require an
871
+ * editor instance to work and cannot be added to a context.
872
+ *
873
+ * **Note:** You can add a context plugin to an editor instance, though.
874
+ *
875
+ * If you are using multiple editor instances on one page and use any context plugins, create a context to share the configuration and
876
+ * plugins among these editors. Some plugins will use the information about all existing editors to better integrate between them.
877
+ *
878
+ * If you are using plugins that do not require an editor to work (e.g. [comments](https://ckeditor.com/collaboration/comments/)),
879
+ * enable and configure them using the context.
880
+ *
881
+ * If you are using only a single editor on each page, use {@link module:core/editor/editor~Editor.create `Editor.create()`} instead.
882
+ * In such a case, a context instance will be created by the editor instance in a transparent way.
883
+ *
884
+ * See {@link ~Context.create `Context.create()`} for usage examples.
885
+ */ class Context {
886
+ /**
887
+ * Stores all the configurations specific to this context instance.
888
+ */ config;
889
+ /**
890
+ * The plugins loaded and in use by this context instance.
891
+ */ plugins;
892
+ locale;
893
+ /**
894
+ * Shorthand for {@link module:utils/locale~Locale#t}.
895
+ */ t;
896
+ /**
897
+ * A list of editors that this context instance is injected to.
898
+ */ editors;
899
+ /**
900
+ * The default configuration which is built into the `Context` class.
901
+ *
902
+ * It is used in CKEditor 5 builds featuring `Context` to provide the default configuration options which are later used during the
903
+ * context initialization.
904
+ *
905
+ * ```ts
906
+ * Context.defaultConfig = {
907
+ * foo: 1,
908
+ * bar: 2
909
+ * };
910
+ *
911
+ * Context
912
+ * .create()
913
+ * .then( context => {
914
+ * context.config.get( 'foo' ); // -> 1
915
+ * context.config.get( 'bar' ); // -> 2
916
+ * } );
917
+ *
918
+ * // The default options can be overridden by the configuration passed to create().
919
+ * Context
920
+ * .create( { bar: 3 } )
921
+ * .then( context => {
922
+ * context.config.get( 'foo' ); // -> 1
923
+ * context.config.get( 'bar' ); // -> 3
924
+ * } );
925
+ * ```
926
+ *
927
+ * See also {@link module:core/context~Context.builtinPlugins `Context.builtinPlugins`}
928
+ * and {@link module:core/editor/editor~Editor.defaultConfig `Editor.defaultConfig`}.
929
+ */ static defaultConfig;
930
+ /**
931
+ * An array of plugins built into the `Context` class.
932
+ *
933
+ * It is used in CKEditor 5 builds featuring `Context` to provide a list of context plugins which are later automatically initialized
934
+ * during the context initialization.
935
+ *
936
+ * They will be automatically initialized by `Context` unless `config.plugins` is passed.
937
+ *
938
+ * ```ts
939
+ * // Build some context plugins into the Context class first.
940
+ * Context.builtinPlugins = [ FooPlugin, BarPlugin ];
941
+ *
942
+ * // Normally, you need to define config.plugins, but since Context.builtinPlugins was
943
+ * // defined, now you can call create() without any configuration.
944
+ * Context
945
+ * .create()
946
+ * .then( context => {
947
+ * context.plugins.get( FooPlugin ); // -> An instance of the Foo plugin.
948
+ * context.plugins.get( BarPlugin ); // -> An instance of the Bar plugin.
949
+ * } );
950
+ * ```
951
+ *
952
+ * See also {@link module:core/context~Context.defaultConfig `Context.defaultConfig`}
953
+ * and {@link module:core/editor/editor~Editor.builtinPlugins `Editor.builtinPlugins`}.
954
+ */ static builtinPlugins;
955
+ /**
956
+ * Reference to the editor which created the context.
957
+ * Null when the context was created outside of the editor.
958
+ *
959
+ * It is used to destroy the context when removing the editor that has created the context.
960
+ */ _contextOwner = null;
961
+ /**
962
+ * Creates a context instance with a given configuration.
963
+ *
964
+ * Usually not to be used directly. See the static {@link module:core/context~Context.create `create()`} method.
965
+ *
966
+ * @param config The context configuration.
967
+ */ constructor(config){
968
+ // We don't pass translations to the config, because its behavior of splitting keys
969
+ // with dots (e.g. `resize.width` => `resize: { width }`) breaks the translations.
970
+ const { translations, ...rest } = config || {};
971
+ this.config = new Config(rest, this.constructor.defaultConfig);
972
+ const availablePlugins = this.constructor.builtinPlugins;
973
+ this.config.define('plugins', availablePlugins);
974
+ this.plugins = new PluginCollection(this, availablePlugins);
975
+ const languageConfig = this.config.get('language') || {};
976
+ this.locale = new Locale({
977
+ uiLanguage: typeof languageConfig === 'string' ? languageConfig : languageConfig.ui,
978
+ contentLanguage: this.config.get('language.content'),
979
+ translations
980
+ });
981
+ this.t = this.locale.t;
982
+ this.editors = new Collection();
983
+ }
984
+ /**
985
+ * Loads and initializes plugins specified in the configuration.
986
+ *
987
+ * @returns A promise which resolves once the initialization is completed, providing an array of loaded plugins.
988
+ */ initPlugins() {
989
+ const plugins = this.config.get('plugins') || [];
990
+ const substitutePlugins = this.config.get('substitutePlugins') || [];
991
+ // Plugins for substitution should be checked as well.
992
+ for (const Plugin of plugins.concat(substitutePlugins)){
993
+ if (typeof Plugin != 'function') {
994
+ /**
995
+ * Only a constructor function is allowed as a {@link module:core/contextplugin~ContextPlugin context plugin}.
996
+ *
997
+ * @error context-initplugins-constructor-only
998
+ */ throw new CKEditorError('context-initplugins-constructor-only', null, {
999
+ Plugin
1000
+ });
1001
+ }
1002
+ if (Plugin.isContextPlugin !== true) {
1003
+ /**
1004
+ * Only a plugin marked as a {@link module:core/contextplugin~ContextPlugin.isContextPlugin context plugin}
1005
+ * is allowed to be used with a context.
1006
+ *
1007
+ * @error context-initplugins-invalid-plugin
1008
+ */ throw new CKEditorError('context-initplugins-invalid-plugin', null, {
1009
+ Plugin
1010
+ });
1011
+ }
1012
+ }
1013
+ return this.plugins.init(plugins, [], substitutePlugins);
1014
+ }
1015
+ /**
1016
+ * Destroys the context instance and all editors used with the context,
1017
+ * releasing all resources used by the context.
1018
+ *
1019
+ * @returns A promise that resolves once the context instance is fully destroyed.
1020
+ */ destroy() {
1021
+ return Promise.all(Array.from(this.editors, (editor)=>editor.destroy())).then(()=>this.plugins.destroy());
1022
+ }
1023
+ /**
1024
+ * Adds a reference to the editor which is used with this context.
1025
+ *
1026
+ * When the given editor has created the context, the reference to this editor will be stored
1027
+ * as a {@link ~Context#_contextOwner}.
1028
+ *
1029
+ * This method should only be used by the editor.
1030
+ *
1031
+ * @internal
1032
+ * @param isContextOwner Stores the given editor as a context owner.
1033
+ */ _addEditor(editor, isContextOwner) {
1034
+ if (this._contextOwner) {
1035
+ /**
1036
+ * Cannot add multiple editors to the context which is created by the editor.
1037
+ *
1038
+ * @error context-addeditor-private-context
1039
+ */ throw new CKEditorError('context-addeditor-private-context');
1040
+ }
1041
+ this.editors.add(editor);
1042
+ if (isContextOwner) {
1043
+ this._contextOwner = editor;
1044
+ }
1045
+ }
1046
+ /**
1047
+ * Removes a reference to the editor which was used with this context.
1048
+ * When the context was created by the given editor, the context will be destroyed.
1049
+ *
1050
+ * This method should only be used by the editor.
1051
+ *
1052
+ * @internal
1053
+ * @return A promise that resolves once the editor is removed from the context or when the context was destroyed.
1054
+ */ _removeEditor(editor) {
1055
+ if (this.editors.has(editor)) {
1056
+ this.editors.remove(editor);
1057
+ }
1058
+ if (this._contextOwner === editor) {
1059
+ return this.destroy();
1060
+ }
1061
+ return Promise.resolve();
1062
+ }
1063
+ /**
1064
+ * Returns the context configuration which will be copied to the editors created using this context.
1065
+ *
1066
+ * The configuration returned by this method has the plugins configuration removed – plugins are shared with all editors
1067
+ * through another mechanism.
1068
+ *
1069
+ * This method should only be used by the editor.
1070
+ *
1071
+ * @internal
1072
+ * @returns Configuration as a plain object.
1073
+ */ _getEditorConfig() {
1074
+ const result = {};
1075
+ for (const name of this.config.names()){
1076
+ if (![
1077
+ 'plugins',
1078
+ 'removePlugins',
1079
+ 'extraPlugins'
1080
+ ].includes(name)) {
1081
+ result[name] = this.config.get(name);
1082
+ }
1083
+ }
1084
+ return result;
1085
+ }
1086
+ /**
1087
+ * Creates and initializes a new context instance.
1088
+ *
1089
+ * ```ts
1090
+ * const commonConfig = { ... }; // Configuration for all the plugins and editors.
1091
+ * const editorPlugins = [ ... ]; // Regular plugins here.
1092
+ *
1093
+ * Context
1094
+ * .create( {
1095
+ * // Only context plugins here.
1096
+ * plugins: [ ... ],
1097
+ *
1098
+ * // Configure the language for all the editors (it cannot be overwritten).
1099
+ * language: { ... },
1100
+ *
1101
+ * // Configuration for context plugins.
1102
+ * comments: { ... },
1103
+ * ...
1104
+ *
1105
+ * // Default configuration for editor plugins.
1106
+ * toolbar: { ... },
1107
+ * image: { ... },
1108
+ * ...
1109
+ * } )
1110
+ * .then( context => {
1111
+ * const promises = [];
1112
+ *
1113
+ * promises.push( ClassicEditor.create(
1114
+ * document.getElementById( 'editor1' ),
1115
+ * {
1116
+ * editorPlugins,
1117
+ * context
1118
+ * }
1119
+ * ) );
1120
+ *
1121
+ * promises.push( ClassicEditor.create(
1122
+ * document.getElementById( 'editor2' ),
1123
+ * {
1124
+ * editorPlugins,
1125
+ * context,
1126
+ * toolbar: { ... } // You can overwrite the configuration of the context.
1127
+ * }
1128
+ * ) );
1129
+ *
1130
+ * return Promise.all( promises );
1131
+ * } );
1132
+ * ```
1133
+ *
1134
+ * @param config The context configuration.
1135
+ * @returns A promise resolved once the context is ready. The promise resolves with the created context instance.
1136
+ */ static create(config) {
1137
+ return new Promise((resolve)=>{
1138
+ const context = new this(config);
1139
+ resolve(context.initPlugins().then(()=>context));
1140
+ });
1141
+ }
1142
+ }
1143
+
1144
+ /**
1145
+ * The base class for {@link module:core/context~Context} plugin classes.
1146
+ *
1147
+ * A context plugin can either be initialized for an {@link module:core/editor/editor~Editor editor} or for
1148
+ * a {@link module:core/context~Context context}. In other words, it can either
1149
+ * work within one editor instance or with one or more editor instances that use a single context.
1150
+ * It is the context plugin's role to implement handling for both modes.
1151
+ *
1152
+ * There are a few rules for interaction between the editor plugins and context plugins:
1153
+ *
1154
+ * * A context plugin can require another context plugin.
1155
+ * * An {@link module:core/plugin~Plugin editor plugin} can require a context plugin.
1156
+ * * A context plugin MUST NOT require an {@link module:core/plugin~Plugin editor plugin}.
1157
+ */ class ContextPlugin extends /* #__PURE__ */ ObservableMixin() {
1158
+ /**
1159
+ * The context or editor instance.
1160
+ */ context;
1161
+ /**
1162
+ * Creates a new plugin instance.
1163
+ */ constructor(context){
1164
+ super();
1165
+ this.context = context;
1166
+ }
1167
+ /**
1168
+ * @inheritDoc
1169
+ */ destroy() {
1170
+ this.stopListening();
1171
+ }
1172
+ /**
1173
+ * @inheritDoc
1174
+ */ static get isContextPlugin() {
1175
+ return true;
1176
+ }
1177
+ /**
1178
+ * @inheritDoc
1179
+ */ static get isOfficialPlugin() {
1180
+ return false;
1181
+ }
1182
+ /**
1183
+ * @inheritDoc
1184
+ */ static get isPremiumPlugin() {
1185
+ return false;
1186
+ }
1187
+ }
1188
+
1189
+ /**
1190
+ * Collection of commands. Its instance is available in {@link module:core/editor/editor~Editor#commands `editor.commands`}.
1191
+ */ class CommandCollection {
1192
+ /**
1193
+ * Command map.
1194
+ */ _commands;
1195
+ /**
1196
+ * Creates collection instance.
1197
+ */ constructor(){
1198
+ this._commands = new Map();
1199
+ }
1200
+ /**
1201
+ * Registers a new command.
1202
+ *
1203
+ * @param commandName The name of the command.
1204
+ */ add(commandName, command) {
1205
+ this._commands.set(commandName, command);
1206
+ }
1207
+ /**
1208
+ * Retrieves a command from the collection.
1209
+ *
1210
+ * @param commandName The name of the command.
1211
+ */ get(commandName) {
1212
+ return this._commands.get(commandName);
1213
+ }
1214
+ /**
1215
+ * Executes a command.
1216
+ *
1217
+ * @param commandName The name of the command.
1218
+ * @param commandParams Command parameters.
1219
+ * @returns The value returned by the {@link module:core/command~Command#execute `command.execute()`}.
1220
+ */ execute(commandName, ...commandParams) {
1221
+ const command = this.get(commandName);
1222
+ if (!command) {
1223
+ /**
1224
+ * Command does not exist.
1225
+ *
1226
+ * @error commandcollection-command-not-found
1227
+ * @param commandName Name of the command.
1228
+ */ throw new CKEditorError('commandcollection-command-not-found', this, {
1229
+ commandName
1230
+ });
1231
+ }
1232
+ return command.execute(...commandParams);
1233
+ }
1234
+ /**
1235
+ * Returns iterator of command names.
1236
+ */ *names() {
1237
+ yield* this._commands.keys();
1238
+ }
1239
+ /**
1240
+ * Returns iterator of command instances.
1241
+ */ *commands() {
1242
+ yield* this._commands.values();
1243
+ }
1244
+ /**
1245
+ * Iterable interface.
1246
+ *
1247
+ * Returns `[ commandName, commandInstance ]` pairs.
1248
+ */ [Symbol.iterator]() {
1249
+ return this._commands[Symbol.iterator]();
1250
+ }
1251
+ /**
1252
+ * Destroys all collection commands.
1253
+ */ destroy() {
1254
+ for (const command of this.commands()){
1255
+ command.destroy();
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ /**
1261
+ * A keystroke handler for editor editing. Its instance is available
1262
+ * in {@link module:core/editor/editor~Editor#keystrokes} so plugins
1263
+ * can register their keystrokes.
1264
+ *
1265
+ * E.g. an undo plugin would do this:
1266
+ *
1267
+ * ```ts
1268
+ * editor.keystrokes.set( 'Ctrl+Z', 'undo' );
1269
+ * editor.keystrokes.set( 'Ctrl+Shift+Z', 'redo' );
1270
+ * editor.keystrokes.set( 'Ctrl+Y', 'redo' );
1271
+ * ```
1272
+ */ class EditingKeystrokeHandler extends KeystrokeHandler {
1273
+ /**
1274
+ * The editor instance.
1275
+ */ editor;
1276
+ /**
1277
+ * Creates an instance of the keystroke handler.
1278
+ */ constructor(editor){
1279
+ super();
1280
+ this.editor = editor;
1281
+ }
1282
+ /**
1283
+ * Registers a handler for the specified keystroke.
1284
+ *
1285
+ * The handler can be specified as a command name or a callback.
1286
+ *
1287
+ * @param keystroke Keystroke defined in a format accepted by
1288
+ * the {@link module:utils/keyboard~parseKeystroke} function.
1289
+ * @param callback If a string is passed, then the keystroke will
1290
+ * {@link module:core/editor/editor~Editor#execute execute a command}.
1291
+ * If a function, then it will be called with the
1292
+ * {@link module:engine/view/observer/keyobserver~KeyEventData key event data} object and
1293
+ * a `cancel()` helper to both `preventDefault()` and `stopPropagation()` of the event.
1294
+ * @param options Additional options.
1295
+ * @param options.priority The priority of the keystroke callback. The higher the priority value
1296
+ * the sooner the callback will be executed. Keystrokes having the same priority
1297
+ * are called in the order they were added.
1298
+ */ set(keystroke, callback, options = {}) {
1299
+ if (typeof callback == 'string') {
1300
+ const commandName = callback;
1301
+ callback = (evtData, cancel)=>{
1302
+ this.editor.execute(commandName);
1303
+ cancel();
1304
+ };
1305
+ }
1306
+ super.set(keystroke, callback, options);
1307
+ }
1308
+ }
1309
+
1310
+ const DEFAULT_CATEGORY_ID = 'contentEditing';
1311
+ const DEFAULT_GROUP_ID = 'common';
1312
+ /**
1313
+ * A common namespace for various accessibility features of the editor.
1314
+ *
1315
+ * **Information about editor keystrokes**
1316
+ *
1317
+ * * The information about keystrokes available in the editor is stored in the {@link #keystrokeInfos} property.
1318
+ * * New info entries can be added using the {@link #addKeystrokeInfoCategory}, {@link #addKeystrokeInfoGroup},
1319
+ * and {@link #addKeystrokeInfos} methods.
1320
+ */ class Accessibility {
1321
+ /**
1322
+ * Stores information about keystrokes brought by editor features for the users to interact with the editor, mainly
1323
+ * keystroke combinations and their accessible labels.
1324
+ *
1325
+ * This information is particularly useful for screen reader and other assistive technology users. It gets displayed
1326
+ * by the {@link module:ui/editorui/accessibilityhelp/accessibilityhelp~AccessibilityHelp Accessibility help} dialog.
1327
+ *
1328
+ * Keystrokes are organized in categories and groups. They can be added using ({@link #addKeystrokeInfoCategory},
1329
+ * {@link #addKeystrokeInfoGroup}, and {@link #addKeystrokeInfos}) methods.
1330
+ *
1331
+ * Please note that:
1332
+ * * two categories are always available:
1333
+ * * `'contentEditing'` for keystrokes related to content creation,
1334
+ * * `'navigation'` for keystrokes related to navigation in the UI and the content.
1335
+ * * unless specified otherwise, new keystrokes are added into the `'contentEditing'` category and the `'common'`
1336
+ * keystroke group within that category while using the {@link #addKeystrokeInfos} method.
1337
+ */ keystrokeInfos = new Map();
1338
+ /**
1339
+ * The editor instance.
1340
+ */ _editor;
1341
+ /**
1342
+ * @inheritDoc
1343
+ */ constructor(editor){
1344
+ this._editor = editor;
1345
+ const isMenuBarVisible = editor.config.get('menuBar.isVisible');
1346
+ const t = editor.locale.t;
1347
+ this.addKeystrokeInfoCategory({
1348
+ id: DEFAULT_CATEGORY_ID,
1349
+ label: t('Content editing keystrokes'),
1350
+ description: t('These keyboard shortcuts allow for quick access to content editing features.')
1351
+ });
1352
+ const navigationKeystrokes = [
1353
+ {
1354
+ label: t('Close contextual balloons, dropdowns, and dialogs'),
1355
+ keystroke: 'Esc'
1356
+ },
1357
+ {
1358
+ label: t('Open the accessibility help dialog'),
1359
+ keystroke: 'Alt+0'
1360
+ },
1361
+ {
1362
+ label: t('Move focus between form fields (inputs, buttons, etc.)'),
1363
+ keystroke: [
1364
+ [
1365
+ 'Tab'
1366
+ ],
1367
+ [
1368
+ 'Shift+Tab'
1369
+ ]
1370
+ ]
1371
+ },
1372
+ {
1373
+ label: t('Move focus to the toolbar, navigate between toolbars'),
1374
+ keystroke: 'Alt+F10',
1375
+ mayRequireFn: true
1376
+ },
1377
+ {
1378
+ label: t('Navigate through the toolbar or menu bar'),
1379
+ keystroke: [
1380
+ [
1381
+ 'arrowup'
1382
+ ],
1383
+ [
1384
+ 'arrowright'
1385
+ ],
1386
+ [
1387
+ 'arrowdown'
1388
+ ],
1389
+ [
1390
+ 'arrowleft'
1391
+ ]
1392
+ ]
1393
+ },
1394
+ {
1395
+ // eslint-disable-next-line max-len
1396
+ label: t('Execute the currently focused button. Executing buttons that interact with the editor content moves the focus back to the content.'),
1397
+ keystroke: [
1398
+ [
1399
+ 'Enter'
1400
+ ],
1401
+ [
1402
+ 'Space'
1403
+ ]
1404
+ ]
1405
+ }
1406
+ ];
1407
+ if (isMenuBarVisible) {
1408
+ navigationKeystrokes.push({
1409
+ label: t('Move focus to the menu bar, navigate between menu bars'),
1410
+ keystroke: 'Alt+F9',
1411
+ mayRequireFn: true
1412
+ });
1413
+ }
1414
+ this.addKeystrokeInfoCategory({
1415
+ id: 'navigation',
1416
+ label: t('User interface and content navigation keystrokes'),
1417
+ description: t('Use the following keystrokes for more efficient navigation in the CKEditor 5 user interface.'),
1418
+ groups: [
1419
+ {
1420
+ id: 'common',
1421
+ keystrokes: navigationKeystrokes
1422
+ }
1423
+ ]
1424
+ });
1425
+ }
1426
+ /**
1427
+ * Adds a top-level category in the {@link #keystrokeInfos keystroke information database} with a label and optional description.
1428
+ *
1429
+ * Categories organize keystrokes and help users to find the right keystroke. Each category can have multiple groups
1430
+ * of keystrokes that narrow down the context in which the keystrokes are available. Every keystroke category comes
1431
+ * with a `'common'` group by default.
1432
+ *
1433
+ * By default, two categories are available:
1434
+ * * `'contentEditing'` for keystrokes related to content creation,
1435
+ * * `'navigation'` for keystrokes related to navigation in the UI and the content.
1436
+ *
1437
+ * To create a new keystroke category with new groups, use the following code:
1438
+ *
1439
+ * ```js
1440
+ * class MyPlugin extends Plugin {
1441
+ * // ...
1442
+ * init() {
1443
+ * const editor = this.editor;
1444
+ * const t = editor.t;
1445
+ *
1446
+ * // ...
1447
+ *
1448
+ * editor.accessibility.addKeystrokeInfoCategory( {
1449
+ * id: 'myCategory',
1450
+ * label: t( 'My category' ),
1451
+ * description: t( 'My category description.' ),
1452
+ * groups: [
1453
+ * {
1454
+ * id: 'myGroup',
1455
+ * label: t( 'My keystroke group' ),
1456
+ * keystrokes: [
1457
+ * {
1458
+ * label: t( 'Keystroke label 1' ),
1459
+ * keystroke: 'Ctrl+Shift+N'
1460
+ * },
1461
+ * {
1462
+ * label: t( 'Keystroke label 2' ),
1463
+ * keystroke: 'Ctrl+Shift+M'
1464
+ * }
1465
+ * ]
1466
+ * }
1467
+ * ]
1468
+ * };
1469
+ * }
1470
+ * }
1471
+ * ```
1472
+ *
1473
+ * See {@link #keystrokeInfos}, {@link #addKeystrokeInfoGroup}, and {@link #addKeystrokeInfos}.
1474
+ */ addKeystrokeInfoCategory({ id, label, description, groups }) {
1475
+ this.keystrokeInfos.set(id, {
1476
+ id,
1477
+ label,
1478
+ description,
1479
+ groups: new Map()
1480
+ });
1481
+ this.addKeystrokeInfoGroup({
1482
+ categoryId: id,
1483
+ id: DEFAULT_GROUP_ID
1484
+ });
1485
+ if (groups) {
1486
+ groups.forEach((group)=>{
1487
+ this.addKeystrokeInfoGroup({
1488
+ categoryId: id,
1489
+ ...group
1490
+ });
1491
+ });
1492
+ }
1493
+ }
1494
+ /**
1495
+ * Adds a group of keystrokes in a specific category to the {@link #keystrokeInfos keystroke information database}.
1496
+ *
1497
+ * Groups narrow down the context in which the keystrokes are available. When `categoryId` is not specified,
1498
+ * the group goes to the `'contentEditing'` category (default).
1499
+ *
1500
+ * To create a new group within an existing category, use the following code:
1501
+ *
1502
+ * ```js
1503
+ * class MyPlugin extends Plugin {
1504
+ * // ...
1505
+ * init() {
1506
+ * const editor = this.editor;
1507
+ * const t = editor.t;
1508
+ *
1509
+ * // ...
1510
+ *
1511
+ * editor.accessibility.addKeystrokeInfoGroup( {
1512
+ * id: 'myGroup',
1513
+ * categoryId: 'navigation',
1514
+ * label: t( 'My keystroke group' ),
1515
+ * keystrokes: [
1516
+ * {
1517
+ * label: t( 'Keystroke label 1' ),
1518
+ * keystroke: 'Ctrl+Shift+N'
1519
+ * },
1520
+ * {
1521
+ * label: t( 'Keystroke label 2' ),
1522
+ * keystroke: 'Ctrl+Shift+M'
1523
+ * }
1524
+ * ]
1525
+ * } );
1526
+ * }
1527
+ * }
1528
+ * ```
1529
+ *
1530
+ * See {@link #keystrokeInfos}, {@link #addKeystrokeInfoCategory}, and {@link #addKeystrokeInfos}.
1531
+ */ addKeystrokeInfoGroup({ categoryId = DEFAULT_CATEGORY_ID, id, label, keystrokes }) {
1532
+ const category = this.keystrokeInfos.get(categoryId);
1533
+ if (!category) {
1534
+ throw new CKEditorError('accessibility-unknown-keystroke-info-category', this._editor, {
1535
+ groupId: id,
1536
+ categoryId
1537
+ });
1538
+ }
1539
+ category.groups.set(id, {
1540
+ id,
1541
+ label,
1542
+ keystrokes: keystrokes || []
1543
+ });
1544
+ }
1545
+ /**
1546
+ * Adds information about keystrokes to the {@link #keystrokeInfos keystroke information database}.
1547
+ *
1548
+ * Keystrokes without specified `groupId` or `categoryId` go to the `'common'` group in the `'contentEditing'` category (default).
1549
+ *
1550
+ * To add a keystroke brought by your plugin (using default group and category), use the following code:
1551
+ *
1552
+ * ```js
1553
+ * class MyPlugin extends Plugin {
1554
+ * // ...
1555
+ * init() {
1556
+ * const editor = this.editor;
1557
+ * const t = editor.t;
1558
+ *
1559
+ * // ...
1560
+ *
1561
+ * editor.accessibility.addKeystrokeInfos( {
1562
+ * keystrokes: [
1563
+ * {
1564
+ * label: t( 'Keystroke label' ),
1565
+ * keystroke: 'CTRL+B'
1566
+ * }
1567
+ * ]
1568
+ * } );
1569
+ * }
1570
+ * }
1571
+ * ```
1572
+ * To add a keystroke in a specific existing `'widget'` group in the default `'contentEditing'` category:
1573
+ *
1574
+ * ```js
1575
+ * class MyPlugin extends Plugin {
1576
+ * // ...
1577
+ * init() {
1578
+ * const editor = this.editor;
1579
+ * const t = editor.t;
1580
+ *
1581
+ * // ...
1582
+ *
1583
+ * editor.accessibility.addKeystrokeInfos( {
1584
+ * // Add a keystroke to the existing "widget" group.
1585
+ * groupId: 'widget',
1586
+ * keystrokes: [
1587
+ * {
1588
+ * label: t( 'A an action on a selected widget' ),
1589
+ * keystroke: 'Ctrl+D',
1590
+ * }
1591
+ * ]
1592
+ * } );
1593
+ * }
1594
+ * }
1595
+ * ```
1596
+ *
1597
+ * To add a keystroke to another existing category (using default group):
1598
+ *
1599
+ * ```js
1600
+ * class MyPlugin extends Plugin {
1601
+ * // ...
1602
+ * init() {
1603
+ * const editor = this.editor;
1604
+ * const t = editor.t;
1605
+ *
1606
+ * // ...
1607
+ *
1608
+ * editor.accessibility.addKeystrokeInfos( {
1609
+ * // Add keystrokes to the "navigation" category (one of defaults).
1610
+ * categoryId: 'navigation',
1611
+ * keystrokes: [
1612
+ * {
1613
+ * label: t( 'Keystroke label' ),
1614
+ * keystroke: 'CTRL+B'
1615
+ * }
1616
+ * ]
1617
+ * } );
1618
+ * }
1619
+ * }
1620
+ * ```
1621
+ *
1622
+ * See {@link #keystrokeInfos}, {@link #addKeystrokeInfoGroup}, and {@link #addKeystrokeInfoCategory}.
1623
+ */ addKeystrokeInfos({ categoryId = DEFAULT_CATEGORY_ID, groupId = DEFAULT_GROUP_ID, keystrokes }) {
1624
+ if (!this.keystrokeInfos.has(categoryId)) {
1625
+ /**
1626
+ * Cannot add keystrokes in an unknown category. Use
1627
+ * {@link module:core/accessibility~Accessibility#addKeystrokeInfoCategory}
1628
+ * to add a new category or make sure the specified category exists.
1629
+ *
1630
+ * @error accessibility-unknown-keystroke-info-category
1631
+ * @param categoryId The id of the unknown keystroke category.
1632
+ * @param keystrokes Keystroke definitions about to be added.
1633
+ */ throw new CKEditorError('accessibility-unknown-keystroke-info-category', this._editor, {
1634
+ categoryId,
1635
+ keystrokes
1636
+ });
1637
+ }
1638
+ const category = this.keystrokeInfos.get(categoryId);
1639
+ if (!category.groups.has(groupId)) {
1640
+ /**
1641
+ * Cannot add keystrokes to an unknown group.
1642
+ *
1643
+ * Use {@link module:core/accessibility~Accessibility#addKeystrokeInfoGroup}
1644
+ * to add a new group or make sure the specified group exists.
1645
+ *
1646
+ * @error accessibility-unknown-keystroke-info-group
1647
+ * @param groupId The id of the unknown keystroke group.
1648
+ * @param categoryId The id of category the unknown group should belong to.
1649
+ * @param keystrokes Keystroke definitions about to be added.
1650
+ */ throw new CKEditorError('accessibility-unknown-keystroke-info-group', this._editor, {
1651
+ groupId,
1652
+ categoryId,
1653
+ keystrokes
1654
+ });
1655
+ }
1656
+ category.groups.get(groupId).keystrokes.push(...keystrokes);
1657
+ }
1658
+ }
1659
+
1660
+ function getEditorUsageData(editor) {
1661
+ return {
1662
+ sessionId: getSessionId(),
1663
+ pageSessionId: getPageSessionID(),
1664
+ hostname: window.location.hostname,
1665
+ version: globalThis.CKEDITOR_VERSION,
1666
+ type: getEditorType(editor),
1667
+ plugins: getPluginsUsageData(editor.plugins),
1668
+ distribution: getDistributionUsageData(),
1669
+ env: getEnvUsageData(),
1670
+ integrations: Object.create(null),
1671
+ menuBar: {
1672
+ isVisible: !!editor.config.get('menuBar.isVisible')
1673
+ },
1674
+ language: {
1675
+ ui: editor.locale.uiLanguage,
1676
+ content: editor.locale.contentLanguage
1677
+ },
1678
+ toolbar: {
1679
+ main: getToolbarUsageData(editor.config.get('toolbar')),
1680
+ block: getToolbarUsageData(editor.config.get('blockToolbar')),
1681
+ balloon: getToolbarUsageData(editor.config.get('balloonToolbar'))
1682
+ }
1683
+ };
1684
+ }
1685
+ function getEditorType(editor) {
1686
+ return Object.getPrototypeOf(editor).constructor.editorName;
1687
+ }
1688
+ function getPluginsUsageData(collection) {
1689
+ return Array.from(collection).filter(([PluginConstructor])=>!!PluginConstructor.pluginName).map(([PluginConstructor])=>{
1690
+ const { pluginName, isContextPlugin, isOfficialPlugin, isPremiumPlugin } = PluginConstructor;
1691
+ return {
1692
+ isContext: !!isContextPlugin,
1693
+ isOfficial: !!isOfficialPlugin,
1694
+ isPremium: !!isPremiumPlugin,
1695
+ name: pluginName
1696
+ };
1697
+ });
1698
+ }
1699
+ function getToolbarUsageData(toolbarConfig) {
1700
+ if (!toolbarConfig) {
1701
+ return undefined;
1702
+ }
1703
+ const normalizedToolbar = Array.isArray(toolbarConfig) ? {
1704
+ items: toolbarConfig
1705
+ } : toolbarConfig;
1706
+ const flattenToolbarConfigNames = extractToolbarConfigItemsNames(normalizedToolbar.items || []);
1707
+ const isMultiline = flattenToolbarConfigNames.includes('-');
1708
+ return {
1709
+ isMultiline,
1710
+ shouldNotGroupWhenFull: !!normalizedToolbar.shouldNotGroupWhenFull,
1711
+ items: stripToolbarSeparatorItems(flattenToolbarConfigNames)
1712
+ };
1713
+ function stripToolbarSeparatorItems(items) {
1714
+ return items.filter((item)=>item !== '|' && item !== '-');
1715
+ }
1716
+ function extractToolbarConfigItemsNames(items) {
1717
+ return items.flatMap((item)=>{
1718
+ if (typeof item === 'string') {
1719
+ return [
1720
+ item
1721
+ ];
1722
+ }
1723
+ return extractToolbarConfigItemsNames(item.items);
1724
+ });
1725
+ }
1726
+ }
1727
+ function getDistributionUsageData() {
1728
+ return {
1729
+ channel: window[Symbol.for('cke distribution')] || 'sh'
1730
+ };
1731
+ }
1732
+ function getEnvUsageData() {
1733
+ let os = 'unknown';
1734
+ let browser = 'unknown';
1735
+ if (env.isMac) {
1736
+ os = 'mac';
1737
+ } else if (env.isWindows) {
1738
+ os = 'windows';
1739
+ } else if (env.isiOS) {
1740
+ os = 'ios';
1741
+ } else if (env.isAndroid) {
1742
+ os = 'android';
1743
+ }
1744
+ if (env.isGecko) {
1745
+ browser = 'gecko';
1746
+ } else if (env.isBlink) {
1747
+ browser = 'blink';
1748
+ } else if (env.isSafari) {
1749
+ browser = 'safari';
1750
+ }
1751
+ return {
1752
+ os,
1753
+ browser
1754
+ };
1755
+ }
1756
+ function getSessionId() {
1757
+ if (!localStorage.getItem('__ckeditor-session-id')) {
1758
+ localStorage.setItem('__ckeditor-session-id', crypto.randomUUID());
1759
+ }
1760
+ return localStorage.getItem('__ckeditor-session-id');
1761
+ }
1762
+ function getPageSessionID() {
1763
+ global.window.CKEDITOR_PAGE_SESSION_ID = global.window.CKEDITOR_PAGE_SESSION_ID || crypto.randomUUID();
1764
+ return global.window.CKEDITOR_PAGE_SESSION_ID;
1765
+ }
1766
+
1767
+ /**
1768
+ * The class representing a basic, generic editor.
1769
+ *
1770
+ * Check out the list of its subclasses to learn about specific editor implementations.
1771
+ *
1772
+ * All editor implementations (like {@link module:editor-classic/classiceditor~ClassicEditor} or
1773
+ * {@link module:editor-inline/inlineeditor~InlineEditor}) should extend this class. They can add their
1774
+ * own methods and properties.
1775
+ *
1776
+ * When you are implementing a plugin, this editor represents the API
1777
+ * which your plugin can expect to get when using its {@link module:core/plugin~Plugin#editor} property.
1778
+ *
1779
+ * This API should be sufficient in order to implement the "editing" part of your feature
1780
+ * (schema definition, conversion, commands, keystrokes, etc.).
1781
+ * It does not define the editor UI, which is available only if
1782
+ * the specific editor implements also the {@link ~Editor#ui} property
1783
+ * (as most editor implementations do).
1784
+ */ class Editor extends /* #__PURE__ */ ObservableMixin() {
1785
+ /**
1786
+ * A required name of the editor class. The name should reflect the constructor name.
1787
+ */ static get editorName() {
1788
+ return 'Editor';
1789
+ }
1790
+ /**
1791
+ * A namespace for the accessibility features of the editor.
1792
+ */ accessibility;
1793
+ /**
1794
+ * Commands registered to the editor.
1795
+ *
1796
+ * Use the shorthand {@link #execute `editor.execute()`} method to execute commands:
1797
+ *
1798
+ * ```ts
1799
+ * // Execute the bold command:
1800
+ * editor.execute( 'bold' );
1801
+ *
1802
+ * // Check the state of the bold command:
1803
+ * editor.commands.get( 'bold' ).value;
1804
+ * ```
1805
+ */ commands;
1806
+ /**
1807
+ * Stores all configurations specific to this editor instance.
1808
+ *
1809
+ * ```ts
1810
+ * editor.config.get( 'image.toolbar' );
1811
+ * // -> [ 'imageStyle:block', 'imageStyle:side', '|', 'toggleImageCaption', 'imageTextAlternative' ]
1812
+ * ```
1813
+ */ config;
1814
+ /**
1815
+ * Conversion manager through which you can register model-to-view and view-to-model converters.
1816
+ *
1817
+ * See the {@link module:engine/conversion/conversion~Conversion} documentation to learn how to add converters.
1818
+ */ conversion;
1819
+ /**
1820
+ * The {@link module:engine/controller/datacontroller~DataController data controller}.
1821
+ * Used e.g. for setting and retrieving the editor data.
1822
+ */ data;
1823
+ /**
1824
+ * The {@link module:engine/controller/editingcontroller~EditingController editing controller}.
1825
+ * Controls user input and rendering the content for editing.
1826
+ */ editing;
1827
+ /**
1828
+ * The locale instance.
1829
+ */ locale;
1830
+ /**
1831
+ * The editor's model.
1832
+ *
1833
+ * The central point of the editor's abstract data model.
1834
+ */ model;
1835
+ /**
1836
+ * The plugins loaded and in use by this editor instance.
1837
+ *
1838
+ * ```ts
1839
+ * editor.plugins.get( 'ClipboardPipeline' ); // -> An instance of the clipboard pipeline plugin.
1840
+ * ```
1841
+ */ plugins;
1842
+ /**
1843
+ * An instance of the {@link module:core/editingkeystrokehandler~EditingKeystrokeHandler}.
1844
+ *
1845
+ * It allows setting simple keystrokes:
1846
+ *
1847
+ * ```ts
1848
+ * // Execute the bold command on Ctrl+E:
1849
+ * editor.keystrokes.set( 'Ctrl+E', 'bold' );
1850
+ *
1851
+ * // Execute your own callback:
1852
+ * editor.keystrokes.set( 'Ctrl+E', ( data, cancel ) => {
1853
+ * console.log( data.keyCode );
1854
+ *
1855
+ * // Prevent the default (native) action and stop the underlying keydown event
1856
+ * // so no other editor feature will interfere.
1857
+ * cancel();
1858
+ * } );
1859
+ * ```
1860
+ *
1861
+ * Note: Certain typing-oriented keystrokes (like <kbd>Backspace</kbd> or <kbd>Enter</kbd>) are handled
1862
+ * by a low-level mechanism and trying to listen to them via the keystroke handler will not work reliably.
1863
+ * To handle these specific keystrokes, see the events fired by the
1864
+ * {@link module:engine/view/document~Document editing view document} (`editor.editing.view.document`).
1865
+ */ keystrokes;
1866
+ /**
1867
+ * Shorthand for {@link module:utils/locale~Locale#t}.
1868
+ *
1869
+ * @see module:utils/locale~Locale#t
1870
+ */ t;
1871
+ /**
1872
+ * The default configuration which is built into the editor class.
1873
+ *
1874
+ * It is used in CKEditor 5 builds to provide the default configuration options which are later used during the editor initialization.
1875
+ *
1876
+ * ```ts
1877
+ * ClassicEditor.defaultConfig = {
1878
+ * foo: 1,
1879
+ * bar: 2
1880
+ * };
1881
+ *
1882
+ * ClassicEditor
1883
+ * .create( sourceElement )
1884
+ * .then( editor => {
1885
+ * editor.config.get( 'foo' ); // -> 1
1886
+ * editor.config.get( 'bar' ); // -> 2
1887
+ * } );
1888
+ *
1889
+ * // The default options can be overridden by the configuration passed to create().
1890
+ * ClassicEditor
1891
+ * .create( sourceElement, { bar: 3 } )
1892
+ * .then( editor => {
1893
+ * editor.config.get( 'foo' ); // -> 1
1894
+ * editor.config.get( 'bar' ); // -> 3
1895
+ * } );
1896
+ * ```
1897
+ *
1898
+ * See also {@link module:core/editor/editor~Editor.builtinPlugins}.
1899
+ */ static defaultConfig;
1900
+ /**
1901
+ * An array of plugins built into this editor class.
1902
+ *
1903
+ * It is used in CKEditor 5 builds to provide a list of plugins which are later automatically initialized
1904
+ * during the editor initialization.
1905
+ *
1906
+ * They will be automatically initialized by the editor, unless listed in `config.removePlugins` and
1907
+ * unless `config.plugins` is passed.
1908
+ *
1909
+ * ```ts
1910
+ * // Build some plugins into the editor class first.
1911
+ * ClassicEditor.builtinPlugins = [ FooPlugin, BarPlugin ];
1912
+ *
1913
+ * // Normally, you need to define config.plugins, but since ClassicEditor.builtinPlugins was
1914
+ * // defined, now you can call create() without any configuration.
1915
+ * ClassicEditor
1916
+ * .create( sourceElement )
1917
+ * .then( editor => {
1918
+ * editor.plugins.get( FooPlugin ); // -> An instance of the Foo plugin.
1919
+ * editor.plugins.get( BarPlugin ); // -> An instance of the Bar plugin.
1920
+ * } );
1921
+ *
1922
+ * ClassicEditor
1923
+ * .create( sourceElement, {
1924
+ * // Do not initialize these plugins (note: it is defined by a string):
1925
+ * removePlugins: [ 'Foo' ]
1926
+ * } )
1927
+ * .then( editor => {
1928
+ * editor.plugins.get( FooPlugin ); // -> Undefined.
1929
+ * editor.config.get( BarPlugin ); // -> An instance of the Bar plugin.
1930
+ * } );
1931
+ *
1932
+ * ClassicEditor
1933
+ * .create( sourceElement, {
1934
+ * // Load only this plugin. It can also be defined by a string if
1935
+ * // this plugin was built into the editor class.
1936
+ * plugins: [ FooPlugin ]
1937
+ * } )
1938
+ * .then( editor => {
1939
+ * editor.plugins.get( FooPlugin ); // -> An instance of the Foo plugin.
1940
+ * editor.config.get( BarPlugin ); // -> Undefined.
1941
+ * } );
1942
+ * ```
1943
+ *
1944
+ * See also {@link module:core/editor/editor~Editor.defaultConfig}.
1945
+ */ static builtinPlugins;
1946
+ /**
1947
+ * The editor context.
1948
+ * When it is not provided through the configuration, the editor creates it.
1949
+ */ _context;
1950
+ /**
1951
+ * A set of lock IDs for the {@link #isReadOnly} getter.
1952
+ */ _readOnlyLocks;
1953
+ /**
1954
+ * Creates a new instance of the editor class.
1955
+ *
1956
+ * Usually, not to be used directly. See the static {@link module:core/editor/editor~Editor.create `create()`} method.
1957
+ *
1958
+ * @param config The editor configuration.
1959
+ */ constructor(config = {}){
1960
+ super();
1961
+ if ('sanitizeHtml' in config) {
1962
+ /**
1963
+ * Configuration property `config.sanitizeHtml` was removed in CKEditor version 43.1.0 and is no longer supported.
1964
+ *
1965
+ * Please use `config.htmlEmbed.sanitizeHtml` and/or `config.mergeFields.sanitizeHtml` instead.
1966
+ *
1967
+ * @error editor-config-sanitizehtml-not-supported
1968
+ */ throw new CKEditorError('editor-config-sanitizehtml-not-supported');
1969
+ }
1970
+ const constructor = this.constructor;
1971
+ // We don't pass translations to the config, because its behavior of splitting keys
1972
+ // with dots (e.g. `resize.width` => `resize: { width }`) breaks the translations.
1973
+ const { translations: defaultTranslations, ...defaultConfig } = constructor.defaultConfig || {};
1974
+ const { translations = defaultTranslations, ...rest } = config;
1975
+ // Prefer the language passed as the argument to the constructor instead of the constructor's `defaultConfig`, if both are set.
1976
+ const language = config.language || defaultConfig.language;
1977
+ this._context = config.context || new Context({
1978
+ language,
1979
+ translations
1980
+ });
1981
+ this._context._addEditor(this, !config.context);
1982
+ // Clone the plugins to make sure that the plugin array will not be shared
1983
+ // between editors and make the watchdog feature work correctly.
1984
+ const availablePlugins = Array.from(constructor.builtinPlugins || []);
1985
+ this.config = new Config(rest, defaultConfig);
1986
+ this.config.define('plugins', availablePlugins);
1987
+ this.config.define(this._context._getEditorConfig());
1988
+ checkLicenseKeyIsDefined(this.config);
1989
+ this.plugins = new PluginCollection(this, availablePlugins, this._context.plugins);
1990
+ this.locale = this._context.locale;
1991
+ this.t = this.locale.t;
1992
+ this._readOnlyLocks = new Set();
1993
+ this.commands = new CommandCollection();
1994
+ this.set('state', 'initializing');
1995
+ this.once('ready', ()=>this.state = 'ready', {
1996
+ priority: 'high'
1997
+ });
1998
+ this.once('destroy', ()=>this.state = 'destroyed', {
1999
+ priority: 'high'
2000
+ });
2001
+ this.model = new Model();
2002
+ this.on('change:isReadOnly', ()=>{
2003
+ this.model.document.isReadOnly = this.isReadOnly;
2004
+ });
2005
+ const stylesProcessor = new StylesProcessor();
2006
+ this.data = new DataController(this.model, stylesProcessor);
2007
+ this.editing = new EditingController(this.model, stylesProcessor);
2008
+ this.editing.view.document.bind('isReadOnly').to(this);
2009
+ this.conversion = new Conversion([
2010
+ this.editing.downcastDispatcher,
2011
+ this.data.downcastDispatcher
2012
+ ], this.data.upcastDispatcher);
2013
+ this.conversion.addAlias('dataDowncast', this.data.downcastDispatcher);
2014
+ this.conversion.addAlias('editingDowncast', this.editing.downcastDispatcher);
2015
+ this.keystrokes = new EditingKeystrokeHandler(this);
2016
+ this.keystrokes.listenTo(this.editing.view.document);
2017
+ this.accessibility = new Accessibility(this);
2018
+ verifyLicenseKey(this);
2019
+ // Checks if the license key is defined and throws an error if it is not.
2020
+ function checkLicenseKeyIsDefined(config) {
2021
+ let licenseKey = config.get('licenseKey');
2022
+ if (!licenseKey && window.CKEDITOR_GLOBAL_LICENSE_KEY) {
2023
+ licenseKey = window.CKEDITOR_GLOBAL_LICENSE_KEY;
2024
+ config.set('licenseKey', licenseKey);
2025
+ }
2026
+ if (!licenseKey) {
2027
+ /**
2028
+ * The `licenseKey` is missing in the editor configuration. If you use premium features,
2029
+ * please provide your license key. If you do not have a key yet, please contact us at
2030
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/) or order a trial at
2031
+ * [https://orders.ckeditor.com/trial/premium-features](https://orders.ckeditor.com/trial/premium-features).
2032
+ *
2033
+ * If you do not use premium features, add the `'GPL'` license key instead.
2034
+ *
2035
+ * ```js
2036
+ * Editor.create( document.querySelector( '#editor' ), {
2037
+ * licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
2038
+ * } );
2039
+ * ```
2040
+ *
2041
+ * @error editor-license-key-missing
2042
+ */ throw new CKEditorError('editor-license-key-missing');
2043
+ }
2044
+ }
2045
+ function verifyLicenseKey(editor) {
2046
+ const licenseKey = editor.config.get('licenseKey');
2047
+ const distributionChannel = window[Symbol.for('cke distribution')] || 'sh';
2048
+ if (licenseKey == 'GPL') {
2049
+ if (distributionChannel == 'cloud') {
2050
+ blockEditor('distributionChannel');
2051
+ }
2052
+ return;
2053
+ }
2054
+ const encodedPayload = getPayload(licenseKey);
2055
+ if (!encodedPayload) {
2056
+ blockEditor('invalid');
2057
+ return;
2058
+ }
2059
+ const licensePayload = parseBase64EncodedObject(encodedPayload);
2060
+ if (!licensePayload) {
2061
+ blockEditor('invalid');
2062
+ return;
2063
+ }
2064
+ if (!hasAllRequiredFields(licensePayload)) {
2065
+ blockEditor('invalid');
2066
+ return;
2067
+ }
2068
+ if (licensePayload.distributionChannel && !toArray(licensePayload.distributionChannel).includes(distributionChannel)) {
2069
+ blockEditor('distributionChannel');
2070
+ return;
2071
+ }
2072
+ if (crc32(getCrcInputData(licensePayload)) != licensePayload.vc.toLowerCase()) {
2073
+ blockEditor('invalid');
2074
+ return;
2075
+ }
2076
+ const expirationDate = new Date(licensePayload.exp * 1000);
2077
+ if (expirationDate < releaseDate) {
2078
+ blockEditor('expired');
2079
+ return;
2080
+ }
2081
+ const licensedHosts = licensePayload.licensedHosts;
2082
+ if (licensedHosts && licensedHosts.length > 0 && !checkLicensedHosts(licensedHosts)) {
2083
+ blockEditor('domainLimit');
2084
+ return;
2085
+ }
2086
+ if ([
2087
+ 'evaluation',
2088
+ 'trial'
2089
+ ].includes(licensePayload.licenseType) && licensePayload.exp * 1000 < Date.now()) {
2090
+ blockEditor('expired');
2091
+ return;
2092
+ }
2093
+ if ([
2094
+ 'evaluation',
2095
+ 'trial',
2096
+ 'development'
2097
+ ].includes(licensePayload.licenseType)) {
2098
+ const licenseType = licensePayload.licenseType;
2099
+ console.info(`You are using the ${licenseType} version of CKEditor 5 with limited usage. ` + 'Make sure you will not use it in the production environment.');
2100
+ const timerId = setTimeout(()=>{
2101
+ blockEditor(`${licenseType}Limit`);
2102
+ }, 600000);
2103
+ editor.on('destroy', ()=>{
2104
+ clearTimeout(timerId);
2105
+ });
2106
+ }
2107
+ if (licensePayload.usageEndpoint) {
2108
+ editor.once('ready', ()=>{
2109
+ const request = {
2110
+ requestId: uid(),
2111
+ requestTime: Math.round(Date.now() / 1000),
2112
+ license: licenseKey,
2113
+ editor: collectUsageData(editor)
2114
+ };
2115
+ editor._sendUsageRequest(licensePayload.usageEndpoint, request).then((response)=>{
2116
+ const { status, message } = response;
2117
+ if (message) {
2118
+ console.warn(message);
2119
+ }
2120
+ if (status != 'ok') {
2121
+ blockEditor('usageLimit');
2122
+ }
2123
+ }, ()=>{
2124
+ /**
2125
+ * Your license key cannot be validated because of a network issue.
2126
+ * Please make sure that your setup does not block the request.
2127
+ *
2128
+ * @error license-key-validation-endpoint-not-reachable
2129
+ * @param {String} url The URL that was attempted to reach.
2130
+ */ logError('license-key-validation-endpoint-not-reachable', {
2131
+ url: licensePayload.usageEndpoint
2132
+ });
2133
+ });
2134
+ }, {
2135
+ priority: 'high'
2136
+ });
2137
+ }
2138
+ function getPayload(licenseKey) {
2139
+ const parts = licenseKey.split('.');
2140
+ if (parts.length != 3) {
2141
+ return null;
2142
+ }
2143
+ return parts[1];
2144
+ }
2145
+ function blockEditor(reason) {
2146
+ editor.enableReadOnlyMode(Symbol('invalidLicense'));
2147
+ editor._showLicenseError(reason);
2148
+ }
2149
+ function hasAllRequiredFields(licensePayload) {
2150
+ const requiredFields = [
2151
+ 'exp',
2152
+ 'jti',
2153
+ 'vc'
2154
+ ];
2155
+ return requiredFields.every((field)=>field in licensePayload);
2156
+ }
2157
+ function getCrcInputData(licensePayload) {
2158
+ const keysToCheck = Object.getOwnPropertyNames(licensePayload).sort();
2159
+ const filteredValues = keysToCheck.filter((key)=>key != 'vc' && licensePayload[key] != null).map((key)=>licensePayload[key]);
2160
+ return filteredValues;
2161
+ }
2162
+ function checkLicensedHosts(licensedHosts) {
2163
+ const { hostname } = new URL(window.location.href);
2164
+ if (licensedHosts.includes(hostname)) {
2165
+ return true;
2166
+ }
2167
+ const segments = hostname.split('.');
2168
+ return licensedHosts.filter((host)=>host.includes('*')).map((host)=>host.split('.')).some((octets)=>segments.every((segment, index)=>octets[index] === segment || octets[index] === '*'));
2169
+ }
2170
+ }
2171
+ }
2172
+ /**
2173
+ * Defines whether the editor is in the read-only mode.
2174
+ *
2175
+ * In read-only mode the editor {@link #commands commands} are disabled so it is not possible
2176
+ * to modify the document by using them. Also, the editable element(s) become non-editable.
2177
+ *
2178
+ * In order to make the editor read-only, you need to call the {@link #enableReadOnlyMode} method:
2179
+ *
2180
+ * ```ts
2181
+ * editor.enableReadOnlyMode( 'feature-id' );
2182
+ * ```
2183
+ *
2184
+ * Later, to turn off the read-only mode, call {@link #disableReadOnlyMode}:
2185
+ *
2186
+ * ```ts
2187
+ * editor.disableReadOnlyMode( 'feature-id' );
2188
+ * ```
2189
+ *
2190
+ * @readonly
2191
+ * @observable
2192
+ */ get isReadOnly() {
2193
+ return this._readOnlyLocks.size > 0;
2194
+ }
2195
+ set isReadOnly(value) {
2196
+ /**
2197
+ * The {@link module:core/editor/editor~Editor#isReadOnly Editor#isReadOnly} property is read-only since version `34.0.0`
2198
+ * and can be set only using {@link module:core/editor/editor~Editor#enableReadOnlyMode `Editor#enableReadOnlyMode( lockId )`} and
2199
+ * {@link module:core/editor/editor~Editor#disableReadOnlyMode `Editor#disableReadOnlyMode( lockId )`}.
2200
+ *
2201
+ * Usage before version `34.0.0`:
2202
+ *
2203
+ * ```ts
2204
+ * editor.isReadOnly = true;
2205
+ * editor.isReadOnly = false;
2206
+ * ```
2207
+ *
2208
+ * Usage since version `34.0.0`:
2209
+ *
2210
+ * ```ts
2211
+ * editor.enableReadOnlyMode( 'my-feature-id' );
2212
+ * editor.disableReadOnlyMode( 'my-feature-id' );
2213
+ * ```
2214
+ *
2215
+ * @error editor-isreadonly-has-no-setter
2216
+ */ throw new CKEditorError('editor-isreadonly-has-no-setter');
2217
+ }
2218
+ /**
2219
+ * Turns on the read-only mode in the editor.
2220
+ *
2221
+ * Editor can be switched to or out of the read-only mode by many features, under various circumstances. The editor supports locking
2222
+ * mechanism for the read-only mode. It enables easy control over the read-only mode when many features wants to turn it on or off at
2223
+ * the same time, without conflicting with each other. It guarantees that you will not make the editor editable accidentally (which
2224
+ * could lead to errors).
2225
+ *
2226
+ * Each read-only mode request is identified by a unique id (also called "lock"). If multiple plugins requested to turn on the
2227
+ * read-only mode, then, the editor will become editable only after all these plugins turn the read-only mode off (using the same ids).
2228
+ *
2229
+ * Note, that you cannot force the editor to disable the read-only mode if other plugins set it.
2230
+ *
2231
+ * After the first `enableReadOnlyMode()` call, the {@link #isReadOnly `isReadOnly` property} will be set to `true`:
2232
+ *
2233
+ * ```ts
2234
+ * editor.isReadOnly; // `false`.
2235
+ * editor.enableReadOnlyMode( 'my-feature-id' );
2236
+ * editor.isReadOnly; // `true`.
2237
+ * ```
2238
+ *
2239
+ * You can turn off the read-only mode ("clear the lock") using the {@link #disableReadOnlyMode `disableReadOnlyMode()`} method:
2240
+ *
2241
+ * ```ts
2242
+ * editor.enableReadOnlyMode( 'my-feature-id' );
2243
+ * // ...
2244
+ * editor.disableReadOnlyMode( 'my-feature-id' );
2245
+ * editor.isReadOnly; // `false`.
2246
+ * ```
2247
+ *
2248
+ * All "locks" need to be removed to enable editing:
2249
+ *
2250
+ * ```ts
2251
+ * editor.enableReadOnlyMode( 'my-feature-id' );
2252
+ * editor.enableReadOnlyMode( 'my-other-feature-id' );
2253
+ * // ...
2254
+ * editor.disableReadOnlyMode( 'my-feature-id' );
2255
+ * editor.isReadOnly; // `true`.
2256
+ * editor.disableReadOnlyMode( 'my-other-feature-id' );
2257
+ * editor.isReadOnly; // `false`.
2258
+ * ```
2259
+ *
2260
+ * @param lockId A unique ID for setting the editor to the read-only state.
2261
+ */ enableReadOnlyMode(lockId) {
2262
+ if (typeof lockId !== 'string' && typeof lockId !== 'symbol') {
2263
+ /**
2264
+ * The lock ID is missing or it is not a string or symbol.
2265
+ *
2266
+ * @error editor-read-only-lock-id-invalid
2267
+ */ throw new CKEditorError('editor-read-only-lock-id-invalid', null, {
2268
+ lockId
2269
+ });
2270
+ }
2271
+ if (this._readOnlyLocks.has(lockId)) {
2272
+ return;
2273
+ }
2274
+ this._readOnlyLocks.add(lockId);
2275
+ if (this._readOnlyLocks.size === 1) {
2276
+ // Manually fire the `change:isReadOnly` event as only getter is provided.
2277
+ this.fire('change:isReadOnly', 'isReadOnly', true, false);
2278
+ }
2279
+ }
2280
+ /**
2281
+ * Removes the read-only lock from the editor with given lock ID.
2282
+ *
2283
+ * When no lock is present on the editor anymore, then the {@link #isReadOnly `isReadOnly` property} will be set to `false`.
2284
+ *
2285
+ * @param lockId The lock ID for setting the editor to the read-only state.
2286
+ */ disableReadOnlyMode(lockId) {
2287
+ if (typeof lockId !== 'string' && typeof lockId !== 'symbol') {
2288
+ throw new CKEditorError('editor-read-only-lock-id-invalid', null, {
2289
+ lockId
2290
+ });
2291
+ }
2292
+ if (!this._readOnlyLocks.has(lockId)) {
2293
+ return;
2294
+ }
2295
+ this._readOnlyLocks.delete(lockId);
2296
+ if (this._readOnlyLocks.size === 0) {
2297
+ // Manually fire the `change:isReadOnly` event as only getter is provided.
2298
+ this.fire('change:isReadOnly', 'isReadOnly', false, true);
2299
+ }
2300
+ }
2301
+ /**
2302
+ * Sets the data in the editor.
2303
+ *
2304
+ * ```ts
2305
+ * editor.setData( '<p>This is editor!</p>' );
2306
+ * ```
2307
+ *
2308
+ * If your editor implementation uses multiple roots, you should pass an object with keys corresponding
2309
+ * to the editor root names and values equal to the data that should be set in each root:
2310
+ *
2311
+ * ```ts
2312
+ * editor.setData( {
2313
+ * header: '<p>Content for header part.</p>',
2314
+ * content: '<p>Content for main part.</p>',
2315
+ * footer: '<p>Content for footer part.</p>'
2316
+ * } );
2317
+ * ```
2318
+ *
2319
+ * By default the editor accepts HTML. This can be controlled by injecting a different data processor.
2320
+ * See the {@glink features/markdown Markdown output} guide for more details.
2321
+ *
2322
+ * @param data Input data.
2323
+ */ setData(data) {
2324
+ this.data.set(data);
2325
+ }
2326
+ /**
2327
+ * Gets the data from the editor.
2328
+ *
2329
+ * ```ts
2330
+ * editor.getData(); // -> '<p>This is editor!</p>'
2331
+ * ```
2332
+ *
2333
+ * If your editor implementation uses multiple roots, you should pass root name as one of the options:
2334
+ *
2335
+ * ```ts
2336
+ * editor.getData( { rootName: 'header' } ); // -> '<p>Content for header part.</p>'
2337
+ * ```
2338
+ *
2339
+ * By default, the editor outputs HTML. This can be controlled by injecting a different data processor.
2340
+ * See the {@glink features/markdown Markdown output} guide for more details.
2341
+ *
2342
+ * A warning is logged when you try to retrieve data for a detached root, as most probably this is a mistake. A detached root should
2343
+ * be treated like it is removed, and you should not save its data. Note, that the detached root data is always an empty string.
2344
+ *
2345
+ * @param options Additional configuration for the retrieved data.
2346
+ * Editor features may introduce more configuration options that can be set through this parameter.
2347
+ * @param options.rootName Root name. Defaults to `'main'`.
2348
+ * @param options.trim Whether returned data should be trimmed. This option is set to `'empty'` by default,
2349
+ * which means that whenever editor content is considered empty, an empty string is returned. To turn off trimming
2350
+ * use `'none'`. In such cases exact content will be returned (for example `'<p>&nbsp;</p>'` for an empty editor).
2351
+ * @returns Output data.
2352
+ */ getData(options) {
2353
+ return this.data.get(options);
2354
+ }
2355
+ /**
2356
+ * Loads and initializes plugins specified in the configuration.
2357
+ *
2358
+ * @returns A promise which resolves once the initialization is completed, providing an array of loaded plugins.
2359
+ */ initPlugins() {
2360
+ const config = this.config;
2361
+ const plugins = config.get('plugins');
2362
+ const removePlugins = config.get('removePlugins') || [];
2363
+ const extraPlugins = config.get('extraPlugins') || [];
2364
+ const substitutePlugins = config.get('substitutePlugins') || [];
2365
+ return this.plugins.init(plugins.concat(extraPlugins), removePlugins, substitutePlugins);
2366
+ }
2367
+ /**
2368
+ * Destroys the editor instance, releasing all resources used by it.
2369
+ *
2370
+ * **Note** The editor cannot be destroyed during the initialization phase so if it is called
2371
+ * while the editor {@link #state is being initialized}, it will wait for the editor initialization before destroying it.
2372
+ *
2373
+ * @fires destroy
2374
+ * @returns A promise that resolves once the editor instance is fully destroyed.
2375
+ */ destroy() {
2376
+ let readyPromise = Promise.resolve();
2377
+ if (this.state == 'initializing') {
2378
+ readyPromise = new Promise((resolve)=>this.once('ready', resolve));
2379
+ }
2380
+ return readyPromise.then(()=>{
2381
+ this.fire('destroy');
2382
+ this.stopListening();
2383
+ this.commands.destroy();
2384
+ }).then(()=>this.plugins.destroy()).then(()=>{
2385
+ this.model.destroy();
2386
+ this.data.destroy();
2387
+ this.editing.destroy();
2388
+ this.keystrokes.destroy();
2389
+ })// Remove the editor from the context.
2390
+ // When the context was created by this editor, the context will be destroyed.
2391
+ .then(()=>this._context._removeEditor(this));
2392
+ }
2393
+ /**
2394
+ * Executes the specified command with given parameters.
2395
+ *
2396
+ * Shorthand for:
2397
+ *
2398
+ * ```ts
2399
+ * editor.commands.get( commandName ).execute( ... );
2400
+ * ```
2401
+ *
2402
+ * @param commandName The name of the command to execute.
2403
+ * @param commandParams Command parameters.
2404
+ * @returns The value returned by the {@link module:core/commandcollection~CommandCollection#execute `commands.execute()`}.
2405
+ */ execute(commandName, ...commandParams) {
2406
+ try {
2407
+ return this.commands.execute(commandName, ...commandParams);
2408
+ } catch (err) {
2409
+ // @if CK_DEBUG // throw err;
2410
+ /* istanbul ignore next -- @preserve */ CKEditorError.rethrowUnexpectedError(err, this);
2411
+ }
2412
+ }
2413
+ /**
2414
+ * Focuses the editor.
2415
+ *
2416
+ * **Note** To explicitly focus the editing area of the editor, use the
2417
+ * {@link module:engine/view/view~View#focus `editor.editing.view.focus()`} method of the editing view.
2418
+ *
2419
+ * Check out the {@glink framework/deep-dive/ui/focus-tracking#focus-in-the-editor-ui Focus in the editor UI} section
2420
+ * of the {@glink framework/deep-dive/ui/focus-tracking Deep dive into focus tracking} guide to learn more.
2421
+ */ focus() {
2422
+ this.editing.view.focus();
2423
+ }
2424
+ /* istanbul ignore next -- @preserve */ /**
2425
+ * Creates and initializes a new editor instance.
2426
+ *
2427
+ * This is an abstract method. Every editor type needs to implement its own initialization logic.
2428
+ *
2429
+ * See the `create()` methods of the existing editor types to learn how to use them:
2430
+ *
2431
+ * * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`}
2432
+ * * {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}
2433
+ * * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}
2434
+ * * {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`}
2435
+ */ static create(...args) {
2436
+ throw new Error('This is an abstract method.');
2437
+ }
2438
+ /**
2439
+ * The {@link module:core/context~Context} class.
2440
+ *
2441
+ * Exposed as static editor field for easier access in editor builds.
2442
+ */ static Context = Context;
2443
+ /**
2444
+ * The {@link module:watchdog/editorwatchdog~EditorWatchdog} class.
2445
+ *
2446
+ * Exposed as static editor field for easier access in editor builds.
2447
+ */ static EditorWatchdog = EditorWatchdog;
2448
+ /**
2449
+ * The {@link module:watchdog/contextwatchdog~ContextWatchdog} class.
2450
+ *
2451
+ * Exposed as static editor field for easier access in editor builds.
2452
+ */ static ContextWatchdog = ContextWatchdog;
2453
+ _showLicenseError(reason, pluginName) {
2454
+ setTimeout(()=>{
2455
+ if (reason == 'invalid') {
2456
+ /**
2457
+ * Invalid license key. Please contact our customer support at
2458
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/).
2459
+ *
2460
+ * @error invalid-license-key
2461
+ */ throw new CKEditorError('invalid-license-key', this);
2462
+ }
2463
+ if (reason == 'expired') {
2464
+ /**
2465
+ * Your license key has expired. Please renew your license at
2466
+ * [https://portal.ckeditor.com/](https://portal.ckeditor.com/).
2467
+ *
2468
+ * @error license-key-expired
2469
+ */ throw new CKEditorError('license-key-expired', this);
2470
+ }
2471
+ if (reason == 'domainLimit') {
2472
+ /**
2473
+ * The hostname is not allowed by your license. Please update your license configuration at
2474
+ * [https://portal.ckeditor.com/](https://portal.ckeditor.com/).
2475
+ *
2476
+ * @error license-key-domain-limit
2477
+ */ throw new CKEditorError('license-key-domain-limit', this);
2478
+ }
2479
+ if (reason == 'featureNotAllowed') {
2480
+ /**
2481
+ * The plugin is not allowed by your license.
2482
+ *
2483
+ * Please check your license or contact support at
2484
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/)
2485
+ * for more information.
2486
+ *
2487
+ * @error license-key-feature-not-allowed
2488
+ * @param {String} pluginName
2489
+ */ throw new CKEditorError('license-key-feature-not-allowed', this, {
2490
+ pluginName
2491
+ });
2492
+ }
2493
+ if (reason == 'evaluationLimit') {
2494
+ /**
2495
+ * You have reached the usage limit of your evaluation license key. Restart the editor.
2496
+ *
2497
+ * Please contact our customer support to get full access at
2498
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/).
2499
+ *
2500
+ * @error license-key-evaluation-limit
2501
+ */ throw new CKEditorError('license-key-evaluation-limit', this);
2502
+ }
2503
+ if (reason == 'trialLimit') {
2504
+ /**
2505
+ * You have reached the usage limit of your trial license key. Restart the editor.
2506
+ *
2507
+ * Please contact our customer support to get full access at
2508
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/).
2509
+ *
2510
+ * @error license-key-trial-limit
2511
+ */ throw new CKEditorError('license-key-trial-limit', this);
2512
+ }
2513
+ if (reason == 'developmentLimit') {
2514
+ /**
2515
+ * You have reached the usage limit of your development license key. Restart the editor.
2516
+ *
2517
+ * Please contact our customer support to get full access at
2518
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/).
2519
+ *
2520
+ * @error license-key-development-limit
2521
+ */ throw new CKEditorError('license-key-development-limit', this);
2522
+ }
2523
+ if (reason == 'usageLimit') {
2524
+ /**
2525
+ * You have reached the usage limit of your license key.
2526
+ *
2527
+ * Please contact our customer support to extend the limit at
2528
+ * [https://ckeditor.com/contact/](https://ckeditor.com/contact/).
2529
+ *
2530
+ * @error license-key-usage-limit
2531
+ */ throw new CKEditorError('license-key-usage-limit', this);
2532
+ }
2533
+ if (reason == 'distributionChannel') {
2534
+ /**
2535
+ * Your license doesn't allow using the editor in this distribution channel.
2536
+ *
2537
+ * Having the `'GPL'` license key, you can use the editor installed from npm (self-hosted). If you have
2538
+ * a commercial license, you can use the editor from CDN or — if your plan allows — from npm.
2539
+ *
2540
+ * Please check your installation or contact support at [https://ckeditor.com/contact/](https://ckeditor.com/contact/)
2541
+ * for more information.
2542
+ *
2543
+ * @error license-key-distribution-channel
2544
+ */ throw new CKEditorError('license-key-distribution-channel', this);
2545
+ }
2546
+ }, 0);
2547
+ this._showLicenseError = ()=>{};
2548
+ }
2549
+ async _sendUsageRequest(endpoint, request) {
2550
+ const headers = new Headers({
2551
+ 'Content-Type': 'application/json'
2552
+ });
2553
+ const response = await fetch(new URL(endpoint), {
2554
+ method: 'POST',
2555
+ headers,
2556
+ body: JSON.stringify(request)
2557
+ });
2558
+ if (!response.ok) {
2559
+ // TODO: refine message.
2560
+ throw new Error(`HTTP Response: ${response.status}`);
2561
+ }
2562
+ return response.json();
2563
+ }
2564
+ }
2565
+ function collectUsageData(editor) {
2566
+ const collectedData = getEditorUsageData(editor);
2567
+ function setUsageData(path, value) {
2568
+ if (get(collectedData, path) !== undefined) {
2569
+ /**
2570
+ * The error thrown when trying to set the usage data path that was already set.
2571
+ * Make sure that you are not setting the same path multiple times.
2572
+ *
2573
+ * @error editor-usage-data-path-already-set
2574
+ */ throw new CKEditorError('editor-usage-data-path-already-set', {
2575
+ path
2576
+ });
2577
+ }
2578
+ set(collectedData, path, value);
2579
+ }
2580
+ editor.fire('collectUsageData', {
2581
+ setUsageData
2582
+ });
2583
+ return collectedData;
2584
+ }
2585
+ /**
2586
+ * This error is thrown when trying to pass a `<textarea>` element to a `create()` function of an editor class.
2587
+ *
2588
+ * The only editor type which can be initialized on `<textarea>` elements is
2589
+ * the {@glink getting-started/setup/editor-types#classic-editor classic editor}.
2590
+ * This editor hides the passed element and inserts its own UI next to it. Other types of editors reuse the passed element as their root
2591
+ * editable element and therefore `<textarea>` is not appropriate for them. Use a `<div>` or another text container instead:
2592
+ *
2593
+ * ```html
2594
+ * <div id="editor">
2595
+ * <p>Initial content.</p>
2596
+ * </div>
2597
+ * ```
2598
+ *
2599
+ * @error editor-wrong-element
2600
+ */
2601
+
2602
+ /**
2603
+ * Checks if the editor is initialized on a `<textarea>` element that belongs to a form. If yes, it updates the editor's element
2604
+ * content before submitting the form.
2605
+ *
2606
+ * This helper requires the {@link module:core/editor/utils/elementapimixin~ElementApi ElementApi interface}.
2607
+ *
2608
+ * @param editor Editor instance.
2609
+ */ function attachToForm(editor) {
2610
+ if (!isFunction(editor.updateSourceElement)) {
2611
+ /**
2612
+ * The editor passed to `attachToForm()` must implement the
2613
+ * {@link module:core/editor/utils/elementapimixin~ElementApi} interface.
2614
+ *
2615
+ * @error attachtoform-missing-elementapi-interface
2616
+ */ throw new CKEditorError('attachtoform-missing-elementapi-interface', editor);
2617
+ }
2618
+ const sourceElement = editor.sourceElement;
2619
+ // Only when replacing a textarea which is inside of a form element.
2620
+ if (isTextArea(sourceElement) && sourceElement.form) {
2621
+ let originalSubmit;
2622
+ const form = sourceElement.form;
2623
+ const onSubmit = ()=>editor.updateSourceElement();
2624
+ // Replace the original form#submit() to call a custom submit function first.
2625
+ // Check if #submit is a function because the form might have an input named "submit".
2626
+ if (isFunction(form.submit)) {
2627
+ originalSubmit = form.submit;
2628
+ form.submit = ()=>{
2629
+ onSubmit();
2630
+ originalSubmit.apply(form);
2631
+ };
2632
+ }
2633
+ // Update the replaced textarea with data before each form#submit event.
2634
+ form.addEventListener('submit', onSubmit);
2635
+ // Remove the submit listener and revert the original submit method on
2636
+ // editor#destroy.
2637
+ editor.on('destroy', ()=>{
2638
+ form.removeEventListener('submit', onSubmit);
2639
+ if (originalSubmit) {
2640
+ form.submit = originalSubmit;
2641
+ }
2642
+ });
2643
+ }
2644
+ }
2645
+ function isTextArea(sourceElement) {
2646
+ return !!sourceElement && sourceElement.tagName.toLowerCase() === 'textarea';
2647
+ }
2648
+
2649
+ /**
2650
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
2651
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
2652
+ */ /**
2653
+ * @module core/editor/utils/dataapimixin
2654
+ */ /**
2655
+ * Implementation of the {@link module:core/editor/utils/dataapimixin~DataApi}.
2656
+ *
2657
+ * @deprecated This functionality is already implemented by the `Editor` class.
2658
+ */ function DataApiMixin(base) {
2659
+ return base;
2660
+ }
2661
+
2662
+ /**
2663
+ * Implementation of the {@link module:core/editor/utils/elementapimixin~ElementApi}.
2664
+ */ function ElementApiMixin(base) {
2665
+ class Mixin extends base {
2666
+ sourceElement;
2667
+ updateSourceElement(data) {
2668
+ if (!this.sourceElement) {
2669
+ /**
2670
+ * Cannot update the source element of a detached editor.
2671
+ *
2672
+ * The {@link module:core/editor/utils/elementapimixin~ElementApi#updateSourceElement `updateSourceElement()`}
2673
+ * method cannot be called if you did not pass an element to `Editor.create()`.
2674
+ *
2675
+ * @error editor-missing-sourceelement
2676
+ */ throw new CKEditorError('editor-missing-sourceelement', this);
2677
+ }
2678
+ const shouldUpdateSourceElement = this.config.get('updateSourceElementOnDestroy');
2679
+ const isSourceElementTextArea = this.sourceElement instanceof HTMLTextAreaElement;
2680
+ // The data returned by the editor might be unsafe, so we want to prevent rendering
2681
+ // unsafe content inside the source element different than <textarea>, which is considered
2682
+ // secure. This behavior could be changed by setting the `updateSourceElementOnDestroy`
2683
+ // configuration option to `true`.
2684
+ if (!shouldUpdateSourceElement && !isSourceElementTextArea) {
2685
+ setDataInElement(this.sourceElement, '');
2686
+ return;
2687
+ }
2688
+ const dataToSet = typeof data === 'string' ? data : this.data.get();
2689
+ setDataInElement(this.sourceElement, dataToSet);
2690
+ }
2691
+ }
2692
+ return Mixin;
2693
+ }
2694
+ // Backward compatibility with `mix`.
2695
+ ElementApiMixin.updateSourceElement = ElementApiMixin(Object).prototype.updateSourceElement;
2696
+
2697
+ /**
2698
+ * Marks the source element on which the editor was initialized. This prevents other editor instances from using this element.
2699
+ *
2700
+ * Running multiple editor instances on the same source element causes various issues and it is
2701
+ * crucial this helper is called as soon as the source element is known to prevent collisions.
2702
+ *
2703
+ * @param editor Editor instance.
2704
+ * @param sourceElement Element to bind with the editor instance.
2705
+ */ function secureSourceElement(editor, sourceElement) {
2706
+ if (sourceElement.ckeditorInstance) {
2707
+ /**
2708
+ * A DOM element used to create the editor (e.g.
2709
+ * {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`})
2710
+ * has already been used to create another editor instance. Make sure each editor is
2711
+ * created with an unique DOM element.
2712
+ *
2713
+ * @error editor-source-element-already-used
2714
+ * @param element DOM element that caused the collision.
2715
+ */ throw new CKEditorError('editor-source-element-already-used', editor);
2716
+ }
2717
+ sourceElement.ckeditorInstance = editor;
2718
+ editor.once('destroy', ()=>{
2719
+ delete sourceElement.ckeditorInstance;
2720
+ });
2721
+ }
2722
+
2723
+ /**
2724
+ * The list of pending editor actions.
2725
+ *
2726
+ * This plugin should be used to synchronise plugins that execute long-lasting actions
2727
+ * (e.g. file upload) with the editor integration. It gives the developer who integrates the editor
2728
+ * an easy way to check if there are any actions pending whenever such information is needed.
2729
+ * All plugins that register a pending action also provide a message about the action that is ongoing
2730
+ * which can be displayed to the user. This lets them decide if they want to interrupt the action or wait.
2731
+ *
2732
+ * Adding and updating a pending action:
2733
+ *
2734
+ * ```ts
2735
+ * const pendingActions = editor.plugins.get( 'PendingActions' );
2736
+ * const action = pendingActions.add( 'Upload in progress: 0%.' );
2737
+ *
2738
+ * // You can update the message:
2739
+ * action.message = 'Upload in progress: 10%.';
2740
+ * ```
2741
+ *
2742
+ * Removing a pending action:
2743
+ *
2744
+ * ```ts
2745
+ * const pendingActions = editor.plugins.get( 'PendingActions' );
2746
+ * const action = pendingActions.add( 'Unsaved changes.' );
2747
+ *
2748
+ * pendingActions.remove( action );
2749
+ * ```
2750
+ *
2751
+ * Getting pending actions:
2752
+ *
2753
+ * ```ts
2754
+ * const pendingActions = editor.plugins.get( 'PendingActions' );
2755
+ *
2756
+ * const action1 = pendingActions.add( 'Action 1' );
2757
+ * const action2 = pendingActions.add( 'Action 2' );
2758
+ *
2759
+ * pendingActions.first; // Returns action1
2760
+ * Array.from( pendingActions ); // Returns [ action1, action2 ]
2761
+ * ```
2762
+ *
2763
+ * This plugin is used by features like {@link module:upload/filerepository~FileRepository} to register their ongoing actions
2764
+ * and by features like {@link module:autosave/autosave~Autosave} to detect whether there are any ongoing actions.
2765
+ * Read more about saving the data in the
2766
+ * {@glink getting-started/setup/getting-and-setting-data Saving and getting data} guide.
2767
+ */ class PendingActions extends ContextPlugin {
2768
+ /**
2769
+ * A list of pending actions.
2770
+ */ _actions;
2771
+ /**
2772
+ * @inheritDoc
2773
+ */ static get pluginName() {
2774
+ return 'PendingActions';
2775
+ }
2776
+ /**
2777
+ * @inheritDoc
2778
+ */ static get isOfficialPlugin() {
2779
+ return true;
2780
+ }
2781
+ /**
2782
+ * @inheritDoc
2783
+ */ init() {
2784
+ this.set('hasAny', false);
2785
+ this._actions = new Collection({
2786
+ idProperty: '_id'
2787
+ });
2788
+ this._actions.delegate('add', 'remove').to(this);
2789
+ }
2790
+ /**
2791
+ * Adds an action to the list of pending actions.
2792
+ *
2793
+ * This method returns an action object with an observable message property.
2794
+ * The action object can be later used in the {@link #remove} method. It also allows you to change the message.
2795
+ *
2796
+ * @param message The action message.
2797
+ * @returns An observable object that represents a pending action.
2798
+ */ add(message) {
2799
+ if (typeof message !== 'string') {
2800
+ /**
2801
+ * The message must be a string.
2802
+ *
2803
+ * @error pendingactions-add-invalid-message
2804
+ */ throw new CKEditorError('pendingactions-add-invalid-message', this);
2805
+ }
2806
+ const action = new (ObservableMixin())();
2807
+ action.set('message', message);
2808
+ this._actions.add(action);
2809
+ this.hasAny = true;
2810
+ return action;
2811
+ }
2812
+ /**
2813
+ * Removes an action from the list of pending actions.
2814
+ *
2815
+ * @param action An action object.
2816
+ */ remove(action) {
2817
+ this._actions.remove(action);
2818
+ this.hasAny = !!this._actions.length;
2819
+ }
2820
+ /**
2821
+ * Returns the first action from the list or null if the list is empty
2822
+ *
2823
+ * @returns The pending action object.
2824
+ */ get first() {
2825
+ return this._actions.get(0);
2826
+ }
2827
+ /**
2828
+ * Iterable interface.
2829
+ */ [Symbol.iterator]() {
2830
+ return this._actions[Symbol.iterator]();
2831
+ }
2832
+ }
2833
+
2834
+ var cancel = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m11.591 10.177 4.243 4.242a1 1 0 0 1-1.415 1.415l-4.242-4.243-4.243 4.243a1 1 0 0 1-1.414-1.415l4.243-4.242L4.52 5.934A1 1 0 0 1 5.934 4.52l4.243 4.243 4.242-4.243a1 1 0 1 1 1.415 1.414l-4.243 4.243z\"/></svg>";
2835
+
2836
+ var caption = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 16h9a1 1 0 0 1 0 2H2a1 1 0 0 1 0-2z\"/><path d=\"M17 1a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h14zm0 1.5H3a.5.5 0 0 0-.492.41L2.5 3v9a.5.5 0 0 0 .41.492L3 12.5h14a.5.5 0 0 0 .492-.41L17.5 12V3a.5.5 0 0 0-.41-.492L17 2.5z\" fill-opacity=\".6\"/></svg>";
2837
+
2838
+ var check = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.972 16.615a.997.997 0 0 1-.744-.292l-4.596-4.596a1 1 0 1 1 1.414-1.414l3.926 3.926 9.937-9.937a1 1 0 0 1 1.414 1.415L7.717 16.323a.997.997 0 0 1-.745.292z\"/></svg>";
2839
+
2840
+ var cog = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m11.333 2 .19 2.263a5.899 5.899 0 0 1 1.458.604L14.714 3.4 16.6 5.286l-1.467 1.733c.263.452.468.942.605 1.46L18 8.666v2.666l-2.263.19a5.899 5.899 0 0 1-.604 1.458l1.467 1.733-1.886 1.886-1.733-1.467a5.899 5.899 0 0 1-1.46.605L11.334 18H8.667l-.19-2.263a5.899 5.899 0 0 1-1.458-.604L5.286 16.6 3.4 14.714l1.467-1.733a5.899 5.899 0 0 1-.604-1.458L2 11.333V8.667l2.262-.189a5.899 5.899 0 0 1 .605-1.459L3.4 5.286 5.286 3.4l1.733 1.467a5.899 5.899 0 0 1 1.46-.605L8.666 2h2.666zM10 6.267a3.733 3.733 0 1 0 0 7.466 3.733 3.733 0 0 0 0-7.466z\"/></svg>";
2841
+
2842
+ var colorPalette = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.209 18.717A8.5 8.5 0 1 1 18.686 9.6h-.008l.002.12a3 3 0 0 1-2.866 2.997h-.268l-.046-.002v.002h-4.791a2 2 0 1 0 0 4 1 1 0 1 1-.128 1.992 8.665 8.665 0 0 1-.372.008Zm-3.918-7.01a1.25 1.25 0 1 0-2.415-.648 1.25 1.25 0 0 0 2.415.647ZM5.723 8.18a1.25 1.25 0 1 0 .647-2.414 1.25 1.25 0 0 0-.647 2.414ZM9.76 6.155a1.25 1.25 0 1 0 .647-2.415 1.25 1.25 0 0 0-.647 2.415Zm4.028 1.759a1.25 1.25 0 1 0 .647-2.415 1.25 1.25 0 0 0-.647 2.415Z\"/></svg>";
2843
+
2844
+ var eraser = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m8.636 9.531-2.758 3.94a.5.5 0 0 0 .122.696l3.224 2.284h1.314l2.636-3.736L8.636 9.53zm.288 8.451L5.14 15.396a2 2 0 0 1-.491-2.786l6.673-9.53a2 2 0 0 1 2.785-.49l3.742 2.62a2 2 0 0 1 .491 2.785l-7.269 10.053-2.147-.066z\"/><path d=\"M4 18h5.523v-1H4zm-2 0h1v-1H2z\"/></svg>";
2845
+
2846
+ var history = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11 1a9 9 0 1 1-8.027 13.075l1.128-1.129A7.502 7.502 0 0 0 18.5 10a7.5 7.5 0 1 0-14.962.759l-.745-.746-.76.76A9 9 0 0 1 11 1z\"/><path d=\"M.475 8.17a.75.75 0 0 1 .978.047l.075.082 1.284 1.643 1.681-1.284a.75.75 0 0 1 .978.057l.073.083a.75.75 0 0 1-.057.978l-.083.073-2.27 1.737a.75.75 0 0 1-.973-.052l-.074-.082-1.741-2.23a.75.75 0 0 1 .13-1.052z\"/><path d=\"M11.5 5v4.999l3.196 3.196-1.06 1.06L10.1 10.72l-.1-.113V5z\"/></svg>";
2847
+
2848
+ var lowVision = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.085 6.22 2.943 4.078a.75.75 0 1 1 1.06-1.06l2.592 2.59A11.094 11.094 0 0 1 10 5.068c4.738 0 8.578 3.101 8.578 5.083 0 1.197-1.401 2.803-3.555 3.887l1.714 1.713a.75.75 0 0 1-.09 1.138.488.488 0 0 1-.15.084.75.75 0 0 1-.821-.16L6.17 7.304c-.258.11-.51.233-.757.365l6.239 6.24-.006.005.78.78c-.388.094-.78.166-1.174.215l-1.11-1.11h.011L4.55 8.197a7.2 7.2 0 0 0-.665.514l-.112.098 4.897 4.897-.005.006 1.276 1.276a10.164 10.164 0 0 1-1.477-.117l-.479-.479-.009.009-4.863-4.863-.022.031a2.563 2.563 0 0 0-.124.2c-.043.077-.08.158-.108.241a.534.534 0 0 0-.028.133.29.29 0 0 0 .008.072.927.927 0 0 0 .082.226c.067.133.145.26.234.379l3.242 3.365.025.01.59.623c-3.265-.918-5.59-3.155-5.59-4.668 0-1.194 1.448-2.838 3.663-3.93zm7.07.531a4.632 4.632 0 0 1 1.108 5.992l.345.344.046-.018a9.313 9.313 0 0 0 2-1.112c.256-.187.5-.392.727-.613.137-.134.27-.277.392-.431.072-.091.141-.185.203-.286.057-.093.107-.19.148-.292a.72.72 0 0 0 .036-.12.29.29 0 0 0 .008-.072.492.492 0 0 0-.028-.133.999.999 0 0 0-.036-.096 2.165 2.165 0 0 0-.071-.145 2.917 2.917 0 0 0-.125-.2 3.592 3.592 0 0 0-.263-.335 5.444 5.444 0 0 0-.53-.523 7.955 7.955 0 0 0-1.054-.768 9.766 9.766 0 0 0-1.879-.891c-.337-.118-.68-.219-1.027-.301zm-2.85.21-.069.002a.508.508 0 0 0-.254.097.496.496 0 0 0-.104.679.498.498 0 0 0 .326.199l.045.005c.091.003.181.003.272.012a2.45 2.45 0 0 1 2.017 1.513c.024.061.043.125.069.185a.494.494 0 0 0 .45.287h.008a.496.496 0 0 0 .35-.158.482.482 0 0 0 .13-.335.638.638 0 0 0-.048-.219 3.379 3.379 0 0 0-.36-.723 3.438 3.438 0 0 0-2.791-1.543l-.028-.001h-.013z\"/></svg>";
2849
+
2850
+ var textAlternative = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.035 1C2.446 1 2 1.54 2 2.098V10.5h1.5v-8h13v8H18V2.098C18 1.539 17.48 1 16.9 1H3.035Zm10.453 2.61a1.885 1.885 0 0 0-1.442.736 1.89 1.89 0 0 0 1.011 2.976 1.903 1.903 0 0 0 2.253-1.114 1.887 1.887 0 0 0-1.822-2.598ZM7.463 8.163a.611.611 0 0 0-.432.154L5.071 10.5h5.119L7.88 8.348a.628.628 0 0 0-.417-.185Zm6.236 1.059a.62.62 0 0 0-.42.164L12.07 10.5h2.969l-.92-1.113a.618.618 0 0 0-.42-.165ZM.91 11.5a.91.91 0 0 0-.91.912v6.877c0 .505.405.91.91.91h18.178a.91.91 0 0 0 .912-.91v-6.877a.908.908 0 0 0-.912-.912H.91ZM3.668 13h1.947l2.135 5.7H5.898l-.28-.946H3.601l-.278.945H1.516L3.668 13Zm4.947 0h1.801v4.3h2.7v1.4h-4.5V13h-.001Zm4.5 0h5.4v1.4h-1.798v4.3h-1.701v-4.3h-1.9V13h-.001Zm-8.517 1.457-.614 2.059h1.262l-.648-2.059Z\"/></svg>";
2851
+
2852
+ var loupe = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.68 13.74h-.001l4.209 4.208a1 1 0 1 0 1.414-1.414l-4.267-4.268a6 6 0 1 0-1.355 1.474ZM13 9a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z\"/></svg>";
2853
+
2854
+ var previousArrow = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.463 5.187a.888.888 0 1 1 1.254 1.255L9.16 10l3.557 3.557a.888.888 0 1 1-1.254 1.255L7.26 10.61a.888.888 0 0 1 .16-1.382l4.043-4.042z\"/></svg>";
2855
+
2856
+ var nextArrow = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.537 14.813a.888.888 0 1 1-1.254-1.255L10.84 10 7.283 6.442a.888.888 0 1 1 1.254-1.255L12.74 9.39a.888.888 0 0 1-.16 1.382l-4.043 4.042z\"/></svg>";
2857
+
2858
+ var image = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.66 9.118a.693.693 0 0 1 .956.032l3.65 3.411 2.422-2.238a.695.695 0 0 1 .945 0L17.5 13.6V2.5h-15v11.1l4.16-4.482ZM17.8 1c.652 0 1.2.47 1.2 1.1v14.362c0 .64-.532 1.038-1.184 1.038H2.184C1.532 17.5 1 17.103 1 16.462V2.1C1 1.47 1.537 1 2.2 1h15.6Zm-5.655 6a2.128 2.128 0 0 1 .157-2.364A2.133 2.133 0 1 1 12.145 7Z\"/></svg>";
2859
+
2860
+ var imageUpload = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.201 1C.538 1 0 1.47 0 2.1v14.363c0 .64.534 1.037 1.186 1.037h9.494a2.97 2.97 0 0 1-.414-.287 2.998 2.998 0 0 1-1.055-2.03 3.003 3.003 0 0 1 .693-2.185l.383-.455-.02.018-3.65-3.41a.695.695 0 0 0-.957-.034L1.5 13.6V2.5h15v5.535a2.97 2.97 0 0 1 1.412.932l.088.105V2.1c0-.63-.547-1.1-1.2-1.1H1.202Zm11.713 2.803a2.146 2.146 0 0 0-2.049 1.992 2.14 2.14 0 0 0 1.28 2.096 2.13 2.13 0 0 0 2.644-3.11 2.134 2.134 0 0 0-1.875-.978Z\"/><path d=\"M15.522 19.1a.79.79 0 0 0 .79-.79v-5.373l2.059 2.455a.79.79 0 1 0 1.211-1.015l-3.352-3.995a.79.79 0 0 0-.995-.179.784.784 0 0 0-.299.221l-3.35 3.99a.79.79 0 1 0 1.21 1.017l1.936-2.306v5.185c0 .436.353.79.79.79Z\"/><path d=\"M15.522 19.1a.79.79 0 0 0 .79-.79v-5.373l2.059 2.455a.79.79 0 1 0 1.211-1.015l-3.352-3.995a.79.79 0 0 0-.995-.179.784.784 0 0 0-.299.221l-3.35 3.99a.79.79 0 1 0 1.21 1.017l1.936-2.306v5.185c0 .436.353.79.79.79Z\"/></svg>";
2861
+
2862
+ var imageAssetManager = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.201 1c-.662 0-1.2.47-1.2 1.1v14.248c0 .64.533 1.152 1.185 1.152h6.623v-7.236L6.617 9.15a.694.694 0 0 0-.957-.033L1.602 13.55V2.553l14.798.003V9.7H18V2.1c0-.63-.547-1.1-1.2-1.1H1.202Zm11.723 2.805a2.094 2.094 0 0 0-1.621.832 2.127 2.127 0 0 0 1.136 3.357 2.13 2.13 0 0 0 2.611-1.506 2.133 2.133 0 0 0-.76-2.244 2.13 2.13 0 0 0-1.366-.44Z\"/><path clip-rule=\"evenodd\" d=\"M19.898 12.369v6.187a.844.844 0 0 1-.844.844h-8.719a.844.844 0 0 1-.843-.844v-7.312a.844.844 0 0 1 .843-.844h2.531a.843.843 0 0 1 .597.248l.838.852h4.75c.223 0 .441.114.6.272a.844.844 0 0 1 .247.597Zm-1.52.654-4.377.02-1.1-1.143H11v6h7.4l-.023-4.877Z\"/></svg>";
2863
+
2864
+ var imageUrl = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.201 1C.538 1 0 1.47 0 2.1v14.363c0 .64.534 1.037 1.186 1.037h7.029a5.401 5.401 0 0 1 .615-4.338l.762-1.232-2.975-2.78a.696.696 0 0 0-.957-.033L1.5 13.6V2.5h15v6.023c.449.131.887.32 1.307.573l.058.033c.046.028.09.057.135.086V2.1c0-.63-.547-1.1-1.2-1.1H1.202Zm11.713 2.803a2.15 2.15 0 0 0-1.611.834 2.118 2.118 0 0 0-.438 1.158 2.14 2.14 0 0 0 1.277 2.096 2.132 2.132 0 0 0 2.645-3.11 2.13 2.13 0 0 0-1.873-.978Z\"/><path d=\"M16.63 10.294a3.003 3.003 0 0 0-4.142.887l-.117.177a.647.647 0 0 0-.096.492.664.664 0 0 0 .278.418.7.7 0 0 0 .944-.234 1.741 1.741 0 0 1 2.478-.463 1.869 1.869 0 0 1 .476 2.55.637.637 0 0 0-.071.5.646.646 0 0 0 .309.396.627.627 0 0 0 .869-.19l.027-.041a3.226 3.226 0 0 0-.956-4.492Zm-6.061 3.78-.044.066a3.228 3.228 0 0 0 .82 4.403 3.005 3.005 0 0 0 4.275-.798l.13-.197a.626.626 0 0 0 .092-.475.638.638 0 0 0-.268-.402.713.713 0 0 0-.99.26l-.018.029a1.741 1.741 0 0 1-2.477.461 1.87 1.87 0 0 1-.475-2.55l.029-.047a.647.647 0 0 0 .086-.485.66.66 0 0 0-.275-.408l-.04-.027a.609.609 0 0 0-.845.17Z\"/><path d=\"M15.312 13.925c.24-.36.154-.838-.19-1.067-.346-.23-.82-.124-1.059.236l-1.268 1.907c-.239.36-.153.838.192 1.067.345.23.818.123 1.057-.236l1.268-1.907Z\"/></svg>";
2865
+
2866
+ var alignBottom = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m9.239 13.938-2.88-1.663a.75.75 0 0 1 .75-1.3L9 12.067V4.75a.75.75 0 1 1 1.5 0v7.318l1.89-1.093a.75.75 0 0 1 .75 1.3l-2.879 1.663a.752.752 0 0 1-.511.187.752.752 0 0 1-.511-.187zM4.25 17a.75.75 0 1 1 0-1.5h10.5a.75.75 0 0 1 0 1.5H4.25z\"/></svg>";
2867
+
2868
+ var alignMiddle = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.75 11.875a.752.752 0 0 1 .508.184l2.883 1.666a.75.75 0 0 1-.659 1.344l-.091-.044-1.892-1.093.001 4.318a.75.75 0 1 1-1.5 0v-4.317l-1.89 1.092a.75.75 0 0 1-.75-1.3l2.879-1.663a.752.752 0 0 1 .51-.187zM15.25 9a.75.75 0 1 1 0 1.5H4.75a.75.75 0 1 1 0-1.5h10.5zM9.75.375a.75.75 0 0 1 .75.75v4.318l1.89-1.093.092-.045a.75.75 0 0 1 .659 1.344l-2.883 1.667a.752.752 0 0 1-.508.184.752.752 0 0 1-.511-.187L6.359 5.65a.75.75 0 0 1 .75-1.299L9 5.442V1.125a.75.75 0 0 1 .75-.75z\"/></svg>";
2869
+
2870
+ var alignTop = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m10.261 7.062 2.88 1.663a.75.75 0 0 1-.75 1.3L10.5 8.933v7.317a.75.75 0 1 1-1.5 0V8.932l-1.89 1.093a.75.75 0 0 1-.75-1.3l2.879-1.663a.752.752 0 0 1 .511-.187.752.752 0 0 1 .511.187zM15.25 4a.75.75 0 1 1 0 1.5H4.75a.75.75 0 0 1 0-1.5h10.5z\"/></svg>";
2871
+
2872
+ var alignLeft = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3.75c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0 8c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0 4c0 .414.336.75.75.75h9.929a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0-8c0 .414.336.75.75.75h9.929a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75z\"/></svg>";
2873
+
2874
+ var alignCenter = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3.75c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0 8c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm2.286 4c0 .414.336.75.75.75h9.928a.75.75 0 1 0 0-1.5H5.036a.75.75 0 0 0-.75.75zm0-8c0 .414.336.75.75.75h9.928a.75.75 0 1 0 0-1.5H5.036a.75.75 0 0 0-.75.75z\"/></svg>";
2875
+
2876
+ var alignRight = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M18 3.75a.75.75 0 0 1-.75.75H2.75a.75.75 0 1 1 0-1.5h14.5a.75.75 0 0 1 .75.75zm0 8a.75.75 0 0 1-.75.75H2.75a.75.75 0 1 1 0-1.5h14.5a.75.75 0 0 1 .75.75zm0 4a.75.75 0 0 1-.75.75H7.321a.75.75 0 1 1 0-1.5h9.929a.75.75 0 0 1 .75.75zm0-8a.75.75 0 0 1-.75.75H7.321a.75.75 0 1 1 0-1.5h9.929a.75.75 0 0 1 .75.75z\"/></svg>";
2877
+
2878
+ var alignJustify = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3.75c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0 8c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0 4c0 .414.336.75.75.75h9.929a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm0-8c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75z\"/></svg>";
2879
+
2880
+ var objectBlockLeft = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm0 12h16v1.5H2z\"/><path d=\"M12.003 7v5.5a1 1 0 0 1-1 1H2.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H3.5V12h6.997V7.5z\"/></svg>";
2881
+
2882
+ var objectCenter = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm0 12h16v1.5H2z\"/><path d=\"M15.003 7v5.5a1 1 0 0 1-1 1H5.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H6.5V12h6.997V7.5z\"/></svg>";
2883
+
2884
+ var objectBlockRight = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm0 12h16v1.5H2z\"/><path d=\"M18.003 7v5.5a1 1 0 0 1-1 1H8.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H9.5V12h6.997V7.5z\"/></svg>";
2885
+
2886
+ var objectFullWidth = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm0 12h16v1.5H2z\"/><path d=\"M18 7v5.5a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1zm-1.505.5H3.504V12h12.991V7.5z\"/></svg>";
2887
+
2888
+ var objectInline = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm11.5 9H18v1.5h-4.5zM2 15h16v1.5H2z\"/><path d=\"M12.003 7v5.5a1 1 0 0 1-1 1H2.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H3.5V12h6.997V7.5z\"/></svg>";
2889
+
2890
+ var objectLeft = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm11.5 9H18v1.5h-4.5zm0-3H18v1.5h-4.5zm0-3H18v1.5h-4.5zM2 15h16v1.5H2z\"/><path d=\"M12.003 7v5.5a1 1 0 0 1-1 1H2.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H3.5V12h6.997V7.5z\"/></svg>";
2891
+
2892
+ var objectRight = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path opacity=\".5\" d=\"M2 3h16v1.5H2zm0 12h16v1.5H2zm0-9h5v1.5H2zm0 3h5v1.5H2zm0 3h5v1.5H2z\"/><path d=\"M18.003 7v5.5a1 1 0 0 1-1 1H8.996a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h8.007a1 1 0 0 1 1 1zm-1.506.5H9.5V12h6.997V7.5z\"/></svg>";
2893
+
2894
+ var objectSizeFull = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\"><path d=\"M2.5 17v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zm2 0v1h-1v-1h1zM1 15.5v1H0v-1h1zm19 0v1h-1v-1h1zm-19-2v1H0v-1h1zm19 0v1h-1v-1h1zm-19-2v1H0v-1h1zm19 0v1h-1v-1h1zm-19-2v1H0v-1h1zm19 0v1h-1v-1h1zm-19-2v1H0v-1h1zm19 0v1h-1v-1h1zm-19-2v1H0v-1h1zm19 0v1h-1v-1h1zm0-2v1h-1v-1h1zm-19 0v1H0v-1h1zM14.5 2v1h-1V2h1zm2 0v1h-1V2h1zm2 0v1h-1V2h1zm-8 0v1h-1V2h1zm-2 0v1h-1V2h1zm-2 0v1h-1V2h1zm-2 0v1h-1V2h1zm8 0v1h-1V2h1zm-10 0v1h-1V2h1z\"/><path d=\"M18.095 2H1.905C.853 2 0 2.895 0 4v12c0 1.105.853 2 1.905 2h16.19C19.147 18 20 17.105 20 16V4c0-1.105-.853-2-1.905-2zm0 1.5c.263 0 .476.224.476.5v12c0 .276-.213.5-.476.5H1.905a.489.489 0 0 1-.476-.5V4c0-.276.213-.5.476-.5h16.19z\"/></svg>";
2895
+
2896
+ var objectSizeCustom = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:v=\"https://vecta.io/nano\" viewBox=\"0 0 20 20\"><path d=\"M.95 1.43a.95.95 0 0 0-.95.95v3.1a.95.95 0 0 0 .95.95h.75v6.3H.95a.95.95 0 0 0-.95.95v3.1a.95.95 0 0 0 .95.95h3.1a.95.95 0 0 0 .95-.95v-.65h1.932l1.539-1.5H5v-.95a.95.95 0 0 0-.95-.95H3.2v-6.3h.85A.95.95 0 0 0 5 5.48v-.55h10v.55a.95.95 0 0 0 .95.95h3.1a.95.95 0 0 0 .95-.95v-3.1a.95.95 0 0 0-.95-.95h-3.1a.95.95 0 0 0-.95.95v1.05H5V2.38a.95.95 0 0 0-.95-.95H.95zm.55 3.5v-2h2v2h-2zm0 9.3v2h2v-2h-2zm15-11.3v2h2v-2h-2z\"/><path d=\"M8.139 20.004v-2.388l7.045-7.048 2.391 2.391-7.046 7.046h-2.39zm11.421-9.101a.64.64 0 0 1-.138.206l-1.165 1.168-2.391-2.391 1.167-1.163a.63.63 0 0 1 .206-.138.635.635 0 0 1 .243-.049.63.63 0 0 1 .449.187l1.491 1.488c.059.059.108.129.138.206s.049.16.049.243a.6.6 0 0 1-.049.243z\"/></svg>";
2897
+
2898
+ var objectSizeLarge = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.5 16.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1ZM1 15v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 13v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 11v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 9v1H0V9h1Zm19 0v1h-1V9h1ZM1 7v1H0V7h1Zm19 0v1h-1V7h1ZM1 5v1H0V5h1Zm19 0v1h-1V5h1Zm0-2v1h-1V3h1ZM1 3v1H0V3h1Zm13.5-1.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm-8 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm8 0v1h-1v-1h1Zm-10 0v1h-1v-1h1Z\"/><path d=\"M13 5.5H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2ZM13 7a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-8A.5.5 0 0 1 2 7h11Z\"/></svg>";
2899
+
2900
+ var objectSizeSmall = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.5 16.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1ZM1 15v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 13v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 11v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 9v1H0V9h1Zm19 0v1h-1V9h1ZM1 7v1H0V7h1Zm19 0v1h-1V7h1ZM1 5v1H0V5h1Zm19 0v1h-1V5h1Zm0-2v1h-1V3h1ZM1 3v1H0V3h1Zm13.5-1.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm-8 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm8 0v1h-1v-1h1Zm-10 0v1h-1v-1h1Z\"/><path d=\"M7 9.5H2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2ZM7 11a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-4A.5.5 0 0 1 2 11h5Z\"/></svg>";
2901
+
2902
+ var objectSizeMedium = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.5 16.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1ZM1 15v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 13v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 11v1H0v-1h1Zm19 0v1h-1v-1h1ZM1 9v1H0V9h1Zm19 0v1h-1V9h1ZM1 7v1H0V7h1Zm19 0v1h-1V7h1ZM1 5v1H0V5h1Zm19 0v1h-1V5h1Zm0-2v1h-1V3h1ZM1 3v1H0V3h1Zm13.5-1.5v1h-1v-1h1Zm2 0v1h-1v-1h1Zm2 0v1h-1v-1h1Zm-8 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm-2 0v1h-1v-1h1Zm8 0v1h-1v-1h1Zm-10 0v1h-1v-1h1Z\"/><path d=\"M10 7.5H2a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2ZM10 9a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-6A.5.5 0 0 1 2 9h8Z\"/></svg>";
2903
+
2904
+ var pencil = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m7.3 17.37-.061.088a1.518 1.518 0 0 1-.934.535l-4.178.663-.806-4.153a1.495 1.495 0 0 1 .187-1.058l.056-.086L8.77 2.639c.958-1.351 2.803-1.076 4.296-.03 1.497 1.047 2.387 2.693 1.433 4.055L7.3 17.37zM9.14 4.728l-5.545 8.346 3.277 2.294 5.544-8.346L9.14 4.728zM6.07 16.512l-3.276-2.295.53 2.73 2.746-.435zM9.994 3.506 13.271 5.8c.316-.452-.16-1.333-1.065-1.966-.905-.634-1.895-.78-2.212-.328zM8 18.5 9.375 17H19v1.5H8z\"/></svg>";
2905
+
2906
+ var pilcrow = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.999 2H15a1 1 0 0 1 0 2h-1.004v13a1 1 0 1 1-2 0V4H8.999v13a1 1 0 1 1-2 0v-7A4 4 0 0 1 3 6a4 4 0 0 1 3.999-4z\"/></svg>";
2907
+
2908
+ var quote = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 10.423a6.5 6.5 0 0 1 6.056-6.408l.038.67C6.448 5.423 5.354 7.663 5.22 10H9c.552 0 .5.432.5.986v4.511c0 .554-.448.503-1 .503h-5c-.552 0-.5-.449-.5-1.003v-4.574zm8 0a6.5 6.5 0 0 1 6.056-6.408l.038.67c-2.646.739-3.74 2.979-3.873 5.315H17c.552 0 .5.432.5.986v4.511c0 .554-.448.503-1 .503h-5c-.552 0-.5-.449-.5-1.003v-4.574z\"/></svg>";
2909
+
2910
+ var threeVerticalDots = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"9.5\" cy=\"4.5\" r=\"1.5\"/><circle cx=\"9.5\" cy=\"10.5\" r=\"1.5\"/><circle cx=\"9.5\" cy=\"16.5\" r=\"1.5\"/></svg>";
2911
+
2912
+ var dragIndicator = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 3.25a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/><path d=\"M12 3.25a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/><path d=\"M5 10a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/><path d=\"M12 10a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/><path d=\"M5 16.75a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/><path d=\"M12 16.75a1.5 1.5 0 1 0 3 0 1.5 1.5 0 1 0-3 0\"/></svg>";
2913
+
2914
+ var bold = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.187 17H5.773c-.637 0-1.092-.138-1.364-.415-.273-.277-.409-.718-.409-1.323V4.738c0-.617.14-1.062.419-1.332.279-.27.73-.406 1.354-.406h4.68c.69 0 1.288.041 1.793.124.506.083.96.242 1.36.478.341.197.644.447.906.75a3.262 3.262 0 0 1 .808 2.162c0 1.401-.722 2.426-2.167 3.075C15.05 10.175 16 11.315 16 13.01a3.756 3.756 0 0 1-2.296 3.504 6.1 6.1 0 0 1-1.517.377c-.571.073-1.238.11-2 .11zm-.217-6.217H7v4.087h3.069c1.977 0 2.965-.69 2.965-2.072 0-.707-.256-1.22-.768-1.537-.512-.319-1.277-.478-2.296-.478zM7 5.13v3.619h2.606c.729 0 1.292-.067 1.69-.2a1.6 1.6 0 0 0 .91-.765c.165-.267.247-.566.247-.897 0-.707-.26-1.176-.778-1.409-.519-.232-1.31-.348-2.375-.348H7z\"/></svg>";
2915
+
2916
+ var paragraph = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.5 5.5H7v5h3.5a2.5 2.5 0 1 0 0-5zM5 3h6.5v.025a5 5 0 0 1 0 9.95V13H7v4a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z\"/></svg>";
2917
+
2918
+ var plus = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 2a1 1 0 0 0-1 1v6H3a1 1 0 1 0 0 2h6v6a1 1 0 1 0 2 0v-6h6a1 1 0 1 0 0-2h-6V3a1 1 0 0 0-1-1Z\"/></svg>";
2919
+
2920
+ var text = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.816 11.5 7.038 4.785 4.261 11.5h5.555Zm.62 1.5H3.641l-1.666 4.028H.312l5.789-14h1.875l5.789 14h-1.663L10.436 13Z\"/><path d=\"m12.09 17-.534-1.292.848-1.971.545 1.319L12.113 17h-.023Zm1.142-5.187.545 1.319L15.5 9.13l1.858 4.316h-3.45l.398.965h3.467L18.887 17H20l-3.873-9h-1.254l-1.641 3.813Z\"/></svg>";
2921
+
2922
+ var importExport = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 4.5 14 0H3v12.673l.868-1.041c.185-.222.4-.402.632-.54V1.5h8v5h5v7.626a2.24 2.24 0 0 1 1.5.822V4.5ZM14 5V2l3.3 3H14Zm-3.692 12.5c.062.105.133.206.213.303L11.52 19H8v-.876a2.243 2.243 0 0 0 1.82-.624h.488Zm7.518-.657a.75.75 0 0 0-1.152-.96L15.5 17.29V12H14v5.29l-1.174-1.408a.75.75 0 0 0-1.152.96l2.346 2.816a.95.95 0 0 0 1.46 0l2.346-2.815Zm-15.056-.38a.75.75 0 0 1-.096-1.056l2.346-2.815a.95.95 0 0 1 1.46 0l2.346 2.815a.75.75 0 1 1-1.152.96L6.5 14.96V20H5v-5.04l-1.174 1.408a.75.75 0 0 1-1.056.096Z\"/></svg>";
2923
+
2924
+ var redo = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m14.958 9.367-2.189 1.837a.75.75 0 0 0 .965 1.149l3.788-3.18a.747.747 0 0 0 .21-.284.75.75 0 0 0-.17-.945L13.77 4.762a.75.75 0 1 0-.964 1.15l2.331 1.955H6.22A.75.75 0 0 0 6 7.9a4 4 0 1 0 1.477 7.718l-.344-1.489A2.5 2.5 0 1 1 6.039 9.4l-.008-.032h8.927z\"/></svg>";
2925
+
2926
+ var undo = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m5.042 9.367 2.189 1.837a.75.75 0 0 1-.965 1.149l-3.788-3.18a.747.747 0 0 1-.21-.284.75.75 0 0 1 .17-.945L6.23 4.762a.75.75 0 1 1 .964 1.15L4.863 7.866h8.917A.75.75 0 0 1 14 7.9a4 4 0 1 1-1.477 7.718l.344-1.489a2.5 2.5 0 1 0 1.094-4.73l.008-.032H5.042z\"/></svg>";
2927
+
2928
+ var bulletedList = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 5.75c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zm-6 0C1 4.784 1.777 4 2.75 4c.966 0 1.75.777 1.75 1.75 0 .966-.777 1.75-1.75 1.75C1.784 7.5 1 6.723 1 5.75zm6 9c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zm-6 0c0-.966.777-1.75 1.75-1.75.966 0 1.75.777 1.75 1.75 0 .966-.777 1.75-1.75 1.75-.966 0-1.75-.777-1.75-1.75z\"/></svg>";
2929
+
2930
+ var numberedList = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 5.75c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zM3.5 3v5H2V3.7H1v-1h2.5V3zM.343 17.857l2.59-3.257H2.92a.6.6 0 1 0-1.04 0H.302a2 2 0 1 1 3.995 0h-.001c-.048.405-.16.734-.333.988-.175.254-.59.692-1.244 1.312H4.3v1h-4l.043-.043zM7 14.75a.75.75 0 0 1 .75-.75h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75z\"/></svg>";
2931
+
2932
+ var todoList = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m2.315 14.705 2.224-2.24a.689.689 0 0 1 .963 0 .664.664 0 0 1 0 .949L2.865 16.07a.682.682 0 0 1-.112.089.647.647 0 0 1-.852-.051L.688 14.886a.635.635 0 0 1 0-.903.647.647 0 0 1 .91 0l.717.722zm5.185.045a.75.75 0 0 1 .75-.75h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75zM2.329 5.745l2.21-2.226a.689.689 0 0 1 .963 0 .664.664 0 0 1 0 .95L2.865 7.125a.685.685 0 0 1-.496.196.644.644 0 0 1-.468-.187L.688 5.912a.635.635 0 0 1 0-.903.647.647 0 0 1 .91 0l.73.736zM7.5 5.75A.75.75 0 0 1 8.25 5h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75z\"/></svg>";
2933
+
2934
+ var codeBlock = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.87 12.61a.75.75 0 0 1-.089.976l-.085.07-3.154 2.254 3.412 2.414a.75.75 0 0 1 .237.95l-.057.095a.75.75 0 0 1-.95.237l-.096-.058-4.272-3.022-.003-1.223 4.01-2.867a.75.75 0 0 1 1.047.174zm2.795-.231.095.057 4.011 2.867-.003 1.223-4.272 3.022-.095.058a.75.75 0 0 1-.88-.151l-.07-.086-.058-.095a.75.75 0 0 1 .15-.88l.087-.07 3.412-2.414-3.154-2.253-.085-.071a.75.75 0 0 1 .862-1.207zM16 0a2 2 0 0 1 2 2v9.354l-.663-.492-.837-.001V2a.5.5 0 0 0-.5-.5H2a.5.5 0 0 0-.5.5v15a.5.5 0 0 0 .5.5h3.118L7.156 19H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h14zM5.009 15l.003 1H3v-1h2.009zm2.188-2-1.471 1H5v-1h2.197zM10 11v.095L8.668 12H7v-1h3zm4-2v1H7V9h7zm0-2v1H7V7h7zm-4-2v1H5V5h5zM6 3v1H3V3h3z\"/></svg>";
2935
+
2936
+ var browseFiles = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.627 16.5zm5.873-.196zm0-7.001V8h-13v8.5h4.341c.191.54.457 1.044.785 1.5H2a1.5 1.5 0 0 1-1.5-1.5v-13A1.5 1.5 0 0 1 2 2h4.5a1.5 1.5 0 0 1 1.06.44L9.122 4H16a1.5 1.5 0 0 1 1.5 1.5v1A1.5 1.5 0 0 1 19 8v2.531a6.027 6.027 0 0 0-1.5-1.228zM16 6.5v-1H8.5l-2-2H2v13h1V8a1.5 1.5 0 0 1 1.5-1.5H16z\"/><path d=\"M14.5 19.5a5 5 0 1 1 0-10 5 5 0 0 1 0 10zM15 14v-2h-1v2h-2v1h2v2h1v-2h2v-1h-2z\"/></svg>";
2937
+
2938
+ var heading1 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 9v10h-2v-8h-2V9h4zM4 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1H10a1 1 0 0 1-1-1V11H4v4.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1H3a1 1 0 0 1 1 1v4.5z\"/></svg>";
2939
+
2940
+ var heading2 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V11H3v4.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1H2a1 1 0 0 1 1 1v4.5zm16.076 8.343V18.5h-6.252c.067-.626.27-1.22.61-1.78.338-.561 1.006-1.305 2.005-2.232.804-.749 1.297-1.257 1.479-1.523.245-.368.368-.732.368-1.092 0-.398-.107-.703-.32-.917-.214-.214-.51-.32-.886-.32-.372 0-.669.111-.889.336-.22.224-.347.596-.38 1.117l-1.778-.178c.106-.982.438-1.686.997-2.114.558-.427 1.257-.64 2.095-.64.918 0 1.64.247 2.164.742.525.495.787 1.11.787 1.847 0 .419-.075.818-.225 1.197-.15.378-.388.775-.714 1.19-.216.275-.605.67-1.168 1.187-.563.516-.92.859-1.07 1.028a3.11 3.11 0 0 0-.365.495h3.542z\"/></svg>";
2941
+
2942
+ var heading3 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V11H3v4.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1H2a1 1 0 0 1 1 1v4.5zm9.989 7.53 1.726-.209c.055.44.203.777.445 1.01.24.232.533.349.876.349.368 0 .678-.14.93-.42.251-.279.377-.655.377-1.13 0-.448-.12-.803-.362-1.066a1.153 1.153 0 0 0-.882-.393c-.228 0-.501.044-.819.133l.197-1.453c.482.012.85-.092 1.105-.315.253-.222.38-.517.38-.885 0-.313-.093-.563-.279-.75-.186-.185-.434-.278-.743-.278a1.07 1.07 0 0 0-.78.317c-.216.212-.347.52-.394.927l-1.644-.28c.114-.562.287-1.012.517-1.348.231-.337.553-.601.965-.794a3.24 3.24 0 0 1 1.387-.289c.876 0 1.579.28 2.108.838.436.457.653.973.653 1.549 0 .817-.446 1.468-1.339 1.955.533.114.96.37 1.28.768.319.398.478.878.478 1.441 0 .817-.298 1.513-.895 2.088-.596.576-1.339.864-2.228.864-.842 0-1.54-.243-2.094-.727-.555-.485-.876-1.118-.965-1.901z\"/></svg>";
2943
+
2944
+ var heading4 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V11h-5v4.5a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v4.5zm13.55 10v-1.873h-3.81v-1.561l4.037-5.91h1.498v5.904h1.156v1.567h-1.156V18.5H17.05zm0-3.44v-3.18l-2.14 3.18h2.14z\"/></svg>";
2945
+
2946
+ var heading5 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V11h-5v4.5a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v4.5zm9.578 7.607 1.777-.184c.05.402.201.72.45.955a1.223 1.223 0 0 0 1.81-.101c.258-.303.387-.759.387-1.368 0-.572-.128-1-.384-1.286-.256-.285-.59-.428-1-.428-.512 0-.971.226-1.377.679l-1.448-.21.915-4.843h4.716v1.67H15.56l-.28 1.58a2.697 2.697 0 0 1 1.219-.298 2.68 2.68 0 0 1 2.012.863c.55.576.825 1.323.825 2.241a3.36 3.36 0 0 1-.666 2.05c-.605.821-1.445 1.232-2.52 1.232-.86 0-1.56-.23-2.101-.692-.542-.461-.866-1.081-.971-1.86z\"/></svg>";
2947
+
2948
+ var heading6 = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 8.5h5V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v11.5a1 1 0 0 1-1 1h-.5a1 1 0 0 1-1-1V11h-5v4.5a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h.5a1 1 0 0 1 1 1v4.5zm15.595 2.973-1.726.19c-.043-.355-.153-.617-.33-.787-.178-.169-.409-.253-.692-.253-.377 0-.695.169-.956.507-.26.339-.424 1.043-.492 2.114.445-.525.997-.787 1.657-.787.745 0 1.383.284 1.914.85.531.568.797 1.3.797 2.197 0 .952-.28 1.716-.838 2.291-.559.576-1.276.864-2.152.864-.94 0-1.712-.365-2.317-1.095-.605-.73-.908-1.927-.908-3.59 0-1.705.316-2.935.946-3.688.63-.753 1.45-1.13 2.457-1.13.706 0 1.291.198 1.755.594.463.395.758.97.885 1.723zm-4.043 3.891c0 .58.133 1.028.4 1.343.266.315.57.473.914.473.33 0 .605-.13.825-.388.22-.258.33-.68.33-1.27 0-.604-.118-1.047-.355-1.329a1.115 1.115 0 0 0-.89-.422c-.342 0-.632.134-.869.403s-.355.666-.355 1.19z\"/></svg>";
2949
+
2950
+ var horizontalLine = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 9h16v2H2z\"/></svg>";
2951
+
2952
+ var html = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17 0a2 2 0 0 1 2 2v7a1 1 0 0 1 1 1v5a1 1 0 0 1-.883.993l-.118.006L19 17a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2l-.001-1.001-.116-.006A1 1 0 0 1 0 15v-5a1 1 0 0 1 .999-1L1 2a2 2 0 0 1 2-2h14zm.499 15.999h-15L2.5 17a.5.5 0 0 0 .5.5h14a.5.5 0 0 0 .5-.5l-.001-1.001zm-3.478-6.013-.014.014H14v.007l-1.525 1.525-1.46-1.46-.015.013V10h-1v5h1v-3.53l1.428 1.43.048.043.131-.129L14 11.421V15h1v-5h-.965l-.014-.014zM2 10H1v5h1v-2h2v2h1v-5H4v2H2v-2zm7 0H6v1h1v4h1v-4h1v-1zm8 0h-1v5h3v-1h-2v-4zm0-8.5H3a.5.5 0 0 0-.5.5l-.001 6.999h15L17.5 2a.5.5 0 0 0-.5-.5zM10 7v1H4V7h6zm3-2v1H4V5h9zm-3-2v1H4V3h6z\"/></svg>";
2953
+
2954
+ var indent = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3.75c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm5 6c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zM2.75 16.5h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 1 0 0 1.5zM1.632 6.95 5.02 9.358a.4.4 0 0 1-.013.661l-3.39 2.207A.4.4 0 0 1 1 11.892V7.275a.4.4 0 0 1 .632-.326z\"/></svg>";
2955
+
2956
+ var outdent = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2 3.75c0 .414.336.75.75.75h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 0 0-.75.75zm5 6c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zM2.75 16.5h14.5a.75.75 0 1 0 0-1.5H2.75a.75.75 0 1 0 0 1.5zm1.618-9.55L.98 9.358a.4.4 0 0 0 .013.661l3.39 2.207A.4.4 0 0 0 5 11.892V7.275a.4.4 0 0 0-.632-.326z\"/></svg>";
2957
+
2958
+ var table = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 5.5v3h4v-3H3Zm0 4v3h4v-3H3Zm0 4v3h4v-3H3Zm5 3h4v-3H8v3Zm5 0h4v-3h-4v3Zm4-4v-3h-4v3h4Zm0-4v-3h-4v3h4Zm1.5 8A1.5 1.5 0 0 1 17 18H3a1.5 1.5 0 0 1-1.5-1.5V3c.222-.863 1.068-1.5 2-1.5h13c.932 0 1.778.637 2 1.5v13.5Zm-6.5-4v-3H8v3h4Zm0-4v-3H8v3h4Z\"/></svg>";
2959
+
2960
+ const icons = {
2961
+ bold,
2962
+ cancel,
2963
+ caption,
2964
+ check,
2965
+ cog,
2966
+ colorPalette,
2967
+ eraser,
2968
+ history,
2969
+ image,
2970
+ imageUpload,
2971
+ imageAssetManager,
2972
+ imageUrl,
2973
+ lowVision,
2974
+ textAlternative,
2975
+ loupe,
2976
+ previousArrow,
2977
+ nextArrow,
2978
+ importExport,
2979
+ paragraph,
2980
+ plus,
2981
+ text,
2982
+ alignBottom,
2983
+ alignMiddle,
2984
+ alignTop,
2985
+ alignLeft,
2986
+ alignCenter,
2987
+ alignRight,
2988
+ alignJustify,
2989
+ objectLeft,
2990
+ objectCenter,
2991
+ objectRight,
2992
+ objectFullWidth,
2993
+ objectInline,
2994
+ objectBlockLeft,
2995
+ objectBlockRight,
2996
+ objectSizeCustom,
2997
+ objectSizeFull,
2998
+ objectSizeLarge,
2999
+ objectSizeSmall,
3000
+ objectSizeMedium,
3001
+ pencil,
3002
+ pilcrow,
3003
+ quote,
3004
+ threeVerticalDots,
3005
+ dragIndicator,
3006
+ redo,
3007
+ undo,
3008
+ bulletedList,
3009
+ numberedList,
3010
+ todoList,
3011
+ codeBlock,
3012
+ browseFiles,
3013
+ heading1,
3014
+ heading2,
3015
+ heading3,
3016
+ heading4,
3017
+ heading5,
3018
+ heading6,
3019
+ horizontalLine,
3020
+ html,
3021
+ indent,
3022
+ outdent,
3023
+ table
3024
+ };
3025
+
3026
+ export { Command, Context, ContextPlugin, DataApiMixin, Editor, ElementApiMixin, MultiCommand, PendingActions, Plugin, attachToForm, icons, secureSourceElement };
3027
+ //# sourceMappingURL=index.js.map