@ckeditor/ckeditor5-engine 39.0.1 → 40.0.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 (244) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/LICENSE.md +1 -1
  3. package/README.md +8 -8
  4. package/package.json +2 -6
  5. package/src/controller/datacontroller.d.ts +334 -334
  6. package/src/controller/datacontroller.js +481 -481
  7. package/src/controller/editingcontroller.d.ts +98 -98
  8. package/src/controller/editingcontroller.js +191 -191
  9. package/src/conversion/conversion.d.ts +478 -478
  10. package/src/conversion/conversion.js +601 -601
  11. package/src/conversion/conversionhelpers.d.ts +26 -26
  12. package/src/conversion/conversionhelpers.js +32 -32
  13. package/src/conversion/downcastdispatcher.d.ts +562 -562
  14. package/src/conversion/downcastdispatcher.js +547 -547
  15. package/src/conversion/downcasthelpers.d.ts +1226 -1226
  16. package/src/conversion/downcasthelpers.js +2183 -2183
  17. package/src/conversion/mapper.d.ts +503 -503
  18. package/src/conversion/mapper.js +536 -536
  19. package/src/conversion/modelconsumable.d.ts +201 -201
  20. package/src/conversion/modelconsumable.js +333 -333
  21. package/src/conversion/upcastdispatcher.d.ts +492 -492
  22. package/src/conversion/upcastdispatcher.js +460 -460
  23. package/src/conversion/upcasthelpers.d.ts +499 -499
  24. package/src/conversion/upcasthelpers.js +950 -950
  25. package/src/conversion/viewconsumable.d.ts +369 -369
  26. package/src/conversion/viewconsumable.js +532 -532
  27. package/src/dataprocessor/basichtmlwriter.d.ts +18 -18
  28. package/src/dataprocessor/basichtmlwriter.js +19 -19
  29. package/src/dataprocessor/dataprocessor.d.ts +61 -61
  30. package/src/dataprocessor/dataprocessor.js +5 -5
  31. package/src/dataprocessor/htmldataprocessor.d.ts +76 -76
  32. package/src/dataprocessor/htmldataprocessor.js +96 -96
  33. package/src/dataprocessor/htmlwriter.d.ts +16 -16
  34. package/src/dataprocessor/htmlwriter.js +5 -5
  35. package/src/dataprocessor/xmldataprocessor.d.ts +90 -90
  36. package/src/dataprocessor/xmldataprocessor.js +108 -108
  37. package/src/dev-utils/model.d.ts +124 -124
  38. package/src/dev-utils/model.js +395 -395
  39. package/src/dev-utils/operationreplayer.d.ts +51 -51
  40. package/src/dev-utils/operationreplayer.js +112 -112
  41. package/src/dev-utils/utils.d.ts +37 -37
  42. package/src/dev-utils/utils.js +73 -73
  43. package/src/dev-utils/view.d.ts +319 -319
  44. package/src/dev-utils/view.js +967 -967
  45. package/src/index.d.ts +114 -114
  46. package/src/index.js +78 -78
  47. package/src/model/batch.d.ts +106 -106
  48. package/src/model/batch.js +96 -96
  49. package/src/model/differ.d.ts +387 -387
  50. package/src/model/differ.js +1149 -1149
  51. package/src/model/document.d.ts +272 -272
  52. package/src/model/document.js +361 -361
  53. package/src/model/documentfragment.d.ts +200 -200
  54. package/src/model/documentfragment.js +306 -306
  55. package/src/model/documentselection.d.ts +420 -420
  56. package/src/model/documentselection.js +993 -993
  57. package/src/model/element.d.ts +165 -165
  58. package/src/model/element.js +281 -281
  59. package/src/model/history.d.ts +114 -114
  60. package/src/model/history.js +207 -207
  61. package/src/model/item.d.ts +14 -14
  62. package/src/model/item.js +5 -5
  63. package/src/model/liveposition.d.ts +77 -77
  64. package/src/model/liveposition.js +93 -93
  65. package/src/model/liverange.d.ts +102 -102
  66. package/src/model/liverange.js +120 -120
  67. package/src/model/markercollection.d.ts +335 -335
  68. package/src/model/markercollection.js +403 -403
  69. package/src/model/model.d.ts +919 -919
  70. package/src/model/model.js +842 -842
  71. package/src/model/node.d.ts +256 -256
  72. package/src/model/node.js +375 -375
  73. package/src/model/nodelist.d.ts +91 -91
  74. package/src/model/nodelist.js +163 -163
  75. package/src/model/operation/attributeoperation.d.ts +103 -103
  76. package/src/model/operation/attributeoperation.js +148 -148
  77. package/src/model/operation/detachoperation.d.ts +60 -60
  78. package/src/model/operation/detachoperation.js +77 -77
  79. package/src/model/operation/insertoperation.d.ts +90 -90
  80. package/src/model/operation/insertoperation.js +135 -135
  81. package/src/model/operation/markeroperation.d.ts +91 -91
  82. package/src/model/operation/markeroperation.js +107 -107
  83. package/src/model/operation/mergeoperation.d.ts +100 -100
  84. package/src/model/operation/mergeoperation.js +167 -167
  85. package/src/model/operation/moveoperation.d.ts +96 -96
  86. package/src/model/operation/moveoperation.js +164 -164
  87. package/src/model/operation/nooperation.d.ts +38 -38
  88. package/src/model/operation/nooperation.js +48 -48
  89. package/src/model/operation/operation.d.ts +96 -96
  90. package/src/model/operation/operation.js +62 -62
  91. package/src/model/operation/operationfactory.d.ts +18 -18
  92. package/src/model/operation/operationfactory.js +44 -44
  93. package/src/model/operation/renameoperation.d.ts +83 -83
  94. package/src/model/operation/renameoperation.js +115 -115
  95. package/src/model/operation/rootattributeoperation.d.ts +98 -98
  96. package/src/model/operation/rootattributeoperation.js +155 -155
  97. package/src/model/operation/rootoperation.d.ts +76 -76
  98. package/src/model/operation/rootoperation.js +90 -90
  99. package/src/model/operation/splitoperation.d.ts +109 -109
  100. package/src/model/operation/splitoperation.js +194 -194
  101. package/src/model/operation/transform.d.ts +100 -100
  102. package/src/model/operation/transform.js +1985 -1985
  103. package/src/model/operation/utils.d.ts +71 -71
  104. package/src/model/operation/utils.js +213 -213
  105. package/src/model/position.d.ts +539 -539
  106. package/src/model/position.js +979 -979
  107. package/src/model/range.d.ts +458 -458
  108. package/src/model/range.js +875 -875
  109. package/src/model/rootelement.d.ts +60 -60
  110. package/src/model/rootelement.js +74 -74
  111. package/src/model/schema.d.ts +1186 -1186
  112. package/src/model/schema.js +1242 -1242
  113. package/src/model/selection.d.ts +482 -482
  114. package/src/model/selection.js +789 -789
  115. package/src/model/text.d.ts +66 -66
  116. package/src/model/text.js +85 -85
  117. package/src/model/textproxy.d.ts +144 -144
  118. package/src/model/textproxy.js +189 -189
  119. package/src/model/treewalker.d.ts +186 -186
  120. package/src/model/treewalker.js +244 -244
  121. package/src/model/typecheckable.d.ts +285 -285
  122. package/src/model/typecheckable.js +16 -16
  123. package/src/model/utils/autoparagraphing.d.ts +37 -37
  124. package/src/model/utils/autoparagraphing.js +63 -63
  125. package/src/model/utils/deletecontent.d.ts +58 -58
  126. package/src/model/utils/deletecontent.js +488 -488
  127. package/src/model/utils/findoptimalinsertionrange.d.ts +32 -32
  128. package/src/model/utils/findoptimalinsertionrange.js +57 -57
  129. package/src/model/utils/getselectedcontent.d.ts +30 -30
  130. package/src/model/utils/getselectedcontent.js +125 -125
  131. package/src/model/utils/insertcontent.d.ts +46 -46
  132. package/src/model/utils/insertcontent.js +705 -705
  133. package/src/model/utils/insertobject.d.ts +44 -44
  134. package/src/model/utils/insertobject.js +139 -139
  135. package/src/model/utils/modifyselection.d.ts +48 -48
  136. package/src/model/utils/modifyselection.js +186 -186
  137. package/src/model/utils/selection-post-fixer.d.ts +74 -74
  138. package/src/model/utils/selection-post-fixer.js +260 -260
  139. package/src/model/writer.d.ts +851 -851
  140. package/src/model/writer.js +1306 -1306
  141. package/src/view/attributeelement.d.ts +108 -108
  142. package/src/view/attributeelement.js +184 -184
  143. package/src/view/containerelement.d.ts +49 -49
  144. package/src/view/containerelement.js +80 -80
  145. package/src/view/datatransfer.d.ts +79 -79
  146. package/src/view/datatransfer.js +98 -98
  147. package/src/view/document.d.ts +184 -184
  148. package/src/view/document.js +120 -120
  149. package/src/view/documentfragment.d.ts +149 -149
  150. package/src/view/documentfragment.js +228 -228
  151. package/src/view/documentselection.d.ts +306 -306
  152. package/src/view/documentselection.js +256 -256
  153. package/src/view/domconverter.d.ts +640 -640
  154. package/src/view/domconverter.js +1450 -1425
  155. package/src/view/downcastwriter.d.ts +996 -996
  156. package/src/view/downcastwriter.js +1696 -1696
  157. package/src/view/editableelement.d.ts +62 -62
  158. package/src/view/editableelement.js +62 -62
  159. package/src/view/element.d.ts +468 -468
  160. package/src/view/element.js +724 -724
  161. package/src/view/elementdefinition.d.ts +87 -87
  162. package/src/view/elementdefinition.js +5 -5
  163. package/src/view/emptyelement.d.ts +41 -41
  164. package/src/view/emptyelement.js +73 -73
  165. package/src/view/filler.d.ts +111 -111
  166. package/src/view/filler.js +150 -150
  167. package/src/view/item.d.ts +14 -14
  168. package/src/view/item.js +5 -5
  169. package/src/view/matcher.d.ts +486 -486
  170. package/src/view/matcher.js +507 -507
  171. package/src/view/node.d.ts +163 -163
  172. package/src/view/node.js +228 -228
  173. package/src/view/observer/arrowkeysobserver.d.ts +45 -45
  174. package/src/view/observer/arrowkeysobserver.js +40 -40
  175. package/src/view/observer/bubblingemittermixin.d.ts +166 -166
  176. package/src/view/observer/bubblingemittermixin.js +172 -172
  177. package/src/view/observer/bubblingeventinfo.d.ts +47 -47
  178. package/src/view/observer/bubblingeventinfo.js +37 -37
  179. package/src/view/observer/clickobserver.d.ts +43 -43
  180. package/src/view/observer/clickobserver.js +29 -29
  181. package/src/view/observer/compositionobserver.d.ts +82 -82
  182. package/src/view/observer/compositionobserver.js +60 -60
  183. package/src/view/observer/domeventdata.d.ts +50 -50
  184. package/src/view/observer/domeventdata.js +47 -47
  185. package/src/view/observer/domeventobserver.d.ts +73 -73
  186. package/src/view/observer/domeventobserver.js +79 -79
  187. package/src/view/observer/fakeselectionobserver.d.ts +47 -47
  188. package/src/view/observer/fakeselectionobserver.js +91 -91
  189. package/src/view/observer/focusobserver.d.ts +82 -82
  190. package/src/view/observer/focusobserver.js +86 -86
  191. package/src/view/observer/inputobserver.d.ts +86 -86
  192. package/src/view/observer/inputobserver.js +164 -164
  193. package/src/view/observer/keyobserver.d.ts +66 -66
  194. package/src/view/observer/keyobserver.js +39 -39
  195. package/src/view/observer/mouseobserver.d.ts +89 -89
  196. package/src/view/observer/mouseobserver.js +29 -29
  197. package/src/view/observer/mutationobserver.d.ts +86 -86
  198. package/src/view/observer/mutationobserver.js +206 -206
  199. package/src/view/observer/observer.d.ts +89 -89
  200. package/src/view/observer/observer.js +84 -84
  201. package/src/view/observer/selectionobserver.d.ts +148 -148
  202. package/src/view/observer/selectionobserver.js +202 -202
  203. package/src/view/observer/tabobserver.d.ts +46 -46
  204. package/src/view/observer/tabobserver.js +42 -42
  205. package/src/view/placeholder.d.ts +96 -96
  206. package/src/view/placeholder.js +267 -267
  207. package/src/view/position.d.ts +189 -189
  208. package/src/view/position.js +324 -324
  209. package/src/view/range.d.ts +279 -279
  210. package/src/view/range.js +430 -430
  211. package/src/view/rawelement.d.ts +73 -73
  212. package/src/view/rawelement.js +105 -105
  213. package/src/view/renderer.d.ts +265 -265
  214. package/src/view/renderer.js +999 -999
  215. package/src/view/rooteditableelement.d.ts +41 -41
  216. package/src/view/rooteditableelement.js +69 -69
  217. package/src/view/selection.d.ts +375 -375
  218. package/src/view/selection.js +559 -559
  219. package/src/view/styles/background.d.ts +33 -33
  220. package/src/view/styles/background.js +74 -74
  221. package/src/view/styles/border.d.ts +43 -43
  222. package/src/view/styles/border.js +316 -316
  223. package/src/view/styles/margin.d.ts +29 -29
  224. package/src/view/styles/margin.js +34 -34
  225. package/src/view/styles/padding.d.ts +29 -29
  226. package/src/view/styles/padding.js +34 -34
  227. package/src/view/styles/utils.d.ts +93 -93
  228. package/src/view/styles/utils.js +219 -219
  229. package/src/view/stylesmap.d.ts +675 -675
  230. package/src/view/stylesmap.js +766 -766
  231. package/src/view/text.d.ts +74 -74
  232. package/src/view/text.js +93 -93
  233. package/src/view/textproxy.d.ts +97 -97
  234. package/src/view/textproxy.js +124 -124
  235. package/src/view/treewalker.d.ts +195 -195
  236. package/src/view/treewalker.js +327 -327
  237. package/src/view/typecheckable.d.ts +448 -448
  238. package/src/view/typecheckable.js +19 -19
  239. package/src/view/uielement.d.ts +96 -96
  240. package/src/view/uielement.js +182 -182
  241. package/src/view/upcastwriter.d.ts +417 -417
  242. package/src/view/upcastwriter.js +359 -359
  243. package/src/view/view.d.ts +487 -487
  244. package/src/view/view.js +546 -546
