@ckeditor/ckeditor5-engine 44.1.0-alpha.5 → 44.2.0-alpha.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 (369) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/index-content.css +2 -2
  3. package/dist/index-editor.css +2 -2
  4. package/dist/index.css +4 -4
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.js +646 -77
  7. package/dist/index.js.map +1 -1
  8. package/package.json +23 -3
  9. package/src/controller/datacontroller.d.ts +1 -1
  10. package/src/controller/datacontroller.js +1 -1
  11. package/src/controller/editingcontroller.d.ts +1 -1
  12. package/src/controller/editingcontroller.js +1 -1
  13. package/src/conversion/conversion.d.ts +1 -1
  14. package/src/conversion/conversion.js +1 -1
  15. package/src/conversion/conversionhelpers.d.ts +1 -1
  16. package/src/conversion/conversionhelpers.js +1 -1
  17. package/src/conversion/downcastdispatcher.d.ts +1 -1
  18. package/src/conversion/downcastdispatcher.js +1 -1
  19. package/src/conversion/downcasthelpers.d.ts +1 -1
  20. package/src/conversion/downcasthelpers.js +1 -1
  21. package/src/conversion/mapper.d.ts +249 -20
  22. package/src/conversion/mapper.js +524 -38
  23. package/src/conversion/modelconsumable.d.ts +1 -1
  24. package/src/conversion/modelconsumable.js +1 -1
  25. package/src/conversion/upcastdispatcher.d.ts +1 -1
  26. package/src/conversion/upcastdispatcher.js +1 -1
  27. package/src/conversion/upcasthelpers.d.ts +1 -1
  28. package/src/conversion/upcasthelpers.js +1 -1
  29. package/src/conversion/viewconsumable.d.ts +1 -1
  30. package/src/conversion/viewconsumable.js +1 -1
  31. package/src/dataprocessor/basichtmlwriter.d.ts +1 -1
  32. package/src/dataprocessor/basichtmlwriter.js +1 -1
  33. package/src/dataprocessor/dataprocessor.d.ts +1 -1
  34. package/src/dataprocessor/dataprocessor.js +1 -1
  35. package/src/dataprocessor/htmldataprocessor.d.ts +1 -1
  36. package/src/dataprocessor/htmldataprocessor.js +1 -1
  37. package/src/dataprocessor/htmlwriter.d.ts +1 -1
  38. package/src/dataprocessor/htmlwriter.js +1 -1
  39. package/src/dataprocessor/xmldataprocessor.d.ts +1 -1
  40. package/src/dataprocessor/xmldataprocessor.js +1 -1
  41. package/src/dev-utils/model.d.ts +1 -1
  42. package/src/dev-utils/model.js +1 -1
  43. package/src/dev-utils/operationreplayer.d.ts +1 -1
  44. package/src/dev-utils/operationreplayer.js +1 -1
  45. package/src/dev-utils/utils.d.ts +1 -1
  46. package/src/dev-utils/utils.js +1 -1
  47. package/src/dev-utils/view.d.ts +1 -1
  48. package/src/dev-utils/view.js +1 -1
  49. package/src/index.d.ts +4 -2
  50. package/src/index.js +2 -1
  51. package/src/model/batch.d.ts +1 -1
  52. package/src/model/batch.js +7 -3
  53. package/src/model/differ.d.ts +1 -1
  54. package/src/model/differ.js +1 -1
  55. package/src/model/document.d.ts +1 -1
  56. package/src/model/document.js +1 -1
  57. package/src/model/documentfragment.d.ts +1 -1
  58. package/src/model/documentfragment.js +1 -1
  59. package/src/model/documentselection.d.ts +1 -1
  60. package/src/model/documentselection.js +1 -1
  61. package/src/model/element.d.ts +1 -1
  62. package/src/model/element.js +1 -1
  63. package/src/model/history.d.ts +1 -1
  64. package/src/model/history.js +1 -1
  65. package/src/model/item.d.ts +1 -1
  66. package/src/model/item.js +1 -1
  67. package/src/model/liveposition.d.ts +1 -1
  68. package/src/model/liveposition.js +1 -1
  69. package/src/model/liverange.d.ts +1 -1
  70. package/src/model/liverange.js +1 -1
  71. package/src/model/markercollection.d.ts +1 -1
  72. package/src/model/markercollection.js +1 -1
  73. package/src/model/model.d.ts +1 -1
  74. package/src/model/model.js +1 -1
  75. package/src/model/node.d.ts +1 -1
  76. package/src/model/node.js +1 -1
  77. package/src/model/nodelist.d.ts +1 -1
  78. package/src/model/nodelist.js +1 -1
  79. package/src/model/operation/attributeoperation.d.ts +1 -1
  80. package/src/model/operation/attributeoperation.js +1 -1
  81. package/src/model/operation/detachoperation.d.ts +1 -1
  82. package/src/model/operation/detachoperation.js +1 -1
  83. package/src/model/operation/insertoperation.d.ts +1 -1
  84. package/src/model/operation/insertoperation.js +1 -1
  85. package/src/model/operation/markeroperation.d.ts +1 -1
  86. package/src/model/operation/markeroperation.js +1 -1
  87. package/src/model/operation/mergeoperation.d.ts +1 -1
  88. package/src/model/operation/mergeoperation.js +1 -1
  89. package/src/model/operation/moveoperation.d.ts +1 -1
  90. package/src/model/operation/moveoperation.js +1 -1
  91. package/src/model/operation/nooperation.d.ts +1 -1
  92. package/src/model/operation/nooperation.js +1 -1
  93. package/src/model/operation/operation.d.ts +4 -1
  94. package/src/model/operation/operation.js +2 -2
  95. package/src/model/operation/operationfactory.d.ts +1 -1
  96. package/src/model/operation/operationfactory.js +1 -1
  97. package/src/model/operation/renameoperation.d.ts +1 -1
  98. package/src/model/operation/renameoperation.js +1 -1
  99. package/src/model/operation/rootattributeoperation.d.ts +1 -1
  100. package/src/model/operation/rootattributeoperation.js +1 -1
  101. package/src/model/operation/rootoperation.d.ts +1 -1
  102. package/src/model/operation/rootoperation.js +1 -1
  103. package/src/model/operation/splitoperation.d.ts +1 -1
  104. package/src/model/operation/splitoperation.js +1 -1
  105. package/src/model/operation/transform.d.ts +1 -1
  106. package/src/model/operation/transform.js +1 -1
  107. package/src/model/operation/utils.d.ts +1 -1
  108. package/src/model/operation/utils.js +1 -1
  109. package/src/model/position.d.ts +1 -1
  110. package/src/model/position.js +1 -1
  111. package/src/model/range.d.ts +1 -1
  112. package/src/model/range.js +1 -1
  113. package/src/model/rootelement.d.ts +1 -1
  114. package/src/model/rootelement.js +1 -1
  115. package/src/model/schema.d.ts +1 -1
  116. package/src/model/schema.js +1 -1
  117. package/src/model/selection.d.ts +1 -1
  118. package/src/model/selection.js +9 -2
  119. package/src/model/text.d.ts +1 -1
  120. package/src/model/text.js +1 -1
  121. package/src/model/textproxy.d.ts +1 -1
  122. package/src/model/textproxy.js +1 -1
  123. package/src/model/treewalker.d.ts +17 -1
  124. package/src/model/treewalker.js +26 -1
  125. package/src/model/typecheckable.d.ts +1 -1
  126. package/src/model/typecheckable.js +1 -1
  127. package/src/model/utils/autoparagraphing.d.ts +1 -1
  128. package/src/model/utils/autoparagraphing.js +1 -1
  129. package/src/model/utils/deletecontent.d.ts +1 -1
  130. package/src/model/utils/deletecontent.js +1 -1
  131. package/src/model/utils/getselectedcontent.d.ts +1 -1
  132. package/src/model/utils/getselectedcontent.js +1 -1
  133. package/src/model/utils/insertcontent.d.ts +1 -1
  134. package/src/model/utils/insertcontent.js +1 -1
  135. package/src/model/utils/insertobject.d.ts +1 -1
  136. package/src/model/utils/insertobject.js +1 -1
  137. package/src/model/utils/modifyselection.d.ts +1 -1
  138. package/src/model/utils/modifyselection.js +1 -1
  139. package/src/model/utils/selection-post-fixer.d.ts +1 -1
  140. package/src/model/utils/selection-post-fixer.js +1 -1
  141. package/src/model/writer.d.ts +1 -1
  142. package/src/model/writer.js +1 -1
  143. package/src/view/attributeelement.d.ts +1 -1
  144. package/src/view/attributeelement.js +1 -1
  145. package/src/view/containerelement.d.ts +1 -1
  146. package/src/view/containerelement.js +1 -1
  147. package/src/view/datatransfer.d.ts +1 -1
  148. package/src/view/datatransfer.js +1 -1
  149. package/src/view/document.d.ts +1 -1
  150. package/src/view/document.js +1 -1
  151. package/src/view/documentfragment.d.ts +6 -4
  152. package/src/view/documentfragment.js +7 -7
  153. package/src/view/documentselection.d.ts +1 -1
  154. package/src/view/documentselection.js +1 -1
  155. package/src/view/domconverter.d.ts +1 -1
  156. package/src/view/domconverter.js +1 -1
  157. package/src/view/downcastwriter.d.ts +1 -1
  158. package/src/view/downcastwriter.js +1 -1
  159. package/src/view/editableelement.d.ts +1 -1
  160. package/src/view/editableelement.js +1 -1
  161. package/src/view/element.d.ts +1 -1
  162. package/src/view/element.js +3 -3
  163. package/src/view/elementdefinition.d.ts +1 -1
  164. package/src/view/elementdefinition.js +1 -1
  165. package/src/view/emptyelement.d.ts +1 -1
  166. package/src/view/emptyelement.js +1 -1
  167. package/src/view/filler.d.ts +1 -1
  168. package/src/view/filler.js +1 -1
  169. package/src/view/item.d.ts +1 -1
  170. package/src/view/item.js +1 -1
  171. package/src/view/matcher.d.ts +1 -1
  172. package/src/view/matcher.js +1 -1
  173. package/src/view/node.d.ts +13 -4
  174. package/src/view/node.js +5 -4
  175. package/src/view/observer/arrowkeysobserver.d.ts +1 -1
  176. package/src/view/observer/arrowkeysobserver.js +1 -1
  177. package/src/view/observer/bubblingemittermixin.d.ts +1 -1
  178. package/src/view/observer/bubblingemittermixin.js +1 -1
  179. package/src/view/observer/bubblingeventinfo.d.ts +1 -1
  180. package/src/view/observer/bubblingeventinfo.js +1 -1
  181. package/src/view/observer/clickobserver.d.ts +1 -1
  182. package/src/view/observer/clickobserver.js +1 -1
  183. package/src/view/observer/compositionobserver.d.ts +1 -1
  184. package/src/view/observer/compositionobserver.js +1 -1
  185. package/src/view/observer/domeventdata.d.ts +1 -1
  186. package/src/view/observer/domeventdata.js +1 -1
  187. package/src/view/observer/domeventobserver.d.ts +1 -1
  188. package/src/view/observer/domeventobserver.js +1 -1
  189. package/src/view/observer/fakeselectionobserver.d.ts +1 -1
  190. package/src/view/observer/fakeselectionobserver.js +1 -1
  191. package/src/view/observer/focusobserver.d.ts +1 -1
  192. package/src/view/observer/focusobserver.js +1 -1
  193. package/src/view/observer/inputobserver.d.ts +1 -1
  194. package/src/view/observer/inputobserver.js +1 -1
  195. package/src/view/observer/keyobserver.d.ts +1 -1
  196. package/src/view/observer/keyobserver.js +1 -1
  197. package/src/view/observer/mouseobserver.d.ts +1 -1
  198. package/src/view/observer/mouseobserver.js +1 -1
  199. package/src/view/observer/mutationobserver.d.ts +1 -1
  200. package/src/view/observer/mutationobserver.js +1 -1
  201. package/src/view/observer/observer.d.ts +1 -1
  202. package/src/view/observer/observer.js +1 -1
  203. package/src/view/observer/selectionobserver.d.ts +1 -1
  204. package/src/view/observer/selectionobserver.js +1 -1
  205. package/src/view/observer/tabobserver.d.ts +1 -1
  206. package/src/view/observer/tabobserver.js +1 -1
  207. package/src/view/observer/touchobserver.d.ts +73 -0
  208. package/src/view/observer/touchobserver.js +29 -0
  209. package/src/view/placeholder.d.ts +1 -1
  210. package/src/view/placeholder.js +23 -17
  211. package/src/view/position.d.ts +1 -1
  212. package/src/view/position.js +1 -1
  213. package/src/view/range.d.ts +1 -1
  214. package/src/view/range.js +1 -1
  215. package/src/view/rawelement.d.ts +1 -1
  216. package/src/view/rawelement.js +1 -1
  217. package/src/view/renderer.d.ts +1 -1
  218. package/src/view/renderer.js +1 -1
  219. package/src/view/rooteditableelement.d.ts +1 -1
  220. package/src/view/rooteditableelement.js +1 -1
  221. package/src/view/selection.d.ts +1 -1
  222. package/src/view/selection.js +1 -1
  223. package/src/view/styles/background.d.ts +1 -1
  224. package/src/view/styles/background.js +1 -1
  225. package/src/view/styles/border.d.ts +1 -1
  226. package/src/view/styles/border.js +1 -1
  227. package/src/view/styles/margin.d.ts +1 -1
  228. package/src/view/styles/margin.js +1 -1
  229. package/src/view/styles/padding.d.ts +1 -1
  230. package/src/view/styles/padding.js +1 -1
  231. package/src/view/styles/utils.d.ts +1 -1
  232. package/src/view/styles/utils.js +1 -1
  233. package/src/view/stylesmap.d.ts +1 -1
  234. package/src/view/stylesmap.js +1 -1
  235. package/src/view/text.d.ts +1 -1
  236. package/src/view/text.js +1 -1
  237. package/src/view/textproxy.d.ts +1 -1
  238. package/src/view/textproxy.js +1 -1
  239. package/src/view/treewalker.d.ts +17 -1
  240. package/src/view/treewalker.js +25 -1
  241. package/src/view/typecheckable.d.ts +1 -1
  242. package/src/view/typecheckable.js +1 -1
  243. package/src/view/uielement.d.ts +1 -1
  244. package/src/view/uielement.js +1 -1
  245. package/src/view/upcastwriter.d.ts +1 -1
  246. package/src/view/upcastwriter.js +1 -1
  247. package/src/view/view.d.ts +1 -1
  248. package/src/view/view.js +1 -1
  249. package/theme/placeholder.css +1 -1
  250. package/theme/renderer.css +1 -1
  251. package/dist/controller/datacontroller.d.ts +0 -339
  252. package/dist/controller/editingcontroller.d.ts +0 -102
  253. package/dist/conversion/conversion.d.ts +0 -482
  254. package/dist/conversion/conversionhelpers.d.ts +0 -30
  255. package/dist/conversion/downcastdispatcher.d.ts +0 -566
  256. package/dist/conversion/downcasthelpers.d.ts +0 -1194
  257. package/dist/conversion/mapper.d.ts +0 -507
  258. package/dist/conversion/modelconsumable.d.ts +0 -205
  259. package/dist/conversion/upcastdispatcher.d.ts +0 -496
  260. package/dist/conversion/upcasthelpers.d.ts +0 -503
  261. package/dist/conversion/viewconsumable.d.ts +0 -373
  262. package/dist/dataprocessor/basichtmlwriter.d.ts +0 -22
  263. package/dist/dataprocessor/dataprocessor.d.ts +0 -65
  264. package/dist/dataprocessor/htmldataprocessor.d.ts +0 -80
  265. package/dist/dataprocessor/htmlwriter.d.ts +0 -20
  266. package/dist/dataprocessor/xmldataprocessor.d.ts +0 -94
  267. package/dist/dev-utils/model.d.ts +0 -130
  268. package/dist/dev-utils/operationreplayer.d.ts +0 -55
  269. package/dist/dev-utils/utils.d.ts +0 -41
  270. package/dist/dev-utils/view.d.ts +0 -324
  271. package/dist/index.d.ts +0 -122
  272. package/dist/model/batch.d.ts +0 -110
  273. package/dist/model/differ.d.ts +0 -511
  274. package/dist/model/document.d.ts +0 -278
  275. package/dist/model/documentfragment.d.ts +0 -223
  276. package/dist/model/documentselection.d.ts +0 -424
  277. package/dist/model/element.d.ts +0 -191
  278. package/dist/model/history.d.ts +0 -118
  279. package/dist/model/item.d.ts +0 -18
  280. package/dist/model/liveposition.d.ts +0 -81
  281. package/dist/model/liverange.d.ts +0 -106
  282. package/dist/model/markercollection.d.ts +0 -339
  283. package/dist/model/model.d.ts +0 -923
  284. package/dist/model/node.d.ts +0 -262
  285. package/dist/model/nodelist.d.ts +0 -119
  286. package/dist/model/operation/attributeoperation.d.ts +0 -107
  287. package/dist/model/operation/detachoperation.d.ts +0 -64
  288. package/dist/model/operation/insertoperation.d.ts +0 -94
  289. package/dist/model/operation/markeroperation.d.ts +0 -95
  290. package/dist/model/operation/mergeoperation.d.ts +0 -104
  291. package/dist/model/operation/moveoperation.d.ts +0 -100
  292. package/dist/model/operation/nooperation.d.ts +0 -42
  293. package/dist/model/operation/operation.d.ts +0 -100
  294. package/dist/model/operation/operationfactory.d.ts +0 -22
  295. package/dist/model/operation/renameoperation.d.ts +0 -87
  296. package/dist/model/operation/rootattributeoperation.d.ts +0 -102
  297. package/dist/model/operation/rootoperation.d.ts +0 -80
  298. package/dist/model/operation/splitoperation.d.ts +0 -113
  299. package/dist/model/operation/transform.d.ts +0 -104
  300. package/dist/model/operation/utils.d.ts +0 -75
  301. package/dist/model/position.d.ts +0 -549
  302. package/dist/model/range.d.ts +0 -462
  303. package/dist/model/rootelement.d.ts +0 -64
  304. package/dist/model/schema.d.ts +0 -1334
  305. package/dist/model/selection.d.ts +0 -486
  306. package/dist/model/text.d.ts +0 -70
  307. package/dist/model/textproxy.d.ts +0 -148
  308. package/dist/model/treewalker.d.ts +0 -190
  309. package/dist/model/typecheckable.d.ts +0 -289
  310. package/dist/model/utils/autoparagraphing.d.ts +0 -41
  311. package/dist/model/utils/deletecontent.d.ts +0 -62
  312. package/dist/model/utils/getselectedcontent.d.ts +0 -34
  313. package/dist/model/utils/insertcontent.d.ts +0 -50
  314. package/dist/model/utils/insertobject.d.ts +0 -51
  315. package/dist/model/utils/modifyselection.d.ts +0 -52
  316. package/dist/model/utils/selection-post-fixer.d.ts +0 -78
  317. package/dist/model/writer.d.ts +0 -855
  318. package/dist/view/attributeelement.d.ts +0 -112
  319. package/dist/view/containerelement.d.ts +0 -53
  320. package/dist/view/datatransfer.d.ts +0 -83
  321. package/dist/view/document.d.ts +0 -188
  322. package/dist/view/documentfragment.d.ts +0 -157
  323. package/dist/view/documentselection.d.ts +0 -310
  324. package/dist/view/domconverter.d.ts +0 -665
  325. package/dist/view/downcastwriter.d.ts +0 -1000
  326. package/dist/view/editableelement.d.ts +0 -66
  327. package/dist/view/element.d.ts +0 -472
  328. package/dist/view/elementdefinition.d.ts +0 -91
  329. package/dist/view/emptyelement.d.ts +0 -45
  330. package/dist/view/filler.d.ts +0 -115
  331. package/dist/view/item.d.ts +0 -18
  332. package/dist/view/matcher.d.ts +0 -490
  333. package/dist/view/node.d.ts +0 -166
  334. package/dist/view/observer/arrowkeysobserver.d.ts +0 -49
  335. package/dist/view/observer/bubblingemittermixin.d.ts +0 -170
  336. package/dist/view/observer/bubblingeventinfo.d.ts +0 -51
  337. package/dist/view/observer/clickobserver.d.ts +0 -47
  338. package/dist/view/observer/compositionobserver.d.ts +0 -86
  339. package/dist/view/observer/domeventdata.d.ts +0 -54
  340. package/dist/view/observer/domeventobserver.d.ts +0 -82
  341. package/dist/view/observer/fakeselectionobserver.d.ts +0 -51
  342. package/dist/view/observer/focusobserver.d.ts +0 -98
  343. package/dist/view/observer/inputobserver.d.ts +0 -90
  344. package/dist/view/observer/keyobserver.d.ts +0 -70
  345. package/dist/view/observer/mouseobserver.d.ts +0 -93
  346. package/dist/view/observer/mutationobserver.d.ts +0 -119
  347. package/dist/view/observer/observer.d.ts +0 -93
  348. package/dist/view/observer/selectionobserver.d.ts +0 -151
  349. package/dist/view/observer/tabobserver.d.ts +0 -50
  350. package/dist/view/placeholder.d.ts +0 -100
  351. package/dist/view/position.d.ts +0 -192
  352. package/dist/view/range.d.ts +0 -283
  353. package/dist/view/rawelement.d.ts +0 -77
  354. package/dist/view/renderer.d.ts +0 -281
  355. package/dist/view/rooteditableelement.d.ts +0 -45
  356. package/dist/view/selection.d.ts +0 -379
  357. package/dist/view/styles/background.d.ts +0 -37
  358. package/dist/view/styles/border.d.ts +0 -47
  359. package/dist/view/styles/margin.d.ts +0 -33
  360. package/dist/view/styles/padding.d.ts +0 -33
  361. package/dist/view/styles/utils.d.ts +0 -97
  362. package/dist/view/stylesmap.d.ts +0 -685
  363. package/dist/view/text.d.ts +0 -78
  364. package/dist/view/textproxy.d.ts +0 -101
  365. package/dist/view/treewalker.d.ts +0 -199
  366. package/dist/view/typecheckable.d.ts +0 -452
  367. package/dist/view/uielement.d.ts +0 -100
  368. package/dist/view/upcastwriter.d.ts +0 -421
  369. package/dist/view/view.d.ts +0 -488
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
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
2
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
4
  */
