@ckeditor/ckeditor5-engine 29.0.0 → 31.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.
package/LICENSE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Software License Agreement
2
2
  ==========================
3
3
 
4
- **CKEditor 5 Editing Engine** – https://github.com/ckeditor/ckeditor5-engine <br>
4
+ **CKEditor 5 editing engine** – https://github.com/ckeditor/ckeditor5-engine <br>
5
5
  Copyright (c) 2003-2021, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
6
6
 
7
7
  Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
package/README.md CHANGED
@@ -21,7 +21,7 @@ The CKEditor 5 editing engine implements a flexible MVC-based architecture for c
21
21
 
22
22
  ## Documentation
23
23
 
24
- For a general introduction see the [Overview of CKEditor 5 Framework](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/overview.html) guide and then the [Editing engine architecture](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/architecture/editing-engine.html) guide.
24
+ For a general introduction see the [Overview of CKEditor 5 Framework](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/overview.html) guide and then the [Editing engine architecture guide](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/architecture/editing-engine.html).
25
25
 
26
26
  Additionally, refer to the [`@ckeditor/ckeditor5-engine` package](https://ckeditor.com/docs/ckeditor5/latest/api/engine.html) page in [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/) for even more information.
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-engine",
3
- "version": "29.0.0",
3
+ "version": "31.0.0",
4
4
  "description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",
5
5
  "keywords": [
6
6
  "wysiwyg",
@@ -23,28 +23,30 @@
23
23
  ],
24
24
  "main": "src/index.js",
25
25
  "dependencies": {
26
- "@ckeditor/ckeditor5-utils": "^29.0.0",
26
+ "@ckeditor/ckeditor5-utils": "^31.0.0",
27
27
  "lodash-es": "^4.17.15"
28
28
  },
29
29
  "devDependencies": {
30
- "@ckeditor/ckeditor5-basic-styles": "^29.0.0",
31
- "@ckeditor/ckeditor5-block-quote": "^29.0.0",
32
- "@ckeditor/ckeditor5-clipboard": "^29.0.0",
33
- "@ckeditor/ckeditor5-core": "^29.0.0",
34
- "@ckeditor/ckeditor5-editor-classic": "^29.0.0",
35
- "@ckeditor/ckeditor5-enter": "^29.0.0",
36
- "@ckeditor/ckeditor5-essentials": "^29.0.0",
37
- "@ckeditor/ckeditor5-heading": "^29.0.0",
38
- "@ckeditor/ckeditor5-image": "^29.0.0",
39
- "@ckeditor/ckeditor5-link": "^29.0.0",
40
- "@ckeditor/ckeditor5-list": "^29.0.0",
41
- "@ckeditor/ckeditor5-paragraph": "^29.0.0",
42
- "@ckeditor/ckeditor5-table": "^29.0.0",
43
- "@ckeditor/ckeditor5-theme-lark": "^29.0.0",
44
- "@ckeditor/ckeditor5-typing": "^29.0.0",
45
- "@ckeditor/ckeditor5-ui": "^29.0.0",
46
- "@ckeditor/ckeditor5-undo": "^29.0.0",
47
- "@ckeditor/ckeditor5-widget": "^29.0.0",
30
+ "@ckeditor/ckeditor5-basic-styles": "^31.0.0",
31
+ "@ckeditor/ckeditor5-block-quote": "^31.0.0",
32
+ "@ckeditor/ckeditor5-clipboard": "^31.0.0",
33
+ "@ckeditor/ckeditor5-cloud-services": "^31.0.0",
34
+ "@ckeditor/ckeditor5-core": "^31.0.0",
35
+ "@ckeditor/ckeditor5-editor-classic": "^31.0.0",
36
+ "@ckeditor/ckeditor5-enter": "^31.0.0",
37
+ "@ckeditor/ckeditor5-essentials": "^31.0.0",
38
+ "@ckeditor/ckeditor5-heading": "^31.0.0",
39
+ "@ckeditor/ckeditor5-image": "^31.0.0",
40
+ "@ckeditor/ckeditor5-link": "^31.0.0",
41
+ "@ckeditor/ckeditor5-list": "^31.0.0",
42
+ "@ckeditor/ckeditor5-mention": "^31.0.0",
43
+ "@ckeditor/ckeditor5-paragraph": "^31.0.0",
44
+ "@ckeditor/ckeditor5-table": "^31.0.0",
45
+ "@ckeditor/ckeditor5-theme-lark": "^31.0.0",
46
+ "@ckeditor/ckeditor5-typing": "^31.0.0",
47
+ "@ckeditor/ckeditor5-ui": "^31.0.0",
48
+ "@ckeditor/ckeditor5-undo": "^31.0.0",
49
+ "@ckeditor/ckeditor5-widget": "^31.0.0",
48
50
  "webpack": "^4.43.0",
49
51
  "webpack-cli": "^3.3.11"
50
52
  },
@@ -64,6 +66,7 @@
64
66
  "files": [
65
67
  "lang",
66
68
  "src",
67
- "theme"
69
+ "theme",
70
+ "ckeditor5-metadata.json"
68
71
  ]
69
72
  }
