@ckeditor/ckeditor5-engine 36.0.1 → 37.0.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 (200) hide show
  1. package/README.md +1 -1
  2. package/package.json +24 -23
  3. package/src/controller/datacontroller.d.ts +331 -0
  4. package/src/controller/datacontroller.js +62 -109
  5. package/src/controller/editingcontroller.d.ts +98 -0
  6. package/src/controller/editingcontroller.js +22 -46
  7. package/src/conversion/conversion.d.ts +476 -0
  8. package/src/conversion/conversion.js +328 -347
  9. package/src/conversion/conversionhelpers.d.ts +26 -0
  10. package/src/conversion/conversionhelpers.js +1 -5
  11. package/src/conversion/downcastdispatcher.d.ts +547 -0
  12. package/src/conversion/downcastdispatcher.js +74 -152
  13. package/src/conversion/downcasthelpers.d.ts +1226 -0
  14. package/src/conversion/downcasthelpers.js +843 -762
  15. package/src/conversion/mapper.d.ts +499 -0
  16. package/src/conversion/mapper.js +84 -99
  17. package/src/conversion/modelconsumable.d.ts +201 -0
  18. package/src/conversion/modelconsumable.js +96 -99
  19. package/src/conversion/upcastdispatcher.d.ts +492 -0
  20. package/src/conversion/upcastdispatcher.js +73 -100
  21. package/src/conversion/upcasthelpers.d.ts +499 -0
  22. package/src/conversion/upcasthelpers.js +406 -373
  23. package/src/conversion/viewconsumable.d.ts +177 -0
  24. package/src/conversion/viewconsumable.js +157 -162
  25. package/src/dataprocessor/basichtmlwriter.d.ts +18 -0
  26. package/src/dataprocessor/basichtmlwriter.js +0 -9
  27. package/src/dataprocessor/dataprocessor.d.ts +61 -0
  28. package/src/dataprocessor/htmldataprocessor.d.ts +76 -0
  29. package/src/dataprocessor/htmldataprocessor.js +6 -28
  30. package/src/dataprocessor/htmlwriter.d.ts +16 -0
  31. package/src/dataprocessor/xmldataprocessor.d.ts +90 -0
  32. package/src/dataprocessor/xmldataprocessor.js +8 -40
  33. package/src/dev-utils/model.d.ts +124 -0
  34. package/src/dev-utils/model.js +41 -38
  35. package/src/dev-utils/operationreplayer.d.ts +51 -0
  36. package/src/dev-utils/operationreplayer.js +6 -14
  37. package/src/dev-utils/utils.d.ts +37 -0
  38. package/src/dev-utils/utils.js +5 -18
  39. package/src/dev-utils/view.d.ts +319 -0
  40. package/src/dev-utils/view.js +205 -226
  41. package/src/index.d.ts +105 -0
  42. package/src/index.js +1 -0
  43. package/src/model/batch.d.ts +106 -0
  44. package/src/model/differ.d.ts +329 -0
  45. package/src/model/document.d.ts +245 -0
  46. package/src/model/document.js +1 -1
  47. package/src/model/documentfragment.d.ts +196 -0
  48. package/src/model/documentfragment.js +2 -2
  49. package/src/model/documentselection.d.ts +420 -0
  50. package/src/model/element.d.ts +165 -0
  51. package/src/model/history.d.ts +114 -0
  52. package/src/model/item.d.ts +14 -0
  53. package/src/model/liveposition.d.ts +77 -0
  54. package/src/model/liverange.d.ts +102 -0
  55. package/src/model/markercollection.d.ts +335 -0
  56. package/src/model/model.d.ts +812 -0
  57. package/src/model/model.js +59 -30
  58. package/src/model/node.d.ts +256 -0
  59. package/src/model/nodelist.d.ts +91 -0
  60. package/src/model/operation/attributeoperation.d.ts +98 -0
  61. package/src/model/operation/detachoperation.d.ts +55 -0
  62. package/src/model/operation/insertoperation.d.ts +85 -0
  63. package/src/model/operation/markeroperation.d.ts +86 -0
  64. package/src/model/operation/mergeoperation.d.ts +95 -0
  65. package/src/model/operation/moveoperation.d.ts +91 -0
  66. package/src/model/operation/nooperation.d.ts +33 -0
  67. package/src/model/operation/operation.d.ts +89 -0
  68. package/src/model/operation/operationfactory.d.ts +18 -0
  69. package/src/model/operation/renameoperation.d.ts +78 -0
  70. package/src/model/operation/rootattributeoperation.d.ts +97 -0
  71. package/src/model/operation/rootattributeoperation.js +1 -1
  72. package/src/model/operation/splitoperation.d.ts +104 -0
  73. package/src/model/operation/transform.d.ts +100 -0
  74. package/src/model/operation/utils.d.ts +71 -0
  75. package/src/model/position.d.ts +539 -0
  76. package/src/model/position.js +1 -1
  77. package/src/model/range.d.ts +458 -0
  78. package/src/model/range.js +1 -1
  79. package/src/model/rootelement.d.ts +40 -0
  80. package/src/model/schema.d.ts +1176 -0
  81. package/src/model/schema.js +15 -15
  82. package/src/model/selection.d.ts +472 -0
  83. package/src/model/text.d.ts +66 -0
  84. package/src/model/text.js +0 -2
  85. package/src/model/textproxy.d.ts +144 -0
  86. package/src/model/treewalker.d.ts +186 -0
  87. package/src/model/treewalker.js +19 -10
  88. package/src/model/typecheckable.d.ts +255 -0
  89. package/src/model/utils/autoparagraphing.d.ts +37 -0
  90. package/src/model/utils/deletecontent.d.ts +58 -0
  91. package/src/model/utils/findoptimalinsertionrange.d.ts +32 -0
  92. package/src/model/utils/getselectedcontent.d.ts +30 -0
  93. package/src/model/utils/insertcontent.d.ts +46 -0
  94. package/src/model/utils/insertcontent.js +2 -12
  95. package/src/model/utils/insertobject.d.ts +44 -0
  96. package/src/model/utils/insertobject.js +3 -14
  97. package/src/model/utils/modifyselection.d.ts +48 -0
  98. package/src/model/utils/selection-post-fixer.d.ts +65 -0
  99. package/src/model/writer.d.ts +726 -0
  100. package/src/model/writer.js +6 -4
  101. package/src/view/attributeelement.d.ts +108 -0
  102. package/src/view/attributeelement.js +25 -69
  103. package/src/view/containerelement.d.ts +49 -0
  104. package/src/view/containerelement.js +10 -43
  105. package/src/view/datatransfer.d.ts +75 -0
  106. package/src/view/document.d.ts +184 -0
  107. package/src/view/document.js +15 -84
  108. package/src/view/documentfragment.d.ts +150 -0
  109. package/src/view/documentfragment.js +40 -81
  110. package/src/view/documentselection.d.ts +219 -0
  111. package/src/view/documentselection.js +75 -121
  112. package/src/view/domconverter.d.ts +620 -0
  113. package/src/view/domconverter.js +159 -276
  114. package/src/view/downcastwriter.d.ts +804 -0
  115. package/src/view/downcastwriter.js +336 -380
  116. package/src/view/editableelement.d.ts +52 -0
  117. package/src/view/editableelement.js +9 -49
  118. package/src/view/element.d.ts +466 -0
  119. package/src/view/element.js +150 -222
  120. package/src/view/elementdefinition.d.ts +87 -0
  121. package/src/view/emptyelement.d.ts +41 -0
  122. package/src/view/emptyelement.js +11 -44
  123. package/src/view/filler.d.ts +111 -0
  124. package/src/view/filler.js +24 -21
  125. package/src/view/item.d.ts +14 -0
  126. package/src/view/matcher.d.ts +486 -0
  127. package/src/view/matcher.js +247 -218
  128. package/src/view/node.d.ts +160 -0
  129. package/src/view/node.js +26 -100
  130. package/src/view/observer/arrowkeysobserver.d.ts +41 -0
  131. package/src/view/observer/arrowkeysobserver.js +0 -13
  132. package/src/view/observer/bubblingemittermixin.d.ts +166 -0
  133. package/src/view/observer/bubblingemittermixin.js +36 -25
  134. package/src/view/observer/bubblingeventinfo.d.ts +47 -0
  135. package/src/view/observer/bubblingeventinfo.js +3 -29
  136. package/src/view/observer/clickobserver.d.ts +43 -0
  137. package/src/view/observer/clickobserver.js +9 -19
  138. package/src/view/observer/compositionobserver.d.ts +82 -0
  139. package/src/view/observer/compositionobserver.js +13 -42
  140. package/src/view/observer/domeventdata.d.ts +50 -0
  141. package/src/view/observer/domeventdata.js +5 -30
  142. package/src/view/observer/domeventobserver.d.ts +69 -0
  143. package/src/view/observer/domeventobserver.js +19 -21
  144. package/src/view/observer/fakeselectionobserver.d.ts +46 -0
  145. package/src/view/observer/fakeselectionobserver.js +2 -15
  146. package/src/view/observer/focusobserver.d.ts +82 -0
  147. package/src/view/observer/focusobserver.js +14 -40
  148. package/src/view/observer/inputobserver.d.ts +86 -0
  149. package/src/view/observer/inputobserver.js +18 -64
  150. package/src/view/observer/keyobserver.d.ts +67 -0
  151. package/src/view/observer/keyobserver.js +8 -42
  152. package/src/view/observer/mouseobserver.d.ts +89 -0
  153. package/src/view/observer/mouseobserver.js +8 -28
  154. package/src/view/observer/mutationobserver.d.ts +82 -0
  155. package/src/view/observer/mutationobserver.js +7 -37
  156. package/src/view/observer/observer.d.ts +84 -0
  157. package/src/view/observer/observer.js +12 -25
  158. package/src/view/observer/selectionobserver.d.ts +143 -0
  159. package/src/view/observer/selectionobserver.js +9 -99
  160. package/src/view/observer/tabobserver.d.ts +42 -0
  161. package/src/view/observer/tabobserver.js +0 -14
  162. package/src/view/placeholder.d.ts +85 -0
  163. package/src/view/placeholder.js +26 -43
  164. package/src/view/position.d.ts +189 -0
  165. package/src/view/position.js +36 -83
  166. package/src/view/range.d.ts +279 -0
  167. package/src/view/range.js +79 -122
  168. package/src/view/rawelement.d.ts +73 -0
  169. package/src/view/rawelement.js +34 -48
  170. package/src/view/renderer.d.ts +265 -0
  171. package/src/view/renderer.js +105 -193
  172. package/src/view/rooteditableelement.d.ts +41 -0
  173. package/src/view/rooteditableelement.js +12 -40
  174. package/src/view/selection.d.ts +375 -0
  175. package/src/view/selection.js +79 -153
  176. package/src/view/styles/background.d.ts +33 -0
  177. package/src/view/styles/background.js +14 -12
  178. package/src/view/styles/border.d.ts +43 -0
  179. package/src/view/styles/border.js +58 -48
  180. package/src/view/styles/margin.d.ts +29 -0
  181. package/src/view/styles/margin.js +13 -11
  182. package/src/view/styles/padding.d.ts +29 -0
  183. package/src/view/styles/padding.js +13 -11
  184. package/src/view/styles/utils.d.ts +93 -0
  185. package/src/view/styles/utils.js +22 -48
  186. package/src/view/stylesmap.d.ts +675 -0
  187. package/src/view/stylesmap.js +249 -244
  188. package/src/view/text.d.ts +74 -0
  189. package/src/view/text.js +16 -46
  190. package/src/view/textproxy.d.ts +97 -0
  191. package/src/view/textproxy.js +10 -59
  192. package/src/view/treewalker.d.ts +195 -0
  193. package/src/view/treewalker.js +43 -106
  194. package/src/view/typecheckable.d.ts +401 -0
  195. package/src/view/uielement.d.ts +96 -0
  196. package/src/view/uielement.js +28 -62
  197. package/src/view/upcastwriter.d.ts +328 -0
  198. package/src/view/upcastwriter.js +124 -134
  199. package/src/view/view.d.ts +327 -0
  200. package/src/view/view.js +79 -150
@@ -14,12 +14,12 @@ import ModelElement from '../model/element';
14
14
  import ModelPosition from '../model/position';
15
15
  import ViewAttributeElement from '../view/attributeelement';
16
16
  import ConversionHelpers from './conversionhelpers';
17
- import { cloneDeep } from 'lodash-es';
18
17
  import { CKEditorError, toArray } from '@ckeditor/ckeditor5-utils';
18
+ import { cloneDeep } from 'lodash-es';
19
19
  /**
20
20
  * Downcast conversion helper functions.
21
21
  *
22
- * Learn more about {@glink framework/guides/deep-dive/conversion/downcast downcast helpers}.
22
+ * Learn more about {@glink framework/deep-dive/conversion/downcast downcast helpers}.
23
23
  *
24
24
  * @extends module:engine/conversion/conversionhelpers~ConversionHelpers
25
25
  */
@@ -29,33 +29,35 @@ export default class DowncastHelpers extends ConversionHelpers {
29
29
  *
30
30
  * This conversion results in creating a view element. For example, model `<paragraph>Foo</paragraph>` becomes `<p>Foo</p>` in the view.
31
31
  *
32
- * editor.conversion.for( 'downcast' ).elementToElement( {
33
- * model: 'paragraph',
34
- * view: 'p'
35
- * } );
36
- *
37
- * editor.conversion.for( 'downcast' ).elementToElement( {
38
- * model: 'paragraph',
39
- * view: 'div',
40
- * converterPriority: 'high'
41
- * } );
42
- *
43
- * editor.conversion.for( 'downcast' ).elementToElement( {
44
- * model: 'fancyParagraph',
45
- * view: {
46
- * name: 'p',
47
- * classes: 'fancy'
48
- * }
49
- * } );
50
- *
51
- * editor.conversion.for( 'downcast' ).elementToElement( {
52
- * model: 'heading',
53
- * view: ( modelElement, conversionApi ) => {
54
- * const { writer } = conversionApi;
55
- *
56
- * return writer.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) );
57
- * }
58
- * } );
32
+ * ```ts
33
+ * editor.conversion.for( 'downcast' ).elementToElement( {
34
+ * model: 'paragraph',
35
+ * view: 'p'
36
+ * } );
37
+ *
38
+ * editor.conversion.for( 'downcast' ).elementToElement( {
39
+ * model: 'paragraph',
40
+ * view: 'div',
41
+ * converterPriority: 'high'
42
+ * } );
43
+ *
44
+ * editor.conversion.for( 'downcast' ).elementToElement( {
45
+ * model: 'fancyParagraph',
46
+ * view: {
47
+ * name: 'p',
48
+ * classes: 'fancy'
49
+ * }
50
+ * } );
51
+ *
52
+ * editor.conversion.for( 'downcast' ).elementToElement( {
53
+ * model: 'heading',
54
+ * view: ( modelElement, conversionApi ) => {
55
+ * const { writer } = conversionApi;
56
+ *
57
+ * return writer.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) );
58
+ * }
59
+ * } );
60
+ * ```
59
61
  *