5
5
  import { logWarning, EmitterMixin, CKEditorError, compareArrays, toArray, toMap, isIterable, ObservableMixin, count, EventInfo, Collection, keyCodes, isText, env, remove as remove$1, insertAt, diff, fastDiff, isNode, isComment, indexOf, global, isValidAttributeName, first, getAncestors, DomEmitterMixin, getCode, isArrowKeyCode, scrollViewportToShowTarget, uid, spliceArray, priorities, isInsideSurrogatePair, isInsideCombinedSymbol, isInsideEmojiSequence } from '@ckeditor/ckeditor5-utils/dist/index.js';
6
6
  import { clone, isObject, unset, get, merge, set, isPlainObject, extend, debounce, isEqualWith, cloneDeep, isEqual } from 'lodash-es';
@@ -28,23 +28,21 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
28
28
  * @param options.keepOnFocus If set `true`, the placeholder stay visible when the host element is focused.
29
29
  */ function enablePlaceholder({ view, element, text, isDirectHost = true, keepOnFocus = false }) {
30
30
  const doc = view.document;
31
- // Use a single a single post fixer per—document to update all placeholders.
31
+ // Use a single post fixer per—document to update all placeholders.
32
32
  if (!documentPlaceholders.has(doc)) {
33
33
  documentPlaceholders.set(doc, new Map());
34
34
  // If a post-fixer callback makes a change, it should return `true` so other post–fixers
35
35
  // can re–evaluate the document again.
36
- doc.registerPostFixer((writer)=>updateDocumentPlaceholders(doc, writer));
36
+ doc.registerPostFixer((writer)=>updateDocumentPlaceholders(documentPlaceholders.get(doc), writer));
37
37
  // Update placeholders on isComposing state change since rendering is disabled while in composition mode.
38
38
  doc.on('change:isComposing', ()=>{
39
- view.change((writer)=>updateDocumentPlaceholders(doc, writer));
39
+ view.change((writer)=>updateDocumentPlaceholders(documentPlaceholders.get(doc), writer));
40
40
  }, {
41
41
  priority: 'high'
42
42
  });
43
43
  }
44
44
  if (element.is('editableElement')) {
45
- element.on('change:placeholder', (evtInfo, evt, text)=>{
46
- setPlaceholder(text);
47
- });
45
+ element.on('change:placeholder', (evtInfo, evt, text)=>setPlaceholder(text));
48
46
  }
49
47
  if (element.placeholder) {
50
48
  setPlaceholder(element.placeholder);
@@ -55,15 +53,21 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
55
53
  showPlaceholderTextDeprecationWarning();
56
54
  }
57
55
  function setPlaceholder(text) {
58
- // Store information about the element placeholder under its document.
59
- documentPlaceholders.get(doc).set(element, {
56
+ const config = {
60
57
  text,
61
58
  isDirectHost,
62
59
  keepOnFocus,
63
60
  hostElement: isDirectHost ? element : null
64
- });
61
+ };
62
+ // Store information about the element placeholder under its document.
63
+ documentPlaceholders.get(doc).set(element, config);
65
64
  // Update the placeholders right away.
66
- view.change((writer)=>updateDocumentPlaceholders(doc, writer));
65
+ view.change((writer)=>updateDocumentPlaceholders([
66
+ [
67
+ element,
68
+ config
69
+ ]
70
+ ], writer));
67
71
  }
68
72
  }