@@ -145,6 +145,7 @@ export default class DataController {
145
145
 
146
146
  this.decorate( 'init' );
147
147
  this.decorate( 'set' );
148
+ this.decorate( 'get' );
148
149
 
149
150
  // Fire the `ready` event when the initialization has completed. Such low-level listener gives possibility
150
151
  // to plug into the initialization pipeline without interrupting the initialization flow.
@@ -163,6 +164,7 @@ export default class DataController {
163
164
  * Returns the model's data converted by downcast dispatchers attached to {@link #downcastDispatcher} and
164
165
  * formatted by the {@link #processor data processor}.
165
166
  *
167
+ * @fires get
166
168
  * @param {Object} [options] Additional configuration for the retrieved data. `DataController` provides two optional
167
169
  * properties: `rootName` and `trim`. Other properties of this object are specified by various editor features.
168
170
  * @param {String} [options.rootName='main'] Root name.
@@ -523,6 +525,15 @@ export default class DataController {
523
525
  *
524
526
  * @event set
525
527
  */
528
+
529
+ /**
530
+ * Event fired after {@link #get get() method} has been run.
531
+ *
532
+ * The `get` event is fired by decorated {@link #get} method.
533
+ * See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.
534
+ *
535
+ * @event get
536
+ */
526
537
  }
527
538
 
528
539
  mix( DataController, ObservableMixin );
@@ -559,5 +570,43 @@ function _getMarkersRelativeToElement( element ) {
559
570
  }
560
571
  }
561
572
 
562
- return result;
573
+ // Sort the markers in a stable fashion to ensure that the order that they are
574
+ // added to the model's marker collection does not affect how they are
575
+ // downcast. One particular use case that we're targeting here is one where
576
+ // two markers are adjacent but not overlapping, such as an insertion/deletion
577
+ // suggestion pair represting the replacement of a range of text. In this
578
+ // case, putting the markers in DOM order causes the first marker's end to be
579
+ // serialized right after the second marker's start, while putting the markers
580
+ // in reverse DOM order causes it to be right before the second marker's
581
+ // start. So, we sort in a way that ensures non-intersecting ranges are in
582
+ // reverse DOM order, and intersecting ranges are in something approximating
583
+ // reverse DOM order (since reverse DOM order doesn't have a precise meaning
584
+ // when working with intersectng ranges).
585
+ return result.sort( ( [ n1, r1 ], [ n2, r2 ] ) => {
586
+ if ( r1.end.compareWith( r2.start ) !== 'after' ) {
587
+ // m1.end <= m2.start -- m1 is entirely <= m2
588
+ return 1;
589
+ } else if ( r1.start.compareWith( r2.end ) !== 'before' ) {
590
+ // m1.start >= m2.end -- m1 is entirely >= m2
591
+ return -1;
592
+ } else {
593
+ // they overlap, so use their start positions as the primary sort key and
594
+ // end positions as the secondary sort key
595
+ switch ( r1.start.compareWith( r2.start ) ) {
596
+ case 'before':
597
+ return 1;
598
+ case 'after':
599
+ return -1;
600
+ default:
601
+ switch ( r1.end.compareWith( r2.end ) ) {
602
+ case 'before':
603
+ return 1;
604
+ case 'after':
605
+ return -1;
606
+ default:
607
+ return n2.localeCompare( n1 );
608
+ }
609
+ }
610
+ }
611
+ } );
563
612
  }
@@ -272,8 +272,11 @@ export default class DowncastHelpers extends ConversionHelpers {
272
272
  /**
273
273
  * Model marker to view element conversion helper.
274
274
  *
275
- * **Note**: This method should be used only for editing downcast. For data downcast, use
276
- * {@link #markerToData `#markerToData()`} that produces valid HTML data.
275
+ * **Note**: This method should be used mainly for editing downcast and it is recommended
276
+ * to use {@link #markerToData `#markerToData()`} helper instead.
277
+ *
278
+ * This helper may produce invalid HTML code (e.g. a span between table cells).
279
+ * It should be used only when you are sure that the produced HTML will be semantically correct.
277
280
  *
278
281
  * This conversion results in creating a view element on the boundaries of the converted marker. If the converted marker
279
282
  * is collapsed, only one element is created. For example, model marker set like this: `<paragraph>F[oo b]ar</paragraph>`
@@ -406,32 +409,32 @@ export default class DowncastHelpers extends ConversionHelpers {
406
409
  * This conversion creates a representation for model marker boundaries in the view:
407
410
  *
408
411
  * * If the marker boundary is before or after a model element, a view attribute is set on a corresponding view element.
409
- * * In other cases, a view element with the specified tag name is inserted at corresponding view position.
412
+ * * In other cases, a view element with the specified tag name is inserted at the corresponding view position.
410
413
  *
411
- * Typically, marker names use the `group:uniqueId:otherData` convention. For example: `comment:e34zfk9k2n459df53sjl34:zx32c`.
414
+ * Typically, the marker names use the `group:uniqueId:otherData` convention. For example: `comment:e34zfk9k2n459df53sjl34:zx32c`.
412
415
  * The default configuration for this conversion is that the first part is the `group` part and the rest of
413
416
  * the marker name becomes the `name` part.
414
417
  *
415
418
  * Tag and attribute names and values are generated from the marker name:
416
419
  *
417
- * * Templates for attributes are `data-[group]-start-before="[name]"`, `data-[group]-start-after="[name]"`,
420
+ * * The templates for attributes are `data-[group]-start-before="[name]"`, `data-[group]-start-after="[name]"`,
418
421
  * `data-[group]-end-before="[name]"` and `data-[group]-end-after="[name]"`.
419
- * * Templates for view elements are `<[group]-start name="[name]">` and `<[group]-end name="[name]">`.
422
+ * * The templates for view elements are `<[group]-start name="[name]">` and `<[group]-end name="[name]">`.
420
423
  *
421
424
  * Attributes mark whether the given marker's start or end boundary is before or after the given element.
422
- * Attributes `data-[group]-start-before` and `data-[group]-end-after` are favored.
425
+ * The `data-[group]-start-before` and `data-[group]-end-after` attributes are favored.
423
426
  * The other two are used when the former two cannot be used.
424
427
  *
425
428
  * The conversion configuration can take a function that will generate different group and name parts.
426
- * If such function is set as the `config.view` parameter, it is passed a marker name and it is expected to return an object with two
429
+ * If such a function is set as the `config.view` parameter, it is passed a marker name and it is expected to return an object with two
427
430
  * properties: `group` and `name`. If the function returns a falsy value, the conversion will not take place.
428
431
  *
429
432
  * Basic usage:
430
433
  *
431
434
  * // Using the default conversion.
432
- * // In this case, all markers whose name starts with 'comment:' will be converted.
435
+ * // In this case, all markers with names starting with 'comment:' will be converted.
433
436
  * // The `group` parameter will be set to `comment`.
434
- * // The `name` parameter will be the rest of the marker name (without `:`).
437
+ * // The `name` parameter will be the rest of the marker name (without the `:`).
435
438
  * editor.conversion.for( 'dataDowncast' ).markerToData( {
436
439
  * model: 'comment'
437
440
  * } );
@@ -454,7 +457,7 @@ export default class DowncastHelpers extends ConversionHelpers {
454
457
  * <p>Foo <myMarker-start></myMarker-start>bar</p>
455
458
  * <figure data-myMarker-end-after="" class="image"><img src="abc.jpg" /></figure>
456
459
  *
457
- * **Note:** A situation where some markers have the `name` part and some do not have it is incorrect and should be avoided.
460
+ * **Note:** A situation where some markers have the `name` part and some do not, is incorrect and should be avoided.
458
461
  *
459
462
  * Examples where `data-group-start-after` and `data-group-end-before` are used:
460
463
  *
@@ -498,14 +501,14 @@ export default class DowncastHelpers extends ConversionHelpers {
498
501
  *
499
502
  * This kind of conversion is useful for saving data into the database, so it should be used in the data conversion pipeline.
500
503
  *
501
- * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
502
- * to the conversion process.
504
+ * See the {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} API guide to learn how to
505
+ * add a converter to the conversion process.
503
506
  *
504
507
  * @method #markerToData
505
508
  * @param {Object} config Conversion configuration.
506
- * @param {String} config.model The name of the model marker (or model marker group) to convert.
509
+ * @param {String} config.model The name of the model marker (or the model marker group) to convert.
507
510
  * @param {Function} [config.view] A function that takes the model marker name and
508
- * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as a parameters
511
+ * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi downcast conversion API} as the parameters
509
512
  * and returns an object with the `group` and `name` properties.
510
513
  * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
511
514
  * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}
@@ -548,7 +551,7 @@ export function insertText() {
548
551
  */
549
552
  export function remove() {
550
553
  return ( evt, data, conversionApi ) => {
551
- // Find view range start position by mapping model position at which the remove happened.
554
+ // Find the view range start position by mapping the model position at which the remove happened.
552
555
  const viewStart = conversionApi.mapper.toViewPosition( data.position );
553
556
 
554
557
  const modelEnd = data.position.getShiftedBy( data.length );
@@ -569,7 +572,7 @@ export function remove() {
569
572
 
570
573
  /**
571
574
  * Creates a `<span>` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from the information
572
- * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If a priority
575
+ * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If the priority
573
576
  * is not provided in the descriptor, the default priority will be used.
574
577
  *
575
578
  * @param {module:engine/view/downcastwriter~DowncastWriter} writer
@@ -966,7 +969,7 @@ function handleMarkerBoundary( range, isStart, conversionApi, data, viewMarkerDa
966
969
 
967
970
  const viewElement = conversionApi.mapper.toViewElement( modelElement );
968
971
 
969
- // On rare circumstances, the model element could be not mapped to any view element and that would cause an error.
972
+ // In rare circumstances, the model element may be not mapped to any view element and that would cause an error.
970
973
  // One of those situations is a soft break inside code block.
971
974
  if ( viewElement ) {
972
975
  insertMarkerAsAttribute( viewElement, isStart, isBefore, conversionApi, data, viewMarkerData );
@@ -7,7 +7,6 @@ import Matcher from '../view/matcher';
7
7
  import ConversionHelpers from './conversionhelpers';
8
8
 
9
9
  import { cloneDeep } from 'lodash-es';
10
- import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
11
10
 
12
11
  import priorities from '@ckeditor/ckeditor5-utils/src/priorities';
13
12
  import { isParagraphable, wrapInParagraph } from '../model/utils/autoparagraphing';
@@ -294,13 +293,17 @@ export default class UpcastHelpers extends ConversionHelpers {
294
293
  /**
295
294
  * View element to model marker conversion helper.
296
295
  *
297
- * **Note**: This method was deprecated. Please use {@link #dataToMarker} instead.
298
- *
299
296
  * This conversion results in creating a model marker. For example, if the marker was stored in a view as an element:
300
297
  * `<p>Fo<span data-marker="comment" data-comment-id="7"></span>o</p><p>B<span data-marker="comment" data-comment-id="7"></span>ar</p>`,
301
298
  * after the conversion is done, the marker will be available in
302
299
  * {@link module:engine/model/model~Model#markers model document markers}.
303
300
  *
301
+ * **Note**: When this helper is used in the data upcast in combination with
302
+ * {@link module:engine/conversion/downcasthelpers~DowncastHelpers#markerToData `#markerToData()`} in the data downcast,
303
+ * then invalid HTML code (e.g. a span between table cells) may be produced by the latter converter.
304
+ *
305
+ * In most of the cases, the {@link #dataToMarker} should be used instead.
306
+ *
304
307
  * editor.conversion.for( 'upcast' ).elementToMarker( {
305
308
  * view: 'marker-search',
306
309
  * model: 'search'
@@ -330,7 +333,6 @@ export default class UpcastHelpers extends ConversionHelpers {
330
333
  * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
331
334
  * to the conversion process.
332
335
  *
333
- * @deprecated
334
336
  * @method #elementToMarker
335
337
  * @param {Object} config Conversion configuration.
336
338
  * @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.
@@ -340,15 +342,6 @@ export default class UpcastHelpers extends ConversionHelpers {
340
342
  * @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}
341
343
  */
342
344
  elementToMarker( config ) {
343
- /**
344
- * The {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToMarker `UpcastHelpers#elementToMarker()`}
345
- * method was deprecated and will be removed in the near future.
346
- * Please use {@link module:engine/conversion/upcasthelpers~UpcastHelpers#dataToMarker `UpcastHelpers#dataToMarker()`} instead.
347
- *
348
- * @error upcast-helpers-element-to-marker-deprecated
349
- */
350
- logWarning( 'upcast-helpers-element-to-marker-deprecated' );
351
-
352
345
  return this.add( upcastElementToMarker( config ) );
353
346
  }
354
347
 
@@ -651,11 +644,11 @@ function upcastDataToMarker( config ) {
651
644
  // Below is a hack that is needed to properly handle `converterPriority` for both elements and attributes.
652
645
  // Attribute conversion needs to be performed *after* element conversion.
653
646
  // This converter handles both element conversion and attribute conversion, which means that if a single
654
- // `config.converterPriority` is used, it will lead to problems. For example, if `'high'` priority is used,
655
- // then attribute conversion will be performed before a lot of element upcast converters.
656
- // On the other hand we want to support `config.converterPriority` and overwriting converters.
647
+ // `config.converterPriority` is used, it will lead to problems. For example, if the `'high'` priority is used,
648
+ // the attribute conversion will be performed before a lot of element upcast converters.
649
+ // On the other hand, we want to support `config.converterPriority` and converter overwriting.
657
650
  //
658
- // To have it work, we need to do some extra processing for priority for attribute converter.
651
+ // To make it work, we need to do some extra processing for priority for attribute converter.
659
652
  // Priority `'low'` value should be the base value and then we will change it depending on `config.converterPriority` value.
660
653
  //
661
654
  // This hack probably would not be needed if attributes are upcasted separately.
@@ -28,26 +28,23 @@ export default class HtmlDataProcessor {
28
28
  /**
29
29
  * A DOM parser instance used to parse an HTML string to an HTML document.
30
30
  *
31
- * @private
32
31
  * @member {DOMParser}
33
32
  */
34
- this._domParser = new DOMParser();
33
+ this.domParser = new DOMParser();
35
34
 
36
35
  /**
37
36
  * A DOM converter used to convert DOM elements to view elements.
38
37
  *
39
- * @private
40
38
  * @member {module:engine/view/domconverter~DomConverter}
41
39
  */
42
- this._domConverter = new DomConverter( document, { blockFillerMode: 'nbsp' } );
40
+ this.domConverter = new DomConverter( document, { renderingMode: 'data' } );
43
41
 
44
42
  /**
45
43
  * A basic HTML writer instance used to convert DOM elements to an HTML string.
46
44
  *
47
- * @private
48
- * @member {module:engine/dataprocessor/basichtmlwriter~BasicHtmlWriter}
45
+ * @member {module:engine/dataprocessor/htmlwriter~HtmlWriter}
49
46
  */
50
- this._htmlWriter = new BasicHtmlWriter();
47
+ this.htmlWriter = new BasicHtmlWriter();
51
48
  }
52
49
 
53
50
  /**
@@ -59,10 +56,10 @@ export default class HtmlDataProcessor {
59
56
  */
60
57
  toData( viewFragment ) {
61
58
  // Convert view DocumentFragment to DOM DocumentFragment.
62
- const domFragment = this._domConverter.viewToDom( viewFragment, document );
59
+ const domFragment = this.domConverter.viewToDom( viewFragment, document );
63
60
 
64
61
  // Convert DOM DocumentFragment to HTML output.
65
- return this._htmlWriter.getHtml( domFragment );
62
+ return this.htmlWriter.getHtml( domFragment );
66
63
  }
67
64
 
68
65
  /**
@@ -76,7 +73,7 @@ export default class HtmlDataProcessor {
76
73
  const domFragment = this._toDom( data );
77
74
 
78
75
  // Convert DOM DocumentFragment to view DocumentFragment.
79
- return this._domConverter.domToView( domFragment );
76
+ return this.domConverter.domToView( domFragment );
80
77
  }
81
78
 
82
79
  /**
@@ -90,22 +87,22 @@ export default class HtmlDataProcessor {
90
87
  * be treated as raw data.
91
88
  */
92
89
  registerRawContentMatcher( pattern ) {
93
- this._domConverter.registerRawContentMatcher( pattern );
90
+ this.domConverter.registerRawContentMatcher( pattern );
94
91
  }
95
92
 
96
93
  /**
97
94
  * If the processor is set to use marked fillers, it will insert `&nbsp;` fillers wrapped in `<span>` elements
98
95
  * (`<span data-cke-filler="true">&nbsp;</span>`) instead of regular `&nbsp;` characters.
99
96
  *
100
- * This mode allows for more precise handling of block fillers (so they do not leak into the editor content) but bloats the
101
- * editor data with additional markup.
97
+ * This mode allows for a more precise handling of the block fillers (so they do not leak into the editor content) but
98
+ * bloats the editor data with additional markup.
102
99
  *
103
100
  * This mode may be required by some features and will be turned on by them automatically.
104
101
  *
105
- * @param {'default'|'marked'} type Whether to use the default or marked `&nbsp;` block fillers.
102
+ * @param {'default'|'marked'} type Whether to use the default or the marked `&nbsp;` block fillers.
106
103
  */
107
104
  useFillerType( type ) {
108
- this._domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp';
105
+ this.domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp';
109
106
  }
110
107
 
111
108
  /**
@@ -117,7 +114,7 @@ export default class HtmlDataProcessor {
117
114
  * @returns {DocumentFragment}
118
115
  */
119
116
  _toDom( data ) {
120
- const document = this._domParser.parseFromString( data, 'text/html' );
117
+ const document = this.domParser.parseFromString( data, 'text/html' );
121
118
  const fragment = document.createDocumentFragment();
122
119
 
123
120
  // The rules for parsing an HTML string can be read on https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhtml.
@@ -26,7 +26,7 @@ export default class XmlDataProcessor {
26
26
  *
27
27
  * @param {module:engine/view/document~Document} document The view document instance.
28
28
  * @param {Object} options Configuration options.
29
- * @param {Array<String>} [options.namespaces=[]] A list of namespaces allowed to use in the XML input.
29
+ * @param {Array.<String>} [options.namespaces=[]] A list of namespaces allowed to use in the XML input.
30
30
  */
31
31
  constructor( document, options = {} ) {
32
32
  /**
@@ -35,35 +35,31 @@ export default class XmlDataProcessor {
35
35
  * For example, registering namespaces [ 'attribute', 'container' ] allows to use `<attirbute:tagName></attribute:tagName>`
36
36
  * and `<container:tagName></container:tagName>` input. It is mainly for debugging.
37
37
  *
38
- * @public
39
- * @member {DOMParser}
38
+ * @member {Array.<String>}
40
39
  */
41
40
  this.namespaces = options.namespaces || [];
42
41
 
43
42
  /**
44
43
  * DOM parser instance used to parse an XML string to an XML document.
45
44
  *
46
- * @private
47
45
  * @member {DOMParser}
48
46
  */
49
- this._domParser = new DOMParser();
47
+ this.domParser = new DOMParser();
50
48
 
51
49
  /**
52
50
  * DOM converter used to convert DOM elements to view elements.
53
51
  *
54
- * @private
55
52
  * @member {module:engine/view/domconverter~DomConverter}
56
53
  */
57
- this._domConverter = new DomConverter( document, { blockFillerMode: 'nbsp' } );
54
+ this.domConverter = new DomConverter( document, { renderingMode: 'data' } );
58
55
 
59
56
  /**
60
57
  * A basic HTML writer instance used to convert DOM elements to an XML string.
61
58
  * There is no need to use a dedicated XML writer because the basic HTML writer works well in this case.
62
59
  *
63
- * @private
64
- * @member {module:engine/dataprocessor/basichtmlwriter~BasicHtmlWriter}
60
+ * @member {module:engine/dataprocessor/htmlwriter~HtmlWriter}
65
61
  */
66
- this._htmlWriter = new BasicHtmlWriter();
62
+ this.htmlWriter = new BasicHtmlWriter();
67
63
  }
68
64
 
69
65
  /**
@@ -75,11 +71,11 @@ export default class XmlDataProcessor {
75
71
  */
76
72
  toData( viewFragment ) {
77
73
  // Convert view DocumentFragment to DOM DocumentFragment.
78
- const domFragment = this._domConverter.viewToDom( viewFragment, document );
74
+ const domFragment = this.domConverter.viewToDom( viewFragment, document );
79
75
 
80
76
  // Convert DOM DocumentFragment to XML output.
81
77
  // There is no need to use dedicated for XML serializing method because BasicHtmlWriter works well in this case.
82
- return this._htmlWriter.getHtml( domFragment );
78
+ return this.htmlWriter.getHtml( domFragment );
83
79
  }
84
80
 
85
81
  /**
@@ -93,7 +89,7 @@ export default class XmlDataProcessor {
93
89
  const domFragment = this._toDom( data );
94
90
 
95
91
  // Convert DOM DocumentFragment to view DocumentFragment.
96
- return this._domConverter.domToView( domFragment, { keepOriginalCase: true } );
92
+ return this.domConverter.domToView( domFragment, { keepOriginalCase: true } );
97
93
  }
98
94
 
99
95
  /**
@@ -107,22 +103,22 @@ export default class XmlDataProcessor {
107
103
  * be treated as raw data.
108
104
  */
109
105
  registerRawContentMatcher( pattern ) {
110
- this._domConverter.registerRawContentMatcher( pattern );
106
+ this.domConverter.registerRawContentMatcher( pattern );
111
107
  }
112
108
 
113
109
  /**
114
110
  * If the processor is set to use marked fillers, it will insert `&nbsp;` fillers wrapped in `<span>` elements
115
111
  * (`<span data-cke-filler="true">&nbsp;</span>`) instead of regular `&nbsp;` characters.
116
112
  *
117
- * This mode allows for more precise handling of block fillers (so they do not leak into editor content) but bloats the
118
- * editor data with additional markup.
113
+ * This mode allows for a more precise handling of block fillers (so they do not leak into editor content) but
114
+ * bloats the editor data with additional markup.
119
115
  *
120
116
  * This mode may be required by some features and will be turned on by them automatically.
121
117
  *
122
- * @param {'default'|'marked'} type Whether to use the default or marked `&nbsp;` block fillers.
118
+ * @param {'default'|'marked'} type Whether to use the default or the marked `&nbsp;` block fillers.
123
119
  */
124
120
  useFillerType( type ) {
125
- this._domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp';
121
+ this.domConverter.blockFillerMode = type == 'marked' ? 'markedNbsp' : 'nbsp';
126
122
  }
127
123
 
128
124
  /**
@@ -140,7 +136,7 @@ export default class XmlDataProcessor {
140
136
  // Wrap data into root element with optional namespace definitions.
141
137
  data = `<xml ${ namespaces }>${ data }</xml>`;
142
138
 
143
- const parsedDocument = this._domParser.parseFromString( data, 'text/xml' );
139
+ const parsedDocument = this.domParser.parseFromString( data, 'text/xml' );
144
140
 
145
141
  // Parse validation.
146
142
  const parserError = parsedDocument.querySelector( 'parsererror' );
@@ -39,6 +39,13 @@ const allowedTypes = {
39
39
  'ui': UIElement,
40
40
  'raw': RawElement
41
41
  };
42
+ // Returns simplified implementation of {@link module:engine/view/domconverter~DomConverter#setContentOf DomConverter.setContentOf} method.
43
+ // Used to render UIElement and RawElement.
44
+ const domConverterStub = {
45
+ setContentOf: ( node, html ) => {
46
+ node.innerHTML = html;
47
+ }
48
+ };
42
49
 
43
50
  /**
44
51
  * Writes the content of the {@link module:engine/view/document~Document document} to an HTML-like string.
@@ -59,6 +66,9 @@ const allowedTypes = {
59
66
  * {@link module:engine/view/uielement~UIElement} will be printed.
60
67
  * @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
61
68
  * {@link module:engine/view/rawelement~RawElement} will be printed.
69
+ * @param {Object} [options.domConverter=null] When set to an actual {@link module:engine/view/domconverter~DomConverter DomConverter}
70
+ * instance it lets the conversion go through exactly the same flow the editing view is going, i.e. with view data
71
+ * filtering. Otherwise the simple stub is used.
62
72
  * @returns {String} The stringified data.
63
73
  */
64
74
  export function getData( view, options = {} ) {
@@ -75,7 +85,8 @@ export function getData( view, options = {} ) {
75
85
  showPriority: options.showPriority,
76
86
  renderUIElements: options.renderUIElements,
77
87
  renderRawElements: options.renderRawElements,
78
- ignoreRoot: true
88
+ ignoreRoot: true,
89
+ domConverter: options.domConverter
79
90
  };
80
91
 
81
92
  return withoutSelection ?
@@ -241,6 +252,9 @@ setData._parse = parse;
241
252
  * {@link module:engine/view/uielement~UIElement} will be printed.
242
253
  * @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
243
254
  * {@link module:engine/view/rawelement~RawElement} will be printed.
255
+ * @param {Object} [options.domConverter={}] When set to an actual {@link module:engine/view/domconverter~DomConverter DomConverter}
256
+ * instance it lets the conversion go through exactly the same flow the editing view is going, i.e. with view data
257
+ * filtering. Otherwise the simple stub is used.
244
258
  * @returns {String} An HTML-like string representing the view.
245
259
  */
246
260
  export function stringify( node, selectionOrPositionOrRange = null, options = {} ) {
@@ -630,6 +644,9 @@ class ViewStringify {
630
644
  * @param {Boolean} [options.renderUIElements=false] When set to `true`, the inner content of each
631
645
  * {@link module:engine/view/uielement~UIElement} will be printed.
632
646
  * @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
647
+ * @param {Object} [options.domConverter={}] When set to an actual {@link module:engine/view/domconverter~DomConverter DomConverter}
648
+ * instance it lets the conversion go through exactly the same flow the editing view is going, i.e. with view data
649
+ * filtering. Otherwise the simple stub is used.
633
650
  * {@link module:engine/view/rawelement~RawElement} will be printed.
634
651
  */
635
652
  constructor( root, selection, options ) {
@@ -648,6 +665,7 @@ class ViewStringify {
648
665
  this.sameSelectionCharacters = !!options.sameSelectionCharacters;
649
666
  this.renderUIElements = !!options.renderUIElements;
650
667
  this.renderRawElements = !!options.renderRawElements;
668
+ this.domConverter = options.domConverter || domConverterStub;
651
669
  }
652
670
 
653
671
  /**
@@ -681,12 +699,12 @@ class ViewStringify {
681
699
  }
682
700
 
683
701
  if ( ( this.renderUIElements && root.is( 'uiElement' ) ) ) {
684
- callback( root.render( document ).innerHTML );
702
+ callback( root.render( document, this.domConverter ).innerHTML );
685
703
  } else if ( this.renderRawElements && root.is( 'rawElement' ) ) {
686
704
  // There's no DOM element for "root" to pass to render(). Creating
687
705
  // a surrogate container to render the children instead.
688
706
  const rawContentContainer = document.createElement( 'div' );
689
- root.render( rawContentContainer );
707
+ root.render( rawContentContainer, this.domConverter );
690
708
 
691
709
  callback( rawContentContainer.innerHTML );
692
710
  } else {
package/src/index.js CHANGED
@@ -30,6 +30,7 @@ export { default as TreeWalker } from './model/treewalker';
30
30
  export { default as Element } from './model/element';
31
31
 
32
32
  export { default as DomConverter } from './view/domconverter';
33
+ export { default as Renderer } from './view/renderer';
33
34
  export { default as ViewDocument } from './view/document';
34
35
 
35
36
  export { getFillerOffset } from './view/containerelement';
@@ -52,12 +52,13 @@ export default class MarkerCollection {
52
52
  }
53
53
 
54
54
  /**
55
- * Checks if marker with given `markerName` is in the collection.
55
+ * Checks if given {@link ~Marker marker} or marker name is in the collection.
56
56
  *
57
- * @param {String} markerName Marker name.
58
- * @returns {Boolean} `true` if marker with given `markerName` is in the collection, `false` otherwise.
57
+ * @param {String|module:engine/model/markercollection~Marker} markerOrName Name of marker or marker instance to check.
58
+ * @returns {Boolean} `true` if marker is in the collection, `false` otherwise.
59
59
  */
60
- has( markerName ) {
60
+ has( markerOrName ) {
61
+ const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
61
62
  return this._markers.has( markerName );
62
63
  }
63
64