@ckeditor/ckeditor5-engine 32.0.0 → 34.1.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 +2 -2
- package/README.md +2 -1
- package/package.json +22 -22
- package/src/controller/datacontroller.js +58 -66
- package/src/controller/editingcontroller.js +82 -5
- package/src/conversion/conversion.js +14 -13
- package/src/conversion/downcastdispatcher.js +297 -366
- package/src/conversion/downcasthelpers.js +859 -80
- package/src/conversion/mapper.js +104 -59
- package/src/conversion/modelconsumable.js +84 -34
- package/src/conversion/upcastdispatcher.js +33 -6
- package/src/conversion/upcasthelpers.js +21 -2
- package/src/dataprocessor/htmldataprocessor.js +1 -1
- package/src/dev-utils/model.js +13 -11
- package/src/index.js +12 -0
- package/src/model/batch.js +12 -12
- package/src/model/differ.js +114 -68
- package/src/model/document.js +32 -31
- package/src/model/history.js +160 -22
- package/src/model/markercollection.js +28 -4
- package/src/model/model.js +122 -4
- package/src/model/schema.js +79 -10
- package/src/model/treewalker.js +2 -3
- package/src/model/utils/deletecontent.js +15 -2
- package/src/model/utils/findoptimalinsertionrange.js +68 -0
- package/src/model/utils/insertobject.js +173 -0
- package/src/model/utils/modifyselection.js +14 -7
- package/src/model/writer.js +16 -26
- package/src/view/attributeelement.js +0 -10
- package/src/view/document.js +2 -1
- package/src/view/domconverter.js +47 -11
- package/src/view/downcastwriter.js +90 -49
- package/src/view/element.js +0 -27
- package/src/view/emptyelement.js +0 -3
- package/src/view/matcher.js +2 -2
- package/src/view/observer/clickobserver.js +0 -1
- package/src/view/observer/inputobserver.js +1 -1
- package/src/view/observer/tabobserver.js +68 -0
- package/src/view/placeholder.js +1 -1
- package/src/view/rawelement.js +0 -3
- package/src/view/uielement.js +0 -3
- package/src/view/view.js +4 -0
- package/theme/placeholder.css +9 -0
package/LICENSE.md
CHANGED
|
@@ -2,7 +2,7 @@ Software License Agreement
|
|
|
2
2
|
==========================
|
|
3
3
|
|
|
4
4
|
**CKEditor 5 editing engine** – https://github.com/ckeditor/ckeditor5-engine <br>
|
|
5
|
-
Copyright (c) 2003-2022, [CKSource
|
|
5
|
+
Copyright (c) 2003-2022, [CKSource Holding sp. z o.o.](https://cksource.com) 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).
|
|
8
8
|
|
|
@@ -14,4 +14,4 @@ Where not otherwise indicated, all CKEditor content is authored by CKSource engi
|
|
|
14
14
|
Trademarks
|
|
15
15
|
----------
|
|
16
16
|
|
|
17
|
-
**CKEditor** is a trademark of [CKSource
|
|
17
|
+
**CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
|
package/README.md
CHANGED
|
@@ -3,7 +3,8 @@ CKEditor 5 editing engine
|
|
|
3
3
|
|
|
4
4
|
[](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)
|
|
5
5
|
[](https://coveralls.io/github/ckeditor/ckeditor5?branch=master)
|
|
6
|
-
[](https://travis-ci.com/ckeditor/ckeditor5)
|
|
6
|
+
[](https://app.travis-ci.com/github/ckeditor/ckeditor5)
|
|
7
|
+

|
|
7
8
|
|
|
8
9
|
The CKEditor 5 editing engine implements a flexible MVC-based architecture for creating rich text editing features.
|
|
9
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "34.1.0",
|
|
4
4
|
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wysiwyg",
|
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
],
|
|
24
24
|
"main": "src/index.js",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@ckeditor/ckeditor5-utils": "^
|
|
26
|
+
"@ckeditor/ckeditor5-utils": "^34.1.0",
|
|
27
27
|
"lodash-es": "^4.17.15"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@ckeditor/ckeditor5-basic-styles": "^
|
|
31
|
-
"@ckeditor/ckeditor5-block-quote": "^
|
|
32
|
-
"@ckeditor/ckeditor5-clipboard": "^
|
|
33
|
-
"@ckeditor/ckeditor5-cloud-services": "^
|
|
34
|
-
"@ckeditor/ckeditor5-core": "^
|
|
35
|
-
"@ckeditor/ckeditor5-editor-classic": "^
|
|
36
|
-
"@ckeditor/ckeditor5-enter": "^
|
|
37
|
-
"@ckeditor/ckeditor5-essentials": "^
|
|
38
|
-
"@ckeditor/ckeditor5-heading": "^
|
|
39
|
-
"@ckeditor/ckeditor5-image": "^
|
|
40
|
-
"@ckeditor/ckeditor5-link": "^
|
|
41
|
-
"@ckeditor/ckeditor5-list": "^
|
|
42
|
-
"@ckeditor/ckeditor5-mention": "^
|
|
43
|
-
"@ckeditor/ckeditor5-paragraph": "^
|
|
44
|
-
"@ckeditor/ckeditor5-table": "^
|
|
45
|
-
"@ckeditor/ckeditor5-theme-lark": "^
|
|
46
|
-
"@ckeditor/ckeditor5-typing": "^
|
|
47
|
-
"@ckeditor/ckeditor5-ui": "^
|
|
48
|
-
"@ckeditor/ckeditor5-undo": "^
|
|
49
|
-
"@ckeditor/ckeditor5-widget": "^
|
|
30
|
+
"@ckeditor/ckeditor5-basic-styles": "^34.1.0",
|
|
31
|
+
"@ckeditor/ckeditor5-block-quote": "^34.1.0",
|
|
32
|
+
"@ckeditor/ckeditor5-clipboard": "^34.1.0",
|
|
33
|
+
"@ckeditor/ckeditor5-cloud-services": "^34.1.0",
|
|
34
|
+
"@ckeditor/ckeditor5-core": "^34.1.0",
|
|
35
|
+
"@ckeditor/ckeditor5-editor-classic": "^34.1.0",
|
|
36
|
+
"@ckeditor/ckeditor5-enter": "^34.1.0",
|
|
37
|
+
"@ckeditor/ckeditor5-essentials": "^34.1.0",
|
|
38
|
+
"@ckeditor/ckeditor5-heading": "^34.1.0",
|
|
39
|
+
"@ckeditor/ckeditor5-image": "^34.1.0",
|
|
40
|
+
"@ckeditor/ckeditor5-link": "^34.1.0",
|
|
41
|
+
"@ckeditor/ckeditor5-list": "^34.1.0",
|
|
42
|
+
"@ckeditor/ckeditor5-mention": "^34.1.0",
|
|
43
|
+
"@ckeditor/ckeditor5-paragraph": "^34.1.0",
|
|
44
|
+
"@ckeditor/ckeditor5-table": "^34.1.0",
|
|
45
|
+
"@ckeditor/ckeditor5-theme-lark": "^34.1.0",
|
|
46
|
+
"@ckeditor/ckeditor5-typing": "^34.1.0",
|
|
47
|
+
"@ckeditor/ckeditor5-ui": "^34.1.0",
|
|
48
|
+
"@ckeditor/ckeditor5-undo": "^34.1.0",
|
|
49
|
+
"@ckeditor/ckeditor5-widget": "^34.1.0",
|
|
50
50
|
"webpack": "^5.58.1",
|
|
51
51
|
"webpack-cli": "^4.9.0"
|
|
52
52
|
},
|
|
@@ -14,7 +14,7 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
|
14
14
|
import Mapper from '../conversion/mapper';
|
|
15
15
|
|
|
16
16
|
import DowncastDispatcher from '../conversion/downcastdispatcher';
|
|
17
|
-
import { insertText } from '../conversion/downcasthelpers';
|
|
17
|
+
import { insertAttributesAndChildren, insertText } from '../conversion/downcasthelpers';
|
|
18
18
|
|
|
19
19
|
import UpcastDispatcher from '../conversion/upcastdispatcher';
|
|
20
20
|
import { convertText, convertToModelFragment } from '../conversion/upcasthelpers';
|
|
@@ -31,7 +31,7 @@ import HtmlDataProcessor from '../dataprocessor/htmldataprocessor';
|
|
|
31
31
|
* Controller for the data pipeline. The data pipeline controls how data is retrieved from the document
|
|
32
32
|
* and set inside it. Hence, the controller features two methods which allow to {@link ~DataController#get get}
|
|
33
33
|
* and {@link ~DataController#set set} data of the {@link ~DataController#model model}
|
|
34
|
-
* using given:
|
|
34
|
+
* using the given:
|
|
35
35
|
*
|
|
36
36
|
* * {@link module:engine/dataprocessor/dataprocessor~DataProcessor data processor},
|
|
37
37
|
* * downcast converters,
|
|
@@ -61,8 +61,8 @@ export default class DataController {
|
|
|
61
61
|
this.model = model;
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* Mapper used for the conversion. It has no permanent bindings, because
|
|
65
|
-
* cleared directly after the data are converted. However, the mapper is defined as a class property, because
|
|
64
|
+
* Mapper used for the conversion. It has no permanent bindings, because these are created while getting data and
|
|
65
|
+
* ae cleared directly after the data are converted. However, the mapper is defined as a class property, because
|
|
66
66
|
* it needs to be passed to the `DowncastDispatcher` as a conversion API.
|
|
67
67
|
*
|
|
68
68
|
* @readonly
|
|
@@ -81,6 +81,7 @@ export default class DataController {
|
|
|
81
81
|
schema: model.schema
|
|
82
82
|
} );
|
|
83
83
|
this.downcastDispatcher.on( 'insert:$text', insertText(), { priority: 'lowest' } );
|
|
84
|
+
this.downcastDispatcher.on( 'insert', insertAttributesAndChildren(), { priority: 'lowest' } );
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
87
|
* Upcast dispatcher used by the {@link #set set method}. Upcast converters should be attached to it.
|
|
@@ -138,7 +139,7 @@ export default class DataController {
|
|
|
138
139
|
//
|
|
139
140
|
// Note that if there is no default converter for the element it will be skipped, for instance `<b>foo</b>` will be
|
|
140
141
|
// converted to nothing. We therefore add `convertToModelFragment` as a last converter so it converts children of that
|
|
141
|
-
// element to the document fragment
|
|
142
|
+
// element to the document fragment so `<b>foo</b>` will still be converted to `foo` even if there is no converter for `<b>`.
|
|
142
143
|
this.upcastDispatcher.on( 'text', convertText(), { priority: 'lowest' } );
|
|
143
144
|
this.upcastDispatcher.on( 'element', convertToModelFragment(), { priority: 'lowest' } );
|
|
144
145
|
this.upcastDispatcher.on( 'documentFragment', convertToModelFragment(), { priority: 'lowest' } );
|
|
@@ -147,14 +148,14 @@ export default class DataController {
|
|
|
147
148
|
this.decorate( 'set' );
|
|
148
149
|
this.decorate( 'get' );
|
|
149
150
|
|
|
150
|
-
// Fire the `ready` event when the initialization has completed. Such low-level listener
|
|
151
|
+
// Fire the `ready` event when the initialization has completed. Such low-level listener offers the possibility
|
|
151
152
|
// to plug into the initialization pipeline without interrupting the initialization flow.
|
|
152
153
|
this.on( 'init', () => {
|
|
153
154
|
this.fire( 'ready' );
|
|
154
155
|
}, { priority: 'lowest' } );
|
|
155
156
|
|
|
156
|
-
// Fix empty roots after DataController is 'ready' (note that init method could be decorated and stopped).
|
|
157
|
-
// We need to handle this event because initial data could be empty and post-fixer would not get triggered.
|
|
157
|
+
// Fix empty roots after DataController is 'ready' (note that the init method could be decorated and stopped).
|
|
158
|
+
// We need to handle this event because initial data could be empty and the post-fixer would not get triggered.
|
|
158
159
|
this.on( 'ready', () => {
|
|
159
160
|
this.model.enqueueChange( { isUndoable: false }, autoParagraphEmptyRoots );
|
|
160
161
|
}, { priority: 'lowest' } );
|
|
@@ -170,7 +171,7 @@ export default class DataController {
|
|
|
170
171
|
* @param {String} [options.rootName='main'] Root name.
|
|
171
172
|
* @param {String} [options.trim='empty'] Whether returned data should be trimmed. This option is set to `empty` by default,
|
|
172
173
|
* which means whenever editor content is considered empty, an empty string will be returned. To turn off trimming completely
|
|
173
|
-
* use `'none'`. In such cases exact content will be returned (for example `<p> </p>` for an empty editor).
|
|
174
|
+
* use `'none'`. In such cases the exact content will be returned (for example a `<p> </p>` for an empty editor).
|
|
174
175
|
* @returns {String} Output data.
|
|
175
176
|
*/
|
|
176
177
|
get( options = {} ) {
|
|
@@ -179,7 +180,7 @@ export default class DataController {
|
|
|
179
180
|
if ( !this._checkIfRootsExists( [ rootName ] ) ) {
|
|
180
181
|
/**
|
|
181
182
|
* Cannot get data from a non-existing root. This error is thrown when {@link #get DataController#get() method}
|
|
182
|
-
* is called with non-existent root name. For example, if there is an editor instance with only `main` root,
|
|
183
|
+
* is called with a non-existent root name. For example, if there is an editor instance with only `main` root,
|
|
183
184
|
* calling {@link #get} like:
|
|
184
185
|
*
|
|
185
186
|
* data.get( { rootName: 'root2' } );
|
|
@@ -203,10 +204,10 @@ export default class DataController {
|
|
|
203
204
|
/**
|
|
204
205
|
* Returns the content of the given {@link module:engine/model/element~Element model's element} or
|
|
205
206
|
* {@link module:engine/model/documentfragment~DocumentFragment model document fragment} converted by the downcast converters
|
|
206
|
-
* attached to {@link #downcastDispatcher} and formatted by the {@link #processor data processor}.
|
|
207
|
+
* attached to the {@link #downcastDispatcher} and formatted by the {@link #processor data processor}.
|
|
207
208
|
*
|
|
208
209
|
* @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} modelElementOrFragment
|
|
209
|
-
*
|
|
210
|
+
* The element whose content will be stringified.
|
|
210
211
|
* @param {Object} [options] Additional configuration passed to the conversion process.
|
|
211
212
|
* @returns {String} Output data.
|
|
212
213
|
*/
|
|
@@ -221,12 +222,12 @@ export default class DataController {
|
|
|
221
222
|
/**
|
|
222
223
|
* Returns the content of the given {@link module:engine/model/element~Element model element} or
|
|
223
224
|
* {@link module:engine/model/documentfragment~DocumentFragment model document fragment} converted by the downcast
|
|
224
|
-
* converters attached to {@link #downcastDispatcher}
|
|
225
|
+
* converters attached to {@link #downcastDispatcher} into a
|
|
225
226
|
* {@link module:engine/view/documentfragment~DocumentFragment view document fragment}.
|
|
226
227
|
*
|
|
227
228
|
* @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} modelElementOrFragment
|
|
228
229
|
* Element or document fragment whose content will be converted.
|
|
229
|
-
* @param {Object} [options={}] Additional configuration that will be available through
|
|
230
|
+
* @param {Object} [options={}] Additional configuration that will be available through the
|
|
230
231
|
* {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi#options} during the conversion process.
|
|
231
232
|
* @returns {module:engine/view/documentfragment~DocumentFragment} Output view DocumentFragment.
|
|
232
233
|
*/
|
|
@@ -234,7 +235,7 @@ export default class DataController {
|
|
|
234
235
|
const viewDocument = this.viewDocument;
|
|
235
236
|
const viewWriter = this._viewWriter;
|
|
236
237
|
|
|
237
|
-
// Clear bindings so the call to this method
|
|
238
|
+
// Clear bindings so the call to this method returns correct results.
|
|
238
239
|
this.mapper.clearBindings();
|
|
239
240
|
|
|
240
241
|
// First, convert elements.
|
|
@@ -243,57 +244,46 @@ export default class DataController {
|
|
|
243
244
|
|
|
244
245
|
this.mapper.bindElements( modelElementOrFragment, viewDocumentFragment );
|
|
245
246
|
|
|
246
|
-
//
|
|
247
|
-
this.downcastDispatcher.conversionApi.options = options;
|
|
248
|
-
|
|
249
|
-
// We have no view controller and rendering to DOM in DataController so view.change() block is not used here.
|
|
250
|
-
this.downcastDispatcher.convertInsert( modelRange, viewWriter );
|
|
251
|
-
|
|
252
|
-
// Convert markers.
|
|
247
|
+
// Prepare list of markers.
|
|
253
248
|
// For document fragment, simply take the markers assigned to this document fragment.
|
|
254
249
|
// For model root, all markers in that root will be taken.
|
|
255
250
|
// For model element, we need to check which markers are intersecting with this element and relatively modify the markers' ranges.
|
|
256
251
|
// Collapsed markers at element boundary, although considered as not intersecting with the element, will also be returned.
|
|
257
252
|
const markers = modelElementOrFragment.is( 'documentFragment' ) ?
|
|
258
|
-
|
|
253
|
+
modelElementOrFragment.markers :
|
|
259
254
|
_getMarkersRelativeToElement( modelElementOrFragment );
|
|
260
255
|
|
|
261
|
-
|
|
262
|
-
this.downcastDispatcher.convertMarkerAdd( name, range, viewWriter );
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Clean `conversionApi`.
|
|
266
|
-
delete this.downcastDispatcher.conversionApi.options;
|
|
256
|
+
this.downcastDispatcher.convert( modelRange, markers, viewWriter, options );
|
|
267
257
|
|
|
268
258
|
return viewDocumentFragment;
|
|
269
259
|
}
|
|
270
260
|
|
|
271
261
|
/**
|
|
272
|
-
* Sets initial input data parsed by the {@link #processor data processor} and
|
|
262
|
+
* Sets the initial input data parsed by the {@link #processor data processor} and
|
|
273
263
|
* converted by the {@link #upcastDispatcher view-to-model converters}.
|
|
274
|
-
* Initial data can be set
|
|
264
|
+
* Initial data can be only set to a document whose {@link module:engine/model/document~Document#version} is equal 0.
|
|
275
265
|
*
|
|
276
266
|
* **Note** This method is {@link module:utils/observablemixin~ObservableMixin#decorate decorated} which is
|
|
277
267
|
* used by e.g. collaborative editing plugin that syncs remote data on init.
|
|
278
268
|
*
|
|
279
|
-
* When data is passed as a string it is initialized on
|
|
269
|
+
* When data is passed as a string, it is initialized on the default `main` root:
|
|
280
270
|
*
|
|
281
|
-
* dataController.init( '<p>Foo</p>' ); // Initializes data on the `main` root.
|
|
271
|
+
* dataController.init( '<p>Foo</p>' ); // Initializes data on the `main` root only, as no other is specified.
|
|
282
272
|
*
|
|
283
|
-
* To initialize data on a different root or multiple roots at once, object containing `rootName` - `data` pairs should be passed:
|
|
273
|
+
* To initialize data on a different root or multiple roots at once, an object containing `rootName` - `data` pairs should be passed:
|
|
284
274
|
*
|
|
285
|
-
* dataController.init( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Initializes data on the `main` and `title` roots.
|
|
275
|
+
* dataController.init( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Initializes data on both the `main` and `title` roots.
|
|
286
276
|
*
|
|
287
277
|
* @fires init
|
|
288
|
-
* @param {String|Object.<String,String>} data Input data as a string or an object containing `rootName` - `data`
|
|
278
|
+
* @param {String|Object.<String,String>} data Input data as a string or an object containing the `rootName` - `data`
|
|
289
279
|
* pairs to initialize data on multiple roots at once.
|
|
290
280
|
* @returns {Promise} Promise that is resolved after the data is set on the editor.
|
|
291
281
|
*/
|
|
292
282
|
init( data ) {
|
|
293
283
|
if ( this.model.document.version ) {
|
|
294
284
|
/**
|
|
295
|
-
* Cannot set initial data to
|
|
296
|
-
* Initial data should be set once, during {@link module:core/editor/editor~Editor} initialization,
|
|
285
|
+
* Cannot set initial data to a non-empty {@link module:engine/model/document~Document}.
|
|
286
|
+
* Initial data should be set once, during the {@link module:core/editor/editor~Editor} initialization,
|
|
297
287
|
* when the {@link module:engine/model/document~Document#version} is equal 0.
|
|
298
288
|
*
|
|
299
289
|
* @error datacontroller-init-document-not-empty
|
|
@@ -310,7 +300,7 @@ export default class DataController {
|
|
|
310
300
|
|
|
311
301
|
if ( !this._checkIfRootsExists( Object.keys( initialData ) ) ) {
|
|
312
302
|
/**
|
|
313
|
-
* Cannot init data on a non-
|
|
303
|
+
* Cannot init data on a non-existent root. This error is thrown when {@link #init DataController#init() method}
|
|
314
304
|
* is called with non-existent root name. For example, if there is an editor instance with only `main` root,
|
|
315
305
|
* calling {@link #init} like:
|
|
316
306
|
*
|
|
@@ -334,48 +324,48 @@ export default class DataController {
|
|
|
334
324
|
}
|
|
335
325
|
|
|
336
326
|
/**
|
|
337
|
-
* Sets input data parsed by the {@link #processor data processor} and
|
|
327
|
+
* Sets the input data parsed by the {@link #processor data processor} and
|
|
338
328
|
* converted by the {@link #upcastDispatcher view-to-model converters}.
|
|
339
|
-
* This method can be used any time to replace existing editor data
|
|
329
|
+
* This method can be used any time to replace existing editor data with the new one without clearing the
|
|
340
330
|
* {@link module:engine/model/document~Document#history document history}.
|
|
341
331
|
*
|
|
342
332
|
* This method also creates a batch with all the changes applied. If all you need is to parse data, use
|
|
343
333
|
* the {@link #parse} method.
|
|
344
334
|
*
|
|
345
|
-
* When data is passed as a string it is set on
|
|
335
|
+
* When data is passed as a string it is set on the default `main` root:
|
|
346
336
|
*
|
|
347
|
-
* dataController.set( '<p>Foo</p>' ); // Sets data on the `main` root.
|
|
337
|
+
* dataController.set( '<p>Foo</p>' ); // Sets data on the `main` root, as no other is specified.
|
|
348
338
|
*
|
|
349
|
-
* To set data on a different root or multiple roots at once, object containing `rootName` - `data` pairs should be passed:
|
|
339
|
+
* To set data on a different root or multiple roots at once, an object containing `rootName` - `data` pairs should be passed:
|
|
350
340
|
*
|
|
351
|
-
* dataController.set( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Sets data on the `main` and `title` roots.
|
|
341
|
+
* dataController.set( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Sets data on the `main` and `title` roots as specified.
|
|
352
342
|
*
|
|
353
|
-
* To set the data with preserved undo stack and add the change to the undo stack, set `{ isUndoable: true }` as `batchType` option.
|
|
343
|
+
* To set the data with a preserved undo stack and add the change to the undo stack, set `{ isUndoable: true }` as a `batchType` option.
|
|
354
344
|
*
|
|
355
345
|
* dataController.set( '<p>Foo</p>', { batchType: { isUndoable: true } } );
|
|
356
346
|
*
|
|
357
347
|
* @fires set
|
|
358
|
-
* @param {String|Object.<String,String>} data Input data as a string or an object containing `rootName` - `data`
|
|
348
|
+
* @param {String|Object.<String,String>} data Input data as a string or an object containing the `rootName` - `data`
|
|
359
349
|
* pairs to set data on multiple roots at once.
|
|
360
350
|
* @param {Object} [options={}] Options for setting data.
|
|
361
351
|
* @param {Object} [options.batchType] The batch type that will be used to create a batch for the changes applied by this method.
|
|
362
352
|
* By default, the batch will be set as {@link module:engine/model/batch~Batch#isUndoable not undoable} and the undo stack will be
|
|
363
|
-
* cleared after the new data is applied (all undo steps will be removed). If batch type `isUndoable` flag
|
|
364
|
-
* the undo stack will be preserved.
|
|
353
|
+
* cleared after the new data is applied (all undo steps will be removed). If the batch type `isUndoable` flag is be set to `true`,
|
|
354
|
+
* the undo stack will be preserved instead and not cleared when new data is applied.
|
|
365
355
|
*/
|
|
366
356
|
set( data, options = {} ) {
|
|
367
357
|
let newData = {};
|
|
368
358
|
|
|
369
359
|
if ( typeof data === 'string' ) {
|
|
370
|
-
newData.main = data; //
|
|
360
|
+
newData.main = data; // The default root is 'main'. To set data on a different root, an object should be passed.
|
|
371
361
|
} else {
|
|
372
362
|
newData = data;
|
|
373
363
|
}
|
|
374
364
|
|
|
375
365
|
if ( !this._checkIfRootsExists( Object.keys( newData ) ) ) {
|
|
376
366
|
/**
|
|
377
|
-
* Cannot set data on a non-
|
|
378
|
-
* is called with non-existent root name. For example, if there is an editor instance with only `main` root,
|
|
367
|
+
* Cannot set data on a non-existent root. This error is thrown when the {@link #set DataController#set() method}
|
|
368
|
+
* is called with non-existent root name. For example, if there is an editor instance with only the default `main` root,
|
|
379
369
|
* calling {@link #set} like:
|
|
380
370
|
*
|
|
381
371
|
* data.set( { main: '<p>Foo</p>', root2: '<p>Bar</p>' } );
|
|
@@ -428,7 +418,7 @@ export default class DataController {
|
|
|
428
418
|
* {@link module:engine/model/documentfragment~DocumentFragment#markers static markers map}.
|
|
429
419
|
*
|
|
430
420
|
* @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} viewElementOrFragment
|
|
431
|
-
*
|
|
421
|
+
* The element or document fragment whose content will be converted.
|
|
432
422
|
* @param {module:engine/model/schema~SchemaContextDefinition} [context='$root'] Base context in which the view will
|
|
433
423
|
* be converted to the model. See: {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#convert}.
|
|
434
424
|
* @returns {module:engine/model/documentfragment~DocumentFragment} Output document fragment.
|
|
@@ -440,7 +430,7 @@ export default class DataController {
|
|
|
440
430
|
}
|
|
441
431
|
|
|
442
432
|
/**
|
|
443
|
-
* Adds
|
|
433
|
+
* Adds the style processor normalization rules.
|
|
444
434
|
*
|
|
445
435
|
* You can implement your own rules as well as use one of the available processor rules:
|
|
446
436
|
*
|
|
@@ -456,18 +446,18 @@ export default class DataController {
|
|
|
456
446
|
}
|
|
457
447
|
|
|
458
448
|
/**
|
|
459
|
-
* Registers a {@link module:engine/view/matcher~MatcherPattern} on {@link #htmlProcessor htmlProcessor}
|
|
460
|
-
* and {@link #processor processor} for view elements whose content should be treated as
|
|
461
|
-
* and not processed during conversion from DOM to view elements.
|
|
449
|
+
* Registers a {@link module:engine/view/matcher~MatcherPattern} on an {@link #htmlProcessor htmlProcessor}
|
|
450
|
+
* and a {@link #processor processor} for view elements whose content should be treated as raw data
|
|
451
|
+
* and not processed during the conversion from DOM to view elements.
|
|
462
452
|
*
|
|
463
|
-
* The raw data can be later accessed by {@link module:engine/view/element~Element#getCustomProperty view element custom property}
|
|
453
|
+
* The raw data can be later accessed by the {@link module:engine/view/element~Element#getCustomProperty view element custom property}
|
|
464
454
|
* `"$rawContent"`.
|
|
465
455
|
*
|
|
466
456
|
* @param {module:engine/view/matcher~MatcherPattern} pattern Pattern matching all view elements whose content should
|
|
467
457
|
* be treated as a raw data.
|
|
468
458
|
*/
|
|
469
459
|
registerRawContentMatcher( pattern ) {
|
|
470
|
-
// No need to register the pattern if both `htmlProcessor` and `processor` are the same instances.
|
|
460
|
+
// No need to register the pattern if both the `htmlProcessor` and `processor` are the same instances.
|
|
471
461
|
if ( this.processor && this.processor !== this.htmlProcessor ) {
|
|
472
462
|
this.processor.registerRawContentMatcher( pattern );
|
|
473
463
|
}
|
|
@@ -483,7 +473,7 @@ export default class DataController {
|
|
|
483
473
|
}
|
|
484
474
|
|
|
485
475
|
/**
|
|
486
|
-
* Checks
|
|
476
|
+
* Checks whether all provided root names are actually existing editor roots.
|
|
487
477
|
*
|
|
488
478
|
* @private
|
|
489
479
|
* @param {Array.<String>} rootNames Root names to check.
|
|
@@ -506,7 +496,7 @@ export default class DataController {
|
|
|
506
496
|
*/
|
|
507
497
|
|
|
508
498
|
/**
|
|
509
|
-
*
|
|
499
|
+
* An event fired after the {@link #init `init()` method} was run. It can be {@link #listenTo listened to} in order to adjust or modify
|
|
510
500
|
* the initialization flow. However, if the `init` event is stopped or prevented, the {@link #event:ready `ready` event}
|
|
511
501
|
* should be fired manually.
|
|
512
502
|
*
|
|
@@ -517,9 +507,9 @@ export default class DataController {
|
|
|
517
507
|
*/
|
|
518
508
|
|
|
519
509
|
/**
|
|
520
|
-
*
|
|
510
|
+
* An event fired after {@link #set set() method} has been run.
|
|
521
511
|
*
|
|
522
|
-
* The `set` event is fired by decorated {@link #set} method.
|
|
512
|
+
* The `set` event is fired by the decorated {@link #set} method.
|
|
523
513
|
* See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.
|
|
524
514
|
*
|
|
525
515
|
* @event set
|
|
@@ -528,7 +518,7 @@ export default class DataController {
|
|
|
528
518
|
/**
|
|
529
519
|
* Event fired after the {@link #get get() method} has been run.
|
|
530
520
|
*
|
|
531
|
-
* The `get` event is fired by decorated {@link #get} method.
|
|
521
|
+
* The `get` event is fired by the decorated {@link #get} method.
|
|
532
522
|
* See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.
|
|
533
523
|
*
|
|
534
524
|
* @event get
|
|
@@ -547,7 +537,7 @@ function _getMarkersRelativeToElement( element ) {
|
|
|
547
537
|
const doc = element.root.document;
|
|
548
538
|
|
|
549
539
|
if ( !doc ) {
|
|
550
|
-
return
|
|
540
|
+
return new Map();
|
|
551
541
|
}
|
|
552
542
|
|
|
553
543
|
const elementRange = ModelRange._createIn( element );
|
|
@@ -581,7 +571,7 @@ function _getMarkersRelativeToElement( element ) {
|
|
|
581
571
|
// reverse DOM order, and intersecting ranges are in something approximating
|
|
582
572
|
// reverse DOM order (since reverse DOM order doesn't have a precise meaning
|
|
583
573
|
// when working with intersecting ranges).
|
|
584
|
-
|
|
574
|
+
result.sort( ( [ n1, r1 ], [ n2, r2 ] ) => {
|
|
585
575
|
if ( r1.end.compareWith( r2.start ) !== 'after' ) {
|
|
586
576
|
// m1.end <= m2.start -- m1 is entirely <= m2
|
|
587
577
|
return 1;
|
|
@@ -608,4 +598,6 @@ function _getMarkersRelativeToElement( element ) {
|
|
|
608
598
|
}
|
|
609
599
|
}
|
|
610
600
|
} );
|
|
601
|
+
|
|
602
|
+
return new Map( result );
|
|
611
603
|
}
|
|
@@ -11,16 +11,24 @@ import RootEditableElement from '../view/rooteditableelement';
|
|
|
11
11
|
import View from '../view/view';
|
|
12
12
|
import Mapper from '../conversion/mapper';
|
|
13
13
|
import DowncastDispatcher from '../conversion/downcastdispatcher';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
clearAttributes,
|
|
16
|
+
convertCollapsedSelection,
|
|
17
|
+
convertRangeSelection,
|
|
18
|
+
insertAttributesAndChildren,
|
|
19
|
+
insertText,
|
|
20
|
+
remove
|
|
21
|
+
} from '../conversion/downcasthelpers';
|
|
15
22
|
|
|
16
23
|
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
|
|
17
24
|
import mix from '@ckeditor/ckeditor5-utils/src/mix';
|
|
25
|
+
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
18
26
|
import { convertSelectionChange } from '../conversion/upcasthelpers';
|
|
19
27
|
|
|
20
28
|
// @if CK_DEBUG_ENGINE // const { dumpTrees, initDocumentDumping } = require( '../dev-utils/utils' );
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
|
-
*
|
|
31
|
+
* A controller for the editing pipeline. The editing pipeline controls the {@link ~EditingController#model model} rendering,
|
|
24
32
|
* including selection handling. It also creates the {@link ~EditingController#view view} which builds a
|
|
25
33
|
* browser-independent virtualization over the DOM elements. The editing controller also attaches default converters.
|
|
26
34
|
*
|
|
@@ -51,7 +59,7 @@ export default class EditingController {
|
|
|
51
59
|
this.view = new View( stylesProcessor );
|
|
52
60
|
|
|
53
61
|
/**
|
|
54
|
-
*
|
|
62
|
+
* A mapper that describes the model-view binding.
|
|
55
63
|
*
|
|
56
64
|
* @readonly
|
|
57
65
|
* @member {module:engine/conversion/mapper~Mapper}
|
|
@@ -59,7 +67,7 @@ export default class EditingController {
|
|
|
59
67
|
this.mapper = new Mapper();
|
|
60
68
|
|
|
61
69
|
/**
|
|
62
|
-
* Downcast dispatcher that converts changes from the model to {@link #view
|
|
70
|
+
* Downcast dispatcher that converts changes from the model to the {@link #view editing view}.
|
|
63
71
|
*
|
|
64
72
|
* @readonly
|
|
65
73
|
* @member {module:engine/conversion/downcastdispatcher~DowncastDispatcher} #downcastDispatcher
|
|
@@ -74,7 +82,7 @@ export default class EditingController {
|
|
|
74
82
|
const markers = this.model.markers;
|
|
75
83
|
|
|
76
84
|
// When plugins listen on model changes (on selection change, post fixers, etc.) and change the view as a result of
|
|
77
|
-
// model's change, they might trigger view rendering before the conversion is completed (e.g. before the selection
|
|
85
|
+
// the model's change, they might trigger view rendering before the conversion is completed (e.g. before the selection
|
|
78
86
|
// is converted). We disable rendering for the length of the outermost model change() block to prevent that.
|
|
79
87
|
//
|
|
80
88
|
// See https://github.com/ckeditor/ckeditor5-engine/issues/1528
|
|
@@ -101,6 +109,7 @@ export default class EditingController {
|
|
|
101
109
|
|
|
102
110
|
// Attach default model converters.
|
|
103
111
|
this.downcastDispatcher.on( 'insert:$text', insertText(), { priority: 'lowest' } );
|
|
112
|
+
this.downcastDispatcher.on( 'insert', insertAttributesAndChildren(), { priority: 'lowest' } );
|
|
104
113
|
this.downcastDispatcher.on( 'remove', remove(), { priority: 'low' } );
|
|
105
114
|
|
|
106
115
|
// Attach default model selection converters.
|
|
@@ -144,6 +153,74 @@ export default class EditingController {
|
|
|
144
153
|
this.view.destroy();
|
|
145
154
|
this.stopListening();
|
|
146
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Calling this method will refresh the marker by triggering the downcast conversion for it.
|
|
159
|
+
*
|
|
160
|
+
* Reconverting the marker is useful when you want to change its {@link module:engine/view/element~Element view element}
|
|
161
|
+
* without changing any marker data. For instance:
|
|
162
|
+
*
|
|
163
|
+
* let isCommentActive = false;
|
|
164
|
+
*
|
|
165
|
+
* model.conversion.markerToHighlight( {
|
|
166
|
+
* model: 'comment',
|
|
167
|
+
* view: data => {
|
|
168
|
+
* const classes = [ 'comment-marker' ];
|
|
169
|
+
*
|
|
170
|
+
* if ( isCommentActive ) {
|
|
171
|
+
* classes.push( 'comment-marker--active' );
|
|
172
|
+
* }
|
|
173
|
+
*
|
|
174
|
+
* return { classes };
|
|
175
|
+
* }
|
|
176
|
+
* } );
|
|
177
|
+
*
|
|
178
|
+
* // ...
|
|
179
|
+
*
|
|
180
|
+
* // Change the property that indicates if marker is displayed as active or not.
|
|
181
|
+
* isCommentActive = true;
|
|
182
|
+
*
|
|
183
|
+
* // Reconverting will downcast and synchronize the marker with the new isCommentActive state value.
|
|
184
|
+
* editor.editing.reconvertMarker( 'comment' );
|
|
185
|
+
*
|
|
186
|
+
* **Note**: If you want to reconvert a model item, use {@link #reconvertItem} instead.
|
|
187
|
+
*
|
|
188
|
+
* @param {String|module:engine/model/markercollection~Marker} markerOrName Name of a marker to update, or a marker instance.
|
|
189
|
+
*/
|
|
190
|
+
reconvertMarker( markerOrName ) {
|
|
191
|
+
const markerName = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;
|
|
192
|
+
const currentMarker = this.model.markers.get( markerName );
|
|
193
|
+
|
|
194
|
+
if ( !currentMarker ) {
|
|
195
|
+
/**
|
|
196
|
+
* The marker with the provided name does not exist and cannot be reconverted.
|
|
197
|
+
*
|
|
198
|
+
* @error editingcontroller-reconvertmarker-marker-not-exist
|
|
199
|
+
* @param {String} markerName The name of the reconverted marker.
|
|
200
|
+
*/
|
|
201
|
+
throw new CKEditorError( 'editingcontroller-reconvertmarker-marker-not-exist', this, { markerName } );
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.model.change( () => {
|
|
205
|
+
this.model.markers._refresh( currentMarker );
|
|
206
|
+
} );
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Calling this method will downcast a model item on demand (by requesting a refresh in the {@link module:engine/model/differ~Differ}).
|
|
211
|
+
*
|
|
212
|
+
* You can use it if you want the view representation of a specific item updated as a response to external modifications. For instance,
|
|
213
|
+
* when the view structure depends not only on the associated model data but also on some external state.
|
|
214
|
+
*
|
|
215
|
+
* **Note**: If you want to reconvert a model marker, use {@link #reconvertMarker} instead.
|
|
216
|
+
*
|
|
217
|
+
* @param {module:engine/model/item~Item} item Item to refresh.
|
|
218
|
+
*/
|
|
219
|
+
reconvertItem( item ) {
|
|
220
|
+
this.model.change( () => {
|
|
221
|
+
this.model.document.differ._refreshItem( item );
|
|
222
|
+
} );
|
|
223
|
+
}
|
|
147
224
|
}
|
|
148
225
|
|
|
149
226
|
mix( EditingController, ObservableMixin );
|