@ckeditor/ckeditor5-engine 30.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE.md +17 -0
  2. package/README.md +30 -0
  3. package/package.json +70 -0
  4. package/src/controller/datacontroller.js +563 -0
  5. package/src/controller/editingcontroller.js +149 -0
  6. package/src/conversion/conversion.js +644 -0
  7. package/src/conversion/conversionhelpers.js +40 -0
  8. package/src/conversion/downcastdispatcher.js +914 -0
  9. package/src/conversion/downcasthelpers.js +1706 -0
  10. package/src/conversion/mapper.js +696 -0
  11. package/src/conversion/modelconsumable.js +329 -0
  12. package/src/conversion/upcastdispatcher.js +807 -0
  13. package/src/conversion/upcasthelpers.js +997 -0
  14. package/src/conversion/viewconsumable.js +623 -0
  15. package/src/dataprocessor/basichtmlwriter.js +32 -0
  16. package/src/dataprocessor/dataprocessor.jsdoc +64 -0
  17. package/src/dataprocessor/htmldataprocessor.js +159 -0
  18. package/src/dataprocessor/htmlwriter.js +22 -0
  19. package/src/dataprocessor/xmldataprocessor.js +161 -0
  20. package/src/dev-utils/model.js +482 -0
  21. package/src/dev-utils/operationreplayer.js +140 -0
  22. package/src/dev-utils/utils.js +103 -0
  23. package/src/dev-utils/view.js +1091 -0
  24. package/src/index.js +52 -0
  25. package/src/model/batch.js +82 -0
  26. package/src/model/differ.js +1282 -0
  27. package/src/model/document.js +483 -0
  28. package/src/model/documentfragment.js +390 -0
  29. package/src/model/documentselection.js +1261 -0
  30. package/src/model/element.js +438 -0
  31. package/src/model/history.js +138 -0
  32. package/src/model/item.jsdoc +14 -0
  33. package/src/model/liveposition.js +182 -0
  34. package/src/model/liverange.js +221 -0
  35. package/src/model/markercollection.js +553 -0
  36. package/src/model/model.js +934 -0
  37. package/src/model/node.js +507 -0
  38. package/src/model/nodelist.js +217 -0
  39. package/src/model/operation/attributeoperation.js +202 -0
  40. package/src/model/operation/detachoperation.js +103 -0
  41. package/src/model/operation/insertoperation.js +188 -0
  42. package/src/model/operation/markeroperation.js +154 -0
  43. package/src/model/operation/mergeoperation.js +216 -0
  44. package/src/model/operation/moveoperation.js +209 -0
  45. package/src/model/operation/nooperation.js +58 -0
  46. package/src/model/operation/operation.js +139 -0
  47. package/src/model/operation/operationfactory.js +49 -0
  48. package/src/model/operation/renameoperation.js +155 -0
  49. package/src/model/operation/rootattributeoperation.js +211 -0
  50. package/src/model/operation/splitoperation.js +254 -0
  51. package/src/model/operation/transform.js +2389 -0
  52. package/src/model/operation/utils.js +292 -0
  53. package/src/model/position.js +1164 -0
  54. package/src/model/range.js +1049 -0
  55. package/src/model/rootelement.js +111 -0
  56. package/src/model/schema.js +1851 -0
  57. package/src/model/selection.js +902 -0
  58. package/src/model/text.js +138 -0
  59. package/src/model/textproxy.js +279 -0
  60. package/src/model/treewalker.js +414 -0
  61. package/src/model/utils/autoparagraphing.js +77 -0
  62. package/src/model/utils/deletecontent.js +528 -0
  63. package/src/model/utils/getselectedcontent.js +150 -0
  64. package/src/model/utils/insertcontent.js +824 -0
  65. package/src/model/utils/modifyselection.js +229 -0
  66. package/src/model/utils/selection-post-fixer.js +297 -0
  67. package/src/model/writer.js +1574 -0
  68. package/src/view/attributeelement.js +274 -0
  69. package/src/view/containerelement.js +123 -0
  70. package/src/view/document.js +221 -0
  71. package/src/view/documentfragment.js +273 -0
  72. package/src/view/documentselection.js +387 -0
  73. package/src/view/domconverter.js +1437 -0
  74. package/src/view/downcastwriter.js +2121 -0
  75. package/src/view/editableelement.js +118 -0
  76. package/src/view/element.js +945 -0
  77. package/src/view/elementdefinition.jsdoc +59 -0
  78. package/src/view/emptyelement.js +119 -0
  79. package/src/view/filler.js +161 -0
  80. package/src/view/item.jsdoc +14 -0
  81. package/src/view/matcher.js +776 -0
  82. package/src/view/node.js +391 -0
  83. package/src/view/observer/arrowkeysobserver.js +58 -0
  84. package/src/view/observer/bubblingemittermixin.js +307 -0
  85. package/src/view/observer/bubblingeventinfo.js +71 -0
  86. package/src/view/observer/clickobserver.js +46 -0
  87. package/src/view/observer/compositionobserver.js +79 -0
  88. package/src/view/observer/domeventdata.js +82 -0
  89. package/src/view/observer/domeventobserver.js +99 -0
  90. package/src/view/observer/fakeselectionobserver.js +118 -0
  91. package/src/view/observer/focusobserver.js +106 -0
  92. package/src/view/observer/inputobserver.js +44 -0
  93. package/src/view/observer/keyobserver.js +83 -0
  94. package/src/view/observer/mouseobserver.js +56 -0
  95. package/src/view/observer/mutationobserver.js +345 -0
  96. package/src/view/observer/observer.js +118 -0
  97. package/src/view/observer/selectionobserver.js +242 -0
  98. package/src/view/placeholder.js +285 -0
  99. package/src/view/position.js +426 -0
  100. package/src/view/range.js +533 -0
  101. package/src/view/rawelement.js +148 -0
  102. package/src/view/renderer.js +1037 -0
  103. package/src/view/rooteditableelement.js +107 -0
  104. package/src/view/selection.js +718 -0
  105. package/src/view/styles/background.js +73 -0
  106. package/src/view/styles/border.js +362 -0
  107. package/src/view/styles/margin.js +41 -0
  108. package/src/view/styles/padding.js +40 -0
  109. package/src/view/styles/utils.js +277 -0
  110. package/src/view/stylesmap.js +938 -0
  111. package/src/view/text.js +147 -0
  112. package/src/view/textproxy.js +199 -0
  113. package/src/view/treewalker.js +496 -0
  114. package/src/view/uielement.js +238 -0
  115. package/src/view/upcastwriter.js +484 -0
  116. package/src/view/view.js +721 -0
  117. package/theme/placeholder.css +27 -0