@@ -1,403 +1,403 @@
1
- /**
2
- * @license Copyright (c) 2003-2023, 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
- /**
6
- * @module engine/model/markercollection
7
- */
8
- import TypeCheckable from './typecheckable';
9
- import LiveRange from './liverange';
10
- import { CKEditorError, EmitterMixin } from '@ckeditor/ckeditor5-utils';
11
- /**
12
- * The collection of all {@link module:engine/model/markercollection~Marker markers} attached to the document.
13
- * It lets you {@link module:engine/model/markercollection~MarkerCollection#get get} markers or track them using
14
- * {@link module:engine/model/markercollection~MarkerCollection#event:update} event.
15
- *
16
- * To create, change or remove makers use {@link module:engine/model/writer~Writer model writers'} methods:
17
- * {@link module:engine/model/writer~Writer#addMarker} or {@link module:engine/model/writer~Writer#removeMarker}. Since
18
- * the writer is the only proper way to change the data model it is not possible to change markers directly using this
19
- * collection. All markers created by the writer will be automatically added to this collection.
20
- *
21
- * By default there is one marker collection available as {@link module:engine/model/model~Model#markers model property}.
22
- *
23
- * @see module:engine/model/markercollection~Marker
24
- */
25
- export default class MarkerCollection extends EmitterMixin() {
26
- constructor() {
27
- super(...arguments);
28
- /**
29
- * Stores {@link ~Marker markers} added to the collection.
30
- */
31
- this._markers = new Map();
32
- }
33
- /**
34
- * Iterable interface.
35
- *
36
- * Iterates over all {@link ~Marker markers} added to the collection.
37
- */
38
- [Symbol.iterator]() {
39
- return this._markers.values();
40
- }
41
- /**
42
- * Checks if given {@link ~Marker marker} or marker name is in the collection.
43
- *
44
- * @param markerOrName Name of marker or marker instance to check.
45
- * @returns `true` if marker is in the collection, `false` otherwise.
46
- */
47
- has(markerOrName) {
48
- const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
49
- return this._markers.has(markerName);
50
- }
51
- /**
52
- * Returns {@link ~Marker marker} with given `markerName`.
53
- *
54
- * @param markerName Name of marker to get.
55
- * @returns Marker with given name or `null` if such marker was
56
- * not added to the collection.
57
- */
58
- get(markerName) {
59
- return this._markers.get(markerName) || null;
60
- }
61
- /**
62
- * Creates and adds a {@link ~Marker marker} to the `MarkerCollection` with given name on given
63
- * {@link module:engine/model/range~Range range}.
64
- *
65
- * If `MarkerCollection` already had a marker with given name (or {@link ~Marker marker} was passed), the marker in
66
- * collection is updated and {@link module:engine/model/markercollection~MarkerCollection#event:update} event is fired
67
- * but only if there was a change (marker range or {@link module:engine/model/markercollection~Marker#managedUsingOperations}
68
- * flag has changed.
69
- *
70
- * @internal
71
- * @fires update
72
- * @param markerOrName Name of marker to set or marker instance to update.
73
- * @param range Marker range.
74
- * @param managedUsingOperations Specifies whether the marker is managed using operations.
75
- * @param affectsData Specifies whether the marker affects the data produced by the data pipeline
76
- * (is persisted in the editor's data).
77
- * @returns `Marker` instance which was added or updated.
78
- */
79
- _set(markerOrName, range, managedUsingOperations = false, affectsData = false) {
80
- const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
81
- if (markerName.includes(',')) {
82
- /**
83
- * Marker name cannot contain the "," character.
84
- *
85
- * @error markercollection-incorrect-marker-name
86
- */
87
- throw new CKEditorError('markercollection-incorrect-marker-name', this);
88
- }
89
- const oldMarker = this._markers.get(markerName);
90
- if (oldMarker) {
91
- const oldMarkerData = oldMarker.getData();
92
- const oldRange = oldMarker.getRange();
93
- let hasChanged = false;
94
- if (!oldRange.isEqual(range)) {
95
- oldMarker._attachLiveRange(LiveRange.fromRange(range));
96
- hasChanged = true;
97
- }
98
- if (managedUsingOperations != oldMarker.managedUsingOperations) {
99
- oldMarker._managedUsingOperations = managedUsingOperations;
100
- hasChanged = true;
101
- }
102
- if (typeof affectsData === 'boolean' && affectsData != oldMarker.affectsData) {
103
- oldMarker._affectsData = affectsData;
104
- hasChanged = true;
105
- }
106
- if (hasChanged) {
107
- this.fire(`update:${markerName}`, oldMarker, oldRange, range, oldMarkerData);
108
- }
109
- return oldMarker;
110
- }
111
- const liveRange = LiveRange.fromRange(range);
112
- const marker = new Marker(markerName, liveRange, managedUsingOperations, affectsData);
113
- this._markers.set(markerName, marker);
114
- this.fire(`update:${markerName}`, marker, null, range, { ...marker.getData(), range: null });
115
- return marker;
116
- }
117
- /**
118
- * Removes given {@link ~Marker marker} or a marker with given name from the `MarkerCollection`.
119
- *
120
- * @internal
121
- * @fires update
122
- * @param markerOrName Marker or name of a marker to remove.
123
- * @returns `true` if marker was found and removed, `false` otherwise.
124
- */
125
- _remove(markerOrName) {
126
- const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
127
- const oldMarker = this._markers.get(markerName);
128
- if (oldMarker) {
129
- this._markers.delete(markerName);
130
- this.fire(`update:${markerName}`, oldMarker, oldMarker.getRange(), null, oldMarker.getData());
131
- this._destroyMarker(oldMarker);
132
- return true;
133
- }
134
- return false;
135
- }
136
- /**
137
- * Fires an {@link module:engine/model/markercollection~MarkerCollection#event:update} event for the given {@link ~Marker marker}
138
- * but does not change the marker. Useful to force {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast
139
- * conversion} for the marker.
140
- *
141
- * @internal
142
- * @fires update
143
- * @param markerOrName Marker or name of a marker to refresh.
144
- */
145
- _refresh(markerOrName) {
146
- const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
147
- const marker = this._markers.get(markerName);
148
- if (!marker) {
149
- /**
150
- * Marker with provided name does not exists.
151
- *
152
- * @error markercollection-refresh-marker-not-exists
153
- */
154
- throw new CKEditorError('markercollection-refresh-marker-not-exists', this);
155
- }
156
- const range = marker.getRange();
157
- this.fire(`update:${markerName}`, marker, range, range, marker.getData());
158
- }
159
- /**
160
- * Returns iterator that iterates over all markers, which ranges contain given {@link module:engine/model/position~Position position}.
161
- */
162
- *getMarkersAtPosition(position) {
163
- for (const marker of this) {
164
- if (marker.getRange().containsPosition(position)) {
165
- yield marker;
166
- }
167
- }
168
- }
169
- /**
170
- * Returns iterator that iterates over all markers, which intersects with given {@link module:engine/model/range~Range range}.
171
- */
172
- *getMarkersIntersectingRange(range) {
173
- for (const marker of this) {
174
- if (marker.getRange().getIntersection(range) !== null) {
175
- yield marker;
176
- }
177
- }
178
- }
179
- /**
180
- * Destroys marker collection and all markers inside it.
181
- */
182
- destroy() {
183
- for (const marker of this._markers.values()) {
184
- this._destroyMarker(marker);
185
- }
186
- this._markers = null;
187
- this.stopListening();
188
- }
189
- /**
190
- * Iterates over all markers that starts with given `prefix`.
191
- *
192
- * ```ts
193
- * const markerFooA = markersCollection.set( 'foo:a', rangeFooA );
194
- * const markerFooB = markersCollection.set( 'foo:b', rangeFooB );
195
- * const markerBarA = markersCollection.set( 'bar:a', rangeBarA );
196
- * const markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );
197
- * Array.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]
198
- * Array.from( markersCollection.getMarkersGroup( 'a' ) ); // []
199
- * ```
200
- */
201
- *getMarkersGroup(prefix) {
202
- for (const marker of this._markers.values()) {
203
- if (marker.name.startsWith(prefix + ':')) {
204
- yield marker;
205
- }
206
- }
207
- }
208
- /**
209
- * Destroys the marker.
210
- */
211
- _destroyMarker(marker) {
212
- marker.stopListening();
213
- marker._detachLiveRange();
214
- }
215
- }
216
- /**
217
- * `Marker` is a continuous part of the model (like a range), is named and represents some kind of information about the
218
- * marked part of the model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
219
- * the model document tree, markers are not stored directly in the document tree but in the
220
- * {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving
221
- * additional meaning to the part of a model document between marker start and marker end.
222
- *
223
- * In this sense, markers are similar to adding and converting attributes on nodes. The difference is that attribute is
224
- * connected with a given node (e.g. a character is bold no matter if it gets moved or content around it changes).
225
- * Markers on the other hand are continuous ranges and are characterized by their start and end position. This means that
226
- * any character in the marker is marked by the marker. For example, if a character is moved outside of marker it stops being
227
- * "special" and the marker is shrunk. Similarly, when a character is moved into the marker from other place in document
228
- * model, it starts being "special" and the marker is enlarged.
229
- *
230
- * Another upside of markers is that finding marked part of document is fast and easy. Using attributes to mark some nodes
231
- * and then trying to find that part of document would require traversing whole document tree. Marker gives instant access
232
- * to the range which it is marking at the moment.
233
- *
234
- * Markers are built from a name and a range.
235
- *
236
- * Range of the marker is updated automatically when document changes, using
237
- * {@link module:engine/model/liverange~LiveRange live range} mechanism.
238
- *
239
- * Name is used to group and identify markers. Names have to be unique, but markers can be grouped by
240
- * using common prefixes, separated with `:`, for example: `user:john` or `search:3`. That's useful in term of creating
241
- * namespaces for custom elements (e.g. comments, highlights). You can use this prefixes in
242
- * {@link module:engine/model/markercollection~MarkerCollection#event:update} listeners to listen on changes in a group of markers.
243
- * For instance: `model.markers.on( 'update:user', callback );` will be called whenever any `user:*` markers changes.
244
- *
245
- * There are two types of markers.
246
- *
247
- * 1. Markers managed directly, without using operations. They are added directly by {@link module:engine/model/writer~Writer}
248
- * to the {@link module:engine/model/markercollection~MarkerCollection} without any additional mechanism. They can be used
249
- * as bookmarks or visual markers. They are great for showing results of the find, or select link when the focus is in the input.
250
- *
251
- * 1. Markers managed using operations. These markers are also stored in {@link module:engine/model/markercollection~MarkerCollection}
252
- * but changes in these markers is managed the same way all other changes in the model structure - using operations.
253
- * Therefore, they are handled in the undo stack and synchronized between clients if the collaboration plugin is enabled.
254
- * This type of markers is useful for solutions like spell checking or comments.
255
- *
256
- * Both type of them should be added / updated by {@link module:engine/model/writer~Writer#addMarker}
257
- * and removed by {@link module:engine/model/writer~Writer#removeMarker} methods.
258
- *
259
- * ```ts
260
- * model.change( ( writer ) => {
261
- * const marker = writer.addMarker( name, { range, usingOperation: true } );
262
- *
263
- * // ...
264
- *
265
- * writer.removeMarker( marker );
266
- * } );
267
- * ```
268
- *
269
- * See {@link module:engine/model/writer~Writer} to find more examples.
270
- *
271
- * Since markers need to track change in the document, for efficiency reasons, it is best to create and keep as little
272
- * markers as possible and remove them as soon as they are not needed anymore.
273
- *
274
- * Markers can be downcasted and upcasted.
275
- *
276
- * Markers downcast happens on {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker} and
277
- * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:removeMarker} events.
278
- * Use {@link module:engine/conversion/downcasthelpers downcast converters} or attach a custom converter to mentioned events.
279
- * For {@link module:engine/controller/datacontroller~DataController data pipeline}, marker should be downcasted to an element.
280
- * Then, it can be upcasted back to a marker. Again, use {@link module:engine/conversion/upcasthelpers upcast converters} or
281
- * attach a custom converter to {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element}.
282
- *
283
- * `Marker` instances are created and destroyed only by {@link ~MarkerCollection MarkerCollection}.
284
- */
285
- class Marker extends EmitterMixin(TypeCheckable) {
286
- /**
287
- * Creates a marker instance.
288
- *
289
- * @param name Marker name.
290
- * @param liveRange Range marked by the marker.
291
- * @param managedUsingOperations Specifies whether the marker is managed using operations.
292
- * @param affectsData Specifies whether the marker affects the data produced by the data pipeline (is persisted in the editor's data).
293
- */
294
- constructor(name, liveRange, managedUsingOperations, affectsData) {
295
- super();
296
- this.name = name;
297
- this._liveRange = this._attachLiveRange(liveRange);
298
- this._managedUsingOperations = managedUsingOperations;
299
- this._affectsData = affectsData;
300
- }
301
- /**
302
- * A value indicating if the marker is managed using operations.
303
- * See {@link ~Marker marker class description} to learn more about marker types.
304
- * See {@link module:engine/model/writer~Writer#addMarker}.
305
- */
306
- get managedUsingOperations() {
307
- if (!this._liveRange) {
308
- throw new CKEditorError('marker-destroyed', this);
309
- }
310
- return this._managedUsingOperations;
311
- }
312
- /**
313
- * A value indicating if the marker changes the data.
314
- */
315
- get affectsData() {
316
- if (!this._liveRange) {
317
- throw new CKEditorError('marker-destroyed', this);
318
- }
319
- return this._affectsData;
320
- }
321
- /**
322
- * Returns the marker data (properties defining the marker).
323
- */
324
- getData() {
325
- return {
326
- range: this.getRange(),
327
- affectsData: this.affectsData,
328
- managedUsingOperations: this.managedUsingOperations
329
- };
330
- }
331
- /**
332
- * Returns current marker start position.
333
- */
334
- getStart() {
335
- if (!this._liveRange) {
336
- throw new CKEditorError('marker-destroyed', this);
337
- }
338
- return this._liveRange.start.clone();
339
- }
340
- /**
341
- * Returns current marker end position.
342
- */
343
- getEnd() {
344
- if (!this._liveRange) {
345
- throw new CKEditorError('marker-destroyed', this);
346
- }
347
- return this._liveRange.end.clone();
348
- }
349
- /**
350
- * Returns a range that represents the current state of the marker.
351
- *
352
- * Keep in mind that returned value is a {@link module:engine/model/range~Range Range}, not a
353
- * {@link module:engine/model/liverange~LiveRange LiveRange}. This means that it is up-to-date and relevant only
354
- * until next model document change. Do not store values returned by this method. Instead, store {@link ~Marker#name}
355
- * and get `Marker` instance from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection} every
356
- * time there is a need to read marker properties. This will guarantee that the marker has not been removed and
357
- * that it's data is up-to-date.
358
- */
359
- getRange() {
360
- if (!this._liveRange) {
361
- throw new CKEditorError('marker-destroyed', this);
362
- }
363
- return this._liveRange.toRange();
364
- }
365
- /**
366
- * Binds new live range to the marker and detach the old one if is attached.
367
- *
368
- * @internal
369
- * @param liveRange Live range to attach
370
- * @returns Attached live range.
371
- */
372
- _attachLiveRange(liveRange) {
373
- if (this._liveRange) {
374
- this._detachLiveRange();
375
- }
376
- // Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).
377
- liveRange.delegate('change:range').to(this);
378
- liveRange.delegate('change:content').to(this);
379
- this._liveRange = liveRange;
380
- return liveRange;
381
- }
382
- /**
383
- * Unbinds and destroys currently attached live range.
384
- *
385
- * @internal
386
- */
387
- _detachLiveRange() {
388
- this._liveRange.stopDelegating('change:range', this);
389
- this._liveRange.stopDelegating('change:content', this);
390
- this._liveRange.detach();
391
- this._liveRange = null;
392
- }
393
- }
394
- // The magic of type inference using `is` method is centralized in `TypeCheckable` class.
395
- // Proper overload would interfere with that.
396
- Marker.prototype.is = function (type) {
397
- return type === 'marker' || type === 'model:marker';
398
- };
399
- /**
400
- * Cannot use a {@link module:engine/model/markercollection~MarkerCollection#destroy destroyed marker} instance.
401
- *
402
- * @error marker-destroyed
403
- */
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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
+ /**
6
+ * @module engine/model/markercollection
7
+ */
8
+ import TypeCheckable from './typecheckable';
9
+ import LiveRange from './liverange';
10
+ import { CKEditorError, EmitterMixin } from '@ckeditor/ckeditor5-utils';
11
+ /**
12
+ * The collection of all {@link module:engine/model/markercollection~Marker markers} attached to the document.
13
+ * It lets you {@link module:engine/model/markercollection~MarkerCollection#get get} markers or track them using
14
+ * {@link module:engine/model/markercollection~MarkerCollection#event:update} event.
15
+ *
16
+ * To create, change or remove makers use {@link module:engine/model/writer~Writer model writers'} methods:
17
+ * {@link module:engine/model/writer~Writer#addMarker} or {@link module:engine/model/writer~Writer#removeMarker}. Since
18
+ * the writer is the only proper way to change the data model it is not possible to change markers directly using this
19
+ * collection. All markers created by the writer will be automatically added to this collection.
20
+ *
21
+ * By default there is one marker collection available as {@link module:engine/model/model~Model#markers model property}.
22
+ *
23
+ * @see module:engine/model/markercollection~Marker
24
+ */
25
+ export default class MarkerCollection extends EmitterMixin() {
26
+ constructor() {
27
+ super(...arguments);
28
+ /**
29
+ * Stores {@link ~Marker markers} added to the collection.
30
+ */
31
+ this._markers = new Map();
32
+ }
33
+ /**
34
+ * Iterable interface.
35
+ *
36
+ * Iterates over all {@link ~Marker markers} added to the collection.
37
+ */
38
+ [Symbol.iterator]() {
39
+ return this._markers.values();
40
+ }
41
+ /**
42
+ * Checks if given {@link ~Marker marker} or marker name is in the collection.
43
+ *
44
+ * @param markerOrName Name of marker or marker instance to check.
45
+ * @returns `true` if marker is in the collection, `false` otherwise.
46
+ */
47
+ has(markerOrName) {
48
+ const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
49
+ return this._markers.has(markerName);
50
+ }
51
+ /**
52
+ * Returns {@link ~Marker marker} with given `markerName`.
53
+ *
54
+ * @param markerName Name of marker to get.
55
+ * @returns Marker with given name or `null` if such marker was
56
+ * not added to the collection.
57
+ */
58
+ get(markerName) {
59
+ return this._markers.get(markerName) || null;
60
+ }
61
+ /**
62
+ * Creates and adds a {@link ~Marker marker} to the `MarkerCollection` with given name on given
63
+ * {@link module:engine/model/range~Range range}.
64
+ *
65
+ * If `MarkerCollection` already had a marker with given name (or {@link ~Marker marker} was passed), the marker in
66
+ * collection is updated and {@link module:engine/model/markercollection~MarkerCollection#event:update} event is fired
67
+ * but only if there was a change (marker range or {@link module:engine/model/markercollection~Marker#managedUsingOperations}
68
+ * flag has changed.
69
+ *
70
+ * @internal
71
+ * @fires update
72
+ * @param markerOrName Name of marker to set or marker instance to update.
73
+ * @param range Marker range.
74
+ * @param managedUsingOperations Specifies whether the marker is managed using operations.
75
+ * @param affectsData Specifies whether the marker affects the data produced by the data pipeline
76
+ * (is persisted in the editor's data).
77
+ * @returns `Marker` instance which was added or updated.
78
+ */
79
+ _set(markerOrName, range, managedUsingOperations = false, affectsData = false) {
80
+ const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
81
+ if (markerName.includes(',')) {
82
+ /**
83
+ * Marker name cannot contain the "," character.
84
+ *
85
+ * @error markercollection-incorrect-marker-name
86
+ */
87
+ throw new CKEditorError('markercollection-incorrect-marker-name', this);
88
+ }
89
+ const oldMarker = this._markers.get(markerName);
90
+ if (oldMarker) {
91
+ const oldMarkerData = oldMarker.getData();
92
+ const oldRange = oldMarker.getRange();
93
+ let hasChanged = false;
94
+ if (!oldRange.isEqual(range)) {
95
+ oldMarker._attachLiveRange(LiveRange.fromRange(range));
96
+ hasChanged = true;
97
+ }
98
+ if (managedUsingOperations != oldMarker.managedUsingOperations) {
99
+ oldMarker._managedUsingOperations = managedUsingOperations;
100
+ hasChanged = true;
101
+ }
102
+ if (typeof affectsData === 'boolean' && affectsData != oldMarker.affectsData) {
103
+ oldMarker._affectsData = affectsData;
104
+ hasChanged = true;
105
+ }
106
+ if (hasChanged) {
107
+ this.fire(`update:${markerName}`, oldMarker, oldRange, range, oldMarkerData);
108
+ }
109
+ return oldMarker;
110
+ }
111
+ const liveRange = LiveRange.fromRange(range);
112
+ const marker = new Marker(markerName, liveRange, managedUsingOperations, affectsData);
113
+ this._markers.set(markerName, marker);
114
+ this.fire(`update:${markerName}`, marker, null, range, { ...marker.getData(), range: null });
115
+ return marker;
116
+ }
117
+ /**
118
+ * Removes given {@link ~Marker marker} or a marker with given name from the `MarkerCollection`.
119
+ *
120
+ * @internal
121
+ * @fires update
122
+ * @param markerOrName Marker or name of a marker to remove.
123
+ * @returns `true` if marker was found and removed, `false` otherwise.
124
+ */
125
+ _remove(markerOrName) {
126
+ const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
127
+ const oldMarker = this._markers.get(markerName);
128
+ if (oldMarker) {
129
+ this._markers.delete(markerName);
130
+ this.fire(`update:${markerName}`, oldMarker, oldMarker.getRange(), null, oldMarker.getData());
131
+ this._destroyMarker(oldMarker);
132
+ return true;
133
+ }
134
+ return false;
135
+ }
136
+ /**
137
+ * Fires an {@link module:engine/model/markercollection~MarkerCollection#event:update} event for the given {@link ~Marker marker}
138
+ * but does not change the marker. Useful to force {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast
139
+ * conversion} for the marker.
140
+ *
141
+ * @internal
142
+ * @fires update
143
+ * @param markerOrName Marker or name of a marker to refresh.
144
+ */
145
+ _refresh(markerOrName) {
146
+ const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
147
+ const marker = this._markers.get(markerName);
148
+ if (!marker) {
149
+ /**
150
+ * Marker with provided name does not exists.
151
+ *
152
+ * @error markercollection-refresh-marker-not-exists
153
+ */
154
+ throw new CKEditorError('markercollection-refresh-marker-not-exists', this);
155
+ }
156
+ const range = marker.getRange();
157
+ this.fire(`update:${markerName}`, marker, range, range, marker.getData());
158
+ }
159
+ /**
160
+ * Returns iterator that iterates over all markers, which ranges contain given {@link module:engine/model/position~Position position}.
161
+ */
162
+ *getMarkersAtPosition(position) {
163
+ for (const marker of this) {
164
+ if (marker.getRange().containsPosition(position)) {
165
+ yield marker;
166
+ }
167
+ }
168
+ }
169
+ /**
170
+ * Returns iterator that iterates over all markers, which intersects with given {@link module:engine/model/range~Range range}.
171
+ */
172
+ *getMarkersIntersectingRange(range) {
173
+ for (const marker of this) {
174
+ if (marker.getRange().getIntersection(range) !== null) {
175
+ yield marker;
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Destroys marker collection and all markers inside it.
181
+ */
182
+ destroy() {
183
+ for (const marker of this._markers.values()) {
184
+ this._destroyMarker(marker);
185
+ }
186
+ this._markers = null;
187
+ this.stopListening();
188
+ }
189
+ /**
190
+ * Iterates over all markers that starts with given `prefix`.
191
+ *
192
+ * ```ts
193
+ * const markerFooA = markersCollection.set( 'foo:a', rangeFooA );
194
+ * const markerFooB = markersCollection.set( 'foo:b', rangeFooB );
195
+ * const markerBarA = markersCollection.set( 'bar:a', rangeBarA );
196
+ * const markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );
197
+ * Array.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]
198
+ * Array.from( markersCollection.getMarkersGroup( 'a' ) ); // []
199
+ * ```
200
+ */
201
+ *getMarkersGroup(prefix) {
202
+ for (const marker of this._markers.values()) {
203
+ if (marker.name.startsWith(prefix + ':')) {
204
+ yield marker;
205
+ }
206
+ }
207
+ }
208
+ /**
209
+ * Destroys the marker.
210
+ */
211
+ _destroyMarker(marker) {
212
+ marker.stopListening();
213
+ marker._detachLiveRange();
214
+ }
215
+ }
216
+ /**
217
+ * `Marker` is a continuous part of the model (like a range), is named and represents some kind of information about the
218
+ * marked part of the model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
219
+ * the model document tree, markers are not stored directly in the document tree but in the
220
+ * {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving
221
+ * additional meaning to the part of a model document between marker start and marker end.
222
+ *
223
+ * In this sense, markers are similar to adding and converting attributes on nodes. The difference is that attribute is
224
+ * connected with a given node (e.g. a character is bold no matter if it gets moved or content around it changes).
225
+ * Markers on the other hand are continuous ranges and are characterized by their start and end position. This means that
226
+ * any character in the marker is marked by the marker. For example, if a character is moved outside of marker it stops being
227
+ * "special" and the marker is shrunk. Similarly, when a character is moved into the marker from other place in document
228
+ * model, it starts being "special" and the marker is enlarged.
229
+ *
230
+ * Another upside of markers is that finding marked part of document is fast and easy. Using attributes to mark some nodes
231
+ * and then trying to find that part of document would require traversing whole document tree. Marker gives instant access
232
+ * to the range which it is marking at the moment.
233
+ *
234
+ * Markers are built from a name and a range.
235
+ *
236
+ * Range of the marker is updated automatically when document changes, using
237
+ * {@link module:engine/model/liverange~LiveRange live range} mechanism.
238
+ *
239
+ * Name is used to group and identify markers. Names have to be unique, but markers can be grouped by
240
+ * using common prefixes, separated with `:`, for example: `user:john` or `search:3`. That's useful in term of creating
241
+ * namespaces for custom elements (e.g. comments, highlights). You can use this prefixes in
242
+ * {@link module:engine/model/markercollection~MarkerCollection#event:update} listeners to listen on changes in a group of markers.
243
+ * For instance: `model.markers.on( 'update:user', callback );` will be called whenever any `user:*` markers changes.
244
+ *
245
+ * There are two types of markers.
246
+ *
247
+ * 1. Markers managed directly, without using operations. They are added directly by {@link module:engine/model/writer~Writer}
248
+ * to the {@link module:engine/model/markercollection~MarkerCollection} without any additional mechanism. They can be used
249
+ * as bookmarks or visual markers. They are great for showing results of the find, or select link when the focus is in the input.
250
+ *
251
+ * 1. Markers managed using operations. These markers are also stored in {@link module:engine/model/markercollection~MarkerCollection}
252
+ * but changes in these markers is managed the same way all other changes in the model structure - using operations.
253
+ * Therefore, they are handled in the undo stack and synchronized between clients if the collaboration plugin is enabled.
254
+ * This type of markers is useful for solutions like spell checking or comments.
255
+ *
256
+ * Both type of them should be added / updated by {@link module:engine/model/writer~Writer#addMarker}
257
+ * and removed by {@link module:engine/model/writer~Writer#removeMarker} methods.
258
+ *
259
+ * ```ts
260
+ * model.change( ( writer ) => {
261
+ * const marker = writer.addMarker( name, { range, usingOperation: true } );
262
+ *
263
+ * // ...
264
+ *
265
+ * writer.removeMarker( marker );
266
+ * } );
267
+ * ```
268
+ *
269
+ * See {@link module:engine/model/writer~Writer} to find more examples.
270
+ *
271
+ * Since markers need to track change in the document, for efficiency reasons, it is best to create and keep as little
272
+ * markers as possible and remove them as soon as they are not needed anymore.
273
+ *
274
+ * Markers can be downcasted and upcasted.
275
+ *
276
+ * Markers downcast happens on {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker} and
277
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:removeMarker} events.
278
+ * Use {@link module:engine/conversion/downcasthelpers downcast converters} or attach a custom converter to mentioned events.
279
+ * For {@link module:engine/controller/datacontroller~DataController data pipeline}, marker should be downcasted to an element.
280
+ * Then, it can be upcasted back to a marker. Again, use {@link module:engine/conversion/upcasthelpers upcast converters} or
281
+ * attach a custom converter to {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element}.
282
+ *
283
+ * `Marker` instances are created and destroyed only by {@link ~MarkerCollection MarkerCollection}.
284
+ */
285
+ class Marker extends EmitterMixin(TypeCheckable) {
286
+ /**
287
+ * Creates a marker instance.
288
+ *
289
+ * @param name Marker name.
290
+ * @param liveRange Range marked by the marker.
291
+ * @param managedUsingOperations Specifies whether the marker is managed using operations.
292
+ * @param affectsData Specifies whether the marker affects the data produced by the data pipeline (is persisted in the editor's data).
293
+ */
294
+ constructor(name, liveRange, managedUsingOperations, affectsData) {
295
+ super();
296
+ this.name = name;
297
+ this._liveRange = this._attachLiveRange(liveRange);
298
+ this._managedUsingOperations = managedUsingOperations;
299
+ this._affectsData = affectsData;
300
+ }
301
+ /**
302
+ * A value indicating if the marker is managed using operations.
303
+ * See {@link ~Marker marker class description} to learn more about marker types.
304
+ * See {@link module:engine/model/writer~Writer#addMarker}.
305
+ */
306
+ get managedUsingOperations() {
307
+ if (!this._liveRange) {
308
+ throw new CKEditorError('marker-destroyed', this);
309
+ }
310
+ return this._managedUsingOperations;
311
+ }
312
+ /**
313
+ * A value indicating if the marker changes the data.
314
+ */
315
+ get affectsData() {
316
+ if (!this._liveRange) {
317
+ throw new CKEditorError('marker-destroyed', this);
318
+ }
319
+ return this._affectsData;
320
+ }
321
+ /**
322
+ * Returns the marker data (properties defining the marker).
323
+ */
324
+ getData() {
325
+ return {
326
+ range: this.getRange(),
327
+ affectsData: this.affectsData,
328
+ managedUsingOperations: this.managedUsingOperations
329
+ };
330
+ }
331
+ /**
332
+ * Returns current marker start position.
333
+ */
334
+ getStart() {
335
+ if (!this._liveRange) {
336
+ throw new CKEditorError('marker-destroyed', this);
337
+ }
338
+ return this._liveRange.start.clone();
339
+ }
340
+ /**
341
+ * Returns current marker end position.
342
+ */
343
+ getEnd() {
344
+ if (!this._liveRange) {
345
+ throw new CKEditorError('marker-destroyed', this);
346
+ }
347
+ return this._liveRange.end.clone();
348
+ }
349
+ /**
350
+ * Returns a range that represents the current state of the marker.
351
+ *
352
+ * Keep in mind that returned value is a {@link module:engine/model/range~Range Range}, not a
353
+ * {@link module:engine/model/liverange~LiveRange LiveRange}. This means that it is up-to-date and relevant only
354
+ * until next model document change. Do not store values returned by this method. Instead, store {@link ~Marker#name}
355
+ * and get `Marker` instance from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection} every
356
+ * time there is a need to read marker properties. This will guarantee that the marker has not been removed and
357
+ * that it's data is up-to-date.
358
+ */
359
+ getRange() {
360
+ if (!this._liveRange) {
361
+ throw new CKEditorError('marker-destroyed', this);
362
+ }
363
+ return this._liveRange.toRange();
364
+ }
365
+ /**
366
+ * Binds new live range to the marker and detach the old one if is attached.
367
+ *
368
+ * @internal
369
+ * @param liveRange Live range to attach
370
+ * @returns Attached live range.
371
+ */
372
+ _attachLiveRange(liveRange) {
373
+ if (this._liveRange) {
374
+ this._detachLiveRange();
375
+ }
376
+ // Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).
377
+ liveRange.delegate('change:range').to(this);
378
+ liveRange.delegate('change:content').to(this);
379
+ this._liveRange = liveRange;
380
+ return liveRange;
381
+ }
382
+ /**
383
+ * Unbinds and destroys currently attached live range.
384
+ *
385
+ * @internal
386
+ */
387
+ _detachLiveRange() {
388
+ this._liveRange.stopDelegating('change:range', this);
389
+ this._liveRange.stopDelegating('change:content', this);
390
+ this._liveRange.detach();
391
+ this._liveRange = null;
392
+ }
393
+ }
394
+ // The magic of type inference using `is` method is centralized in `TypeCheckable` class.
395
+ // Proper overload would interfere with that.
396
+ Marker.prototype.is = function (type) {
397
+ return type === 'marker' || type === 'model:marker';
398
+ };
399
+ /**
400
+ * Cannot use a {@link module:engine/model/markercollection~MarkerCollection#destroy destroyed marker} instance.
401
+ *
402
+ * @error marker-destroyed
403
+ */