@ckeditor/ckeditor5-engine 31.0.0 → 33.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 +2 -2
- package/package.json +25 -25
- package/src/controller/datacontroller.js +71 -80
- package/src/controller/editingcontroller.js +83 -6
- package/src/conversion/conversion.js +15 -14
- package/src/conversion/conversionhelpers.js +1 -1
- package/src/conversion/downcastdispatcher.js +298 -367
- package/src/conversion/downcasthelpers.js +771 -63
- package/src/conversion/mapper.js +105 -60
- package/src/conversion/modelconsumable.js +85 -35
- package/src/conversion/upcastdispatcher.js +3 -6
- package/src/conversion/upcasthelpers.js +4 -2
- package/src/conversion/viewconsumable.js +1 -1
- package/src/dataprocessor/basichtmlwriter.js +1 -1
- package/src/dataprocessor/dataprocessor.jsdoc +1 -1
- package/src/dataprocessor/htmldataprocessor.js +9 -31
- package/src/dataprocessor/htmlwriter.js +1 -1
- package/src/dataprocessor/xmldataprocessor.js +1 -1
- package/src/dev-utils/model.js +16 -14
- package/src/dev-utils/operationreplayer.js +1 -1
- package/src/dev-utils/utils.js +1 -1
- package/src/dev-utils/view.js +7 -7
- package/src/index.js +2 -1
- package/src/model/batch.js +77 -10
- package/src/model/differ.js +87 -59
- package/src/model/document.js +13 -4
- package/src/model/documentfragment.js +1 -1
- package/src/model/documentselection.js +1 -1
- package/src/model/element.js +1 -1
- package/src/model/history.js +1 -1
- package/src/model/item.jsdoc +1 -1
- package/src/model/liveposition.js +1 -1
- package/src/model/liverange.js +1 -1
- package/src/model/markercollection.js +29 -5
- package/src/model/model.js +18 -9
- package/src/model/node.js +1 -1
- package/src/model/nodelist.js +1 -1
- package/src/model/operation/attributeoperation.js +1 -1
- package/src/model/operation/detachoperation.js +1 -1
- package/src/model/operation/insertoperation.js +1 -1
- package/src/model/operation/markeroperation.js +1 -1
- package/src/model/operation/mergeoperation.js +1 -1
- package/src/model/operation/moveoperation.js +1 -1
- package/src/model/operation/nooperation.js +1 -1
- package/src/model/operation/operation.js +1 -1
- package/src/model/operation/operationfactory.js +1 -1
- package/src/model/operation/renameoperation.js +1 -1
- package/src/model/operation/rootattributeoperation.js +1 -1
- package/src/model/operation/splitoperation.js +1 -1
- package/src/model/operation/transform.js +1 -1
- package/src/model/operation/utils.js +1 -1
- package/src/model/position.js +1 -1
- package/src/model/range.js +1 -1
- package/src/model/rootelement.js +1 -1
- package/src/model/schema.js +1 -1
- package/src/model/selection.js +1 -1
- package/src/model/text.js +1 -1
- package/src/model/textproxy.js +1 -1
- package/src/model/treewalker.js +1 -1
- package/src/model/utils/autoparagraphing.js +1 -1
- package/src/model/utils/deletecontent.js +1 -1
- package/src/model/utils/getselectedcontent.js +1 -1
- package/src/model/utils/insertcontent.js +1 -1
- package/src/model/utils/modifyselection.js +15 -8
- package/src/model/utils/selection-post-fixer.js +37 -30
- package/src/model/writer.js +17 -27
- package/src/view/attributeelement.js +1 -1
- package/src/view/containerelement.js +1 -1
- package/src/view/document.js +3 -2
- package/src/view/documentfragment.js +1 -1
- package/src/view/documentselection.js +1 -1
- package/src/view/domconverter.js +169 -47
- package/src/view/downcastwriter.js +121 -5
- package/src/view/editableelement.js +1 -1
- package/src/view/element.js +29 -1
- package/src/view/elementdefinition.jsdoc +1 -1
- package/src/view/emptyelement.js +1 -1
- package/src/view/filler.js +1 -1
- package/src/view/item.jsdoc +1 -1
- package/src/view/matcher.js +15 -14
- package/src/view/node.js +1 -1
- package/src/view/observer/arrowkeysobserver.js +1 -1
- package/src/view/observer/bubblingemittermixin.js +1 -1
- package/src/view/observer/bubblingeventinfo.js +1 -1
- package/src/view/observer/clickobserver.js +1 -1
- package/src/view/observer/compositionobserver.js +1 -1
- package/src/view/observer/domeventdata.js +1 -1
- package/src/view/observer/domeventobserver.js +1 -1
- package/src/view/observer/fakeselectionobserver.js +1 -1
- package/src/view/observer/focusobserver.js +1 -1
- package/src/view/observer/inputobserver.js +1 -1
- package/src/view/observer/keyobserver.js +1 -1
- package/src/view/observer/mouseobserver.js +1 -1
- package/src/view/observer/mutationobserver.js +1 -1
- package/src/view/observer/observer.js +1 -1
- package/src/view/observer/selectionobserver.js +3 -3
- package/src/view/placeholder.js +1 -1
- package/src/view/position.js +1 -1
- package/src/view/range.js +1 -1
- package/src/view/rawelement.js +1 -1
- package/src/view/renderer.js +7 -17
- package/src/view/rooteditableelement.js +1 -1
- package/src/view/selection.js +1 -1
- package/src/view/styles/background.js +1 -1
- package/src/view/styles/border.js +1 -1
- package/src/view/styles/margin.js +1 -1
- package/src/view/styles/padding.js +1 -1
- package/src/view/styles/utils.js +1 -1
- package/src/view/stylesmap.js +1 -1
- package/src/view/text.js +1 -1
- package/src/view/textproxy.js +1 -1
- package/src/view/treewalker.js +1 -1
- package/src/view/uielement.js +1 -1
- package/src/view/upcastwriter.js +1 -1
- package/src/view/view.js +1 -1
- package/theme/placeholder.css +10 -1
- package/theme/renderer.css +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module engine/dataprocessor/htmldataprocessor
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/* globals document, DOMParser
|
|
10
|
+
/* globals document, DOMParser */
|
|
11
11
|
|
|
12
12
|
import BasicHtmlWriter from './basichtmlwriter';
|
|
13
13
|
import DomConverter from '../view/domconverter';
|
|
@@ -114,37 +114,15 @@ export default class HtmlDataProcessor {
|
|
|
114
114
|
* @returns {DocumentFragment}
|
|
115
115
|
*/
|
|
116
116
|
_toDom( data ) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// In short, parsing tokens in an HTML string starts with the so-called "initial" insertion mode. When a DOM parser is in this
|
|
123
|
-
// state and encounters a comment node, it inserts this comment node as the last child of the newly-created `HTMLDocument` object.
|
|
124
|
-
// The parser then proceeds to successive insertion modes during parsing subsequent tokens and appends in the `HTMLDocument` object
|
|
125
|
-
// other nodes (like <html>, <head>, <body>). This causes that the first leading comments from HTML string become the first nodes
|
|
126
|
-
// in the `HTMLDocument` object, but not in the <body> collection, because they are ultimately located before the <html> element.
|
|
127
|
-
//
|
|
128
|
-
// Therefore, so that such leading comments do not disappear, they all are moved from the `HTMLDocument` object to the document
|
|
129
|
-
// fragment, until the <html> element is encountered.
|
|
130
|
-
//
|
|
131
|
-
// See: https://github.com/ckeditor/ckeditor5/issues/9861.
|
|
132
|
-
let documentChildNode = document.firstChild;
|
|
133
|
-
|
|
134
|
-
while ( !documentChildNode.isSameNode( document.documentElement ) ) {
|
|
135
|
-
const node = documentChildNode;
|
|
136
|
-
|
|
137
|
-
documentChildNode = documentChildNode.nextSibling;
|
|
138
|
-
|
|
139
|
-
// It seems that `DOMParser#parseFromString()` adds only comment nodes directly to the `HTMLDocument` object, before the <html>
|
|
140
|
-
// node. The condition below is just to be sure we are moving only comment nodes.
|
|
141
|
-
|
|
142
|
-
/* istanbul ignore else */
|
|
143
|
-
if ( node.nodeType == Node.COMMENT_NODE ) {
|
|
144
|
-
fragment.appendChild( node );
|
|
145
|
-
}
|
|
117
|
+
// Wrap data with a <body> tag so leading non-layout nodes (like <script>, <style>, HTML comment)
|
|
118
|
+
// will be preserved in the body collection.
|
|
119
|
+
// Do it only for data that is not a full HTML document.
|
|
120
|
+
if ( !data.match( /<(?:html|body|head|meta)(?:\s[^>]*)?>/i ) ) {
|
|
121
|
+
data = `<body>${ data }</body>`;
|
|
146
122
|
}
|
|
147
123
|
|
|
124
|
+
const document = this.domParser.parseFromString( data, 'text/html' );
|
|
125
|
+
const fragment = document.createDocumentFragment();
|
|
148
126
|
const bodyChildNodes = document.body.childNodes;
|
|
149
127
|
|
|
150
128
|
while ( bodyChildNodes.length > 0 ) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
package/src/dev-utils/model.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -31,6 +31,7 @@ import Mapper from '../conversion/mapper';
|
|
|
31
31
|
import {
|
|
32
32
|
convertCollapsedSelection,
|
|
33
33
|
convertRangeSelection,
|
|
34
|
+
insertAttributesAndChildren,
|
|
34
35
|
insertElement,
|
|
35
36
|
insertText,
|
|
36
37
|
insertUIElement,
|
|
@@ -102,7 +103,7 @@ getData._stringify = stringify;
|
|
|
102
103
|
* name will be used.
|
|
103
104
|
* @param {Array<Object>} [options.selectionAttributes] A list of attributes which will be passed to the selection.
|
|
104
105
|
* @param {Boolean} [options.lastRangeBackward=false] If set to `true`, the last range will be added as backward.
|
|
105
|
-
* @param {
|
|
106
|
+
* @param {Object} [options.batchType] Batch type used for inserting elements. See {@link module:engine/model/batch~Batch#constructor}.
|
|
106
107
|
* See {@link module:engine/model/batch~Batch#type}.
|
|
107
108
|
*/
|
|
108
109
|
export function setData( model, data, options = {} ) {
|
|
@@ -128,7 +129,7 @@ export function setData( model, data, options = {} ) {
|
|
|
128
129
|
modelDocumentFragment = parsedResult;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
if (
|
|
132
|
+
if ( options.batchType !== undefined ) {
|
|
132
133
|
model.enqueueChange( options.batchType, writeToModel );
|
|
133
134
|
} else {
|
|
134
135
|
model.change( writeToModel );
|
|
@@ -233,6 +234,7 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu
|
|
|
233
234
|
mapper.bindElements( node.root, viewRoot );
|
|
234
235
|
|
|
235
236
|
downcastDispatcher.on( 'insert:$text', insertText() );
|
|
237
|
+
downcastDispatcher.on( 'insert', insertAttributesAndChildren(), { priority: 'lowest' } );
|
|
236
238
|
downcastDispatcher.on( 'attribute', ( evt, data, conversionApi ) => {
|
|
237
239
|
if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection || data.item.is( '$textProxy' ) ) {
|
|
238
240
|
const converter = wrap( ( modelAttributeValue, { writer } ) => {
|
|
@@ -260,28 +262,28 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu
|
|
|
260
262
|
return writer.createUIElement( name );
|
|
261
263
|
} ) );
|
|
262
264
|
|
|
265
|
+
const markersMap = new Map();
|
|
266
|
+
|
|
267
|
+
if ( markers ) {
|
|
268
|
+
// To provide stable results, sort markers by name.
|
|
269
|
+
for ( const marker of Array.from( markers ).sort( ( a, b ) => a.name < b.name ? 1 : -1 ) ) {
|
|
270
|
+
markersMap.set( marker.name, marker.getRange() );
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
263
274
|
// Convert model to view.
|
|
264
275
|
const writer = view._writer;
|
|
265
|
-
downcastDispatcher.
|
|
276
|
+
downcastDispatcher.convert( range, markersMap, writer );
|
|
266
277
|
|
|
267
278
|
// Convert model selection to view selection.
|
|
268
279
|
if ( selection ) {
|
|
269
280
|
downcastDispatcher.convertSelection( selection, markers || model.markers, writer );
|
|
270
281
|
}
|
|
271
282
|
|
|
272
|
-
if ( markers ) {
|
|
273
|
-
// To provide stable results, sort markers by name.
|
|
274
|
-
markers = Array.from( markers ).sort( ( a, b ) => a.name < b.name ? 1 : -1 );
|
|
275
|
-
|
|
276
|
-
for ( const marker of markers ) {
|
|
277
|
-
downcastDispatcher.convertMarkerAdd( marker.name, marker.getRange(), writer );
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
283
|
// Parse view to data string.
|
|
282
284
|
let data = viewStringify( viewRoot, viewDocument.selection, { sameSelectionCharacters: true } );
|
|
283
285
|
|
|
284
|
-
// Removing
|
|
286
|
+
// Removing unnecessary <div> and </div> added because `viewRoot` was also stringified alongside input data.
|
|
285
287
|
data = data.substr( 5, data.length - 11 );
|
|
286
288
|
|
|
287
289
|
view.destroy();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
package/src/dev-utils/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
package/src/dev-utils/view.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -67,8 +67,8 @@ const domConverterStub = {
|
|
|
67
67
|
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
|
|
68
68
|
* {@link module:engine/view/rawelement~RawElement} will be printed.
|
|
69
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,
|
|
71
|
-
* filtering. Otherwise the simple stub is used.
|
|
70
|
+
* instance, it lets the conversion go through exactly the same flow the editing view is going through,
|
|
71
|
+
* i.e. with view data filtering. Otherwise the simple stub is used.
|
|
72
72
|
* @returns {String} The stringified data.
|
|
73
73
|
*/
|
|
74
74
|
export function getData( view, options = {} ) {
|
|
@@ -253,8 +253,8 @@ setData._parse = parse;
|
|
|
253
253
|
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
|
|
254
254
|
* {@link module:engine/view/rawelement~RawElement} will be printed.
|
|
255
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,
|
|
257
|
-
* filtering. Otherwise the simple stub is used.
|
|
256
|
+
* instance, it lets the conversion go through exactly the same flow the editing view is going through,
|
|
257
|
+
* i.e. with view data filtering. Otherwise the simple stub is used.
|
|
258
258
|
* @returns {String} An HTML-like string representing the view.
|
|
259
259
|
*/
|
|
260
260
|
export function stringify( node, selectionOrPositionOrRange = null, options = {} ) {
|
|
@@ -645,8 +645,8 @@ class ViewStringify {
|
|
|
645
645
|
* {@link module:engine/view/uielement~UIElement} will be printed.
|
|
646
646
|
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
|
|
647
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,
|
|
649
|
-
* filtering. Otherwise the simple stub is used.
|
|
648
|
+
* instance, it lets the conversion go through exactly the same flow the editing view is going through,
|
|
649
|
+
* i.e. with view data filtering. Otherwise the simple stub is used.
|
|
650
650
|
* {@link module:engine/view/rawelement~RawElement} will be printed.
|
|
651
651
|
*/
|
|
652
652
|
constructor( root, selection, options ) {
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -28,6 +28,7 @@ export { default as LivePosition } from './model/liveposition';
|
|
|
28
28
|
export { default as Model } from './model/model';
|
|
29
29
|
export { default as TreeWalker } from './model/treewalker';
|
|
30
30
|
export { default as Element } from './model/element';
|
|
31
|
+
export { default as History } from './model/history';
|
|
31
32
|
|
|
32
33
|
export { default as DomConverter } from './view/domconverter';
|
|
33
34
|
export { default as Renderer } from './view/renderer';
|
package/src/model/batch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* @module engine/model/batch
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* A batch instance groups model changes ({@link module:engine/model/operation/operation~Operation operations}). All operations
|
|
12
14
|
* grouped in a single batch can be reverted together, so you can also think about a batch as of a single undo step. If you want
|
|
@@ -25,9 +27,30 @@ export default class Batch {
|
|
|
25
27
|
*
|
|
26
28
|
* @see module:engine/model/model~Model#enqueueChange
|
|
27
29
|
* @see module:engine/model/model~Model#change
|
|
28
|
-
* @param {
|
|
30
|
+
* @param {Object} [type] A set of flags that specify the type of the batch. Batch type can alter how some of the features work
|
|
31
|
+
* when encountering a given `Batch` instance (for example, when a feature listens to applied operations).
|
|
32
|
+
* @param {Boolean} [type.isUndoable=true] Whether a batch can be undone through undo feature.
|
|
33
|
+
* @param {Boolean} [type.isLocal=true] Whether a batch includes operations created locally (`true`) or operations created on
|
|
34
|
+
* other, remote editors (`false`).
|
|
35
|
+
* @param {Boolean} [type.isUndo=false] Whether a batch was created by the undo feature and undoes other operations.
|
|
36
|
+
* @param {Boolean} [type.isTyping=false] Whether a batch includes operations connected with a typing action.
|
|
29
37
|
*/
|
|
30
|
-
constructor( type =
|
|
38
|
+
constructor( type = {} ) {
|
|
39
|
+
if ( typeof type === 'string' ) {
|
|
40
|
+
type = type === 'transparent' ? { isUndoable: false } : {};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The string value for a `type` property of the `Batch` constructor has been deprecated and will be removed in the near future.
|
|
44
|
+
* Please refer to the {@link module:engine/model/batch~Batch#constructor `Batch` constructor API documentation} for more
|
|
45
|
+
* information.
|
|
46
|
+
*
|
|
47
|
+
* @error batch-constructor-deprecated-string-type
|
|
48
|
+
*/
|
|
49
|
+
logWarning( 'batch-constructor-deprecated-string-type' );
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { isUndoable = true, isLocal = true, isUndo = false, isTyping = false } = type;
|
|
53
|
+
|
|
31
54
|
/**
|
|
32
55
|
* An array of operations that compose this batch.
|
|
33
56
|
*
|
|
@@ -37,17 +60,61 @@ export default class Batch {
|
|
|
37
60
|
this.operations = [];
|
|
38
61
|
|
|
39
62
|
/**
|
|
40
|
-
*
|
|
63
|
+
* Whether the batch can be undone through the undo feature.
|
|
64
|
+
*
|
|
65
|
+
* @readonly
|
|
66
|
+
* @type {Boolean}
|
|
67
|
+
*/
|
|
68
|
+
this.isUndoable = isUndoable;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Whether the batch includes operations created locally (`true`) or operations created on other, remote editors (`false`).
|
|
72
|
+
*
|
|
73
|
+
* @readonly
|
|
74
|
+
* @type {Boolean}
|
|
75
|
+
*/
|
|
76
|
+
this.isLocal = isLocal;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Whether the batch was created by the undo feature and undoes other operations.
|
|
41
80
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
81
|
+
* @readonly
|
|
82
|
+
* @type {Boolean}
|
|
83
|
+
*/
|
|
84
|
+
this.isUndo = isUndo;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether the batch includes operations connected with typing.
|
|
46
88
|
*
|
|
47
89
|
* @readonly
|
|
48
|
-
* @type {
|
|
90
|
+
* @type {Boolean}
|
|
49
91
|
*/
|
|
50
|
-
this.
|
|
92
|
+
this.isTyping = isTyping;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The type of the batch.
|
|
97
|
+
*
|
|
98
|
+
* **This property has been deprecated and is always set to the `'default'` value.**
|
|
99
|
+
*
|
|
100
|
+
* It can be one of the following values:
|
|
101
|
+
* * `'default'` – All "normal" batches. This is the most commonly used type.
|
|
102
|
+
* * `'transparent'` – A batch that should be ignored by other features, i.e. an initial batch or collaborative editing
|
|
103
|
+
* changes.
|
|
104
|
+
*
|
|
105
|
+
* @deprecated
|
|
106
|
+
* @type {'default'}
|
|
107
|
+
*/
|
|
108
|
+
get type() {
|
|
109
|
+
/**
|
|
110
|
+
* The {@link module:engine/model/batch~Batch#type `Batch#type` } property has been deprecated and will be removed in the near
|
|
111
|
+
* future. Use `Batch#isLocal`, `Batch#isUndoable`, `Batch#isUndo` and `Batch#isTyping` instead.
|
|
112
|
+
*
|
|
113
|
+
* @error batch-type-deprecated
|
|
114
|
+
*/
|
|
115
|
+
logWarning( 'batch-type-deprecated' );
|
|
116
|
+
|
|
117
|
+
return 'default';
|
|
51
118
|
}
|
|
52
119
|
|
|
53
120
|
/**
|
package/src/model/differ.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -58,11 +58,12 @@ export default class Differ {
|
|
|
58
58
|
* A map that stores all changed markers.
|
|
59
59
|
*
|
|
60
60
|
* The keys of the map are marker names.
|
|
61
|
-
* The values of the map are objects with the
|
|
62
|
-
*
|
|
61
|
+
* The values of the map are objects with the following properties:
|
|
62
|
+
* - `oldMarkerData`,
|
|
63
|
+
* - `newMarkerData`.
|
|
63
64
|
*
|
|
64
65
|
* @private
|
|
65
|
-
* @type {Map}
|
|
66
|
+
* @type {Map.<String, Object>}
|
|
66
67
|
*/
|
|
67
68
|
this._changedMarkers = new Map();
|
|
68
69
|
|
|
@@ -98,6 +99,14 @@ export default class Differ {
|
|
|
98
99
|
* @type {Array.<Object>|null}
|
|
99
100
|
*/
|
|
100
101
|
this._cachedChangesWithGraveyard = null;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Set of model items that were marked to get refreshed in {@link #_refreshItem}.
|
|
105
|
+
*
|
|
106
|
+
* @private
|
|
107
|
+
* @type {Set.<module:engine/model/item~Item>}
|
|
108
|
+
*/
|
|
109
|
+
this._refreshedItems = new Set();
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
/**
|
|
@@ -110,32 +119,6 @@ export default class Differ {
|
|
|
110
119
|
return this._changesInElement.size == 0 && this._changedMarkers.size == 0;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
|
-
/**
|
|
114
|
-
* Marks given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted in the differ changes
|
|
115
|
-
* set, so it will be effectively re-converted when differ changes will be handled by a dispatcher.
|
|
116
|
-
*
|
|
117
|
-
* @param {module:engine/model/item~Item} item Item to refresh.
|
|
118
|
-
*/
|
|
119
|
-
refreshItem( item ) {
|
|
120
|
-
if ( this._isInInsertedElement( item.parent ) ) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this._markRemove( item.parent, item.startOffset, item.offsetSize );
|
|
125
|
-
this._markInsert( item.parent, item.startOffset, item.offsetSize );
|
|
126
|
-
|
|
127
|
-
const range = Range._createOn( item );
|
|
128
|
-
|
|
129
|
-
for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
|
|
130
|
-
const markerRange = marker.getRange();
|
|
131
|
-
|
|
132
|
-
this.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Clear cache after each buffered operation as it is no longer valid.
|
|
136
|
-
this._cachedChanges = null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
122
|
/**
|
|
140
123
|
* Buffers the given operation. An operation has to be buffered before it is executed.
|
|
141
124
|
*
|
|
@@ -208,9 +191,9 @@ export default class Differ {
|
|
|
208
191
|
const range = Range._createFromPositionAndShift( operation.position, 1 );
|
|
209
192
|
|
|
210
193
|
for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
|
|
211
|
-
const
|
|
194
|
+
const markerData = marker.getData();
|
|
212
195
|
|
|
213
|
-
this.bufferMarkerChange( marker.name,
|
|
196
|
+
this.bufferMarkerChange( marker.name, markerData, markerData );
|
|
214
197
|
}
|
|
215
198
|
|
|
216
199
|
break;
|
|
@@ -267,27 +250,23 @@ export default class Differ {
|
|
|
267
250
|
* Buffers a marker change.
|
|
268
251
|
*
|
|
269
252
|
* @param {String} markerName The name of the marker that changed.
|
|
270
|
-
* @param {module:engine/model/
|
|
271
|
-
*
|
|
272
|
-
* @param {module:engine/model/range~Range|null} newRange Marker range after the change or `null` if the marker was removed.
|
|
273
|
-
* @param {Boolean} affectsData Flag indicating whether marker affects the editor data.
|
|
253
|
+
* @param {module:engine/model/markercollection~MarkerData} oldMarkerData Marker data before the change.
|
|
254
|
+
* @param {module:engine/model/markercollection~MarkerData} newMarkerData Marker data after the change.
|
|
274
255
|
*/
|
|
275
|
-
bufferMarkerChange( markerName,
|
|
256
|
+
bufferMarkerChange( markerName, oldMarkerData, newMarkerData ) {
|
|
276
257
|
const buffered = this._changedMarkers.get( markerName );
|
|
277
258
|
|
|
278
259
|
if ( !buffered ) {
|
|
279
260
|
this._changedMarkers.set( markerName, {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
affectsData
|
|
261
|
+
newMarkerData,
|
|
262
|
+
oldMarkerData
|
|
283
263
|
} );
|
|
284
264
|
} else {
|
|
285
|
-
buffered.
|
|
286
|
-
buffered.affectsData = affectsData;
|
|
265
|
+
buffered.newMarkerData = newMarkerData;
|
|
287
266
|
|
|
288
|
-
if ( buffered.
|
|
289
|
-
// The marker is going to be removed (`
|
|
290
|
-
// (`buffered.
|
|
267
|
+
if ( buffered.oldMarkerData.range == null && newMarkerData.range == null ) {
|
|
268
|
+
// The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change
|
|
269
|
+
// (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all.
|
|
291
270
|
this._changedMarkers.delete( markerName );
|
|
292
271
|
}
|
|
293
272
|
}
|
|
@@ -302,8 +281,8 @@ export default class Differ {
|
|
|
302
281
|
const result = [];
|
|
303
282
|
|
|
304
283
|
for ( const [ name, change ] of this._changedMarkers ) {
|
|
305
|
-
if ( change.
|
|
306
|
-
result.push( { name, range: change.
|
|
284
|
+
if ( change.oldMarkerData.range != null ) {
|
|
285
|
+
result.push( { name, range: change.oldMarkerData.range } );
|
|
307
286
|
}
|
|
308
287
|
}
|
|
309
288
|
|
|
@@ -319,8 +298,8 @@ export default class Differ {
|
|
|
319
298
|
const result = [];
|
|
320
299
|
|
|
321
300
|
for ( const [ name, change ] of this._changedMarkers ) {
|
|
322
|
-
if ( change.
|
|
323
|
-
result.push( { name, range: change.
|
|
301
|
+
if ( change.newMarkerData.range != null ) {
|
|
302
|
+
result.push( { name, range: change.newMarkerData.range } );
|
|
324
303
|
}
|
|
325
304
|
}
|
|
326
305
|
|
|
@@ -333,12 +312,12 @@ export default class Differ {
|
|
|
333
312
|
* @returns {Array.<Object>}
|
|
334
313
|
*/
|
|
335
314
|
getChangedMarkers() {
|
|
336
|
-
return Array.from( this._changedMarkers ).map(
|
|
315
|
+
return Array.from( this._changedMarkers ).map( ( [ name, change ] ) => (
|
|
337
316
|
{
|
|
338
|
-
name
|
|
317
|
+
name,
|
|
339
318
|
data: {
|
|
340
|
-
oldRange:
|
|
341
|
-
newRange:
|
|
319
|
+
oldRange: change.oldMarkerData.range,
|
|
320
|
+
newRange: change.newMarkerData.range
|
|
342
321
|
}
|
|
343
322
|
}
|
|
344
323
|
) );
|
|
@@ -351,13 +330,23 @@ export default class Differ {
|
|
|
351
330
|
*
|
|
352
331
|
* * model structure changes,
|
|
353
332
|
* * attribute changes,
|
|
354
|
-
* * changes of markers which were defined as `
|
|
333
|
+
* * changes of markers which were defined as `affectsData`,
|
|
334
|
+
* * changes of markers' `affectsData` property.
|
|
355
335
|
*
|
|
356
336
|
* @returns {Boolean}
|
|
357
337
|
*/
|
|
358
338
|
hasDataChanges() {
|
|
359
|
-
for ( const
|
|
360
|
-
if (
|
|
339
|
+
for ( const { newMarkerData, oldMarkerData } of this._changedMarkers.values() ) {
|
|
340
|
+
if ( newMarkerData.affectsData !== oldMarkerData.affectsData ) {
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if ( newMarkerData.affectsData ) {
|
|
345
|
+
// Skip markers, which ranges have not changed.
|
|
346
|
+
if ( newMarkerData.range && oldMarkerData.range && newMarkerData.range.isEqual( oldMarkerData.range ) ) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
|
|
361
350
|
return true;
|
|
362
351
|
}
|
|
363
352
|
}
|
|
@@ -540,16 +529,25 @@ export default class Differ {
|
|
|
540
529
|
this._changeCount = 0;
|
|
541
530
|
|
|
542
531
|
// Cache changes.
|
|
543
|
-
this._cachedChangesWithGraveyard = diffSet
|
|
532
|
+
this._cachedChangesWithGraveyard = diffSet;
|
|
544
533
|
this._cachedChanges = diffSet.filter( _changesInGraveyardFilter );
|
|
545
534
|
|
|
546
535
|
if ( options.includeChangesInGraveyard ) {
|
|
547
|
-
return this._cachedChangesWithGraveyard;
|
|
536
|
+
return this._cachedChangesWithGraveyard.slice();
|
|
548
537
|
} else {
|
|
549
|
-
return this._cachedChanges;
|
|
538
|
+
return this._cachedChanges.slice();
|
|
550
539
|
}
|
|
551
540
|
}
|
|
552
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Returns a set of model items that were marked to get refreshed.
|
|
544
|
+
*
|
|
545
|
+
* @return {Set.<module:engine/model/item~Item>}
|
|
546
|
+
*/
|
|
547
|
+
getRefreshedItems() {
|
|
548
|
+
return new Set( this._refreshedItems );
|
|
549
|
+
}
|
|
550
|
+
|
|
553
551
|
/**
|
|
554
552
|
* Resets `Differ`. Removes all buffered changes.
|
|
555
553
|
*/
|
|
@@ -557,6 +555,36 @@ export default class Differ {
|
|
|
557
555
|
this._changesInElement.clear();
|
|
558
556
|
this._elementSnapshots.clear();
|
|
559
557
|
this._changedMarkers.clear();
|
|
558
|
+
this._refreshedItems = new Set();
|
|
559
|
+
this._cachedChanges = null;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Marks the given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted
|
|
564
|
+
* in the differ changes set, so it will be effectively re-converted when the differ changes are handled by a dispatcher.
|
|
565
|
+
*
|
|
566
|
+
* @protected
|
|
567
|
+
* @param {module:engine/model/item~Item} item Item to refresh.
|
|
568
|
+
*/
|
|
569
|
+
_refreshItem( item ) {
|
|
570
|
+
if ( this._isInInsertedElement( item.parent ) ) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
this._markRemove( item.parent, item.startOffset, item.offsetSize );
|
|
575
|
+
this._markInsert( item.parent, item.startOffset, item.offsetSize );
|
|
576
|
+
|
|
577
|
+
this._refreshedItems.add( item );
|
|
578
|
+
|
|
579
|
+
const range = Range._createOn( item );
|
|
580
|
+
|
|
581
|
+
for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
|
|
582
|
+
const markerData = marker.getData();
|
|
583
|
+
|
|
584
|
+
this.bufferMarkerChange( marker.name, markerData, markerData );
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Clear cache after each buffered operation as it is no longer valid.
|
|
560
588
|
this._cachedChanges = null;
|
|
561
589
|
}
|
|
562
590
|
|
package/src/model/document.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -157,14 +157,23 @@ export default class Document {
|
|
|
157
157
|
// Buffer marker changes.
|
|
158
158
|
// This is not covered in buffering operations because markers may change outside of them (when they
|
|
159
159
|
// are modified using `model.markers` collection, not through `MarkerOperation`).
|
|
160
|
-
this.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange ) => {
|
|
160
|
+
this.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange, oldMarkerData ) => {
|
|
161
|
+
// Copy the `newRange` to the new marker data as during the marker removal the range is not updated.
|
|
162
|
+
const newMarkerData = { ...marker.getData(), range: newRange };
|
|
163
|
+
|
|
161
164
|
// Whenever marker is updated, buffer that change.
|
|
162
|
-
this.differ.bufferMarkerChange( marker.name,
|
|
165
|
+
this.differ.bufferMarkerChange( marker.name, oldMarkerData, newMarkerData );
|
|
163
166
|
|
|
164
167
|
if ( oldRange === null ) {
|
|
165
168
|
// If this is a new marker, add a listener that will buffer change whenever marker changes.
|
|
166
169
|
marker.on( 'change', ( evt, oldRange ) => {
|
|
167
|
-
|
|
170
|
+
const markerData = marker.getData();
|
|
171
|
+
|
|
172
|
+
this.differ.bufferMarkerChange(
|
|
173
|
+
marker.name,
|
|
174
|
+
{ ...markerData, range: oldRange },
|
|
175
|
+
markerData
|
|
176
|
+
);
|
|
168
177
|
} );
|
|
169
178
|
}
|
|
170
179
|
} );
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|