60
62
  * The element-to-element conversion supports the reconversion mechanism. It can be enabled by using either the `attributes` or
61
63
  * the `children` props on a model description. You will find a couple examples below.
@@ -63,93 +65,108 @@ export default class DowncastHelpers extends ConversionHelpers {
63
65
  * In order to reconvert an element if any of its direct children have been added or removed, use the `children` property on a `model`
64
66
  * description. For example, this model:
65
67
  *
66
- * <box>
67
- * <paragraph>Some text.</paragraph>
68
- * </box>
68
+ * ```xml
69
+ * <box>
70
+ * <paragraph>Some text.</paragraph>
71
+ * </box>
72
+ * ```
69
73
  *
70
74
  * will be converted into this structure in the view:
71
75
  *
72
- * <div class="box" data-type="single">
73
- * <p>Some text.</p>
74
- * </div>
76
+ * ```html
77
+ * <div class="box" data-type="single">
78
+ * <p>Some text.</p>
79
+ * </div>
80
+ * ```
75
81
  *
76
82
  * But if more items were inserted in the model:
77
83
  *
78
- * <box>
79
- * <paragraph>Some text.</paragraph>
80
- * <paragraph>Other item.</paragraph>
81
- * </box>
84
+ * ```xml
85
+ * <box>
86
+ * <paragraph>Some text.</paragraph>
87
+ * <paragraph>Other item.</paragraph>
88
+ * </box>
89
+ * ```
82
90
  *
83
91
  * it will be converted into this structure in the view (note the element `data-type` change):
84
92
  *
85
- * <div class="box" data-type="multiple">
86
- * <p>Some text.</p>
87
- * <p>Other item.</p>
88
- * </div>
93
+ * ```html
94
+ * <div class="box" data-type="multiple">
95
+ * <p>Some text.</p>
96
+ * <p>Other item.</p>
97
+ * </div>
98
+ * ```
89
99
  *
90
100
  * Such a converter would look like this (note that the `paragraph` elements are converted separately):
91
101
  *
92
- * editor.conversion.for( 'downcast' ).elementToElement( {
93
- * model: {
94
- * name: 'box',
95
- * children: true
96
- * },
97
- * view: ( modelElement, conversionApi ) => {
98
- * const { writer } = conversionApi;
99
- *
100
- * return writer.createContainerElement( 'div', {
101
- * class: 'box',
102
- * 'data-type': modelElement.childCount == 1 ? 'single' : 'multiple'
103
- * } );
104
- * }
105
- * } );
102
+ * ```ts
103
+ * editor.conversion.for( 'downcast' ).elementToElement( {
104
+ * model: {
105
+ * name: 'box',
106
+ * children: true
107
+ * },
108
+ * view: ( modelElement, conversionApi ) => {
109
+ * const { writer } = conversionApi;
110
+ *
111
+ * return writer.createContainerElement( 'div', {
112
+ * class: 'box',
113
+ * 'data-type': modelElement.childCount == 1 ? 'single' : 'multiple'
114
+ * } );
115
+ * }
116
+ * } );
117
+ * ```
106
118
  *
107
119
  * In order to reconvert element if any of its attributes have been updated, use the `attributes` property on a `model`
108
120
  * description. For example, this model:
109
121
  *
110
- * <heading level="2">Some text.</heading>
122
+ * ```xml
123
+ * <heading level="2">Some text.</heading>
124
+ * ```
111
125
  *
112
126
  * will be converted into this structure in the view:
113
127
  *
114
- * <h2>Some text.</h2>
128
+ * ```html
129
+ * <h2>Some text.</h2>
130
+ * ```
115
131
  *
116
132
  * But if the `heading` element's `level` attribute has been updated to `3` for example, then
117
133
  * it will be converted into this structure in the view:
118
134
  *
119
- * <h3>Some text.</h3>
135
+ * ```html
136
+ * <h3>Some text.</h3>
137
+ * ```
120
138
  *
121
139
  * Such a converter would look as follows:
122
140
  *
123
- * editor.conversion.for( 'downcast' ).elementToElement( {
124
- * model: {
125
- * name: 'heading',
126
- * attributes: 'level'
127
- * },
128
- * view: ( modelElement, conversionApi ) => {
129
- * const { writer } = conversionApi;
141
+ * ```ts
142
+ * editor.conversion.for( 'downcast' ).elementToElement( {
143
+ * model: {
144
+ * name: 'heading',
145
+ * attributes: 'level'
146
+ * },
147
+ * view: ( modelElement, conversionApi ) => {
148
+ * const { writer } = conversionApi;
130
149
  *
131
- * return writer.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) );
132
- * }
133
- * } );
150
+ * return writer.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) );
151
+ * }
152
+ * } );
153
+ * ```
134
154
  *
135
155
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
136
156
  * to the conversion process.
137
157
  *
138
158
  * You can read more about the element-to-element conversion in the
139
- * {@glink framework/guides/deep-dive/conversion/downcast downcast conversion} guide.
159
+ * {@glink framework/deep-dive/conversion/downcast downcast conversion} guide.
140
160
  *
141
- * @method #elementToElement
142
- * @param {Object} config Conversion configuration.
143
- * @param {String|Object} config.model The description or a name of the model element to convert.
144
- * @param {String|Array.<String>} [config.model.attributes] The list of attribute names that should be consumed while creating
161
+ * @param config Conversion configuration.
162
+ * @param config.model The description or a name of the model element to convert.
163
+ * @param config.model.attributes The list of attribute names that should be consumed while creating
145
164
  * the view element. Note that the view will be reconverted if any of the listed attributes changes.
146
- * @param {Boolean} [config.model.children] Specifies whether the view element requires reconversion if the list
165
+ * @param config.model.children Specifies whether the view element requires reconversion if the list
147
166
  * of the model child nodes changed.
148
- * @param {module:engine/view/elementdefinition~ElementDefinition|module:engine/conversion/downcasthelpers~ElementCreatorFunction}
149
- * config.view A view element definition or a function that takes the model element and
167
+ * @param config.view A view element definition or a function that takes the model element and
150
168
  * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API}
151
169
  * as parameters and returns a view container element.
152
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
153
170
  */
154
171
  elementToElement(config) {
155
172
  return this.add(downcastElementToElement(config));
@@ -160,68 +177,80 @@ export default class DowncastHelpers extends ConversionHelpers {
160
177
  * This conversion results in creating a view structure with one or more slots defined for the child nodes.
161
178
  * For example, a model `<table>` may become this structure in the view:
162
179
  *
163
- * <figure class="table">
164
- * <table>
165
- * <tbody>${ slot for table rows }</tbody>
166
- * </table>
167
- * </figure>
180
+ * ```html
181
+ * <figure class="table">
182
+ * <table>
183
+ * <tbody>${ slot for table rows }</tbody>
184
+ * </table>
185
+ * </figure>
186
+ * ```
168
187
  *
169
188
  * The children of the model's `<table>` element will be inserted into the `<tbody>` element.
170
189
  * If the `elementToElement()` helper was used, the children would be inserted into the `<figure>`.
171
190
  *
172
191
  * An example converter that converts the following model structure:
173
192
  *
174
- * <wrappedParagraph>Some text.</wrappedParagraph>
193
+ * ```xml
194
+ * <wrappedParagraph>Some text.</wrappedParagraph>
195
+ * ```
175
196
  *
176
197
  * into this structure in the view:
177
198
  *
178
- * <div class="wrapper">
179
- * <p>Some text.</p>
180
- * </div>
199
+ * ```html
200
+ * <div class="wrapper">
201
+ * <p>Some text.</p>
202
+ * </div>
203
+ * ```
181
204
  *
182
205
  * would look like this:
183
206
  *
184
- * editor.conversion.for( 'downcast' ).elementToStructure( {
185
- * model: 'wrappedParagraph',
186
- * view: ( modelElement, conversionApi ) => {
187
- * const { writer } = conversionApi;
207
+ * ```ts
208
+ * editor.conversion.for( 'downcast' ).elementToStructure( {
209
+ * model: 'wrappedParagraph',
210
+ * view: ( modelElement, conversionApi ) => {
211
+ * const { writer } = conversionApi;
188
212
  *
189
- * const wrapperViewElement = writer.createContainerElement( 'div', { class: 'wrapper' } );
190
- * const paragraphViewElement = writer.createContainerElement( 'p' );
213
+ * const wrapperViewElement = writer.createContainerElement( 'div', { class: 'wrapper' } );
214
+ * const paragraphViewElement = writer.createContainerElement( 'p' );
191
215
  *
192
- * writer.insert( writer.createPositionAt( wrapperViewElement, 0 ), paragraphViewElement );
193
- * writer.insert( writer.createPositionAt( paragraphViewElement, 0 ), writer.createSlot() );
216
+ * writer.insert( writer.createPositionAt( wrapperViewElement, 0 ), paragraphViewElement );
217
+ * writer.insert( writer.createPositionAt( paragraphViewElement, 0 ), writer.createSlot() );
194
218
  *
195
- * return wrapperViewElement;
196
- * }
197
- * } );
219
+ * return wrapperViewElement;
220
+ * }
221
+ * } );
222
+ * ```
198
223
  *
199
224
  * The `slorFor()` function can also take a callback that allows filtering which children of the model element
200
225
  * should be converted into this slot.
201
226
  *
202
227
  * Imagine a table feature where for this model structure:
203
228
  *
204
- * <table headingRows="1">
205
- * <tableRow> ... table cells 1 ... </tableRow>
206
- * <tableRow> ... table cells 2 ... </tableRow>
207
- * <tableRow> ... table cells 3 ... </tableRow>
208
- * <caption>Caption text</caption>
209
- * </table>
229
+ * ```xml
230
+ * <table headingRows="1">
231
+ * <tableRow> ... table cells 1 ... </tableRow>
232
+ * <tableRow> ... table cells 2 ... </tableRow>
233
+ * <tableRow> ... table cells 3 ... </tableRow>
234
+ * <caption>Caption text</caption>
235
+ * </table>
236
+ * ```
210
237
  *
211
238
  * we want to generate this view structure:
212
239
  *
213
- * <figure class="table">
214
- * <table>
215
- * <thead>
216
- * <tr> ... table cells 1 ... </tr>
217
- * </thead>
218
- * <tbody>
219
- * <tr> ... table cells 2 ... </tr>
220
- * <tr> ... table cells 3 ... </tr>
221
- * </tbody>
222
- * </table>
223
- * <figcaption>Caption text</figcaption>
224
- * </figure>
240
+ * ```html
241
+ * <figure class="table">
242
+ * <table>
243
+ * <thead>
244
+ * <tr> ... table cells 1 ... </tr>
245
+ * </thead>
246
+ * <tbody>
247
+ * <tr> ... table cells 2 ... </tr>
248
+ * <tr> ... table cells 3 ... </tr>
249
+ * </tbody>
250
+ * </table>
251
+ * <figcaption>Caption text</figcaption>
252
+ * </figure>
253
+ * ```
225
254
  *
226
255
  * The converter has to take the `headingRows` attribute into consideration when allocating the `<tableRow>` elements
227
256
  * into the `<tbody>` and `<thead>` elements. Hence, we need two slots and need to define proper filter callbacks for them.
@@ -231,46 +260,48 @@ export default class DowncastHelpers extends ConversionHelpers {
231
260
  *
232
261
  * Such a converter would look like this:
233
262
  *
234
- * editor.conversion.for( 'downcast' ).elementToStructure( {
235
- * model: {
236
- * name: 'table',
237
- * attributes: [ 'headingRows' ]
238
- * },
239
- * view: ( modelElement, conversionApi ) => {
240
- * const { writer } = conversionApi;
263
+ * ```ts
264
+ * editor.conversion.for( 'downcast' ).elementToStructure( {
265
+ * model: {
266
+ * name: 'table',
267
+ * attributes: [ 'headingRows' ]
268
+ * },
269
+ * view: ( modelElement, conversionApi ) => {
270
+ * const { writer } = conversionApi;
241
271
  *
242
- * const figureElement = writer.createContainerElement( 'figure', { class: 'table' } );
243
- * const tableElement = writer.createContainerElement( 'table' );
272
+ * const figureElement = writer.createContainerElement( 'figure', { class: 'table' } );
273
+ * const tableElement = writer.createContainerElement( 'table' );
244
274
  *
245
- * writer.insert( writer.createPositionAt( figureElement, 0 ), tableElement );
275
+ * writer.insert( writer.createPositionAt( figureElement, 0 ), tableElement );
246
276
  *
247
- * const headingRows = modelElement.getAttribute( 'headingRows' ) || 0;
277
+ * const headingRows = modelElement.getAttribute( 'headingRows' ) || 0;
248
278
  *
249
- * if ( headingRows > 0 ) {
250
- * const tableHead = writer.createContainerElement( 'thead' );
279
+ * if ( headingRows > 0 ) {
280
+ * const tableHead = writer.createContainerElement( 'thead' );
251
281
  *
252
- * const headSlot = writer.createSlot( node => node.is( 'element', 'tableRow' ) && node.index < headingRows );
282
+ * const headSlot = writer.createSlot( node => node.is( 'element', 'tableRow' ) && node.index < headingRows );
253
283
  *
254
- * writer.insert( writer.createPositionAt( tableElement, 'end' ), tableHead );
255
- * writer.insert( writer.createPositionAt( tableHead, 0 ), headSlot );
256
- * }
284
+ * writer.insert( writer.createPositionAt( tableElement, 'end' ), tableHead );
285
+ * writer.insert( writer.createPositionAt( tableHead, 0 ), headSlot );
286
+ * }
257
287
  *
258
- * if ( headingRows < tableUtils.getRows( table ) ) {
259
- * const tableBody = writer.createContainerElement( 'tbody' );
288
+ * if ( headingRows < tableUtils.getRows( table ) ) {
289
+ * const tableBody = writer.createContainerElement( 'tbody' );
260
290
  *
261
- * const bodySlot = writer.createSlot( node => node.is( 'element', 'tableRow' ) && node.index >= headingRows );
291
+ * const bodySlot = writer.createSlot( node => node.is( 'element', 'tableRow' ) && node.index >= headingRows );
262
292
  *
263
- * writer.insert( writer.createPositionAt( tableElement, 'end' ), tableBody );
264
- * writer.insert( writer.createPositionAt( tableBody, 0 ), bodySlot );
265
- * }
293
+ * writer.insert( writer.createPositionAt( tableElement, 'end' ), tableBody );
294
+ * writer.insert( writer.createPositionAt( tableBody, 0 ), bodySlot );
295
+ * }
266
296
  *
267
- * const restSlot = writer.createSlot( node => !node.is( 'element', 'tableRow' ) );
297
+ * const restSlot = writer.createSlot( node => !node.is( 'element', 'tableRow' ) );
268
298
  *
269
- * writer.insert( writer.createPositionAt( figureElement, 'end' ), restSlot );
299
+ * writer.insert( writer.createPositionAt( figureElement, 'end' ), restSlot );
270
300
  *
271
- * return figureElement;
272
- * }
273
- * } );
301
+ * return figureElement;
302
+ * }
303
+ * } );
304
+ * ```
274
305
  *
275
306
  * Note: The children of a model element that's being converted must be allocated in the same order in the view
276
307
  * in which they are placed in the model.
@@ -278,16 +309,14 @@ export default class DowncastHelpers extends ConversionHelpers {
278
309
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
279
310
  * to the conversion process.
280
311
  *
281
- * @method #elementToStructure
282
- * @param {Object} config Conversion configuration.
283
- * @param {String|Object} config.model The description or a name of the model element to convert.
284
- * @param {String} [config.model.name] The name of the model element to convert.
285
- * @param {String|Array.<String>} [config.model.attributes] The list of attribute names that should be consumed while creating
312
+ * @param config Conversion configuration.
313
+ * @param config.model The description or a name of the model element to convert.
314
+ * @param config.model.name The name of the model element to convert.
315
+ * @param config.model.attributes The list of attribute names that should be consumed while creating
286
316
  * the view structure. Note that the view will be reconverted if any of the listed attributes will change.
287
- * @param {module:engine/conversion/downcasthelpers~StructureCreatorFunction} config.view A function
288
- * that takes the model element and {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast
289
- * conversion API} as parameters and returns a view container element with slots for model child nodes to be converted into.
290
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
317
+ * @param config.view A function that takes the model element and
318
+ * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as parameters
319
+ * and returns a view container element with slots for model child nodes to be converted into.
291
320
  */
292
321
  elementToStructure(config) {
293
322
  return this.add(downcastElementToStructure(config));
@@ -298,86 +327,85 @@ export default class DowncastHelpers extends ConversionHelpers {
298
327
  * This conversion results in wrapping view nodes with a view attribute element. For example, a model text node with
299
328
  * `"Foo"` as data and the `bold` attribute becomes `<strong>Foo</strong>` in the view.
300
329
  *
301
- * editor.conversion.for( 'downcast' ).attributeToElement( {
302
- * model: 'bold',
303
- * view: 'strong'
304
- * } );
305
- *
306
- * editor.conversion.for( 'downcast' ).attributeToElement( {
307
- * model: 'bold',
308
- * view: 'b',
309
- * converterPriority: 'high'
310
- * } );
311
- *
312
- * editor.conversion.for( 'downcast' ).attributeToElement( {
313
- * model: 'invert',
314
- * view: {
315
- * name: 'span',
316
- * classes: [ 'font-light', 'bg-dark' ]
317
- * }
318
- * } );
319
- *
320
- * editor.conversion.for( 'downcast' ).attributeToElement( {
321
- * model: {
322
- * key: 'fontSize',
323
- * values: [ 'big', 'small' ]
324
- * },
325
- * view: {
326
- * big: {
327
- * name: 'span',
328
- * styles: {
329
- * 'font-size': '1.2em'
330
- * }
331
- * },
332
- * small: {
333
- * name: 'span',
334
- * styles: {
335
- * 'font-size': '0.8em'
336
- * }
337
- * }
338
- * }
339
- * } );
340
- *
341
- * editor.conversion.for( 'downcast' ).attributeToElement( {
342
- * model: 'bold',
343
- * view: ( modelAttributeValue, conversionApi ) => {
344
- * const { writer } = conversionApi;
345
- *
346
- * return writer.createAttributeElement( 'span', {
347
- * style: 'font-weight:' + modelAttributeValue
348
- * } );
349
- * }
350
- * } );
351
- *
352
- * editor.conversion.for( 'downcast' ).attributeToElement( {
353
- * model: {
354
- * key: 'color',
355
- * name: '$text'
356
- * },
357
- * view: ( modelAttributeValue, conversionApi ) => {
358
- * const { writer } = conversionApi;
359
- *
360
- * return writer.createAttributeElement( 'span', {
361
- * style: 'color:' + modelAttributeValue
362
- * } );
363
- * }
364
- * } );
330
+ * ```ts
331
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
332
+ * model: 'bold',
333
+ * view: 'strong'
334
+ * } );
335
+ *
336
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
337
+ * model: 'bold',
338
+ * view: 'b',
339
+ * converterPriority: 'high'
340
+ * } );
341
+ *
342
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
343
+ * model: 'invert',
344
+ * view: {
345
+ * name: 'span',
346
+ * classes: [ 'font-light', 'bg-dark' ]
347
+ * }
348
+ * } );
349
+ *
350
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
351
+ * model: {
352
+ * key: 'fontSize',
353
+ * values: [ 'big', 'small' ]
354
+ * },
355
+ * view: {
356
+ * big: {
357
+ * name: 'span',
358
+ * styles: {
359
+ * 'font-size': '1.2em'
360
+ * }
361
+ * },
362
+ * small: {
363
+ * name: 'span',
364
+ * styles: {
365
+ * 'font-size': '0.8em'
366
+ * }
367
+ * }
368
+ * }
369
+ * } );
370
+ *
371
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
372
+ * model: 'bold',
373
+ * view: ( modelAttributeValue, conversionApi ) => {
374
+ * const { writer } = conversionApi;
375
+ *
376
+ * return writer.createAttributeElement( 'span', {
377
+ * style: 'font-weight:' + modelAttributeValue
378
+ * } );
379
+ * }
380
+ * } );
381
+ *
382
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
383
+ * model: {
384
+ * key: 'color',
385
+ * name: '$text'
386
+ * },
387
+ * view: ( modelAttributeValue, conversionApi ) => {
388
+ * const { writer } = conversionApi;
389
+ *
390
+ * return writer.createAttributeElement( 'span', {
391
+ * style: 'color:' + modelAttributeValue
392
+ * } );
393
+ * }
394
+ * } );
395
+ * ```
365
396
  *
366
397
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
367
398
  * to the conversion process.
368
399
  *
369
- * @method #attributeToElement
370
- * @param {Object} config Conversion configuration.
371
- * @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array
400
+ * @param config Conversion configuration.
401
+ * @param config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array
372
402
  * of `String`s with possible values if the model attribute is an enumerable.
373
- * @param {module:engine/view/elementdefinition~ElementDefinition|Object|
374
- * module:engine/conversion/downcasthelpers~AttributeElementCreatorFunction} config.view A view element definition or a function
403
+ * @param config.view A view element definition or a function
375
404
  * that takes the model attribute value and
376
405
  * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as parameters and returns a view
377
406
  * attribute element. If `config.model.values` is given, `config.view` should be an object assigning values from `config.model.values`
378
407
  * to view element definitions or functions.
379
- * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
380
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
408
+ * @param config.converterPriority Converter priority.
381
409
  */
382
410
  attributeToElement(config) {
383
411
  return this.add(downcastAttributeToElement(config));
@@ -388,79 +416,80 @@ export default class DowncastHelpers extends ConversionHelpers {
388
416
  * This conversion results in adding an attribute to a view node, basing on an attribute from a model node. For example,
389
417
  * `<imageInline src='foo.jpg'></imageInline>` is converted to `<img src='foo.jpg'></img>`.
390
418
  *
391
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
392
- * model: 'source',
393
- * view: 'src'
394
- * } );
395
- *
396
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
397
- * model: 'source',
398
- * view: 'href',
399
- * converterPriority: 'high'
400
- * } );
401
- *
402
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
403
- * model: {
404
- * name: 'imageInline',
405
- * key: 'source'
406
- * },
407
- * view: 'src'
408
- * } );
409
- *
410
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
411
- * model: {
412
- * name: 'styled',
413
- * values: [ 'dark', 'light' ]
414
- * },
415
- * view: {
416
- * dark: {
417
- * key: 'class',
418
- * value: [ 'styled', 'styled-dark' ]
419
- * },
420
- * light: {
421
- * key: 'class',
422
- * value: [ 'styled', 'styled-light' ]
423
- * }
424
- * }
425
- * } );
426
- *
427
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
428
- * model: 'styled',
429
- * view: modelAttributeValue => ( {
430
- * key: 'class',
431
- * value: 'styled-' + modelAttributeValue
432
- * } )
433
- * } );
419
+ * ```ts
420
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
421
+ * model: 'source',
422
+ * view: 'src'
423
+ * } );
424
+ *
425
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
426
+ * model: 'source',
427
+ * view: 'href',
428
+ * converterPriority: 'high'
429
+ * } );
430
+ *
431
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
432
+ * model: {
433
+ * name: 'imageInline',
434
+ * key: 'source'
435
+ * },
436
+ * view: 'src'
437
+ * } );
438
+ *
439
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
440
+ * model: {
441
+ * name: 'styled',
442
+ * values: [ 'dark', 'light' ]
443
+ * },
444
+ * view: {
445
+ * dark: {
446
+ * key: 'class',
447
+ * value: [ 'styled', 'styled-dark' ]
448
+ * },
449
+ * light: {
450
+ * key: 'class',
451
+ * value: [ 'styled', 'styled-light' ]
452
+ * }
453
+ * }
454
+ * } );
455
+ *
456
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
457
+ * model: 'styled',
458
+ * view: modelAttributeValue => ( {
459
+ * key: 'class',
460
+ * value: 'styled-' + modelAttributeValue
461
+ * } )
462
+ * } );
463
+ * ```
434
464
  *
435
465
  * **Note**: Downcasting to a style property requires providing `value` as an object:
436
466
  *
437
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
438
- * model: 'lineHeight',
439
- * view: modelAttributeValue => ( {
440
- * key: 'style',
441
- * value: {
442
- * 'line-height': modelAttributeValue,
443
- * 'border-bottom': '1px dotted #ba2'
444
- * }
445
- * } )
446
- * } );
467
+ * ```ts
468
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
469
+ * model: 'lineHeight',
470
+ * view: modelAttributeValue => ( {
471
+ * key: 'style',
472
+ * value: {
473
+ * 'line-height': modelAttributeValue,
474
+ * 'border-bottom': '1px dotted #ba2'
475
+ * }
476
+ * } )
477
+ * } );
478
+ * ```
447
479
  *
448
480
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
449
481
  * to the conversion process.
450
482
  *
451
- * @method #attributeToAttribute
452
- * @param {Object} config Conversion configuration.
453
- * @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing
483
+ * @param config Conversion configuration.
484
+ * @param config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing
454
485
  * the attribute key, possible values and, optionally, an element name to convert from.
455
- * @param {String|Object|module:engine/conversion/downcasthelpers~AttributeCreatorFunction} config.view A view attribute key,
456
- * or a `{ key, value }` object or a function that takes the model attribute value and
486
+ * @param config.view A view attribute key, or a `{ key, value }` object or a function that takes the model attribute value and
457
487
  * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API}
458
488
  * as parameters and returns a `{ key, value }` object. If the `key` is `'class'`, the `value` can be a `String` or an
459
489
  * array of `String`s. If the `key` is `'style'`, the `value` is an object with key-value pairs. In other cases, `value` is a `String`.
460
490
  * If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to
461
491
  * `{ key, value }` objects or a functions.
462
- * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
463
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
492
+ * @param config.converterPriority Converter priority.
464
493
  */
465
494
  attributeToAttribute(config) {
466
495
  return this.add(downcastAttributeToAttribute(config));
@@ -478,38 +507,40 @@ export default class DowncastHelpers extends ConversionHelpers {
478
507
  * is collapsed, only one element is created. For example, a model marker set like this: `<paragraph>F[oo b]ar</paragraph>`
479
508
  * becomes `<p>F<span data-marker="search"></span>oo b<span data-marker="search"></span>ar</p>` in the view.
480
509
  *
481
- * editor.conversion.for( 'editingDowncast' ).markerToElement( {
482
- * model: 'search',
483
- * view: 'marker-search'
484
- * } );
485
- *
486
- * editor.conversion.for( 'editingDowncast' ).markerToElement( {
487
- * model: 'search',
488
- * view: 'search-result',
489
- * converterPriority: 'high'
490
- * } );
491
- *
492
- * editor.conversion.for( 'editingDowncast' ).markerToElement( {
493
- * model: 'search',
494
- * view: {
495
- * name: 'span',
496
- * attributes: {
497
- * 'data-marker': 'search'
498
- * }
499
- * }
500
- * } );
501
- *
502
- * editor.conversion.for( 'editingDowncast' ).markerToElement( {
503
- * model: 'search',
504
- * view: ( markerData, conversionApi ) => {
505
- * const { writer } = conversionApi;
506
- *
507
- * return writer.createUIElement( 'span', {
508
- * 'data-marker': 'search',
509
- * 'data-start': markerData.isOpening
510
- * } );
511
- * }
512
- * } );
510
+ * ```ts
511
+ * editor.conversion.for( 'editingDowncast' ).markerToElement( {
512
+ * model: 'search',
513
+ * view: 'marker-search'
514
+ * } );
515
+ *
516
+ * editor.conversion.for( 'editingDowncast' ).markerToElement( {
517
+ * model: 'search',
518
+ * view: 'search-result',
519
+ * converterPriority: 'high'
520
+ * } );
521
+ *
522
+ * editor.conversion.for( 'editingDowncast' ).markerToElement( {
523
+ * model: 'search',
524
+ * view: {
525
+ * name: 'span',
526
+ * attributes: {
527
+ * 'data-marker': 'search'
528
+ * }
529
+ * }
530
+ * } );
531
+ *
532
+ * editor.conversion.for( 'editingDowncast' ).markerToElement( {
533
+ * model: 'search',
534
+ * view: ( markerData, conversionApi ) => {
535
+ * const { writer } = conversionApi;
536
+ *
537
+ * return writer.createUIElement( 'span', {
538
+ * 'data-marker': 'search',
539
+ * 'data-start': markerData.isOpening
540
+ * } );
541
+ * }
542
+ * } );
543
+ * ```
513
544
  *
514
545
  * If a function is passed as the `config.view` parameter, it will be used to generate both boundary elements. The function
515
546
  * receives the `data` object and {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API}
@@ -523,14 +554,12 @@ export default class DowncastHelpers extends ConversionHelpers {
523
554
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
524
555
  * to the conversion process.
525
556
  *
526
- * @method #markerToElement
527
- * @param {Object} config Conversion configuration.
528
- * @param {String} config.model The name of the model marker (or model marker group) to convert.
529
- * @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function that
530
- * takes the model marker data and {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API}
531
- * as a parameters and returns a view UI element.
532
- * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
533
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
557
+ * @param config Conversion configuration.
558
+ * @param config.model The name of the model marker (or model marker group) to convert.
559
+ * @param config.view A view element definition or a function that takes the model marker data and
560
+ * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as a parameters
561
+ * and returns a view UI element.
562
+ * @param config.converterPriority Converter priority.
534
563
  */
535
564
  markerToElement(config) {
536
565
  return this.add(downcastMarkerToElement(config));
@@ -554,26 +583,28 @@ export default class DowncastHelpers extends ConversionHelpers {
554
583
  * to a container element, it is the container element instance itself that applies values from the highlight descriptor.
555
584
  * So, in a sense, the converter takes care of stating what should be applied on what, while the element decides how to apply that.
556
585
  *
557
- * editor.conversion.for( 'downcast' ).markerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
558
- *
559
- * editor.conversion.for( 'downcast' ).markerToHighlight( {
560
- * model: 'comment',
561
- * view: { classes: 'comment' },
562
- * converterPriority: 'high'
563
- * } );
564
- *
565
- * editor.conversion.for( 'downcast' ).markerToHighlight( {
566
- * model: 'comment',
567
- * view: ( data, conversionApi ) => {
568
- * // Assuming that the marker name is in a form of comment:commentType:commentId.
569
- * const [ , commentType, commentId ] = data.markerName.split( ':' );
570
- *
571
- * return {
572
- * classes: [ 'comment', 'comment-' + commentType ],
573
- * attributes: { 'data-comment-id': commentId }
574
- * };
575
- * }
576
- * } );
586
+ * ```ts
587
+ * editor.conversion.for( 'downcast' ).markerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
588
+ *
589
+ * editor.conversion.for( 'downcast' ).markerToHighlight( {
590
+ * model: 'comment',
591
+ * view: { classes: 'comment' },
592
+ * converterPriority: 'high'
593
+ * } );
594
+ *
595
+ * editor.conversion.for( 'downcast' ).markerToHighlight( {
596
+ * model: 'comment',
597
+ * view: ( data, conversionApi ) => {
598
+ * // Assuming that the marker name is in a form of comment:commentType:commentId.
599
+ * const [ , commentType, commentId ] = data.markerName.split( ':' );
600
+ *
601
+ * return {
602
+ * classes: [ 'comment', 'comment-' + commentType ],
603
+ * attributes: { 'data-comment-id': commentId }
604
+ * };
605
+ * }
606
+ * } );
607
+ * ```
577
608
  *
578
609
  * If a function is passed as the `config.view` parameter, it will be used to generate the highlight descriptor. The function
579
610
  * receives the `data` object and {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API}
@@ -584,15 +615,12 @@ export default class DowncastHelpers extends ConversionHelpers {
584
615
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
585
616
  * to the conversion process.
586
617
  *
587
- * @method #markerToHighlight
588
- * @param {Object} config Conversion configuration.
589
- * @param {String} config.model The name of the model marker (or model marker group) to convert.
590
- * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} config.view A highlight descriptor
591
- * that will be used for highlighting or a function that takes the model marker data and
618
+ * @param config Conversion configuration.
619
+ * @param config.model The name of the model marker (or model marker group) to convert.
620
+ * @param config.view A highlight descriptor that will be used for highlighting or a function that takes the model marker data and
592
621
  * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as a parameters
593
622
  * and returns a highlight descriptor.
594
- * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
595
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
623
+ * @param config.converterPriority Converter priority.
596
624
  */
597
625
  markerToHighlight(config) {
598
626
  return this.add(downcastMarkerToHighlight(config));
@@ -625,87 +653,97 @@ export default class DowncastHelpers extends ConversionHelpers {
625
653
  *
626
654
  * Basic usage:
627
655
  *
628
- * // Using the default conversion.
629
- * // In this case, all markers with names starting with 'comment:' will be converted.
630
- * // The `group` parameter will be set to `comment`.
631
- * // The `name` parameter will be the rest of the marker name (without the `:`).
632
- * editor.conversion.for( 'dataDowncast' ).markerToData( {
633
- * model: 'comment'
634
- * } );
656
+ * ```ts
657
+ * // Using the default conversion.
658
+ * // In this case, all markers with names starting with 'comment:' will be converted.
659
+ * // The `group` parameter will be set to `comment`.
660
+ * // The `name` parameter will be the rest of the marker name (without the `:`).
661
+ * editor.conversion.for( 'dataDowncast' ).markerToData( {
662
+ * model: 'comment'
663
+ * } );
664
+ * ```
635
665
  *
636
666
  * An example of a view that may be generated by this conversion (assuming a marker with the name `comment:commentId:uid` marked
637
667
  * by `[]`):
638
668
  *
639
- * // Model:
640
- * <paragraph>Foo[bar</paragraph>
641
- * <imageBlock src="abc.jpg"></imageBlock>]
669
+ * ```
670
+ * // Model:
671
+ * <paragraph>Foo[bar</paragraph>
672
+ * <imageBlock src="abc.jpg"></imageBlock>]
642
673
  *
643
- * // View:
644
- * <p>Foo<comment-start name="commentId:uid"></comment-start>bar</p>
645
- * <figure data-comment-end-after="commentId:uid" class="image"><img src="abc.jpg" /></figure>
674
+ * // View:
675
+ * <p>Foo<comment-start name="commentId:uid"></comment-start>bar</p>
676
+ * <figure data-comment-end-after="commentId:uid" class="image"><img src="abc.jpg" /></figure>
677
+ * ```
646
678
  *
647
679
  * In the example above, the comment starts before "bar" and ends after the image.
648
680
  *
649
681
  * If the `name` part is empty, the following view may be generated:
650
682
  *
651
- * <p>Foo <myMarker-start></myMarker-start>bar</p>
652
- * <figure data-myMarker-end-after="" class="image"><img src="abc.jpg" /></figure>
683
+ * ```html
684
+ * <p>Foo <myMarker-start></myMarker-start>bar</p>
685
+ * <figure data-myMarker-end-after="" class="image"><img src="abc.jpg" /></figure>
686
+ * ```
653
687
  *
654
688
  * **Note:** A situation where some markers have the `name` part and some do not, is incorrect and should be avoided.
655
689
  *
656
690
  * Examples where `data-group-start-after` and `data-group-end-before` are used:
657
691
  *
658
- * // Model:
659
- * <blockQuote>[]<paragraph>Foo</paragraph></blockQuote>
692
+ * ```
693
+ * // Model:
694
+ * <blockQuote>[]<paragraph>Foo</paragraph></blockQuote>
660
695
  *
661
- * // View:
662
- * <blockquote><p data-group-end-before="name" data-group-start-before="name">Foo</p></blockquote>
696
+ * // View:
697
+ * <blockquote><p data-group-end-before="name" data-group-start-before="name">Foo</p></blockquote>
698
+ * ```
663
699
  *
664
700
  * Similarly, when a marker is collapsed after the last element:
665
701
  *
666
- * // Model:
667
- * <blockQuote><paragraph>Foo</paragraph>[]</blockQuote>
702
+ * ```
703
+ * // Model:
704
+ * <blockQuote><paragraph>Foo</paragraph>[]</blockQuote>
668
705
  *
669
- * // View:
670
- * <blockquote><p data-group-end-after="name" data-group-start-after="name">Foo</p></blockquote>
706
+ * // View:
707
+ * <blockquote><p data-group-end-after="name" data-group-start-after="name">Foo</p></blockquote>
708
+ * ```
671
709
  *
672
710
  * When there are multiple markers from the same group stored in the same attribute of the same element, their
673
711
  * name parts are put together in the attribute value, for example: `data-group-start-before="name1,name2,name3"`.
674
712
  *
675
713
  * Other examples of usage:
676
714
  *
677
- * // Using a custom function which is the same as the default conversion:
678
- * editor.conversion.for( 'dataDowncast' ).markerToData( {
679
- * model: 'comment'
680
- * view: markerName => ( {
681
- * group: 'comment',
682
- * name: markerName.substr( 8 ) // Removes 'comment:' part.
683
- * } )
684
- * } );
685
- *
686
- * // Using the converter priority:
687
- * editor.conversion.for( 'dataDowncast' ).markerToData( {
688
- * model: 'comment'
689
- * view: markerName => ( {
690
- * group: 'comment',
691
- * name: markerName.substr( 8 ) // Removes 'comment:' part.
692
- * } ),
693
- * converterPriority: 'high'
694
- * } );
715
+ * ```ts
716
+ * // Using a custom function which is the same as the default conversion:
717
+ * editor.conversion.for( 'dataDowncast' ).markerToData( {
718
+ * model: 'comment'
719
+ * view: markerName => ( {
720
+ * group: 'comment',
721
+ * name: markerName.substr( 8 ) // Removes 'comment:' part.
722
+ * } )
723
+ * } );
724
+ *
725
+ * // Using the converter priority:
726
+ * editor.conversion.for( 'dataDowncast' ).markerToData( {
727
+ * model: 'comment'
728
+ * view: markerName => ( {
729
+ * group: 'comment',
730
+ * name: markerName.substr( 8 ) // Removes 'comment:' part.
731
+ * } ),
732
+ * converterPriority: 'high'
733
+ * } );
734
+ * ```
695
735
  *
696
736
  * This kind of conversion is useful for saving data into the database, so it should be used in the data conversion pipeline.
697
737
  *
698
738
  * See the {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} API guide to learn how to
699
739
  * add a converter to the conversion process.
700
740
  *
701
- * @method #markerToData
702
- * @param {Object} config Conversion configuration.
703
- * @param {String} config.model The name of the model marker (or the model marker group) to convert.
704
- * @param {Function} [config.view] A function that takes the model marker name and
741
+ * @param config Conversion configuration.
742
+ * @param config.model The name of the model marker (or the model marker group) to convert.
743
+ * @param config.view A function that takes the model marker name and
705
744
  * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as the parameters
706
745
  * and returns an object with the `group` and `name` properties.
707
- * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
708
- * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
746
+ * @param config.converterPriority Converter priority.
709
747
  */
710
748
  markerToData(config) {
711
749
  return this.add(downcastMarkerToData(config));
@@ -717,9 +755,11 @@ export default class DowncastHelpers extends ConversionHelpers {
717
755
  * The converter automatically consumes the corresponding value from the consumables list and stops the event (see
718
756
  * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
719
757
  *
720
- * modelDispatcher.on( 'insert:$text', insertText() );
758
+ * ```ts
759
+ * modelDispatcher.on( 'insert:$text', insertText() );
760
+ * ```
721
761
  *
722
- * @returns {Function} Insert text event converter.
762
+ * @returns Insert text event converter.
723
763
  */
724
764
  export function insertText() {
725
765
  return (evt, data, conversionApi) => {
@@ -735,7 +775,7 @@ export function insertText() {
735
775
  /**
736
776
  * Function factory that creates a default downcast converter for triggering attributes and children conversion.
737
777
  *
738
- * @returns {Function} The converter.
778
+ * @returns The converter.
739
779
  */
740
780
  export function insertAttributesAndChildren() {
741
781
  return (evt, data, conversionApi) => {
@@ -750,9 +790,11 @@ export function insertAttributesAndChildren() {
750
790
  /**
751
791
  * Function factory that creates a default downcast converter for node remove changes.
752
792
  *
753
- * modelDispatcher.on( 'remove', remove() );
793
+ * ```ts
794
+ * modelDispatcher.on( 'remove', remove() );
795
+ * ```
754
796
  *
755
- * @returns {Function} Remove event converter.
797
+ * @returns Remove event converter.
756
798
  */
757
799
  export function remove() {
758
800
  return (evt, data, conversionApi) => {
@@ -774,10 +816,6 @@ export function remove() {
774
816
  * Creates a `<span>` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from the information
775
817
  * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If the priority
776
818
  * is not provided in the descriptor, the default priority will be used.
777
- *
778
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer
779
- * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor
780
- * @returns {module:engine/view/attributeelement~AttributeElement}
781
819
  */
782
820
  export function createViewElementFromHighlightDescriptor(writer, descriptor) {
783
821
  const viewElement = writer.createAttributeElement('span', descriptor.attributes);
@@ -795,9 +833,11 @@ export function createViewElementFromHighlightDescriptor(writer, descriptor) {
795
833
  * to a {@link module:engine/view/documentselection~DocumentSelection view selection}. The converter consumes appropriate
796
834
  * value from the `consumable` object and maps model positions from the selection to view positions.
797
835
  *
798
- * modelDispatcher.on( 'selection', convertRangeSelection() );
836
+ * ```ts
837
+ * modelDispatcher.on( 'selection', convertRangeSelection() );
838
+ * ```
799
839
  *
800
- * @returns {Function} Selection converter.
840
+ * @returns Selection converter.
801
841
  */
802
842
  export function convertRangeSelection() {
803
843
  return (evt, data, conversionApi) => {
@@ -821,12 +861,16 @@ export function convertRangeSelection() {
821
861
  * value from the `consumable` object, maps the model selection position to the view position and breaks
822
862
  * {@link module:engine/view/attributeelement~AttributeElement attribute elements} at the selection position.
823
863
  *
824
- * modelDispatcher.on( 'selection', convertCollapsedSelection() );
864
+ * ```ts
865
+ * modelDispatcher.on( 'selection', convertCollapsedSelection() );
866
+ * ```
825
867
  *
826
868
  * An example of the view state before and after converting the collapsed selection:
827
869
  *
828
- * <p><strong>f^oo<strong>bar</p>
829
- * -> <p><strong>f</strong>^<strong>oo</strong>bar</p>
870
+ * ```
871
+ * <p><strong>f^oo<strong>bar</p>
872
+ * -> <p><strong>f</strong>^<strong>oo</strong>bar</p>
873
+ * ```
830
874
  *
831
875
  * By breaking attribute elements like `<strong>`, the selection is in a correct element. Then, when the selection attribute is
832
876
  * converted, broken attributes might be merged again, or the position where the selection is may be wrapped
@@ -835,7 +879,7 @@ export function convertRangeSelection() {
835
879
  * See also {@link module:engine/conversion/downcasthelpers~clearAttributes} which does a clean-up
836
880
  * by merging attributes.
837
881
  *
838
- * @returns {Function} Selection converter.
882
+ * @returns Selection converter.
839
883
  */
840
884
  export function convertCollapsedSelection() {
841
885
  return (evt, data, conversionApi) => {
@@ -859,23 +903,27 @@ export function convertCollapsedSelection() {
859
903
  * {@link module:engine/view/attributeelement~AttributeElement view attribute elements} and merges sibling attributes at all start and end
860
904
  * positions of all ranges.
861
905
  *
862
- * <p><strong>^</strong></p>
863
- * -> <p>^</p>
906
+ * ```
907
+ * <p><strong>^</strong></p>
908
+ * -> <p>^</p>
864
909
  *
865
- * <p><strong>foo</strong>^<strong>bar</strong>bar</p>
866
- * -> <p><strong>foo^bar<strong>bar</p>
910
+ * <p><strong>foo</strong>^<strong>bar</strong>bar</p>
911
+ * -> <p><strong>foo^bar<strong>bar</p>
867
912
  *
868
- * <p><strong>foo</strong><em>^</em><strong>bar</strong>bar</p>
869
- * -> <p><strong>foo^bar<strong>bar</p>
913
+ * <p><strong>foo</strong><em>^</em><strong>bar</strong>bar</p>
914
+ * -> <p><strong>foo^bar<strong>bar</p>
915
+ * ```
870
916
  *
871
917
  * This listener should be assigned before any converter for the new selection:
872
918
  *
873
- * modelDispatcher.on( 'selection', clearAttributes() );
919
+ * ```ts
920
+ * modelDispatcher.on( 'selection', clearAttributes() );
921
+ * ```
874
922
  *
875
923
  * See {@link module:engine/conversion/downcasthelpers~convertCollapsedSelection}
876
924
  * which does the opposite by breaking attributes in the selection position.
877
925
  *
878
- * @returns {Function} Selection converter.
926
+ * @returns Selection converter.
879
927
  */
880
928
  export function clearAttributes() {
881
929
  return (evt, data, conversionApi) => {
@@ -902,10 +950,12 @@ export function clearAttributes() {
902
950
  * model elements having the given attribute. This is useful for attributes like `bold` that may be set on text nodes in the model
903
951
  * but are represented as an element in the view:
904
952
  *
905
- * [paragraph] MODEL ====> VIEW <p>
906
- * |- a {bold: true} |- <b>
907
- * |- b {bold: true} | |- ab
908
- * |- c |- c
953
+ * ```
954
+ * [paragraph] MODEL ====> VIEW <p>
955
+ * |- a {bold: true} |- <b>
956
+ * |- b {bold: true} | |- ab
957
+ * |- c |- c
958
+ * ```
909
959
  *
910
960
  * Passed `Function` will be provided with the attribute value and then all the parameters of the
911
961
  * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute `attribute` event}.
@@ -916,13 +966,15 @@ export function clearAttributes() {
916
966
  * The converter automatically consumes the corresponding value from the consumables list and stops the event (see
917
967
  * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
918
968
  *
919
- * modelDispatcher.on( 'attribute:bold', wrap( ( modelAttributeValue, { writer } ) => {
920
- * return writer.createAttributeElement( 'strong' );
921
- * } );
969
+ * ```ts
970
+ * modelDispatcher.on( 'attribute:bold', wrap( ( modelAttributeValue, { writer } ) => {
971
+ * return writer.createAttributeElement( 'strong' );
972
+ * } );
973
+ * ```
922
974
  *
923
- * @protected
924
- * @param {Function} elementCreator Function returning a view element that will be used for wrapping.
925
- * @returns {Function} Set/change attribute converter.
975
+ * @internal
976
+ * @param elementCreator Function returning a view element that will be used for wrapping.
977
+ * @returns Set/change attribute converter.
926
978
  */
927
979
  export function wrap(elementCreator) {
928
980
  return (evt, data, conversionApi) => {
@@ -966,23 +1018,25 @@ export function wrap(elementCreator) {
966
1018
  *
967
1019
  * The converter automatically consumes the corresponding value from the consumables list and binds the model and view elements.
968
1020
  *
969
- * downcastDispatcher.on(
970
- * 'insert:myElem',
971
- * insertElement( ( modelItem, { writer } ) => {
972
- * const text = writer.createText( 'myText' );
973
- * const myElem = writer.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text );
1021
+ * ```ts
1022
+ * downcastDispatcher.on(
1023
+ * 'insert:myElem',
1024
+ * insertElement( ( modelItem, { writer } ) => {
1025
+ * const text = writer.createText( 'myText' );
1026
+ * const myElem = writer.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text );
974
1027
  *
975
- * // Do something fancy with `myElem` using `modelItem` or other parameters.
1028
+ * // Do something fancy with `myElem` using `modelItem` or other parameters.
976
1029
  *
977
- * return myElem;
978
- * }
979
- * ) );
1030
+ * return myElem;
1031
+ * }
1032
+ * ) );
1033
+ * ```
980
1034
  *
981
- * @protected
982
- * @param {Function} elementCreator Function returning a view element, which will be inserted.
983
- * @param {module:engine/conversion/downcasthelpers~ConsumerFunction} [consumer] Function defining element consumption process.
1035
+ * @internal
1036
+ * @param elementCreator Function returning a view element, which will be inserted.
1037
+ * @param consumer Function defining element consumption process.
984
1038
  * By default this function just consume passed item insertion.
985
- * @returns {Function} Insert element event converter.
1039
+ * @returns Insert element event converter.
986
1040
  */
987
1041
  export function insertElement(elementCreator, consumer = defaultConsumer) {
988
1042
  return (evt, data, conversionApi) => {
@@ -1012,12 +1066,11 @@ export function insertElement(elementCreator, consumer = defaultConsumer) {
1012
1066
  *
1013
1067
  * @see module:engine/conversion/downcasthelpers~DowncastHelpers#elementToStructure
1014
1068
  *
1015
- * @protected
1016
- * @param {module:engine/conversion/downcasthelpers~StructureCreatorFunction} elementCreator Function returning a view structure,
1017
- * which will be inserted.
1018
- * @param {module:engine/conversion/downcasthelpers~ConsumerFunction} consumer A callback that is expected to consume all the consumables
1069
+ * @internal
1070
+ * @param elementCreator Function returning a view structure, which will be inserted.
1071
+ * @param consumer A callback that is expected to consume all the consumables
1019
1072
  * that were used by the element creator.
1020
- * @returns {Function} Insert element event converter.
1073
+ * @returns Insert element event converter.
1021
1074
  */
1022
1075
  export function insertStructure(elementCreator, consumer) {
1023
1076
  return (evt, data, conversionApi) => {
@@ -1055,10 +1108,9 @@ export function insertStructure(elementCreator, consumer) {
1055
1108
  *
1056
1109
  * This converter binds created UI elements with the marker name using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}.
1057
1110
  *
1058
- * @protected
1059
- * @param {module:engine/view/uielement~UIElement|Function} elementCreator A view UI element or a function returning the view element
1060
- * that will be inserted.
1061
- * @returns {Function} Insert element event converter.
1111
+ * @internal
1112
+ * @param elementCreator A view UI element or a function returning the view element that will be inserted.
1113
+ * @returns Insert element event converter.
1062
1114
  */
1063
1115
  export function insertUIElement(elementCreator) {
1064
1116
  return (evt, data, conversionApi) => {
@@ -1097,12 +1149,14 @@ export function insertUIElement(elementCreator) {
1097
1149
  evt.stop();
1098
1150
  };
1099
1151
  }
1100
- // Function factory that returns a default downcast converter for removing a {@link module:engine/view/uielement~UIElement UI element}
1101
- // based on marker remove change.
1102
- //
1103
- // This converter unbinds elements from the marker name.
1104
- //
1105
- // @returns {Function} Removed UI element converter.
1152
+ /**
1153
+ * Function factory that returns a default downcast converter for removing a {@link module:engine/view/uielement~UIElement UI element}
1154
+ * based on marker remove change.
1155
+ *
1156
+ * This converter unbinds elements from the marker name.
1157
+ *
1158
+ * @returns Removed UI element converter.
1159
+ */
1106
1160
  function removeUIElement() {
1107
1161
  return (evt, data, conversionApi) => {
1108
1162
  const elements = conversionApi.mapper.markerNameToElements(data.markerName);
@@ -1117,14 +1171,16 @@ function removeUIElement() {
1117
1171
  evt.stop();
1118
1172
  };
1119
1173
  }
1120
- // Function factory that creates a default converter for model markers.
1121
- //
1122
- // See {@link DowncastHelpers#markerToData} for more information what type of view is generated.
1123
- //
1124
- // This converter binds created UI elements and affected view elements with the marker name
1125
- // using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}.
1126
- //
1127
- // @returns {Function} Add marker converter.
1174
+ /**
1175
+ * Function factory that creates a default converter for model markers.
1176
+ *
1177
+ * See {@link DowncastHelpers#markerToData} for more information what type of view is generated.
1178
+ *
1179
+ * This converter binds created UI elements and affected view elements with the marker name
1180
+ * using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}.
1181
+ *
1182
+ * @returns Add marker converter.
1183
+ */
1128
1184
  function insertMarkerData(viewCreator) {
1129
1185
  return (evt, data, conversionApi) => {
1130
1186
  const viewMarkerData = viewCreator(data.markerName, conversionApi);
@@ -1141,7 +1197,9 @@ function insertMarkerData(viewCreator) {
1141
1197
  evt.stop();
1142
1198
  };
1143
1199
  }
1144
- // Helper function for `insertMarkerData()` that marks a marker boundary at the beginning or end of given `range`.
1200
+ /**
1201
+ * Helper function for `insertMarkerData()` that marks a marker boundary at the beginning or end of given `range`.
1202
+ */
1145
1203
  function handleMarkerBoundary(range, isStart, conversionApi, data, viewMarkerData) {
1146
1204
  const modelPosition = isStart ? range.start : range.end;
1147
1205
  const elementAfter = modelPosition.nodeAfter && modelPosition.nodeAfter.is('element') ? modelPosition.nodeAfter : null;
@@ -1173,7 +1231,9 @@ function handleMarkerBoundary(range, isStart, conversionApi, data, viewMarkerDat
1173
1231
  const viewPosition = conversionApi.mapper.toViewPosition(modelPosition);
1174
1232
  insertMarkerAsElement(viewPosition, isStart, conversionApi, data, viewMarkerData);
1175
1233
  }
1176
- // Helper function for `insertMarkerData()` that marks a marker boundary in the view as an attribute on a view element.
1234
+ /**
1235
+ * Helper function for `insertMarkerData()` that marks a marker boundary in the view as an attribute on a view element.
1236
+ */
1177
1237
  function insertMarkerAsAttribute(viewElement, isStart, isBefore, conversionApi, data, viewMarkerData) {
1178
1238
  const attributeName = `data-${viewMarkerData.group}-${isStart ? 'start' : 'end'}-${isBefore ? 'before' : 'after'}`;
1179
1239
  const markerNames = viewElement.hasAttribute(attributeName) ? viewElement.getAttribute(attributeName).split(',') : [];
@@ -1182,7 +1242,9 @@ function insertMarkerAsAttribute(viewElement, isStart, isBefore, conversionApi,
1182
1242
  conversionApi.writer.setAttribute(attributeName, markerNames.join(','), viewElement);
1183
1243
  conversionApi.mapper.bindElementToMarker(viewElement, data.markerName);
1184
1244
  }
1185
- // Helper function for `insertMarkerData()` that marks a marker boundary in the view as a separate view ui element.
1245
+ /**
1246
+ * Helper function for `insertMarkerData()` that marks a marker boundary in the view as a separate view ui element.
1247
+ */
1186
1248
  function insertMarkerAsElement(position, isStart, conversionApi, data, viewMarkerData) {
1187
1249
  const viewElementName = `${viewMarkerData.group}-${isStart ? 'start' : 'end'}`;
1188
1250
  const attrs = viewMarkerData.name ? { 'name': viewMarkerData.name } : null;
@@ -1190,9 +1252,11 @@ function insertMarkerAsElement(position, isStart, conversionApi, data, viewMarke
1190
1252
  conversionApi.writer.insert(position, viewElement);
1191
1253
  conversionApi.mapper.bindElementToMarker(viewElement, data.markerName);
1192
1254
  }
1193
- // Function factory that creates a converter for removing a model marker data added by the {@link #insertMarkerData} converter.
1194
- //
1195
- // @returns {Function} Remove marker converter.
1255
+ /**
1256
+ * Function factory that creates a converter for removing a model marker data added by the {@link #insertMarkerData} converter.
1257
+ *
1258
+ * @returns Remove marker converter.
1259
+ */
1196
1260
  function removeMarkerData(viewCreator) {
1197
1261
  return (evt, data, conversionApi) => {
1198
1262
  const viewData = viewCreator(data.markerName, conversionApi);
@@ -1231,35 +1295,39 @@ function removeMarkerData(viewCreator) {
1231
1295
  }
1232
1296
  };
1233
1297
  }
1234
- // Function factory that creates a converter which converts the set/change/remove attribute changes from the model to the view.
1235
- //
1236
- // Attributes from the model are converted to the view element attributes in the view. You may provide a custom function to generate
1237
- // a key-value attribute pair to add/change/remove. If not provided, model attributes will be converted to view element
1238
- // attributes on a one-to-one basis.
1239
- //
1240
- // *Note:** The provided attribute creator should always return the same `key` for a given attribute from the model.
1241
- //
1242
- // The converter automatically consumes the corresponding value from the consumables list and stops the event (see
1243
- // {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
1244
- //
1245
- // modelDispatcher.on( 'attribute:customAttr:myElem', changeAttribute( ( value, data ) => {
1246
- // // Change attribute key from `customAttr` to `class` in the view.
1247
- // const key = 'class';
1248
- // let value = data.attributeNewValue;
1249
- //
1250
- // // Force attribute value to 'empty' if the model element is empty.
1251
- // if ( data.item.childCount === 0 ) {
1252
- // value = 'empty';
1253
- // }
1254
- //
1255
- // // Return the key-value pair.
1256
- // return { key, value };
1257
- // } ) );
1258
- //
1259
- // @param {Function} [attributeCreator] Function returning an object with two properties: `key` and `value`, which
1260
- // represent the attribute key and attribute value to be set on a {@link module:engine/view/element~Element view element}.
1261
- // The function is passed the model attribute value as the first parameter and additional data about the change as the second parameter.
1262
- // @returns {Function} Set/change attribute converter.
1298
+ /**
1299
+ * Function factory that creates a converter which converts the set/change/remove attribute changes from the model to the view.
1300
+ *
1301
+ * Attributes from the model are converted to the view element attributes in the view. You may provide a custom function to generate
1302
+ * a key-value attribute pair to add/change/remove. If not provided, model attributes will be converted to view element
1303
+ * attributes on a one-to-one basis.
1304
+ *
1305
+ * *Note:** The provided attribute creator should always return the same `key` for a given attribute from the model.
1306
+ *
1307
+ * The converter automatically consumes the corresponding value from the consumables list and stops the event (see
1308
+ * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).
1309
+ *
1310
+ * ```ts
1311
+ * modelDispatcher.on( 'attribute:customAttr:myElem', changeAttribute( ( value, data ) => {
1312
+ * // Change attribute key from `customAttr` to `class` in the view.
1313
+ * const key = 'class';
1314
+ * let value = data.attributeNewValue;
1315
+ *
1316
+ * // Force attribute value to 'empty' if the model element is empty.
1317
+ * if ( data.item.childCount === 0 ) {
1318
+ * value = 'empty';
1319
+ * }
1320
+ *
1321
+ * // Return the key-value pair.
1322
+ * return { key, value };
1323
+ * } ) );
1324
+ * ```
1325
+ *
1326
+ * @param attributeCreator Function returning an object with two properties: `key` and `value`, which
1327
+ * represent the attribute key and attribute value to be set on a {@link module:engine/view/element~Element view element}.
1328
+ * The function is passed the model attribute value as the first parameter and additional data about the change as the second parameter.
1329
+ * @returns Set/change attribute converter.
1330
+ */
1263
1331
  function changeAttribute(attributeCreator) {
1264
1332
  return (evt, data, conversionApi) => {
1265
1333
  if (!conversionApi.consumable.test(data.item, evt.name)) {
@@ -1281,32 +1349,38 @@ function changeAttribute(attributeCreator) {
1281
1349
  * by an {@link module:engine/conversion/conversion~Conversion#attributeToAttribute `Attribute to Attribute converter`}.
1282
1350
  * In most cases it is caused by converters misconfiguration when only "generic" converter is defined:
1283
1351
  *
1284
- * editor.conversion.for( 'downcast' ).attributeToAttribute( {
1285
- * model: 'attribute-name',
1286
- * view: 'attribute-name'
1287
- * } ) );
1352
+ * ```ts
1353
+ * editor.conversion.for( 'downcast' ).attributeToAttribute( {
1354
+ * model: 'attribute-name',
1355
+ * view: 'attribute-name'
1356
+ * } ) );
1357
+ * ```
1288
1358
  *
1289
1359
  * and given attribute is used on text node, for example:
1290
1360
  *
1291
- * model.change( writer => {
1292
- * writer.insertText( 'Foo', { 'attribute-name': 'bar' }, parent, 0 );
1293
- * } );
1361
+ * ```ts
1362
+ * model.change( writer => {
1363
+ * writer.insertText( 'Foo', { 'attribute-name': 'bar' }, parent, 0 );
1364
+ * } );
1365
+ * ```
1294
1366
  *
1295
1367
  * In such cases, to convert the same attribute for both {@link module:engine/model/element~Element}
1296
1368
  * and {@link module:engine/model/textproxy~TextProxy `Text`} nodes, text specific
1297
1369
  * {@link module:engine/conversion/conversion~Conversion#attributeToElement `Attribute to Element converter`}
1298
1370
  * with higher {@link module:utils/priorities~PriorityString priority} must also be defined:
1299
1371
  *
1300
- * editor.conversion.for( 'downcast' ).attributeToElement( {
1301
- * model: {
1302
- * key: 'attribute-name',
1303
- * name: '$text'
1304
- * },
1305
- * view: ( value, { writer } ) => {
1306
- * return writer.createAttributeElement( 'span', { 'attribute-name': value } );
1307
- * },
1308
- * converterPriority: 'high'
1309
- * } ) );
1372
+ * ```ts
1373
+ * editor.conversion.for( 'downcast' ).attributeToElement( {
1374
+ * model: {
1375
+ * key: 'attribute-name',
1376
+ * name: '$text'
1377
+ * },
1378
+ * view: ( value, { writer } ) => {
1379
+ * return writer.createAttributeElement( 'span', { 'attribute-name': value } );
1380
+ * },
1381
+ * converterPriority: 'high'
1382
+ * } ) );
1383
+ * ```
1310
1384
  *
1311
1385
  * @error conversion-attribute-to-attribute-on-text
1312
1386
  */
@@ -1350,22 +1424,21 @@ function changeAttribute(attributeCreator) {
1350
1424
  }
1351
1425
  };
1352
1426
  }
1353
- // Function factory that creates a converter which converts the text inside marker's range. The converter wraps the text with
1354
- // {@link module:engine/view/attributeelement~AttributeElement} created from the provided descriptor.
1355
- // See {link module:engine/conversion/downcasthelpers~createViewElementFromHighlightDescriptor}.
1356
- //
1357
- // It can also be used to convert the selection that is inside a marker. In that case, an empty attribute element will be
1358
- // created and the selection will be put inside it.
1359
- //
1360
- // If the highlight descriptor does not provide the `priority` property, `10` will be used.
1361
- //
1362
- // If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1363
- //
1364
- // This converter binds the created {@link module:engine/view/attributeelement~AttributeElement attribute elemens} with the marker name
1365
- // using the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.
1366
- //
1367
- // @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
1368
- // @returns {Function}
1427
+ /**
1428
+ * Function factory that creates a converter which converts the text inside marker's range. The converter wraps the text with
1429
+ * {@link module:engine/view/attributeelement~AttributeElement} created from the provided descriptor.
1430
+ * See {link module:engine/conversion/downcasthelpers~createViewElementFromHighlightDescriptor}.
1431
+ *
1432
+ * It can also be used to convert the selection that is inside a marker. In that case, an empty attribute element will be
1433
+ * created and the selection will be put inside it.
1434
+ *
1435
+ * If the highlight descriptor does not provide the `priority` property, `10` will be used.
1436
+ *
1437
+ * If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1438
+ *
1439
+ * This converter binds the created {@link module:engine/view/attributeelement~AttributeElement attribute elemens} with the marker name
1440
+ * using the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.
1441
+ */
1369
1442
  function highlightText(highlightDescriptor) {
1370
1443
  return (evt, data, conversionApi) => {
1371
1444
  if (!data.item) {
@@ -1401,24 +1474,23 @@ function highlightText(highlightDescriptor) {
1401
1474
  }
1402
1475
  };
1403
1476
  }
1404
- // Converter function factory. It creates a function which applies the marker's highlight to an element inside the marker's range.
1405
- //
1406
- // The converter checks if an element has the `addHighlight` function stored as a
1407
- // {@link module:engine/view/element~Element#_setCustomProperty custom property} and, if so, uses it to apply the highlight.
1408
- // In such case the converter will consume all element's children, assuming that they were handled by the element itself.
1409
- //
1410
- // When the `addHighlight` custom property is not present, the element is not converted in any special way.
1411
- // This means that converters will proceed to convert the element's child nodes.
1412
- //
1413
- // If the highlight descriptor does not provide the `priority` property, `10` will be used.
1414
- //
1415
- // If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1416
- //
1417
- // This converter binds altered {@link module:engine/view/containerelement~ContainerElement container elements} with the marker name using
1418
- // the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.
1419
- //
1420
- // @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
1421
- // @returns {Function}
1477
+ /**
1478
+ * Converter function factory. It creates a function which applies the marker's highlight to an element inside the marker's range.
1479
+ *
1480
+ * The converter checks if an element has the `addHighlight` function stored as a
1481
+ * {@link module:engine/view/element~Element#_setCustomProperty custom property} and, if so, uses it to apply the highlight.
1482
+ * In such case the converter will consume all element's children, assuming that they were handled by the element itself.
1483
+ *
1484
+ * When the `addHighlight` custom property is not present, the element is not converted in any special way.
1485
+ * This means that converters will proceed to convert the element's child nodes.
1486
+ *
1487
+ * If the highlight descriptor does not provide the `priority` property, `10` will be used.
1488
+ *
1489
+ * If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1490
+ *
1491
+ * This converter binds altered {@link module:engine/view/containerelement~ContainerElement container elements} with the marker name using
1492
+ * the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.
1493
+ */
1422
1494
  function highlightElement(highlightDescriptor) {
1423
1495
  return (evt, data, conversionApi) => {
1424
1496
  if (!data.item) {
@@ -1448,28 +1520,27 @@ function highlightElement(highlightDescriptor) {
1448
1520
  }
1449
1521
  };
1450
1522
  }
1451
- // Function factory that creates a converter which converts the removing model marker to the view.
1452
- //
1453
- // Both text nodes and elements are handled by this converter but they are handled a bit differently.
1454
- //
1455
- // Text nodes are unwrapped using the {@link module:engine/view/attributeelement~AttributeElement attribute element} created from the
1456
- // provided highlight descriptor. See {link module:engine/conversion/downcasthelpers~HighlightDescriptor}.
1457
- //
1458
- // For elements, the converter checks if an element has the `removeHighlight` function stored as a
1459
- // {@link module:engine/view/element~Element#_setCustomProperty custom property}. If so, it uses it to remove the highlight.
1460
- // In such case, the children of that element will not be converted.
1461
- //
1462
- // When `removeHighlight` is not present, the element is not converted in any special way.
1463
- // The converter will proceed to convert the element's child nodes instead.
1464
- //
1465
- // If the highlight descriptor does not provide the `priority` property, `10` will be used.
1466
- //
1467
- // If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1468
- //
1469
- // This converter unbinds elements from the marker name.
1470
- //
1471
- // @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor
1472
- // @returns {Function}
1523
+ /**
1524
+ * Function factory that creates a converter which converts the removing model marker to the view.
1525
+ *
1526
+ * Both text nodes and elements are handled by this converter but they are handled a bit differently.
1527
+ *
1528
+ * Text nodes are unwrapped using the {@link module:engine/view/attributeelement~AttributeElement attribute element} created from the
1529
+ * provided highlight descriptor. See {link module:engine/conversion/downcasthelpers~HighlightDescriptor}.
1530
+ *
1531
+ * For elements, the converter checks if an element has the `removeHighlight` function stored as a
1532
+ * {@link module:engine/view/element~Element#_setCustomProperty custom property}. If so, it uses it to remove the highlight.
1533
+ * In such case, the children of that element will not be converted.
1534
+ *
1535
+ * When `removeHighlight` is not present, the element is not converted in any special way.
1536
+ * The converter will proceed to convert the element's child nodes instead.
1537
+ *
1538
+ * If the highlight descriptor does not provide the `priority` property, `10` will be used.
1539
+ *
1540
+ * If the highlight descriptor does not provide the `id` property, the name of the marker will be used.
1541
+ *
1542
+ * This converter unbinds elements from the marker name.
1543
+ */
1473
1544
  function removeHighlight(highlightDescriptor) {
1474
1545
  return (evt, data, conversionApi) => {
1475
1546
  // This conversion makes sense only for non-collapsed range.
@@ -1502,17 +1573,17 @@ function removeHighlight(highlightDescriptor) {
1502
1573
  evt.stop();
1503
1574
  };
1504
1575
  }
1505
- // Model element to view element conversion helper.
1506
- //
1507
- // See {@link ~DowncastHelpers#elementToElement `.elementToElement()` downcast helper} for examples and config params description.
1508
- //
1509
- // @param {Object} config Conversion configuration.
1510
- // @param {String|Object} config.model The description or a name of the model element to convert.
1511
- // @param {String|Array.<String>} [config.model.attributes] List of attributes triggering element reconversion.
1512
- // @param {Boolean} [config.model.children] Should reconvert element if the list of model child nodes changed.
1513
- // @param {module:engine/view/elementdefinition~ElementDefinition|module:engine/conversion/downcasthelpers~ElementCreatorFunction}
1514
- // config.view
1515
- // @returns {Function} Conversion helper.
1576
+ /**
1577
+ * Model element to view element conversion helper.
1578
+ *
1579
+ * See {@link ~DowncastHelpers#elementToElement `.elementToElement()` downcast helper} for examples and config params description.
1580
+ *
1581
+ * @param config Conversion configuration.
1582
+ * @param config.model The description or a name of the model element to convert.
1583
+ * @param config.model.attributes List of attributes triggering element reconversion.
1584
+ * @param config.model.children Should reconvert element if the list of model child nodes changed.
1585
+ * @returns Conversion helper.
1586
+ */
1516
1587
  function downcastElementToElement(config) {
1517
1588
  const model = normalizeModelElementConfig(config.model);
1518
1589
  const view = normalizeToElementConfig(config.view, 'container');
@@ -1528,16 +1599,14 @@ function downcastElementToElement(config) {
1528
1599
  }
1529
1600
  };
1530
1601
  }
1531
- // Model element to view structure conversion helper.
1532
- //
1533
- // See {@link ~DowncastHelpers#elementToStructure `.elementToStructure()` downcast helper} for examples and config params description.
1534
- //
1535
- // @param {Object} config Conversion configuration.
1536
- // @param {String|Object} config.model
1537
- // @param {String} [config.model.name]
1538
- // @param {Array.<String>} [config.model.attributes]
1539
- // @param {module:engine/conversion/downcasthelpers~StructureCreatorFunction} config.view
1540
- // @returns {Function} Conversion helper.
1602
+ /**
1603
+ * Model element to view structure conversion helper.
1604
+ *
1605
+ * See {@link ~DowncastHelpers#elementToStructure `.elementToStructure()` downcast helper} for examples and config params description.
1606
+ *
1607
+ * @param config Conversion configuration.
1608
+ * @returns Conversion helper.
1609
+ */
1541
1610
  function downcastElementToStructure(config) {
1542
1611
  const model = normalizeModelElementConfig(config.model);
1543
1612
  const view = normalizeToElementConfig(config.view, 'container');
@@ -1552,34 +1621,38 @@ function downcastElementToStructure(config) {
1552
1621
  * allowed to host `$text` by the {@link module:engine/model/schema~Schema model schema}.
1553
1622
  *
1554
1623
  * For instance, this may be the result of `myElement` allowing the content of
1555
- * {@glink framework/guides/deep-dive/schema#generic-items `$block`} in its schema definition:
1624
+ * {@glink framework/deep-dive/schema#generic-items `$block`} in its schema definition:
1556
1625
  *
1557
- * // Element definition in schema.
1558
- * schema.register( 'myElement', {
1559
- * allowContentOf: '$block',
1626
+ * ```ts
1627
+ * // Element definition in schema.
1628
+ * schema.register( 'myElement', {
1629
+ * allowContentOf: '$block',
1560
1630
  *
1561
- * // ...
1562
- * } );
1631
+ * // ...
1632
+ * } );
1563
1633
  *
1564
- * // ...
1634
+ * // ...
1565
1635
  *
1566
- * // Conversion of myElement with the use of elementToStructure().
1567
- * editor.conversion.for( 'downcast' ).elementToStructure( {
1568
- * model: 'myElement',
1569
- * view: ( modelElement, { writer } ) => {
1570
- * // ...
1571
- * }
1572
- * } );
1636
+ * // Conversion of myElement with the use of elementToStructure().
1637
+ * editor.conversion.for( 'downcast' ).elementToStructure( {
1638
+ * model: 'myElement',
1639
+ * view: ( modelElement, { writer } ) => {
1640
+ * // ...
1641
+ * }
1642
+ * } );
1643
+ * ```
1573
1644
  *
1574
1645
  * In such case, {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`} helper
1575
1646
  * can be used instead to get around this problem:
1576
1647
  *
1577
- * editor.conversion.for( 'downcast' ).elementToElement( {
1578
- * model: 'myElement',
1579
- * view: ( modelElement, { writer } ) => {
1580
- * // ...
1581
- * }
1582
- * } );
1648
+ * ```ts
1649
+ * editor.conversion.for( 'downcast' ).elementToElement( {
1650
+ * model: 'myElement',
1651
+ * view: ( modelElement, { writer } ) => {
1652
+ * // ...
1653
+ * }
1654
+ * } );
1655
+ * ```
1583
1656
  *
1584
1657
  * @error conversion-element-to-structure-disallowed-text
1585
1658
  * @param {String} elementName The name of the element the structure is to be created for.
@@ -1590,20 +1663,21 @@ function downcastElementToStructure(config) {
1590
1663
  dispatcher.on('reduceChanges', createChangeReducer(model), { priority: 'low' });
1591
1664
  };
1592
1665
  }
1593
- // Model attribute to view element conversion helper.
1594
- //
1595
- // See {@link ~DowncastHelpers#attributeToElement `.attributeToElement()` downcast helper} for examples.
1596
- //
1597
- // @param {Object} config Conversion configuration.
1598
- // @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array
1599
- // of `String`s with possible values if the model attribute is an enumerable.
1600
- // @param {module:engine/view/elementdefinition~ElementDefinition|module:engine/conversion/downcasthelpers~AttributeElementCreatorFunction|
1601
- // Object} config.view A view element definition or a function that takes the model attribute value and
1602
- // {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer} as parameters and returns a view attribute element.
1603
- // If `config.model.values` is given, `config.view` should be an object assigning values from `config.model.values` to view element
1604
- // definitions or functions.
1605
- // @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
1606
- // @returns {Function} Conversion helper.
1666
+ /**
1667
+ * Model attribute to view element conversion helper.
1668
+ *
1669
+ * See {@link ~DowncastHelpers#attributeToElement `.attributeToElement()` downcast helper} for examples.
1670
+ *
1671
+ * @param config Conversion configuration.
1672
+ * @param config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array
1673
+ * of `String`s with possible values if the model attribute is an enumerable.
1674
+ * @param config.view A view element definition or a function that takes the model attribute value and
1675
+ * {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer} as parameters and returns a view attribute element.
1676
+ * If `config.model.values` is given, `config.view` should be an object assigning values from `config.model.values` to view element
1677
+ * definitions or functions.
1678
+ * @param config.converterPriority Converter priority.
1679
+ * @returns Conversion helper.
1680
+ */
1607
1681
  function downcastAttributeToElement(config) {
1608
1682
  config = cloneDeep(config);
1609
1683
  let model = config.model;
@@ -1627,21 +1701,23 @@ function downcastAttributeToElement(config) {
1627
1701
  dispatcher.on(eventName, wrap(elementCreator), { priority: config.converterPriority || 'normal' });
1628
1702
  };
1629
1703
  }
1630
- // Model attribute to view attribute conversion helper.
1631
- //
1632
- // See {@link ~DowncastHelpers#attributeToAttribute `.attributeToAttribute()` downcast helper} for examples.
1633
- //
1634
- // @param {Object} config Conversion configuration.
1635
- // @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing
1636
- // the attribute key, possible values and, optionally, an element name to convert from.
1637
- // @param {String|Object|module:engine/conversion/downcasthelpers~AttributeCreatorFunction} config.view A view attribute key,
1638
- // or a `{ key, value }` object or a function that takes the model attribute value and returns a `{ key, value }` object.
1639
- // If `key` is `'class'`, `value` can be a `String` or an array of `String`s. If `key` is `'style'`, `value` is an object with
1640
- // key-value pairs. In other cases, `value` is a `String`.
1641
- // If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to
1642
- // `{ key, value }` objects or a functions.
1643
- // @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
1644
- // @returns {Function} Conversion helper.
1704
+ /**
1705
+ * Model attribute to view attribute conversion helper.
1706
+ *
1707
+ * See {@link ~DowncastHelpers#attributeToAttribute `.attributeToAttribute()` downcast helper} for examples.
1708
+ *
1709
+ * @param config Conversion configuration.
1710
+ * @param config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing
1711
+ * the attribute key, possible values and, optionally, an element name to convert from.
1712
+ * @param config.view A view attribute key, or a `{ key, value }` object or a function that takes the model attribute value and returns
1713
+ * a `{ key, value }` object.
1714
+ * If `key` is `'class'`, `value` can be a `String` or an array of `String`s. If `key` is `'style'`, `value` is an object with
1715
+ * key-value pairs. In other cases, `value` is a `String`.
1716
+ * If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to
1717
+ * `{ key, value }` objects or a functions.
1718
+ * @param config.converterPriority Converter priority.
1719
+ * @returns Conversion helper.
1720
+ */
1645
1721
  function downcastAttributeToAttribute(config) {
1646
1722
  config = cloneDeep(config);
1647
1723
  let model = config.model;
@@ -1665,16 +1741,17 @@ function downcastAttributeToAttribute(config) {
1665
1741
  dispatcher.on(eventName, changeAttribute(elementCreator), { priority: config.converterPriority || 'normal' });
1666
1742
  };
1667
1743
  }
1668
- // Model marker to view element conversion helper.
1669
- //
1670
- // See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.
1671
- //
1672
- // @param {Object} config Conversion configuration.
1673
- // @param {String} config.model The name of the model marker (or model marker group) to convert.
1674
- // @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function
1675
- // that takes the model marker data as a parameter and returns a view UI element.
1676
- // @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
1677
- // @returns {Function} Conversion helper.
1744
+ /**
1745
+ * Model marker to view element conversion helper.
1746
+ *
1747
+ * See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.
1748
+ *
1749
+ * @param config Conversion configuration.
1750
+ * @param config.model The name of the model marker (or model marker group) to convert.
1751
+ * @param config.view A view element definition or a function that takes the model marker data as a parameter and returns a view UI element.
1752
+ * @param config.converterPriority Converter priority.
1753
+ * @returns Conversion helper.
1754
+ */
1678
1755
  function downcastMarkerToElement(config) {
1679
1756
  const view = normalizeToElementConfig(config.view, 'ui');
1680
1757
  return (dispatcher) => {
@@ -1682,15 +1759,13 @@ function downcastMarkerToElement(config) {
1682
1759
  dispatcher.on(`removeMarker:${config.model}`, removeUIElement(), { priority: config.converterPriority || 'normal' });
1683
1760
  };
1684
1761
  }
1685
- // Model marker to view data conversion helper.
1686
- //
1687
- // See {@link ~DowncastHelpers#markerToData `markerToData()` downcast helper} to learn more.
1688
- //
1689
- // @param {Object} config
1690
- // @param {String} config.model
1691
- // @param {Function} [config.view]
1692
- // @param {module:utils/priorities~PriorityString} [config.converterPriority='normal']
1693
- // @returns {Function} Conversion helper.
1762
+ /**
1763
+ * Model marker to view data conversion helper.
1764
+ *
1765
+ * See {@link ~DowncastHelpers#markerToData `markerToData()` downcast helper} to learn more.
1766
+ *
1767
+ * @returns Conversion helper.
1768
+ */
1694
1769
  function downcastMarkerToData(config) {
1695
1770
  config = cloneDeep(config);
1696
1771
  const group = config.model;
@@ -1707,16 +1782,18 @@ function downcastMarkerToData(config) {
1707
1782
  dispatcher.on(`removeMarker:${group}`, removeMarkerData(view), { priority: config.converterPriority || 'normal' });
1708
1783
  };
1709
1784
  }
1710
- // Model marker to highlight conversion helper.
1711
- //
1712
- // See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.
1713
- //
1714
- // @param {Object} config Conversion configuration.
1715
- // @param {String} config.model The name of the model marker (or model marker group) to convert.
1716
- // @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} config.view A highlight descriptor
1717
- // that will be used for highlighting or a function that takes the model marker data as a parameter and returns a highlight descriptor.
1718
- // @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
1719
- // @returns {Function} Conversion helper.
1785
+ /**
1786
+ * Model marker to highlight conversion helper.
1787
+ *
1788
+ * See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.
1789
+ *
1790
+ * @param config Conversion configuration.
1791
+ * @param config.model The name of the model marker (or model marker group) to convert.
1792
+ * @param config.view A highlight descriptor that will be used for highlighting or a function that takes
1793
+ * the model marker data as a parameter and returns a highlight descriptor.
1794
+ * @param config.converterPriority Converter priority.
1795
+ * @returns Conversion helper.
1796
+ */
1720
1797
  function downcastMarkerToHighlight(config) {
1721
1798
  return (dispatcher) => {
1722
1799
  dispatcher.on(`addMarker:${config.model}`, highlightText(config.view), { priority: config.converterPriority || 'normal' });
@@ -1724,13 +1801,11 @@ function downcastMarkerToHighlight(config) {
1724
1801
  dispatcher.on(`removeMarker:${config.model}`, removeHighlight(config.view), { priority: config.converterPriority || 'normal' });
1725
1802
  };
1726
1803
  }
1727
- // Takes `config.model`, and converts it to an object with normalized structure.
1728
- //
1729
- // @param {String|Object} model Model configuration or element name.
1730
- // @param {String} model.name
1731
- // @param {Array.<String>} [model.attributes]
1732
- // @param {Boolean} [model.children]
1733
- // @returns {Object}
1804
+ /**
1805
+ * Takes `config.model`, and converts it to an object with normalized structure.
1806
+ *
1807
+ * @param model Model configuration or element name.
1808
+ */
1734
1809
  function normalizeModelElementConfig(model) {
1735
1810
  if (typeof model == 'string') {
1736
1811
  model = { name: model };
@@ -1746,12 +1821,14 @@ function normalizeModelElementConfig(model) {
1746
1821
  model.children = !!model.children;
1747
1822
  return model;
1748
1823
  }
1749
- // Takes `config.view`, and if it is an {@link module:engine/view/elementdefinition~ElementDefinition}, converts it
1750
- // to a function (because lower level converters accept only element creator functions).
1751
- //
1752
- // @param {module:engine/view/elementdefinition~ElementDefinition|Function} view View configuration.
1753
- // @param {'container'|'attribute'|'ui'} viewElementType View element type to create.
1754
- // @returns {Function} Element creator function to use in lower level converters.
1824
+ /**
1825
+ * Takes `config.view`, and if it is an {@link module:engine/view/elementdefinition~ElementDefinition}, converts it
1826
+ * to a function (because lower level converters accept only element creator functions).
1827
+ *
1828
+ * @param view View configuration.
1829
+ * @param viewElementType View element type to create.
1830
+ * @returns Element creator function to use in lower level converters.
1831
+ */
1755
1832
  function normalizeToElementConfig(view, viewElementType) {
1756
1833
  if (typeof view == 'function') {
1757
1834
  // If `view` is already a function, don't do anything.
@@ -1759,12 +1836,9 @@ function normalizeToElementConfig(view, viewElementType) {
1759
1836
  }
1760
1837
  return ((modelData, conversionApi) => createViewElementFromDefinition(view, conversionApi, viewElementType));
1761
1838
  }
1762
- // Creates a view element instance from the provided {@link module:engine/view/elementdefinition~ElementDefinition} and class.
1763
- //
1764
- // @param {module:engine/view/elementdefinition~ElementDefinition} viewElementDefinition
1765
- // @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter
1766
- // @param {'container'|'attribute'|'ui'} viewElementType
1767
- // @returns {module:engine/view/element~Element}
1839
+ /**
1840
+ * Creates a view element instance from the provided {@link module:engine/view/elementdefinition~ElementDefinition} and class.
1841
+ */
1768
1842
  function createViewElementFromDefinition(viewElementDefinition, conversionApi, viewElementType) {
1769
1843
  if (typeof viewElementDefinition == 'string') {
1770
1844
  // If `viewElementDefinition` is given as a `String`, normalize it to an object with `name` property.
@@ -1819,10 +1893,12 @@ function getFromAttributeCreator(config) {
1819
1893
  return config.view;
1820
1894
  }
1821
1895
  }
1822
- // Takes the configuration, adds default parameters if they do not exist and normalizes other parameters to be used in downcast converters
1823
- // for generating a view attribute.
1824
- //
1825
- // @param {Object} view View configuration.
1896
+ /**
1897
+ * Takes the configuration, adds default parameters if they do not exist and normalizes other parameters to be used in downcast converters
1898
+ * for generating a view attribute.
1899
+ *
1900
+ * @param view View configuration.
1901
+ */
1826
1902
  function normalizeToAttributeConfig(view) {
1827
1903
  if (typeof view == 'string') {
1828
1904
  return modelAttributeValue => ({ key: view, value: modelAttributeValue });
@@ -1842,7 +1918,9 @@ function normalizeToAttributeConfig(view) {
1842
1918
  return view;
1843
1919
  }
1844
1920
  }
1845
- // Helper function for `highlight`. Prepares the actual descriptor object using value passed to the converter.
1921
+ /**
1922
+ * Helper function for `highlight`. Prepares the actual descriptor object using value passed to the converter.
1923
+ */
1846
1924
  function prepareDescriptor(highlightDescriptor, data, conversionApi) {
1847
1925
  // If passed descriptor is a creator function, call it. If not, just use passed value.
1848
1926
  const descriptor = typeof highlightDescriptor == 'function' ?
@@ -1861,13 +1939,14 @@ function prepareDescriptor(highlightDescriptor, data, conversionApi) {
1861
1939
  }
1862
1940
  return descriptor;
1863
1941
  }
1864
- // Creates a function that checks a single differ diff item whether it should trigger reconversion.
1865
- //
1866
- // @param {Object} model A normalized `config.model` converter configuration.
1867
- // @param {String} model.name The name of element.
1868
- // @param {Array.<String>} model.attributes The list of attribute names that should trigger reconversion.
1869
- // @param {Boolean} [model.children] Whether the child list change should trigger reconversion.
1870
- // @returns {Function}
1942
+ /**
1943
+ * Creates a function that checks a single differ diff item whether it should trigger reconversion.
1944
+ *
1945
+ * @param model A normalized `config.model` converter configuration.
1946
+ * @param model.name The name of element.
1947
+ * @param model.attributes The list of attribute names that should trigger reconversion.
1948
+ * @param model.children Whether the child list change should trigger reconversion.
1949
+ */
1871
1950
  function createChangeReducerCallback(model) {
1872
1951
  return (node, change) => {
1873
1952
  if (!node.is('element', model.name)) {
@@ -1887,13 +1966,14 @@ function createChangeReducerCallback(model) {
1887
1966
  return false;
1888
1967
  };
1889
1968
  }
1890
- // Creates a `reduceChanges` event handler for reconversion.
1891
- //
1892
- // @param {Object} model A normalized `config.model` converter configuration.
1893
- // @param {String} model.name The name of element.
1894
- // @param {Array.<String>} model.attributes The list of attribute names that should trigger reconversion.
1895
- // @param {Boolean} [model.children] Whether the child list change should trigger reconversion.
1896
- // @returns {Function}
1969
+ /**
1970
+ * Creates a `reduceChanges` event handler for reconversion.
1971
+ *
1972
+ * @param model A normalized `config.model` converter configuration.
1973
+ * @param model.name The name of element.
1974
+ * @param model.attributes The list of attribute names that should trigger reconversion.
1975
+ * @param model.children Whether the child list change should trigger reconversion.
1976
+ */
1897
1977
  function createChangeReducer(model) {
1898
1978
  const shouldReplace = createChangeReducerCallback(model);
1899
1979
  return (evt, data) => {
@@ -1913,7 +1993,20 @@ function createChangeReducer(model) {
1913
1993
  if (!data.reconvertedElements.has(node)) {
1914
1994
  data.reconvertedElements.add(node);
1915
1995
  const position = ModelPosition._createBefore(node);
1916
- reducedChanges.push({
1996
+ let changeIndex = reducedChanges.length;
1997
+ // We need to insert remove+reinsert before any other change on and inside the re-converted element.
1998
+ // This is important because otherwise we would remove element that had already been modified by the previous change.
1999
+ // Note that there could be some element removed before the re-converted element, so we must not break this behavior.
2000
+ for (let i = reducedChanges.length - 1; i >= 0; i--) {
2001
+ const change = reducedChanges[i];
2002
+ const changePosition = change.type == 'attribute' ? change.range.start : change.position;
2003
+ const positionRelation = changePosition.compareWith(position);
2004
+ if (positionRelation == 'before' || change.type == 'remove' && positionRelation == 'same') {
2005
+ break;
2006
+ }
2007
+ changeIndex = i;
2008
+ }
2009
+ reducedChanges.splice(changeIndex, 0, {
1917
2010
  type: 'remove',
1918
2011
  name: node.name,
1919
2012
  position,
@@ -1929,13 +2022,14 @@ function createChangeReducer(model) {
1929
2022
  data.changes = reducedChanges;
1930
2023
  };
1931
2024
  }
1932
- // Creates a function that checks if an element and its watched attributes can be consumed and consumes them.
1933
- //
1934
- // @param {Object} model A normalized `config.model` converter configuration.
1935
- // @param {String} model.name The name of element.
1936
- // @param {Array.<String>} model.attributes The list of attribute names that should trigger reconversion.
1937
- // @param {Boolean} [model.children] Whether the child list change should trigger reconversion.
1938
- // @returns {module:engine/conversion/downcasthelpers~ConsumerFunction}
2025
+ /**
2026
+ * Creates a function that checks if an element and its watched attributes can be consumed and consumes them.
2027
+ *
2028
+ * @param model A normalized `config.model` converter configuration.
2029
+ * @param model.name The name of element.
2030
+ * @param model.attributes The list of attribute names that should trigger reconversion.
2031
+ * @param model.children Whether the child list change should trigger reconversion.
2032
+ */
1939
2033
  function createConsumer(model) {
1940
2034
  return (node, consumable, options = {}) => {
1941
2035
  const events = ['insert'];
@@ -1954,14 +2048,13 @@ function createConsumer(model) {
1954
2048
  return true;
1955
2049
  };
1956
2050
  }
1957
- // Creates a function that create view slots.
1958
- //
1959
- // @param {module:engine/model/element~Element} element
1960
- // @param {Map.<module:engine/view/element~Element,Array.<module:engine/model/node~Node>>} slotsMap
1961
- // @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
1962
- // @returns {Function} Exposed by writer as createSlot().
2051
+ /**
2052
+ * Creates a function that create view slots.
2053
+ *
2054
+ * @returns Function exposed by writer as createSlot().
2055
+ */
1963
2056
  function createSlotFactory(element, slotsMap, conversionApi) {
1964
- return (writer, modeOrFilter = 'children') => {
2057
+ return (writer, modeOrFilter) => {
1965
2058
  const slot = writer.createContainerElement('$slot');
1966
2059
  let children = null;
1967
2060
  if (modeOrFilter === 'children') {
@@ -1982,11 +2075,9 @@ function createSlotFactory(element, slotsMap, conversionApi) {
1982
2075
  return slot;
1983
2076
  };
1984
2077
  }
1985
- // Checks if all children are covered by slots and there is no child that landed in multiple slots.
1986
- //
1987
- // @param {module:engine/model/element~Element}
1988
- // @param {Map.<module:engine/view/element~Element,Array.<module:engine/model/node~Node>>} slotsMap
1989
- // @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
2078
+ /**
2079
+ * Checks if all children are covered by slots and there is no child that landed in multiple slots.
2080
+ */
1990
2081
  function validateSlotsChildren(element, slotsMap, conversionApi) {
1991
2082
  const childrenInSlots = Array.from(slotsMap.values()).flat();
1992
2083
  const uniqueChildrenInSlots = new Set(childrenInSlots);
@@ -2012,13 +2103,9 @@ function validateSlotsChildren(element, slotsMap, conversionApi) {
2012
2103
  throw new CKEditorError('conversion-slot-filter-incomplete', conversionApi.dispatcher, { element });
2013
2104
  }
2014
2105
  }
2015
- // Fill slots with appropriate view elements.
2016
- //
2017
- // @param {module:engine/view/element~Element} viewElement
2018
- // @param {Map.<module:engine/view/element~Element,Array.<module:engine/model/node~Node>>} slotsMap
2019
- // @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
2020
- // @param {Object} options
2021
- // @param {Boolean} [options.reconversion]
2106
+ /**
2107
+ * Fill slots with appropriate view elements.
2108
+ */
2022
2109
  function fillSlots(viewElement, slotsMap, conversionApi, options) {
2023
2110
  // Set temporary position mapping to redirect child view elements into a proper slots.
2024
2111
  conversionApi.mapper.on('modelToViewPosition', toViewPositionMapping, { priority: 'highest' });
@@ -2041,14 +2128,10 @@ function fillSlots(viewElement, slotsMap, conversionApi, options) {
2041
2128
  data.viewPosition = data.mapper.findPositionIn(currentSlot, index);
2042
2129
  }
2043
2130
  }
2044
- // Inserts view representation of `nodes` into the `viewElement` either by bringing back just removed view nodes
2045
- // or by triggering conversion for them.
2046
- //
2047
- // @param {module:engine/view/element~Element} viewElement
2048
- // @param {Iterable.<module:engine/model/element~Element>} modelNodes
2049
- // @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
2050
- // @param {Object} options
2051
- // @param {Boolean} [options.reconversion]
2131
+ /**
2132
+ * Inserts view representation of `nodes` into the `viewElement` either by bringing back just removed view nodes
2133
+ * or by triggering conversion for them.
2134
+ */
2052
2135
  function reinsertOrConvertNodes(viewElement, modelNodes, conversionApi, options) {
2053
2136
  // Fill with nested view nodes.
2054
2137
  for (const modelChildNode of modelNodes) {
@@ -2059,14 +2142,11 @@ function reinsertOrConvertNodes(viewElement, modelNodes, conversionApi, options)
2059
2142
  }
2060
2143
  }
2061
2144
  }
2062
- // Checks if the view for the given model element could be reused and reinserts it to the view.
2063
- //
2064
- // @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} viewRoot
2065
- // @param {module:engine/model/element~Element} modelElement
2066
- // @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
2067
- // @param {Object} options
2068
- // @param {Boolean} [options.reconversion]
2069
- // @returns {Boolean} `false` if view element can't be reused.
2145
+ /**
2146
+ * Checks if the view for the given model element could be reused and reinserts it to the view.
2147
+ *
2148
+ * @returns `false` if view element can't be reused.
2149
+ */
2070
2150
  function reinsertNode(viewRoot, modelNode, conversionApi, options) {
2071
2151
  const { writer, mapper } = conversionApi;
2072
2152
  // Don't reinsert if this is not a reconversion...
@@ -2086,12 +2166,13 @@ function reinsertNode(viewRoot, modelNode, conversionApi, options) {
2086
2166
  writer.move(writer.createRangeOn(viewChildNode), mapper.toViewPosition(ModelPosition._createBefore(modelNode)));
2087
2167
  return true;
2088
2168
  }
2089
- // The default consumer for insert events.
2090
- // @param {module:engine/model/item~Item} item Model item.
2091
- // @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable The model consumable.
2092
- // @param {Object} [options]
2093
- // @param {Boolean} [options.preflight=false] Whether should consume or just check if can be consumed.
2094
- // @returns {Boolean}
2169
+ /**
2170
+ * The default consumer for insert events.
2171
+ *
2172
+ * @param item Model item.
2173
+ * @param consumable The model consumable.
2174
+ * @param options.preflight Whether should consume or just check if can be consumed.
2175
+ */
2095
2176
  function defaultConsumer(item, consumable, { preflight } = {}) {
2096
2177
  if (preflight) {
2097
2178
  return consumable.test(item, 'insert');