@@ -0,0 +1,776 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module engine/view/matcher
8
+ */
9
+
10
+ import { isPlainObject } from 'lodash-es';
11
+
12
+ import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
13
+
14
+ /**
15
+ * View matcher class.
16
+ * Instance of this class can be used to find {@link module:engine/view/element~Element elements} that match given pattern.
17
+ */
18
+ export default class Matcher {
19
+ /**
20
+ * Creates new instance of Matcher.
21
+ *
22
+ * @param {String|RegExp|Object} [pattern] Match patterns. See {@link module:engine/view/matcher~Matcher#add add method} for
23
+ * more information.
24
+ */
25
+ constructor( ...pattern ) {
26
+ /**
27
+ * @private
28
+ * @type {Array<String|RegExp|Object>}
29
+ */
30
+ this._patterns = [];
31
+
32
+ this.add( ...pattern );
33
+ }
34
+
35
+ /**
36
+ * Adds pattern or patterns to matcher instance.
37
+ *
38
+ * // String.
39
+ * matcher.add( 'div' );
40
+ *
41
+ * // Regular expression.
42
+ * matcher.add( /^\w/ );
43
+ *
44
+ * // Single class.
45
+ * matcher.add( {
46
+ * classes: 'foobar'
47
+ * } );
48
+ *
49
+ * See {@link module:engine/view/matcher~MatcherPattern} for more examples.
50
+ *
51
+ * Multiple patterns can be added in one call:
52
+ *
53
+ * matcher.add( 'div', { classes: 'foobar' } );
54
+ *
55
+ * @param {Object|String|RegExp|Function} pattern Object describing pattern details. If string or regular expression
56
+ * is provided it will be used to match element's name. Pattern can be also provided in a form
57
+ * of a function - then this function will be called with each {@link module:engine/view/element~Element element} as a parameter.
58
+ * Function's return value will be stored under `match` key of the object returned from
59
+ * {@link module:engine/view/matcher~Matcher#match match} or {@link module:engine/view/matcher~Matcher#matchAll matchAll} methods.
60
+ * @param {String|RegExp} [pattern.name] Name or regular expression to match element's name.
61
+ * @param {Object} [pattern.attributes] Object with key-value pairs representing attributes to match. Each object key
62
+ * represents attribute name. Value under that key can be either:
63
+ * * `true` - then attribute is just required (can be empty),
64
+ * * a string - then attribute has to be equal, or
65
+ * * a regular expression - then attribute has to match the expression.
66
+ * @param {String|RegExp|Array} [pattern.classes] Class name or array of class names to match. Each name can be
67
+ * provided in a form of string or regular expression.
68
+ * @param {Object} [pattern.styles] Object with key-value pairs representing styles to match. Each object key
69
+ * represents style name. Value under that key can be either a string or a regular expression and it will be used
70
+ * to match style value.
71
+ */
72
+ add( ...pattern ) {
73
+ for ( let item of pattern ) {
74
+ // String or RegExp pattern is used as element's name.
75
+ if ( typeof item == 'string' || item instanceof RegExp ) {
76
+ item = { name: item };
77
+ }
78
+
79
+ this._patterns.push( item );
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Matches elements for currently stored patterns. Returns match information about first found
85
+ * {@link module:engine/view/element~Element element}, otherwise returns `null`.
86
+ *
87
+ * Example of returned object:
88
+ *
89
+ * {
90
+ * element: <instance of found element>,
91
+ * pattern: <pattern used to match found element>,
92
+ * match: {
93
+ * name: true,
94
+ * attributes: [ 'title', 'href' ],
95
+ * classes: [ 'foo' ],
96
+ * styles: [ 'color', 'position' ]
97
+ * }
98
+ * }
99
+ *
100
+ * @see module:engine/view/matcher~Matcher#add
101
+ * @see module:engine/view/matcher~Matcher#matchAll
102
+ * @param {...module:engine/view/element~Element} element View element to match against stored patterns.
103
+ * @returns {Object|null} result
104
+ * @returns {module:engine/view/element~Element} result.element Matched view element.
105
+ * @returns {Object|String|RegExp|Function} result.pattern Pattern that was used to find matched element.
106
+ * @returns {Object} result.match Object representing matched element parts.
107
+ * @returns {Boolean} [result.match.name] True if name of the element was matched.
108
+ * @returns {Array} [result.match.attributes] Array with matched attribute names.
109
+ * @returns {Array} [result.match.classes] Array with matched class names.
110
+ * @returns {Array} [result.match.styles] Array with matched style names.
111
+ */
112
+ match( ...element ) {
113
+ for ( const singleElement of element ) {
114
+ for ( const pattern of this._patterns ) {
115
+ const match = isElementMatching( singleElement, pattern );
116
+
117
+ if ( match ) {
118
+ return {
119
+ element: singleElement,
120
+ pattern,
121
+ match
122
+ };
123
+ }
124
+ }
125
+ }
126
+
127
+ return null;
128
+ }
129
+
130
+ /**
131
+ * Matches elements for currently stored patterns. Returns array of match information with all found
132
+ * {@link module:engine/view/element~Element elements}. If no element is found - returns `null`.
133
+ *
134
+ * @see module:engine/view/matcher~Matcher#add
135
+ * @see module:engine/view/matcher~Matcher#match
136
+ * @param {...module:engine/view/element~Element} element View element to match against stored patterns.
137
+ * @returns {Array.<Object>|null} Array with match information about found elements or `null`. For more information
138
+ * see {@link module:engine/view/matcher~Matcher#match match method} description.
139
+ */
140
+ matchAll( ...element ) {
141
+ const results = [];
142
+
143
+ for ( const singleElement of element ) {
144
+ for ( const pattern of this._patterns ) {
145
+ const match = isElementMatching( singleElement, pattern );
146
+
147
+ if ( match ) {
148
+ results.push( {
149
+ element: singleElement,
150
+ pattern,
151
+ match
152
+ } );
153
+ }
154
+ }
155
+ }
156
+
157
+ return results.length > 0 ? results : null;
158
+ }
159
+
160
+ /**
161
+ * Returns the name of the element to match if there is exactly one pattern added to the matcher instance
162
+ * and it matches element name defined by `string` (not `RegExp`). Otherwise, returns `null`.
163
+ *
164
+ * @returns {String|null} Element name trying to match.
165
+ */
166
+ getElementName() {
167
+ if ( this._patterns.length !== 1 ) {
168
+ return null;
169
+ }
170
+
171
+ const pattern = this._patterns[ 0 ];
172
+ const name = pattern.name;
173
+
174
+ return ( typeof pattern != 'function' && name && !( name instanceof RegExp ) ) ? name : null;
175
+ }
176
+ }
177
+
178
+ // Returns match information if {@link module:engine/view/element~Element element} is matching provided pattern.
179
+ // If element cannot be matched to provided pattern - returns `null`.
180
+ //
181
+ // @param {module:engine/view/element~Element} element
182
+ // @param {Object|String|RegExp|Function} pattern
183
+ // @returns {Object|null} Returns object with match information or null if element is not matching.
184
+ function isElementMatching( element, pattern ) {
185
+ // If pattern is provided as function - return result of that function;
186
+ if ( typeof pattern == 'function' ) {
187
+ return pattern( element );
188
+ }
189
+
190
+ const match = {};
191
+ // Check element's name.
192
+ if ( pattern.name ) {
193
+ match.name = matchName( pattern.name, element.name );
194
+
195
+ if ( !match.name ) {
196
+ return null;
197
+ }
198
+ }
199
+
200
+ // Check element's attributes.
201
+ if ( pattern.attributes ) {
202
+ match.attributes = matchAttributes( pattern.attributes, element );
203
+
204
+ if ( !match.attributes ) {
205
+ return null;
206
+ }
207
+ }
208
+
209
+ // Check element's classes.
210
+ if ( pattern.classes ) {
211
+ match.classes = matchClasses( pattern.classes, element );
212
+
213
+ if ( !match.classes ) {
214
+ return false;
215
+ }
216
+ }
217
+
218
+ // Check element's styles.
219
+ if ( pattern.styles ) {
220
+ match.styles = matchStyles( pattern.styles, element );
221
+
222
+ if ( !match.styles ) {
223
+ return false;
224
+ }
225
+ }
226
+
227
+ return match;
228
+ }
229
+
230
+ // Checks if name can be matched by provided pattern.
231
+ //
232
+ // @param {String|RegExp} pattern
233
+ // @param {String} name
234
+ // @returns {Boolean} Returns `true` if name can be matched, `false` otherwise.
235
+ function matchName( pattern, name ) {
236
+ // If pattern is provided as RegExp - test against this regexp.
237
+ if ( pattern instanceof RegExp ) {
238
+ return !!name.match( pattern );
239
+ }
240
+
241
+ return pattern === name;
242
+ }
243
+
244
+ // Checks if an array of key/value pairs can be matched against provided patterns.
245
+ //
246
+ // Patterns can be provided in a following ways:
247
+ // - a boolean value matches any attribute with any value (or no value):
248
+ //
249
+ // pattern: true
250
+ //
251
+ // - a RegExp expression or object matches any attribute name:
252
+ //
253
+ // pattern: /h[1-6]/
254
+ //
255
+ // - an object matches any attribute that has the same name as the object item's key, where object item's value is:
256
+ // - equal to `true`, which matches any attribute value:
257
+ //
258
+ // pattern: {
259
+ // required: true
260
+ // }
261
+ //
262
+ // - a string that is equal to attribute value:
263
+ //
264
+ // pattern: {
265
+ // rel: 'nofollow'
266
+ // }
267
+ //
268
+ // - a regular expression that matches attribute value,
269
+ //
270
+ // pattern: {
271
+ // src: /https.*/
272
+ // }
273
+ //
274
+ // - an array with items, where the item is:
275
+ // - a string that is equal to attribute value:
276
+ //
277
+ // pattern: [ 'data-property-1', 'data-property-2' ],
278
+ //
279
+ // - an object with `key` and `value` property, where `key` is a regular expression matching attribute name and
280
+ // `value` is either regular expression matching attribute value or a string equal to attribute value:
281
+ //
282
+ // pattern: [
283
+ // { key: /data-property-.*/, value: true },
284
+ // // or:
285
+ // { key: /data-property-.*/, value: 'foobar' },
286
+ // // or:
287
+ // { key: /data-property-.*/, value: /foo.*/ }
288
+ // ]
289
+ //
290
+ // @param {Object} patterns Object with information about attributes to match.
291
+ // @param {Iterable.<String>} keys Attribute, style or class keys.
292
+ // @param {Function} valueGetter A function providing value for a given item key.
293
+ // @returns {Array|null} Returns array with matched attribute names or `null` if no attributes were matched.
294
+ function matchPatterns( patterns, keys, valueGetter ) {
295
+ const normalizedPatterns = normalizePatterns( patterns );
296
+ const normalizedItems = Array.from( keys );
297
+ const match = [];
298
+
299
+ normalizedPatterns.forEach( ( [ patternKey, patternValue ] ) => {
300
+ normalizedItems.forEach( itemKey => {
301
+ if (
302
+ isKeyMatched( patternKey, itemKey ) &&
303
+ isValueMatched( patternValue, itemKey, valueGetter )
304
+ ) {
305
+ match.push( itemKey );
306
+ }
307
+ } );
308
+ } );
309
+
310
+ // Return matches only if there are at least as many of them as there are patterns.
311
+ // The RegExp pattern can match more than one item.
312
+ if ( !normalizedPatterns.length || match.length < normalizedPatterns.length ) {
313
+ return null;
314
+ }
315
+
316
+ return match;
317
+ }
318
+
319
+ // Bring all the possible pattern forms to an array of arrays where first item is a key and second is a value.
320
+ //
321
+ // Examples:
322
+ //
323
+ // Boolean pattern value:
324
+ //
325
+ // true
326
+ //
327
+ // to
328
+ //
329
+ // [ [ true, true ] ]
330
+ //
331
+ // Textual pattern value:
332
+ //
333
+ // 'attribute-name-or-class-or-style'
334
+ //
335
+ // to
336
+ //
337
+ // [ [ 'attribute-name-or-class-or-style', true ] ]
338
+ //
339
+ // Regular expression:
340
+ //
341
+ // /^data-.*$/
342
+ //
343
+ // to
344
+ //
345
+ // [ [ /^data-.*$/, true ] ]
346
+ //
347
+ // Objects (plain or with `key` and `value` specified explicitly):
348
+ //
349
+ // {
350
+ // src: /^https:.*$/
351
+ // }
352
+ //
353
+ // or
354
+ //
355
+ // [ {
356
+ // key: 'src',
357
+ // value: /^https:.*$/
358
+ // } ]
359
+ //
360
+ // to:
361
+ //
362
+ // [ [ 'src', /^https:.*$/ ] ]
363
+ //
364
+ // @param {Object|Array} patterns
365
+ // @returns {Array|null} Returns an array of objects or null if provided patterns were not in an expected form.
366
+ function normalizePatterns( patterns ) {
367
+ if ( Array.isArray( patterns ) ) {
368
+ return patterns.map( pattern => {
369
+ if ( isPlainObject( pattern ) ) {
370
+ if ( pattern.key === undefined || pattern.value === undefined ) {
371
+ // Documented at the end of matcher.js.
372
+ logWarning( 'matcher-pattern-missing-key-or-value', pattern );
373
+ }
374
+
375
+ return [ pattern.key, pattern.value ];
376
+ }
377
+
378
+ // Assume the pattern is either String or RegExp.
379
+ return [ pattern, true ];
380
+ } );
381
+ }
382
+
383
+ if ( isPlainObject( patterns ) ) {
384
+ return Object.entries( patterns );
385
+ }
386
+
387
+ // Other cases (true, string or regexp).
388
+ return [ [ patterns, true ] ];
389
+ }
390
+
391
+ // @param {String|RegExp} patternKey A pattern representing a key we want to match.
392
+ // @param {String} itemKey An actual item key (e.g. `'src'`, `'background-color'`, `'ck-widget'`) we're testing against pattern.
393
+ // @returns {Boolean}
394
+ function isKeyMatched( patternKey, itemKey ) {
395
+ return patternKey === true ||
396
+ patternKey === itemKey ||
397
+ patternKey instanceof RegExp && itemKey.match( patternKey );
398
+ }
399
+
400
+ // @param {String|RegExp} patternValue A pattern representing a value we want to match.
401
+ // @param {String} itemKey An item key, e.g. `background`, `href`, 'rel', etc.
402
+ // @param {Function} valueGetter A function used to provide a value for a given `itemKey`.
403
+ // @returns {Boolean}
404
+ function isValueMatched( patternValue, itemKey, valueGetter ) {
405
+ if ( patternValue === true ) {
406
+ return true;
407
+ }
408
+
409
+ const itemValue = valueGetter( itemKey );
410
+
411
+ // For now, the reducers are not returning the full tree of properties.
412
+ // Casting to string preserves the old behavior until the root cause is fixed.
413
+ // More can be found in https://github.com/ckeditor/ckeditor5/issues/10399.
414
+ return patternValue === itemValue ||
415
+ patternValue instanceof RegExp && !!String( itemValue ).match( patternValue );
416
+ }
417
+
418
+ // Checks if attributes of provided element can be matched against provided patterns.
419
+ //
420
+ // @param {Object} patterns Object with information about attributes to match. Each key of the object will be
421
+ // used as attribute name. Value of each key can be a string or regular expression to match against attribute value.
422
+ // @param {module:engine/view/element~Element} element Element which attributes will be tested.
423
+ // @returns {Array|null} Returns array with matched attribute names or `null` if no attributes were matched.
424
+ function matchAttributes( patterns, element ) {
425
+ const attributeKeys = new Set( element.getAttributeKeys() );
426
+
427
+ // `style` and `class` attribute keys are deprecated. Only allow them in object pattern
428
+ // for backward compatibility.
429
+ if ( isPlainObject( patterns ) ) {
430
+ if ( patterns.style !== undefined ) {
431
+ // Documented at the end of matcher.js.
432
+ logWarning( 'matcher-pattern-deprecated-attributes-style-key', patterns );
433
+ }
434
+ if ( patterns.class !== undefined ) {
435
+ // Documented at the end of matcher.js.
436
+ logWarning( 'matcher-pattern-deprecated-attributes-class-key', patterns );
437
+ }
438
+ } else {
439
+ attributeKeys.delete( 'style' );
440
+ attributeKeys.delete( 'class' );
441
+ }
442
+
443
+ return matchPatterns( patterns, attributeKeys, key => element.getAttribute( key ) );
444
+ }
445
+
446
+ // Checks if classes of provided element can be matched against provided patterns.
447
+ //
448
+ // @param {Array.<String|RegExp>} patterns Array of strings or regular expressions to match against element's classes.
449
+ // @param {module:engine/view/element~Element} element Element which classes will be tested.
450
+ // @returns {Array|null} Returns array with matched class names or `null` if no classes were matched.
451
+ function matchClasses( patterns, element ) {
452
+ // We don't need `getter` here because patterns for classes are always normalized to `[ className, true ]`.
453
+ return matchPatterns( patterns, element.getClassNames() );
454
+ }
455
+
456
+ // Checks if styles of provided element can be matched against provided patterns.
457
+ //
458
+ // @param {Object} patterns Object with information about styles to match. Each key of the object will be
459
+ // used as style name. Value of each key can be a string or regular expression to match against style value.
460
+ // @param {module:engine/view/element~Element} element Element which styles will be tested.
461
+ // @returns {Array|null} Returns array with matched style names or `null` if no styles were matched.
462
+ function matchStyles( patterns, element ) {
463
+ return matchPatterns( patterns, element.getStyleNames( true ), key => element.getStyle( key ) );
464
+ }
465
+
466
+ /**
467
+ * An entity that is a valid pattern recognized by a matcher. `MatcherPattern` is used by {@link ~Matcher} to recognize
468
+ * if a view element fits in a group of view elements described by the pattern.
469
+ *
470
+ * `MatcherPattern` can be given as a `String`, a `RegExp`, an `Object` or a `Function`.
471
+ *
472
+ * If `MatcherPattern` is given as a `String` or `RegExp`, it will match any view element that has a matching name:
473
+ *
474
+ * // Match any element with name equal to 'div'.
475
+ * const pattern = 'div';
476
+ *
477
+ * // Match any element which name starts on 'p'.
478
+ * const pattern = /^p/;
479
+ *
480
+ * If `MatcherPattern` is given as an `Object`, all the object's properties will be matched with view element properties.
481
+ * If the view element does not meet all of the object's pattern properties, the match will not happen.
482
+ * Available `Object` matching properties:
483
+ *
484
+ * Matching view element:
485
+ *
486
+ * // Match view element's name using String:
487
+ * const pattern = { name: 'p' };
488
+ *
489
+ * // or by providing RegExp:
490
+ * const pattern = { name: /^(ul|ol)$/ };
491
+ *
492
+ * // The name can also be skipped to match any view element with matching attributes:
493
+ * const pattern = {
494
+ * attributes: {
495
+ * 'title': true
496
+ * }
497
+ * };
498
+ *
499
+ * Matching view element attributes:
500
+ *
501
+ * // Match view element with any attribute value.
502
+ * const pattern = {
503
+ * name: 'p',
504
+ * attributes: true
505
+ * };
506
+ *
507
+ * // Match view element which has matching attributes (String).
508
+ * const pattern = {
509
+ * name: 'figure',
510
+ * attributes: 'title' // Match title attribute (can be empty).
511
+ * };
512
+ *
513
+ * // Match view element which has matching attributes (RegExp).
514
+ * const pattern = {
515
+ * name: 'figure',
516
+ * attributes: /^data-.*$/ // Match attributes starting with `data-` e.g. `data-foo` with any value (can be empty).
517
+ * };
518
+ *
519
+ * // Match view element which has matching attributes (Object).
520
+ * const pattern = {
521
+ * name: 'figure',
522
+ * attributes: {
523
+ * title: 'foobar', // Match `title` attribute with 'foobar' value.
524
+ * alt: true, // Match `alt` attribute with any value (can be empty).
525
+ * 'data-type': /^(jpg|png)$/ // Match `data-type` attribute with `jpg` or `png` value.
526
+ * }
527
+ * };
528
+ *
529
+ * // Match view element which has matching attributes (Array).
530
+ * const pattern = {
531
+ * name: 'figure',
532
+ * attributes: [
533
+ * 'title', // Match `title` attribute (can be empty).
534
+ * /^data-*$/, // Match attributes starting with `data-` e.g. `data-foo` with any value (can be empty).
535
+ * ]
536
+ * };
537
+ *
538
+ * // Match view element which has matching attributes (key-value pairs).
539
+ * const pattern = {
540
+ * name: 'input',
541
+ * attributes: [
542
+ * {
543
+ * key: 'type', // Match `type` as an attribute key.
544
+ * value: /^(text|number|date)$/ }, // Match `text`, `number` or `date` values.
545
+ * {
546
+ * key: /^data-.*$/, // Match attributes starting with `data-` e.g. `data-foo`.
547
+ * value: true // Match any value (can be empty).
548
+ * }
549
+ * ]
550
+ * };
551
+ *
552
+ * Matching view element styles:
553
+ *
554
+ * // Match view element with any style.
555
+ * const pattern = {
556
+ * name: 'p',
557
+ * styles: true
558
+ * };
559
+ *
560
+ * // Match view element which has matching styles (String).
561
+ * const pattern = {
562
+ * name: 'p',
563
+ * styles: 'color' // Match attributes with `color` style.
564
+ * };
565
+ *
566
+ * // Match view element which has matching styles (RegExp).
567
+ * const pattern = {
568
+ * name: 'p',
569
+ * styles: /^border.*$/ // Match view element with any border style.
570
+ * };
571
+ *
572
+ * // Match view element which has matching styles (Object).
573
+ * const pattern = {
574
+ * name: 'p',
575
+ * attributes: {
576
+ * color: /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/, // Match `color` in RGB format only.
577
+ * 'font-weight': 600, // Match `font-weight` only if it's `600`.
578
+ * 'text-decoration': true // Match any text decoration.
579
+ * }
580
+ * };
581
+ *
582
+ * // Match view element which has matching styles (Array).
583
+ * const pattern = {
584
+ * name: 'p',
585
+ * attributes: [
586
+ * 'color', // Match `color` with any value.
587
+ * /^border.*$/, // Match all border properties.
588
+ * ]
589
+ * };
590
+ *
591
+ * // Match view element which has matching styles (key-value pairs).
592
+ * const pattern = {
593
+ * name: 'p',
594
+ * attributes: [
595
+ * {
596
+ * key: 'color', // Match `color` as an property key.
597
+ * value: /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/, // Match RGB format only.
598
+ * {
599
+ * key: /^border.*$/, // Match any border style.
600
+ * value: true // Match any value.
601
+ * }
602
+ * ]
603
+ * };
604
+ *
605
+ * Matching view element classes:
606
+ *
607
+ * // Match view element with any class.
608
+ * const pattern = {
609
+ * name: 'p',
610
+ * classes: true
611
+ * };
612
+ *
613
+ * // Match view element which has matching class (String).
614
+ * const pattern = {
615
+ * name: 'p',
616
+ * classes: 'highlighted' // Match `highlighted` class.
617
+ * };
618
+ *
619
+ * // Match view element which has matching classes (RegExp).
620
+ * const pattern = {
621
+ * name: 'figure',
622
+ * classes: /^image-side-(left|right)$/ // Match `image-side-left` or `image-side-right` class.
623
+ * };
624
+ *
625
+ * // Match view element which has matching classes (Object).
626
+ * const pattern = {
627
+ * name: 'p',
628
+ * classes: {
629
+ * highlighted: true, // Match `highlighted` class.
630
+ * marker: true // Match `marker` class.
631
+ * }
632
+ * };
633
+ *
634
+ * // Match view element which has matching classes (Array).
635
+ * const pattern = {
636
+ * name: 'figure',
637
+ * classes: [
638
+ * 'image', // Match `image` class.
639
+ * /^image-side-(left|right)$/ // Match `image-side-left` or `image-side-right` class.
640
+ * ]
641
+ * };
642
+ *
643
+ * // Match view element which has matching classes (key-value pairs).
644
+ * const pattern = {
645
+ * name: 'figure',
646
+ * classes: [
647
+ * {
648
+ * key: 'image', // Match `image` class.
649
+ * value: true
650
+ * {
651
+ * key: /^image-side-(left|right)$/, // Match `image-side-left` or `image-side-right` class.
652
+ * value: true
653
+ * }
654
+ * ]
655
+ * };
656
+ *
657
+ * Pattern can combine multiple properties allowing for more complex view element matching:
658
+ *
659
+ * const pattern = {
660
+ * name: 'span',
661
+ * attributes: [ 'title' ],
662
+ * styles: {
663
+ * 'font-weight': 'bold'
664
+ * },
665
+ * classes: 'highlighted'
666
+ * };
667
+ *
668
+ * If `MatcherPattern` is given as a `Function`, the function takes a view element as a first and only parameter and
669
+ * the function should decide whether that element matches. If so, it should return what part of the view element has been matched.
670
+ * Otherwise, the function should return `null`. The returned result will be included in `match` property of the object
671
+ * returned by {@link ~Matcher#match} call.
672
+ *
673
+ * // Match an empty <div> element.
674
+ * const pattern = element => {
675
+ * if ( element.name == 'div' && element.childCount > 0 ) {
676
+ * // Return which part of the element was matched.
677
+ * return { name: true };
678
+ * }
679
+ *
680
+ * return null;
681
+ * };
682
+ *
683
+ * // Match a <p> element with big font ("heading-like" element).
684
+ * const pattern = element => {
685
+ * if ( element.name == 'p' ) {
686
+ * const fontSize = element.getStyle( 'font-size' );
687
+ * const size = fontSize.match( /(\d+)/px );
688
+ *
689
+ * if ( size && Number( size[ 1 ] ) > 26 ) {
690
+ * return { name: true, attribute: [ 'font-size' ] };
691
+ * }
692
+ * }
693
+ *
694
+ * return null;
695
+ * };
696
+ *
697
+ * `MatcherPattern` is defined in a way that it is a superset of {@link module:engine/view/elementdefinition~ElementDefinition},
698
+ * that is, every `ElementDefinition` also can be used as a `MatcherPattern`.
699
+ *
700
+ * @typedef {String|RegExp|Object|Function} module:engine/view/matcher~MatcherPattern
701
+ *
702
+ * @property {String|RegExp} [name] View element name to match.
703
+ * @property {String|RegExp|Array.<String|RegExp>} [classes] View element's class name(s) to match.
704
+ * @property {Object} [styles] Object with key-value pairs representing styles to match.
705
+ * Each object key represents style name. Value can be given as `String` or `RegExp`.
706
+ * @property {Object} [attributes] Object with key-value pairs representing attributes to match.
707
+ * Each object key represents attribute name. Value can be given as `String` or `RegExp`.
708
+ */
709
+
710
+ /**
711
+ * The key-value matcher pattern is missing key or value. Both must be present.
712
+ * Refer the documentation: {@link module:engine/view/matcher~MatcherPattern}.
713
+ *
714
+ * @param {Object} pattern Pattern with missing properties.
715
+ * @error matcher-pattern-missing-key-or-value
716
+ */
717
+
718
+ /**
719
+ * The key-value matcher pattern for `attributes` option is using deprecated `style` key.
720
+ *
721
+ * Use `styles` matcher pattern option instead:
722
+ *
723
+ * // Instead of:
724
+ * const pattern = {
725
+ * attributes: {
726
+ * key1: 'value1',
727
+ * key2: 'value2',
728
+ * style: /^border.*$/
729
+ * }
730
+ * }
731
+ *
732
+ * // Use:
733
+ * const pattern = {
734
+ * attributes: {
735
+ * key1: 'value1',
736
+ * key2: 'value2'
737
+ * },
738
+ * styles: /^border.*$/
739
+ * }
740
+ *
741
+ * Refer to the {@glink builds/guides/migration/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
742
+ * and {@link module:engine/view/matcher~MatcherPattern} documentation.
743
+ *
744
+ * @param {Object} pattern Pattern with missing properties.
745
+ * @error matcher-pattern-deprecated-attributes-style-key
746
+ */
747
+
748
+ /**
749
+ * The key-value matcher pattern for `attributes` option is using deprecated `class` key.
750
+ *
751
+ * Use `classes` matcher pattern option instead:
752
+ *
753
+ * // Instead of:
754
+ * const pattern = {
755
+ * attributes: {
756
+ * key1: 'value1',
757
+ * key2: 'value2',
758
+ * class: 'foobar'
759
+ * }
760
+ * }
761
+ *
762
+ * // Use:
763
+ * const pattern = {
764
+ * attributes: {
765
+ * key1: 'value1',
766
+ * key2: 'value2'
767
+ * },
768
+ * classes: 'foobar'
769
+ * }
770
+ *
771
+ * Refer to the {@glink builds/guides/migration/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
772
+ * and the {@link module:engine/view/matcher~MatcherPattern} documentation.
773
+ *
774
+ * @param {Object} pattern Pattern with missing properties.
775
+ * @error matcher-pattern-deprecated-attributes-class-key
776
+ */