69
73
  /**
@@ -138,9 +142,7 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
138
142
  if (!element.isAttached()) {
139
143
  return false;
140
144
  }
141
- // Anything but uiElement(s) counts as content.
142
- const hasContent = Array.from(element.getChildren()).some((element)=>!element.is('uiElement'));
143
- if (hasContent) {
145
+ if (hasContent(element)) {
144
146
  return false;
145
147
  }
146
148
  const doc = element.document;
@@ -160,12 +162,21 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
160
162
  // If document is focused and the element is empty but the selection is not anchored inside it.
161
163
  return !!selectionAnchor && selectionAnchor.parent !== element;
162
164
  }
165
+ /**
166
+ * Anything but uiElement(s) counts as content.
167
+ */ function hasContent(element) {
168
+ for (const child of element.getChildren()){
169
+ if (!child.is('uiElement')) {
170
+ return true;
171
+ }
172
+ }
173
+ return false;
174
+ }
163
175
  /**
164
176
  * Updates all placeholders associated with a document in a post–fixer callback.
165
177
  *
166
178
  * @returns True if any changes were made to the view document.
167
- */ function updateDocumentPlaceholders(doc, writer) {
168
- const placeholders = documentPlaceholders.get(doc);
179
+ */ function updateDocumentPlaceholders(placeholders, writer) {
169
180
  const directHostElements = [];
170
181
  let wasViewModified = false;
171
182
  // First set placeholders on the direct hosts.
@@ -254,7 +265,7 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
254
265
  }
255
266
 
256
267
  /**
257
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
268
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
258
269
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
259
270
  */ /**
260
271
  * @module engine/view/typecheckable
@@ -453,11 +464,12 @@ let hasDisplayedPlaceholderDeprecationWarning = false;
453
464
  * @internal
454
465
  * @param type Type of the change.
455
466
  * @param node Changed node.
467
+ * @param data Additional data.
456
468
  * @fires change
457
- */ _fireChange(type, node) {
458
- this.fire(`change:${type}`, node);
469
+ */ _fireChange(type, node, data) {
470
+ this.fire(`change:${type}`, node, data);
459
471
  if (this.parent) {
460
- this.parent._fireChange(type, node);
472
+ this.parent._fireChange(type, node, data);
461
473
  }
462
474
  }
463
475
  /**
@@ -2391,7 +2403,9 @@ TextProxy$1.prototype.is = function(type) {
2391
2403
  * @fires change
2392
2404
  * @returns Number of inserted nodes.
2393
2405
  */ _insertChild(index, items) {
2394
- this._fireChange('children', this);
2406
+ this._fireChange('children', this, {
2407
+ index
2408
+ });
2395
2409
  let count = 0;
2396
2410
  const nodes = normalize$3(this.document, items);
2397
2411
  for (const node of nodes){
@@ -2417,7 +2431,9 @@ TextProxy$1.prototype.is = function(type) {
2417
2431
  * @fires change
2418
2432
  * @returns The array of removed nodes.
2419
2433
  */ _removeChildren(index, howMany = 1) {
2420
- this._fireChange('children', this);
2434
+ this._fireChange('children', this, {
2435
+ index
2436
+ });
2421
2437
  for(let i = index; i < index + howMany; i++){
2422
2438
  this._children[i].parent = null;
2423
2439
  }
@@ -2889,6 +2905,28 @@ RootEditableElement.prototype.is = function(type, name) {
2889
2905
  this._position = prevPosition;
2890
2906
  }
2891
2907
  }
2908
+ /**
2909
+ * Moves tree walker {@link #position} to provided `position`. Tree walker will
2910
+ * continue traversing from that position.
2911
+ *
2912
+ * Note: in contrary to {@link ~TreeWalker#skip}, this method does not iterate over the nodes along the way.
2913
+ * It simply sets the current tree walker position to a new one.
2914
+ * From the performance standpoint, it is better to use {@link ~TreeWalker#jumpTo} rather than {@link ~TreeWalker#skip}.
2915
+ *
2916
+ * If the provided position is before the start boundary, the position will be
2917
+ * set to the start boundary. If the provided position is after the end boundary,
2918
+ * the position will be set to the end boundary.
2919
+ * This is done to prevent the treewalker from traversing outside the boundaries.
2920
+ *
2921
+ * @param position Position to jump to.
2922
+ */ jumpTo(position) {
2923
+ if (this._boundaryStartParent && position.isBefore(this.boundaries.start)) {
2924
+ position = this.boundaries.start;
2925
+ } else if (this._boundaryEndParent && position.isAfter(this.boundaries.end)) {
2926
+ position = this.boundaries.end;
2927
+ }
2928
+ this._position = position.clone();
2929
+ }
2892
2930
  /**
2893
2931
  * Gets the next tree walker's value.
2894
2932
  *
@@ -5493,7 +5531,9 @@ RawElement.prototype.is = function(type, name) {
5493
5531
  * @param items Items to be inserted.
5494
5532
  * @returns Number of inserted nodes.
5495
5533
  */ _insertChild(index, items) {
5496
- this._fireChange('children', this);
5534
+ this._fireChange('children', this, {
5535
+ index
5536
+ });
5497
5537
  let count = 0;
5498
5538
  const nodes = normalize$2(this.document, items);
5499
5539
  for (const node of nodes){
@@ -5516,20 +5556,22 @@ RawElement.prototype.is = function(type, name) {
5516
5556
  * @param howMany Number of nodes to remove.
5517
5557
  * @returns The array of removed nodes.
5518
5558
  */ _removeChildren(index, howMany = 1) {
5519
- this._fireChange('children', this);
5559
+ this._fireChange('children', this, {
5560
+ index
5561
+ });
5520
5562
  for(let i = index; i < index + howMany; i++){
5521
5563
  this._children[i].parent = null;
5522
5564
  }
5523
5565
  return this._children.splice(index, howMany);
5524
5566
  }
5525
5567
  /**
5526
- * Fires `change` event with given type of the change.
5527
- *
5528
5568
  * @internal
5529
5569
  * @param type Type of the change.
5530
5570
  * @param node Changed node.
5531
- */ _fireChange(type, node) {
5532
- this.fire('change:' + type, node);
5571
+ * @param data Additional data.
5572
+ * @fires module:engine/view/node~Node#event:change
5573
+ */ _fireChange(type, node, data) {
5574
+ this.fire(`change:${type}`, node, data);
5533
5575
  }
5534
5576
  /**
5535
5577
  * Sets a custom property. They can be used to add special data to elements.
@@ -10721,7 +10763,7 @@ function sameNodes(child1, child2) {
10721
10763
  }
10722
10764
 
10723
10765
  /**
10724
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
10766
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
10725
10767
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
10726
10768
  */ /**
10727
10769
  * @module engine/view/datatransfer
@@ -11538,7 +11580,7 @@ function getFiles(nativeDataTransfer) {
11538
11580
  }
11539
11581
 
11540
11582
  /**
11541
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
11583
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
11542
11584
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
11543
11585
  */ /**
11544
11586
  * @module engine/model/typecheckable
@@ -11848,6 +11890,29 @@ TextProxy.prototype.is = function(type) {
11848
11890
  this._visitedParent = prevVisitedParent;
11849
11891
  }
11850
11892
  }
11893
+ /**
11894
+ * Moves tree walker {@link #position} to provided `position`. Tree walker will
11895
+ * continue traversing from that position.
11896
+ *
11897
+ * Note: in contrary to {@link ~TreeWalker#skip}, this method does not iterate over the nodes along the way.
11898
+ * It simply sets the current tree walker position to a new one.
11899
+ * From the performance standpoint, it is better to use {@link ~TreeWalker#jumpTo} rather than {@link ~TreeWalker#skip}.
11900
+ *
11901
+ * If the provided position is before the start boundary, the position will be
11902
+ * set to the start boundary. If the provided position is after the end boundary,
11903
+ * the position will be set to the end boundary.
11904
+ * This is done to prevent the treewalker from traversing outside the boundaries.
11905
+ *
11906
+ * @param position Position to jump to.
11907
+ */ jumpTo(position) {
11908
+ if (this._boundaryStartParent && position.isBefore(this.boundaries.start)) {
11909
+ position = this.boundaries.start;
11910
+ } else if (this._boundaryEndParent && position.isAfter(this.boundaries.end)) {
11911
+ position = this.boundaries.end;
11912
+ }
11913
+ this._position = position.clone();
11914
+ this._visitedParent = position.parent;
11915
+ }
11851
11916
  /**
11852
11917
  * Gets the next tree walker's value.
11853
11918
  */ next() {
@@ -13861,6 +13926,9 @@ Range.prototype.is = function(type) {
13861
13926
  * Stores marker names of markers which have changed due to unbinding a view element (so it is assumed that the view element
13862
13927
  * has been removed, moved or renamed).
13863
13928
  */ _unboundMarkerNames = new Set();
13929
+ /**
13930
+ * Manages dynamic cache for the `Mapper` to improve the performance.
13931
+ */ _cache = new MapperCache();
13864
13932
  /**
13865
13933
  * Creates an instance of the mapper.
13866
13934
  */ constructor(){
@@ -13935,7 +14003,11 @@ Range.prototype.is = function(type) {
13935
14003
  if (options.defer) {
13936
14004
  this._deferredBindingRemovals.set(viewElement, viewElement.root);
13937
14005
  } else {
13938
- this._viewToModelMapping.delete(viewElement);
14006
+ const wasFound = this._viewToModelMapping.delete(viewElement);
14007
+ if (wasFound) {
14008
+ // Stop tracking after the element is no longer mapped. We want to track all mapped elements and only mapped elements.
14009
+ this._cache.stopTracking(viewElement);
14010
+ }
13939
14011
  if (this._modelToViewMapping.get(modelElement) == viewElement) {
13940
14012
  this._modelToViewMapping.delete(modelElement);
13941
14013
  }
@@ -13955,7 +14027,11 @@ Range.prototype.is = function(type) {
13955
14027
  const viewElement = this.toViewElement(modelElement);
13956
14028
  this._modelToViewMapping.delete(modelElement);
13957
14029
  if (this._viewToModelMapping.get(viewElement) == modelElement) {
13958
- this._viewToModelMapping.delete(viewElement);
14030
+ const wasFound = this._viewToModelMapping.delete(viewElement);
14031
+ if (wasFound) {
14032
+ // Stop tracking after the element is no longer mapped. We want to track all mapped elements and only mapped elements.
14033
+ this._cache.stopTracking(viewElement);
14034
+ }
13959
14035
  }
13960
14036
  }
13961
14037
  /**
@@ -14102,6 +14178,10 @@ Range.prototype.is = function(type) {
14102
14178
  return elements;
14103
14179
  }
14104
14180
  /**
14181
+ * **This method is deprecated and will be removed in one of the future CKEditor 5 releases.**
14182
+ *
14183
+ * **Using this method will turn off `Mapper` caching system and may degrade performance when operating on bigger documents.**
14184
+ *
14105
14185
  * Registers a callback that evaluates the length in the model of a view element with the given name.
14106
14186
  *
14107
14187
  * The callback is fired with one argument, which is a view element instance. The callback is expected to return
@@ -14131,6 +14211,7 @@ Range.prototype.is = function(type) {
14131
14211
  *
14132
14212
  * @param viewElementName Name of view element for which callback is registered.
14133
14213
  * @param lengthCallback Function return a length of view element instance in model.
14214
+ * @deprecated
14134
14215
  */ registerViewToModelLength(viewElementName, lengthCallback) {
14135
14216
  this._viewToModelLengthCallbacks.set(viewElementName, lengthCallback);
14136
14217
  }
@@ -14233,56 +14314,119 @@ Range.prototype.is = function(type) {
14233
14314
  return len;
14234
14315
  }
14235
14316
  /**
14236
- * Finds the position in the view node (or in its children) with the expected model offset.
14317
+ * Finds the position in a view element or view document fragment node (or in its children) with the expected model offset.
14237
14318
  *
14238
- * Example:
14319
+ * If the passed `viewContainer` is bound to model, `Mapper` will use caching mechanism to improve performance.
14239
14320
  *
14240
- * ```
14241
- * <p>fo<b>bar</b>bom</p> -> expected offset: 4
14321
+ * @param viewContainer Tree view element in which we are looking for the position.
14322
+ * @param modelOffset Expected offset.
14323
+ * @returns Found position.
14324
+ */ findPositionIn(viewContainer, modelOffset) {
14325
+ if (modelOffset === 0) {
14326
+ // Quickly return if asked for a position at the beginning of the container. No need to fire complex mechanisms to find it.
14327
+ return this._moveViewPositionToTextNode(new Position$1(viewContainer, 0));
14328
+ }
14329
+ // Use cache only if there are no custom view-to-model length callbacks and only for bound elements.
14330
+ // View-to-model length callbacks are deprecated and should be removed in one of the following releases.
14331
+ // Then it will be possible to simplify some logic inside `Mapper`.
14332
+ // Note: we could consider requiring `viewContainer` to be a mapped item.
14333
+ const useCache = this._viewToModelLengthCallbacks.size == 0 && this._viewToModelMapping.has(viewContainer);
14334
+ if (useCache) {
14335
+ const cacheItem = this._cache.getClosest(viewContainer, modelOffset);
14336
+ return this._findPositionStartingFrom(cacheItem.viewPosition, cacheItem.modelOffset, modelOffset, viewContainer, true);
14337
+ } else {
14338
+ return this._findPositionStartingFrom(new Position$1(viewContainer, 0), 0, modelOffset, viewContainer, false);
14339
+ }
14340
+ }
14341
+ /**
14342
+ * Performs most of the logic for `Mapper#findPositionIn()`.
14242
14343
  *
14243
- * findPositionIn( p, 4 ):
14244
- * <p>|fo<b>bar</b>bom</p> -> expected offset: 4, actual offset: 0
14245
- * <p>fo|<b>bar</b>bom</p> -> expected offset: 4, actual offset: 2
14246
- * <p>fo<b>bar</b>|bom</p> -> expected offset: 4, actual offset: 5 -> we are too far
14344
+ * It allows to start looking for the requested model offset from a given starting position, to enable caching. Using the cache,
14345
+ * you can set the starting point and skip all the calculations that were already previously done.
14247
14346
  *
14248
- * findPositionIn( b, 4 - ( 5 - 3 ) ):
14249
- * <p>fo<b>|bar</b>bom</p> -> expected offset: 2, actual offset: 0
14250
- * <p>fo<b>bar|</b>bom</p> -> expected offset: 2, actual offset: 3 -> we are too far
14347
+ * This method uses recursion to find positions inside deep structures. Example:
14251
14348
  *
14252
- * findPositionIn( bar, 2 - ( 3 - 3 ) ):
14253
- * We are in the text node so we can simple find the offset.
14254
- * <p>fo<b>ba|r</b>bom</p> -> expected offset: 2, actual offset: 2 -> position found
14255
14349
  * ```
14350
+ * <p>fo<b>bar</b>bom</p> -> target offset: 4
14351
+ * <p>|fo<b>bar</b>bom</p> -> target offset: 4, traversed offset: 0
14352
+ * <p>fo|<b>bar</b>bom</p> -> target offset: 4, traversed offset: 2
14353
+ * <p>fo<b>bar</b>|bom</p> -> target offset: 4, traversed offset: 5 -> we are too far, look recursively in <b>.
14256
14354
  *
14257
- * @param viewParent Tree view element in which we are looking for the position.
14258
- * @param expectedOffset Expected offset.
14259
- * @returns Found position.
14260
- */ findPositionIn(viewParent, expectedOffset) {
14261
- // Last scanned view node.
14262
- let viewNode;
14263
- // Length of the last scanned view node.
14264
- let lastLength = 0;
14265
- let modelOffset = 0;
14266
- let viewOffset = 0;
14355
+ * <p>fo<b>|bar</b>bom</p> -> target offset: 4, traversed offset: 2
14356
+ * <p>fo<b>bar|</b>bom</p> -> target offset: 4, traversed offset: 5 -> we are too far, look inside "bar".
14357
+ *
14358
+ * <p>fo<b>ba|r</b>bom</p> -> target offset: 4, traversed offset: 2 -> position is inside text node at offset 4-2 = 2.
14359
+ * ```
14360
+ *
14361
+ * @param startViewPosition View position to start looking from.
14362
+ * @param startModelOffset Model offset related to `startViewPosition`.
14363
+ * @param targetModelOffset Target model offset to find.
14364
+ * @param viewContainer Mapped ancestor of `startViewPosition`. `startModelOffset` is the offset inside a model element or model
14365
+ * document fragment mapped to `viewContainer`.
14366
+ * @param useCache Whether `Mapper` should cache positions while traversing the view tree looking for `expectedModelOffset`.
14367
+ * @returns View position mapped to `targetModelOffset`.
14368
+ */ _findPositionStartingFrom(startViewPosition, startModelOffset, targetModelOffset, viewContainer, useCache) {
14369
+ let viewParent = startViewPosition.parent;
14370
+ let viewOffset = startViewPosition.offset;
14267
14371
  // In the text node it is simple: the offset in the model equals the offset in the text.
14268
14372
  if (viewParent.is('$text')) {
14269
- return new Position$1(viewParent, expectedOffset);
14373
+ return new Position$1(viewParent, targetModelOffset - startModelOffset);
14270
14374
  }
14271
- // In other cases we add lengths of child nodes to find the proper offset.
14272
- // If it is smaller we add the length.
14273
- while(modelOffset < expectedOffset){
14375
+ // Last scanned view node.
14376
+ let viewNode;
14377
+ // Total model offset of the view nodes that were visited so far.
14378
+ let traversedModelOffset = startModelOffset;
14379
+ // Model length of the last traversed view node.
14380
+ let lastLength = 0;
14381
+ while(traversedModelOffset < targetModelOffset){
14274
14382
  viewNode = viewParent.getChild(viewOffset);
14383
+ if (!viewNode) {
14384
+ // If we still haven't reached the model offset, but we reached end of this `viewParent`, then we need to "leave" this
14385
+ // element and "go up", looking further for the target model offset. This can happen when cached model offset is "deeper"
14386
+ // but target model offset is "higher" in the view tree.
14387
+ //
14388
+ // Example: `<p>Foo<strong><em>Bar</em>^Baz</strong>Xyz</p>`
14389
+ //
14390
+ // Consider `^` is last cached position, when the `targetModelOffset` is `12`. In such case, we need to "go up" from
14391
+ // `<strong>` and continue traversing in `<p>`.
14392
+ //
14393
+ if (viewParent == viewContainer) {
14394
+ /**
14395
+ * A model position could not be mapped to the view because specified model offset was too big and could not be
14396
+ * found inside the mapped view element or view document fragment.
14397
+ *
14398
+ * @error mapping-model-offset-not-found
14399
+ */ throw new CKEditorError('mapping-model-offset-not-found', this, {
14400
+ modelOffset: targetModelOffset,
14401
+ viewContainer
14402
+ });
14403
+ } else {
14404
+ viewOffset = viewParent.parent.getChildIndex(viewParent) + 1;
14405
+ viewParent = viewParent.parent;
14406
+ continue;
14407
+ }
14408
+ }
14275
14409
  lastLength = this.getModelLength(viewNode);
14276
- modelOffset += lastLength;
14410
+ traversedModelOffset += lastLength;
14277
14411
  viewOffset++;
14412
+ if (useCache) {
14413
+ // Note, that we cache the view position before and after a visited element here, so before we (possibly) "enter" it
14414
+ // (see `else` below).
14415
+ //
14416
+ // Since `MapperCache#save` does not overwrite already cached model offsets, this way the cached position is set to
14417
+ // a correct location, that is the closest to the mapped `viewContainer`.
14418
+ //
14419
+ // However, in some cases, we still need to "hoist" the cached position (see `MapperCache#_hoistViewPosition()`).
14420
+ this._cache.save(viewParent, viewOffset, viewContainer, traversedModelOffset);
14421
+ }
14278
14422
  }
14279
- // If it equals we found the position.
14280
- if (modelOffset == expectedOffset) {
14423
+ if (traversedModelOffset == targetModelOffset) {
14424
+ // If it equals we found the position.
14281
14425
  return this._moveViewPositionToTextNode(new Position$1(viewParent, viewOffset));
14282
14426
  } else {
14283
- // ( modelOffset - lastLength ) is the offset to the child we enter,
14284
- // so we subtract it from the expected offset to fine the offset in the child.
14285
- return this.findPositionIn(viewNode, expectedOffset - (modelOffset - lastLength));
14427
+ // If it is higher we overstepped with the last traversed view node.
14428
+ // We need to "enter" it, and look for the view position / model offset inside the last visited view node.
14429
+ return this._findPositionStartingFrom(new Position$1(viewNode, 0), traversedModelOffset - lastLength, targetModelOffset, viewContainer, useCache);
14286
14430
  }
14287
14431
  }
14288
14432
  /**
@@ -14311,6 +14455,401 @@ Range.prototype.is = function(type) {
14311
14455
  return viewPosition;
14312
14456
  }
14313
14457
  }
14458
+ /**
14459
+ * Cache mechanism for {@link module:engine/conversion/mapper~Mapper Mapper}.
14460
+ *
14461
+ * `MapperCache` improves performance for model-to-view position mapping, which is the main `Mapper` task. Asking for a mapping is much
14462
+ * more frequent than actually performing changes, and even if the change happens, we can still partially keep the cache. This makes
14463
+ * caching a useful strategy for `Mapper`.
14464
+ *
14465
+ * `MapperCache` will store some data for view elements or view document fragments that are mapped by the `Mapper`. These view items
14466
+ * are "tracked" by the `MapperCache`. For such view items, we will keep entries of model offsets inside their mapped counterpart. For
14467
+ * the cached model offsets, we will keep a view position that is inside the tracked item. This allows us to either get the mapping
14468
+ * instantly, or at least in less steps than when calculating it from the beginning.
14469
+ *
14470
+ * Important problem related to caching is invalidating the cache. The cache must be invalidated each time the tracked view item changes.
14471
+ * Additionally, we should invalidate as small part of the cache as possible. Since all the logic is encapsulated inside `MapperCache`,
14472
+ * the `MapperCache` listens to view items {@link module:engine/view/node~ViewNodeChangeEvent `change` event} and reacts to it.
14473
+ * Then, it invalidates just the part of the cache that is "after" the changed part of the view.
14474
+ *
14475
+ * As mentioned, `MapperCache` currently is used only for model-to-view position mapping as it was much bigger problem than view-to-model
14476
+ * mapping. However, it should be possible to use it also for view-to-model.
14477
+ *
14478
+ * The main assumptions regarding `MapperCache` are:
14479
+ *
14480
+ * * it is an internal tool, used by `Mapper`, transparent to the outside (no additional effort when developing a plugin or a converter),
14481
+ * * it stores all the necessary data internally, which makes it easier to disable or debug,
14482
+ * * it is optimized for initial downcast process (long insertions), which is crucial for editor init and data save,
14483
+ * * it does not save all possible positions for memory considerations, although it is a possible improvement, which may have increase
14484
+ * performance, as well as simplify some parts of the `MapperCache` logic.
14485
+ *
14486
+ * @internal
14487
+ */ class MapperCache extends /* #__PURE__ */ EmitterMixin() {
14488
+ /**
14489
+ * For every view element or document fragment tracked by `MapperCache`, it holds currently cached data, or more precisely,
14490
+ * model offset to view position mappings. See also `MappingCache` and `CacheItem`.
14491
+ *
14492
+ * If an item is tracked by `MapperCache` it has an entry in this structure, so this structure can be used to check which items
14493
+ * are tracked by `MapperCache`. When an item is no longer tracked, it is removed from this structure.
14494
+ *
14495
+ * Although `MappingCache` and `CacheItem` structures allows for caching any model offsets and view positions, we only cache
14496
+ * values for model offsets that are after a view node. So, in essence, positions inside text nodes are not cached. However, it takes
14497
+ * from one to at most a few steps, to get from a cached position to a position that is inside a view text node.
14498
+ *
14499
+ * Additionally, only one item per `modelOffset` is cached. There can be several view nodes that "end" at the same `modelOffset`.
14500
+ * In this case, we favour positions that are closer to the mapped item. For example
14501
+ *
14502
+ * * for model: `<paragraph>Some <$text bold=true italic=true>formatted</$text> text.</paragraph>`,
14503
+ * * and view: `<p>Some <em><strong>formatted</strong></em> text.</p>`,
14504
+ *
14505
+ * for model offset `14` (after "d"), we store view position after `<em>` element (i.e. view position: at `<p>`, offset `2`).
14506
+ */ _cachedMapping = new WeakMap();
14507
+ /**
14508
+ * When `MapperCache` {@link ~MapperCache#save saves} view position -> model offset mapping, a `CacheItem` is inserted into certain
14509
+ * `MappingCache#cacheList` at some index. Additionally, we store that index with the view node that is before the cached view position.
14510
+ *
14511
+ * This allows to quickly get a cache list item related to certain view node, and hence, for fast cache invalidation.
14512
+ *
14513
+ * For example, consider view: `<p>Some <strong>bold</strong> text.</p>`, where `<p>` is a view element tracked by `MapperCache`.
14514
+ * If all `<p>` children were visited by `MapperCache`, then `<p>` cache list would have four items, related to following model offsets:
14515
+ * `0`, `5`, `9`, `15`. Then, view node `"Some "` would have index `1`, `<strong>` index `2`, and `" text." index `3`.
14516
+ *
14517
+ * Note that the index related with a node is always greater than `0`. The first item in cache list is always for model offset `0`
14518
+ * (and view offset `0`), and it is not related to any node.
14519
+ */ _nodeToCacheListIndex = new WeakMap();
14520
+ /**
14521
+ * Callback fired whenever there is a direct or indirect children change in tracked view element or tracked view document fragment.
14522
+ *
14523
+ * This is specified as a property to make it easier to set as an event callback and to later turn off that event.
14524
+ */ _invalidateOnChildrenChangeCallback = (evt, viewNode, data)=>{
14525
+ // View element or document fragment changed its children at `data.index`. Clear all cache starting from before that index.
14526
+ this._clearCacheInsideParent(viewNode, data.index);
14527
+ };
14528
+ /**
14529
+ * Callback fired whenever a view text node directly or indirectly inside a tracked view element or tracked view document fragment
14530
+ * changes its text data.
14531
+ *
14532
+ * This is specified as a property to make it easier to set as an event callback and to later turn off that event.
14533
+ */ _invalidateOnTextChangeCallback = (evt, viewNode)=>{
14534
+ // Text node has changed. Clear all the cache starting from before this text node.
14535
+ this._clearCacheStartingBefore(viewNode);
14536
+ };
14537
+ /**
14538
+ * Saves cache for given view position mapping <-> model offset mapping. The view position should be after a node (i.e. it cannot
14539
+ * be the first position inside its parent, or in other words, `viewOffset` must be greater than `0`).
14540
+ *
14541
+ * @param viewParent View position parent.
14542
+ * @param viewOffset View position offset. Must be greater than `0`.
14543
+ * @param viewContainer Tracked view position ascendant (it may be the direct parent of the view position).
14544
+ * @param modelOffset Model offset in the model element or document fragment which is mapped to `viewContainer`.
14545
+ */ save(viewParent, viewOffset, viewContainer, modelOffset) {
14546
+ // Get current cache for the tracked ancestor.
14547
+ const cache = this._cachedMapping.get(viewContainer);
14548
+ // See if there is already a cache defined for `modelOffset`.
14549
+ const cacheItem = cache.cacheMap.get(modelOffset);
14550
+ if (cacheItem) {
14551
+ // We already cached this offset. Don't overwrite the cache.
14552
+ //
14553
+ // This assumes that `Mapper` works in a way that we first cache the parent and only then cache children, as we prefer position
14554
+ // after the parent ("closer" to the tracked ancestor). It might be safer to check which position is preferred (newly saved or
14555
+ // the one currently in cache) but it would require additional processing. For now, `Mapper#_findPositionIn()` and
14556
+ // `Mapper#getModelLength()` are implemented so that parents are cached before their children.
14557
+ //
14558
+ // So, don't create new cache if one already exists. Instead, only save `_nodeToCacheListIndex` value for the related view node.
14559
+ const viewChild = viewParent.getChild(viewOffset - 1);
14560
+ // Figure out what index to save with `viewChild`.
14561
+ // We have a `cacheItem` for the `modelOffset`, so we can get a `viewPosition` from there. Before that view position, there
14562
+ // must be a node. That node must have an index set. This will be the index we will want to use.
14563
+ // Since we expect `viewOffset` to be greater than 0, then in almost all cases `modelOffset` will be greater than 0 as well.
14564
+ // As a result, we can expect `cacheItem.viewPosition.nodeBefore` to be set.
14565
+ //
14566
+ // However, in an edge case, were the tracked element contains a 0-model-length view element as the first child (UI element or
14567
+ // an empty attribute element), then `modelOffset` will be 0, and `cacheItem` will be the first cache item, which is before any
14568
+ // view node. In such edge case, `cacheItem.viewPosition.nodeBefore` is undefined, and we manually set to `0`.
14569
+ const index = cacheItem.viewPosition.nodeBefore ? this._nodeToCacheListIndex.get(cacheItem.viewPosition.nodeBefore) : 0;
14570
+ this._nodeToCacheListIndex.set(viewChild, index);
14571
+ return;
14572
+ }
14573
+ const viewPosition = new Position$1(viewParent, viewOffset);
14574
+ const newCacheItem = {
14575
+ viewPosition,
14576
+ modelOffset
14577
+ };
14578
+ // Extend the valid cache range.
14579
+ cache.maxModelOffset = modelOffset > cache.maxModelOffset ? modelOffset : cache.maxModelOffset;
14580
+ // Save the new cache item to the `cacheMap`.
14581
+ cache.cacheMap.set(modelOffset, newCacheItem);
14582
+ // Save the new cache item to the `cacheList`.
14583
+ let i = cache.cacheList.length - 1;
14584
+ // Mostly, we cache elements at the end of `cacheList` and the loop does not execute even once. But when we recursively visit nodes
14585
+ // in `Mapper#_findPositionIn()`, then we will first cache the parent, and then it's children, and they will not be added at the
14586
+ // end of `cacheList`. This is why we need to find correct index to insert them.
14587
+ while(i >= 0 && cache.cacheList[i].modelOffset > modelOffset){
14588
+ i--;
14589
+ }
14590
+ cache.cacheList.splice(i + 1, 0, newCacheItem);
14591
+ if (viewOffset > 0) {
14592
+ const viewChild = viewParent.getChild(viewOffset - 1);
14593
+ // There was an idea to also cache `viewContainer` here but, it could lead to wrong results. If we wanted to cache
14594
+ // `viewContainer`, we probably would need to clear `this._nodeToCacheListIndex` when cache is cleared.
14595
+ // Also, there was no gain from caching this value, the results were almost the same (statistical error).
14596
+ this._nodeToCacheListIndex.set(viewChild, i + 1);
14597
+ }
14598
+ }
14599
+ /**
14600
+ * For given `modelOffset` inside a model element mapped to given `viewContainer`, it returns the closest saved cache item
14601
+ * (view position and related model offset) to the requested one.
14602
+ *
14603
+ * It can be exactly the requested mapping, or it can be mapping that is the closest starting point to look for the requested mapping.
14604
+ *
14605
+ * `viewContainer` must be a view element or document fragment that is mapped by the {@link ~Mapper Mapper}.
14606
+ *
14607
+ * If `viewContainer` is not yet tracked by the `MapperCache`, it will be automatically tracked after calling this method.
14608
+ *
14609
+ * Note: this method will automatically "hoist" cached positions, i.e. it will return a position that is closest to the tracked element.
14610
+ *
14611
+ * For example, if `<p>` is tracked element, and `^` is cached position:
14612
+ *
14613
+ * ```
14614
+ * <p>This is <strong>some <em>heavily <u>formatted</u>^</em></strong> text.</p>
14615
+ * ```
14616
+ *
14617
+ * If this position would be returned, instead, a position directly in `<p>` would be returned:
14618
+ *
14619
+ * ```
14620
+ * <p>This is <strong>some <em>heavily <u>formatted</u></em></strong>^ text.</p>
14621
+ * ```
14622
+ *
14623
+ * Note, that `modelOffset` for both positions is the same.
14624
+ *
14625
+ * @param viewContainer Tracked view element or document fragment, which cache will be used.
14626
+ * @param modelOffset Model offset in a model element or document fragment, which is mapped to `viewContainer`.
14627
+ */ getClosest(viewContainer, modelOffset) {
14628
+ const cache = this._cachedMapping.get(viewContainer);
14629
+ let result;
14630
+ if (cache) {
14631
+ if (modelOffset > cache.maxModelOffset) {
14632
+ result = cache.cacheList[cache.cacheList.length - 1];
14633
+ } else {
14634
+ const cacheItem = cache.cacheMap.get(modelOffset);
14635
+ if (cacheItem) {
14636
+ result = cacheItem;
14637
+ } else {
14638
+ result = this._findInCacheList(cache.cacheList, modelOffset);
14639
+ }
14640
+ }
14641
+ } else {
14642
+ result = this.startTracking(viewContainer);
14643
+ }
14644
+ const viewPosition = this._hoistViewPosition(result.viewPosition);
14645
+ return {
14646
+ modelOffset: result.modelOffset,
14647
+ viewPosition
14648
+ };
14649
+ }
14650
+ /**
14651
+ * Moves a view position to a preferred location.
14652
+ *
14653
+ * The view position is moved up from a non-tracked view element as long as it remains at the end of its current parent.
14654
+ *
14655
+ * See example below to understand when it is important:
14656
+ *
14657
+ * Starting state:
14658
+ *
14659
+ * ```
14660
+ * <p>This is <strong>some <em>heavily <u>formatted</u>^ piece of</em></strong> text.</p>
14661
+ * ```
14662
+ *
14663
+ * Then we remove " piece of " and invalidate some cache:
14664
+ *
14665
+ * ```
14666
+ * <p>This is <strong>some <em>heavily <u>formatted</u>^</em></strong> text.</p>
14667
+ * ```
14668
+ *
14669
+ * Now, if we ask for model offset after letter "d" in "formatted", we should get a position in " text", but we will get in `<em>`.
14670
+ * For this scenario, we need to hoist the position.
14671
+ *
14672
+ * ```
14673
+ * <p>This is <strong>some <em>heavily <u>formatted</u></em></strong>^ text.</p>
14674
+ * ```
14675
+ */ _hoistViewPosition(viewPosition) {
14676
+ while(viewPosition.parent.parent && !this._cachedMapping.has(viewPosition.parent) && viewPosition.isAtEnd){
14677
+ const parent = viewPosition.parent.parent;
14678
+ const offset = parent.getChildIndex(viewPosition.parent) + 1;
14679
+ viewPosition = new Position$1(parent, offset);
14680
+ }
14681
+ return viewPosition;
14682
+ }
14683
+ /**
14684
+ * Starts tracking given `viewContainer`, which must be mapped to a model element or model document fragment.
14685
+ *
14686
+ * Note, that this method is automatically called by
14687
+ * {@link module:engine/conversion/mapper~MapperCache#getClosest `MapperCache#getClosest()`} and there is no need to call it manually.
14688
+ *
14689
+ * This method initializes the cache for `viewContainer` and adds callbacks for
14690
+ * {@link module:engine/view/node~ViewNodeChangeEvent `change` event} fired by `viewContainer`. `MapperCache` listens to `change` event
14691
+ * on the tracked elements to invalidate the stored cache.
14692
+ */ startTracking(viewContainer) {
14693
+ const viewPosition = new Position$1(viewContainer, 0);
14694
+ const initialCacheItem = {
14695
+ viewPosition,
14696
+ modelOffset: 0
14697
+ };
14698
+ const initialCache = {
14699
+ maxModelOffset: 0,
14700
+ cacheList: [
14701
+ initialCacheItem
14702
+ ],
14703
+ cacheMap: new Map([
14704
+ [
14705
+ 0,
14706
+ initialCacheItem
14707
+ ]
14708
+ ])
14709
+ };
14710
+ this._cachedMapping.set(viewContainer, initialCache);
14711
+ // Listen to changes in tracked view containers in order to invalidate the cache.
14712
+ //
14713
+ // Possible performance improvement. This event bubbles, so if there are multiple tracked (mapped) elements that are ancestors
14714
+ // then this will be unnecessarily fired for each ancestor. This could be rewritten to listen only to roots and document fragments.
14715
+ viewContainer.on('change:children', this._invalidateOnChildrenChangeCallback);
14716
+ viewContainer.on('change:text', this._invalidateOnTextChangeCallback);
14717
+ return initialCacheItem;
14718
+ }
14719
+ /**
14720
+ * Stops tracking given `viewContainer`.
14721
+ *
14722
+ * It removes the cached data and stops listening to {@link module:engine/view/node~ViewNodeChangeEvent `change` event} on the
14723
+ * `viewContainer`.
14724
+ */ stopTracking(viewContainer) {
14725
+ viewContainer.off('change:children', this._invalidateOnChildrenChangeCallback);
14726
+ viewContainer.off('change:text', this._invalidateOnTextChangeCallback);
14727
+ this._cachedMapping.delete(viewContainer);
14728
+ }
14729
+ /**
14730
+ * Invalidates cache inside `viewParent`, starting from given `index` in that parent.
14731
+ */ _clearCacheInsideParent(viewParent, index) {
14732
+ if (index == 0) {
14733
+ // Change at the beginning of the parent.
14734
+ if (this._cachedMapping.has(viewParent)) {
14735
+ // If this is a tracked element, clear all cache.
14736
+ this._clearCacheAll(viewParent);
14737
+ } else {
14738
+ // If this is not a tracked element, remove cache starting from before this element.
14739
+ this._clearCacheStartingBefore(viewParent);
14740
+ }
14741
+ } else {
14742
+ // Change in the middle of the parent. Get a view node that's before the change.
14743
+ const lastValidNode = viewParent.getChild(index - 1);
14744
+ // Then, clear all cache starting from before this view node.
14745
+ //
14746
+ // Possible performance improvement. We could have had `_clearCacheAfter( lastValidNode )` instead.
14747
+ // If the `lastValidNode` is the last unchanged node, then we could clear everything AFTER it, not before.
14748
+ // However, with the current setup, it didn't work properly and the actual gain wasn't that big on the tested data.
14749
+ // The problem was with following example: <p>Foo<em><strong>Xyz</strong></em>Bar</p>.
14750
+ // In this example we cache position after <em>, i.e. view position `<p>` 2 is saved with model offset 6.
14751
+ // Now, if we add some text in `<em>`, we won't validate this cached item even though it gets outdated.
14752
+ // So, if there's a need to have `_clearCacheAfter()`, we need to solve the above case first.
14753
+ //
14754
+ this._clearCacheStartingBefore(lastValidNode);
14755
+ }
14756
+ }
14757
+ /**
14758
+ * Clears all the cache for given tracked `viewContainer`.
14759
+ */ _clearCacheAll(viewContainer) {
14760
+ const cache = this._cachedMapping.get(viewContainer);
14761
+ if (cache.maxModelOffset > 0) {
14762
+ cache.maxModelOffset = 0;
14763
+ cache.cacheList.length = 1;
14764
+ cache.cacheMap.clear();
14765
+ cache.cacheMap.set(0, cache.cacheList[0]);
14766
+ }
14767
+ }
14768
+ /**
14769
+ * Clears all the stored cache starting before given `viewNode`. The `viewNode` can be any node that is inside a tracked view element
14770
+ * or view document fragment.
14771
+ */ _clearCacheStartingBefore(viewNode) {
14772
+ // To quickly invalidate the cache, we base on the cache list index stored with the node. See docs for `this._nodeToCacheListIndex`.
14773
+ const cacheListIndex = this._nodeToCacheListIndex.get(viewNode);
14774
+ // If there is no index stored, it means that this `viewNode` has not been cached yet.
14775
+ if (cacheListIndex === undefined) {
14776
+ // If the node is not cached, maybe it's parent is. We will try to invalidate the cache starting from before the parent.
14777
+ // Note, that there always must be a parent if we got here.
14778
+ const viewParent = viewNode.parent;
14779
+ // If the parent is a non-tracked element, try clearing the cache starting before it.
14780
+ //
14781
+ // This situation may happen e.g. if structure like `<p><strong><em>Foo</em></strong>...` was stepped over in
14782
+ // `Mapper#_findPositionIn()` and the children are not cached yet, but the `<strong>` element is. If something changes
14783
+ // inside this structure, make sure to invalidate all the cache after `<strong>`.
14784
+ //
14785
+ // If the parent is a tracked element, then it means there's no cache to clear (nothing after the element is cached).
14786
+ // In this case, there's nothing to do.
14787
+ //
14788
+ if (!this._cachedMapping.has(viewParent)) {
14789
+ this._clearCacheStartingBefore(viewParent);
14790
+ }
14791
+ return;
14792
+ }
14793
+ // Note: there was a consideration to save the `viewContainer` value together with `cacheListIndex` value.
14794
+ // However, it is like it is on purpose. We want to find *current* mapped ancestor for the `viewNode`.
14795
+ // This is an essential step to verify if the cache is still up-to-date.
14796
+ // Actually, we could save `viewContainer` and compare it to current tracked ancestor to quickly invalidate.
14797
+ // But this kinda happens with our flow and other assumptions around caching list index anyway.
14798
+ let viewContainer = viewNode.parent;
14799
+ while(!this._cachedMapping.has(viewContainer)){
14800
+ viewContainer = viewContainer.parent;
14801
+ }
14802
+ this._clearCacheFromIndex(viewContainer, cacheListIndex);
14803
+ }
14804
+ /**
14805
+ * Clears all the cache in the cache list related to given `viewContainer`, starting from `index` (inclusive).
14806
+ */ _clearCacheFromIndex(viewContainer, index) {
14807
+ if (index === 0) {
14808
+ // Don't remove the first entry in the cache (this entry is always a mapping between view offset 0 <-> model offset 0,
14809
+ // and it is a default value that is always expected to be in the cache list).
14810
+ //
14811
+ // The cache mechanism may ask to clear from index `0` in a case where a 0-model-length view element (UI element or empty
14812
+ // attribute element) was at the beginning of tracked element. In such scenario, the view element is mapped through
14813
+ // `nodeToCacheListIndex` to index `0`.
14814
+ index = 1;
14815
+ }
14816
+ // Cache is always available here because we initialize it just before adding a listener that fires `_clearCacheFromIndex()`.
14817
+ const cache = this._cachedMapping.get(viewContainer);
14818
+ const cacheItem = cache.cacheList[index - 1];
14819
+ if (!cacheItem) {
14820
+ return;
14821
+ }
14822
+ cache.maxModelOffset = cacheItem.modelOffset;
14823
+ // Remove from cache all `CacheItem`s that are "after" the index to clear from.
14824
+ const clearedItems = cache.cacheList.splice(index);
14825
+ // For each removed item, make sure to also remove it from `cacheMap` and clear related entry in `_nodeToCacheListIndex`.
14826
+ for (const item of clearedItems){
14827
+ cache.cacheMap.delete(item.modelOffset);
14828
+ const viewNode = item.viewPosition.nodeBefore;
14829
+ this._nodeToCacheListIndex.delete(viewNode);
14830
+ }
14831
+ }
14832
+ /**
14833
+ * Finds a cache item in the given cache list, which `modelOffset` is closest (but smaller or equal) to given `offset`.
14834
+ *
14835
+ * Since `cacheList` is a sorted array, this uses binary search to retrieve the item quickly.
14836
+ */ _findInCacheList(cacheList, offset) {
14837
+ let start = 0;
14838
+ let end = cacheList.length - 1;
14839
+ let index = end - start >> 1;
14840
+ let item = cacheList[index];
14841
+ while(start < end){
14842
+ if (item.modelOffset < offset) {
14843
+ start = index + 1;
14844
+ } else {
14845
+ end = index - 1;
14846
+ }
14847
+ index = start + (end - start >> 1);
14848
+ item = cacheList[index];
14849
+ }
14850
+ return item.modelOffset <= offset ? item : cacheList[index - 1];
14851
+ }
14852
+ }
14314
14853
 
14315
14854
  /**
14316
14855
  * Manages a list of consumable values for the {@link module:engine/model/item~Item model items}.
@@ -16071,10 +16610,13 @@ Node$1.prototype.is = function(type) {
16071
16610
  if (isStartBlockSelected(startBlock, range)) {
16072
16611
  yield startBlock;
16073
16612
  }
16074
- for (const value of range.getWalker()){
16613
+ const treewalker = range.getWalker();
16614
+ for (const value of treewalker){
16075
16615
  const block = value.item;
16076
16616
  if (value.type == 'elementEnd' && isUnvisitedTopBlock(block, visited, range)) {
16077
16617
  yield block;
16618
+ } else if (value.type == 'elementStart' && block.is('model:element') && block.root.document.model.schema.isBlock(block)) {
16619
+ treewalker.jumpTo(Position._createAt(block, 'end'));
16078
16620
  }
16079
16621
  }
16080
16622
  const endBlock = getParentBlock$1(range.end, visited);
@@ -17910,7 +18452,7 @@ function cloneNodes(nodes) {
17910
18452
  }
17911
18453
 
17912
18454
  /**
17913
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
18455
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
17914
18456
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
17915
18457
  */ /**
17916
18458
  * @module engine/conversion/conversionhelpers
@@ -20064,7 +20606,7 @@ function getFromAttributeCreator(config) {
20064
20606
  }
20065
20607
 
20066
20608
  /**
20067
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
20609
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
20068
20610
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
20069
20611
  */ /**
20070
20612
  * @module engine/model/utils/autoparagraphing
@@ -25268,7 +25810,7 @@ function* _getUpcastDefinition(model, view, upcastAlso) {
25268
25810
  }
25269
25811
 
25270
25812
  /**
25271
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
25813
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
25272
25814
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
25273
25815
  */ /* eslint-disable @typescript-eslint/no-unused-vars */ /**
25274
25816
  * @module engine/model/operation/operation
@@ -25287,6 +25829,9 @@ function* _getUpcastDefinition(model, view, upcastAlso) {
25287
25829
  /**
25288
25830
  * {@link module:engine/model/batch~Batch Batch} to which the operation is added or `null` if the operation is not
25289
25831
  * added to any batch yet.
25832
+ *
25833
+ * Note, that a {@link #isDocumentOperation non-document operation} has this property always set to `null`, and is never added
25834
+ * to any batch.
25290
25835
  */ batch;
25291
25836
  /**
25292
25837
  * Base operation constructor.
@@ -25315,7 +25860,7 @@ function* _getUpcastDefinition(model, view, upcastAlso) {
25315
25860
  json.__className = this.constructor.className;
25316
25861
  // Remove reference to the parent `Batch` to avoid circular dependencies.
25317
25862
  delete json.batch;
25318
- // Only document operations are shared with other clients so it is not necessary to keep this information.
25863
+ // This can be derived from `baseVersion` so we can remove it.
25319
25864
  delete json.isDocumentOperation;
25320
25865
  return json;
25321
25866
  }
@@ -29139,8 +29684,12 @@ LivePosition.prototype.is = function(type) {
29139
29684
  * @param operation An operation to add.
29140
29685
  * @returns The added operation.
29141
29686
  */ addOperation(operation) {
29142
- operation.batch = this;
29143
- this.operations.push(operation);
29687
+ if (operation.isDocumentOperation) {
29688
+ // Store only document operations in the batch.
29689
+ // Non-document operations are temporary and should be discarded after they are applied.
29690
+ operation.batch = this;
29691
+ this.operations.push(operation);
29692
+ }
29144
29693
  return operation;
29145
29694
  }
29146
29695
  }
@@ -33446,7 +33995,7 @@ function replaceEntireContentWithParagraph(writer, selection) {
33446
33995
  }
33447
33996
 
33448
33997
  /**
33449
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
33998
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
33450
33999
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
33451
34000
  */ /**
33452
34001
  * @module engine/model/utils/getselectedcontent
@@ -35367,6 +35916,26 @@ function getSearchRange(start, isForward) {
35367
35916
  }
35368
35917
  }
35369
35918
 
35919
+ /**
35920
+ * Touch events observer.
35921
+ *
35922
+ * Note that this observer is not available by default. To make it available it needs to be added to
35923
+ * {@link module:engine/view/view~View} by {@link module:engine/view/view~View#addObserver} method.
35924
+ */ class TouchObserver extends DomEventObserver {
35925
+ /**
35926
+ * @inheritDoc
35927
+ */ domEventType = [
35928
+ 'touchstart',
35929
+ 'touchend',
35930
+ 'touchmove'
35931
+ ];
35932
+ /**
35933
+ * @inheritDoc
35934
+ */ onDomEvent(domEvent) {
35935
+ this.fire(domEvent.type, domEvent);
35936
+ }
35937
+ }
35938
+
35370
35939
  /**
35371
35940
  * View upcast writer. It provides a set of methods used to manipulate non-semantic view trees.
35372
35941
  *
@@ -35690,7 +36259,7 @@ function getSearchRange(start, isForward) {
35690
36259
  }
35691
36260
 
35692
36261
  /**
35693
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
36262
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
35694
36263
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
35695
36264
  */ /**
35696
36265
  * @module engine/view/styles/utils
@@ -37946,5 +38515,5 @@ function* convertAttributes(attributes, converter) {
37946
38515
  }
37947
38516
  }
37948
38517
 
37949
- export { AttributeElement, AttributeOperation, BubblingEventInfo, ClickObserver, Conversion, DataController, DataTransfer, DocumentFragment, DocumentSelection, DomConverter, DomEventData, DomEventObserver, DowncastWriter, EditingController, View as EditingView, Element, FocusObserver, History, HtmlDataProcessor, InsertOperation, LivePosition, LiveRange, MarkerOperation, Matcher, MergeOperation, Model, MouseObserver, MoveOperation, NoOperation, Observer, OperationFactory, Position, Range, RenameOperation, Renderer, RootAttributeOperation, RootOperation, SplitOperation, StylesMap, StylesProcessor, TabObserver, Text, TextProxy, TreeWalker, UpcastWriter, AttributeElement as ViewAttributeElement, ContainerElement as ViewContainerElement, Document$1 as ViewDocument, DocumentFragment$1 as ViewDocumentFragment, EditableElement as ViewEditableElement, Element$1 as ViewElement, EmptyElement as ViewEmptyElement, RawElement as ViewRawElement, RootEditableElement as ViewRootEditableElement, Text$1 as ViewText, TreeWalker$1 as ViewTreeWalker, UIElement as ViewUIElement, XmlDataProcessor, getData as _getModelData, getData$1 as _getViewData, parse as _parseModel, parse$1 as _parseView, setData as _setModelData, setData$1 as _setViewData, stringify as _stringifyModel, stringify$1 as _stringifyView, addBackgroundRules, addBorderRules, addMarginRules, addPaddingRules, autoParagraphEmptyRoots, disablePlaceholder, enablePlaceholder, getBoxSidesShorthandValue, getBoxSidesValueReducer, getBoxSidesValues, getFillerOffset$4 as getFillerOffset, getPositionShorthandNormalizer, getShorthandValues, hidePlaceholder, isAttachment, isColor, isLength, isLineStyle, isParagraphable, isPercentage, isPosition, isRepeat, isURL, needsPlaceholder, showPlaceholder, transformSets, wrapInParagraph };
38518
+ export { AttributeElement, AttributeOperation, BubblingEventInfo, ClickObserver, Conversion, DataController, DataTransfer, DocumentFragment, DocumentSelection, DomConverter, DomEventData, DomEventObserver, DowncastWriter, EditingController, View as EditingView, Element, FocusObserver, History, HtmlDataProcessor, InsertOperation, LivePosition, LiveRange, MarkerOperation, Matcher, MergeOperation, Model, MouseObserver, MoveOperation, NoOperation, Observer, OperationFactory, Position, Range, RenameOperation, Renderer, RootAttributeOperation, RootOperation, SplitOperation, StylesMap, StylesProcessor, TabObserver, Text, TextProxy, TouchObserver, TreeWalker, UpcastWriter, AttributeElement as ViewAttributeElement, ContainerElement as ViewContainerElement, Document$1 as ViewDocument, DocumentFragment$1 as ViewDocumentFragment, EditableElement as ViewEditableElement, Element$1 as ViewElement, EmptyElement as ViewEmptyElement, RawElement as ViewRawElement, RootEditableElement as ViewRootEditableElement, Text$1 as ViewText, TreeWalker$1 as ViewTreeWalker, UIElement as ViewUIElement, XmlDataProcessor, getData as _getModelData, getData$1 as _getViewData, parse as _parseModel, parse$1 as _parseView, setData as _setModelData, setData$1 as _setViewData, stringify as _stringifyModel, stringify$1 as _stringifyView, addBackgroundRules, addBorderRules, addMarginRules, addPaddingRules, autoParagraphEmptyRoots, disablePlaceholder, enablePlaceholder, getBoxSidesShorthandValue, getBoxSidesValueReducer, getBoxSidesValues, getFillerOffset$4 as getFillerOffset, getPositionShorthandNormalizer, getShorthandValues, hidePlaceholder, isAttachment, isColor, isLength, isLineStyle, isParagraphable, isPercentage, isPosition, isRepeat, isURL, needsPlaceholder, showPlaceholder, transformSets, wrapInParagraph };
37950
38519
  //# sourceMappingURL=index.js.map