Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 440dfc7

Browse files
author
Piotr Jasiun
authored
Merge pull request #1196 from ckeditor/t/858
Other: Refactoring: make writer a protected operations util.
2 parents 98b984c + ebd9137 commit 440dfc7

18 files changed

+243
-251
lines changed

src/controller/datacontroller.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,11 @@ export default class DataController {
295295
*
296296
* @fires module:engine/controller/datacontroller~DataController#getSelectedContent
297297
* @param {module:engine/model/selection~Selection} selection The selection of which content will be retrieved.
298+
* @param {module:engine/model/batch~Batch} batch Batch to which deltas will be added.
298299
* @returns {module:engine/model/documentfragment~DocumentFragment} Document fragment holding the clone of the selected content.
299300
*/
300-
getSelectedContent( selection ) {
301-
return getSelectedContent( selection );
301+
getSelectedContent( selection, batch ) {
302+
return getSelectedContent( selection, batch );
302303
}
303304

304305
/**

src/controller/getselectedcontent.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@
77
* @module engine/controller/getselectedcontent
88
*/
99

10-
import DocumentFragment from '../model/documentfragment';
1110
import Range from '../model/range';
1211
import Position from '../model/position';
13-
import Text from '../model/text';
14-
import { remove } from '../model/writer';
1512

1613
/**
1714
* Gets a clone of the selected content.
@@ -25,10 +22,11 @@ import { remove } from '../model/writer';
2522
* <quote><h>st</h></quote><p>se</p>
2623
*
2724
* @param {module:engine/model/selection~Selection} selection The selection of which content will be returned.
25+
* @param {module:engine/model/batch~Batch} batch Batch to which deltas will be added.
2826
* @returns {module:engine/model/documentfragment~DocumentFragment}
2927
*/
30-
export default function getSelectedContent( selection ) {
31-
const frag = new DocumentFragment();
28+
export default function getSelectedContent( selection, batch ) {
29+
const frag = batch.createDocumentFragment();
3230
const range = selection.getFirstRange();
3331

3432
if ( !range || range.isCollapsed ) {
@@ -69,9 +67,9 @@ export default function getSelectedContent( selection ) {
6967
// Clone the whole contents.
7068
for ( const item of flatSubtreeRange.getItems( { shallow: true } ) ) {
7169
if ( item.is( 'textProxy' ) ) {
72-
frag.appendChildren( new Text( item.data, item.getAttributes() ) );
70+
batch.appendText( item.data, item.getAttributes(), frag );
7371
} else {
74-
frag.appendChildren( item.clone( true ) );
72+
batch.append( item.clone( true ), frag );
7573
}
7674
}
7775

@@ -97,16 +95,16 @@ export default function getSelectedContent( selection ) {
9795
const leftExcessRange = new Range( Position.createAt( frag ), newRange.start );
9896
const rightExcessRange = new Range( newRange.end, Position.createAt( frag, 'end' ) );
9997

100-
removeRangeContent( rightExcessRange );
101-
removeRangeContent( leftExcessRange );
98+
removeRangeContent( rightExcessRange, batch );
99+
removeRangeContent( leftExcessRange, batch );
102100
}
103101

104102
return frag;
105103
}
106104

107105
// After https://github.com/ckeditor/ckeditor5-engine/issues/690 is fixed,
108106
// this function will, most likely, be able to rewritten using getMinimalFlatRanges().
109-
function removeRangeContent( range ) {
107+
function removeRangeContent( range, batch ) {
110108
const parentsToCheck = [];
111109

112110
Array.from( range.getItems( { direction: 'backward' } ) )
@@ -128,7 +126,7 @@ function removeRangeContent( range ) {
128126
.forEach( itemRange => {
129127
parentsToCheck.push( itemRange.start.parent );
130128

131-
remove( itemRange );
129+
batch.remove( itemRange );
132130
} );
133131

134132
// Remove ancestors of the removed items if they turned to be empty now
@@ -141,7 +139,7 @@ function removeRangeContent( range ) {
141139

142140
parent = parent.parent;
143141

144-
remove( removeRange );
142+
batch.remove( removeRange );
145143
}
146144
} );
147145
}

src/dev-utils/model.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import ModelSelection from '../model/selection';
2020
import ModelDocumentFragment from '../model/documentfragment';
2121
import ModelElement from '../model/element';
2222
import ModelText from '../model/text';
23-
import modelWriter from '../model/writer';
2423

2524
import ViewConversionDispatcher from '../conversion/viewconversiondispatcher';
2625
import ViewSelection from '../view/selection';
@@ -324,9 +323,7 @@ export function parse( data, schema, batch, options = {} ) {
324323

325324
function convertToModelFragment() {
326325
return ( evt, data, consumable, conversionApi ) => {
327-
const convertedChildren = conversionApi.convertChildren( data.input, consumable, data );
328-
329-
data.output = new ModelDocumentFragment( modelWriter.normalizeNodes( convertedChildren ) );
326+
data.output = conversionApi.convertChildren( data.input, consumable, data );
330327
conversionApi.mapper.bindElements( data.output, data.input );
331328

332329
evt.stop();

src/model/operation/attributeoperation.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import Operation from './operation';
1111
import Range from '../range';
1212
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
13-
import writer from '../writer';
13+
import { _setAttribute } from './utils';
1414
import isEqual from '@ckeditor/ckeditor5-utils/src/lib/lodash/isEqual';
1515

1616
/**
@@ -151,7 +151,7 @@ export default class AttributeOperation extends Operation {
151151
// If value to set is same as old value, don't do anything.
152152
if ( !isEqual( this.oldValue, this.newValue ) ) {
153153
// Execution.
154-
writer.setAttribute( this.range, this.key, this.newValue );
154+
_setAttribute( this.range, this.key, this.newValue );
155155
}
156156

157157
return { range: this.range, key: this.key, oldValue: this.oldValue, newValue: this.newValue };

src/model/operation/detachoperation.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import Operation from './operation';
1111
import Position from '../position';
1212
import Range from '../range';
13-
import { remove } from '../writer';
13+
import { _remove } from './utils';
1414
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
1515

1616
/**
@@ -73,7 +73,7 @@ export default class DetachOperation extends Operation {
7373
throw new CKEditorError( 'detach-operation-on-document-node: Cannot detach document node.' );
7474
}
7575

76-
const nodes = remove( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ) );
76+
const nodes = _remove( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ) );
7777

7878
return { nodes };
7979
}

src/model/operation/insertoperation.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Operation from './operation';
1111
import Position from '../position';
1212
import NodeList from '../nodelist';
1313
import RemoveOperation from './removeoperation';
14-
import { insert, normalizeNodes } from '../writer';
14+
import { _insert, _normalizeNodes } from './utils';
1515
import Text from '../text';
1616
import Element from '../element';
1717

@@ -45,7 +45,7 @@ export default class InsertOperation extends Operation {
4545
* @readonly
4646
* @member {module:engine/model/nodelist~NodeList} module:engine/model/operation/insertoperation~InsertOperation#nodeList
4747
*/
48-
this.nodes = new NodeList( normalizeNodes( nodes ) );
48+
this.nodes = new NodeList( _normalizeNodes( nodes ) );
4949

5050
/**
5151
* @inheritDoc
@@ -94,7 +94,7 @@ export default class InsertOperation extends Operation {
9494
const originalNodes = this.nodes;
9595
this.nodes = new NodeList( [ ...originalNodes ].map( node => node.clone( true ) ) );
9696

97-
const range = insert( this.position, originalNodes );
97+
const range = _insert( this.position, originalNodes );
9898

9999
return { range };
100100
}

src/model/operation/moveoperation.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Position from '../position';
1212
import Range from '../range';
1313
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
1414
import compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';
15-
import writer from './../writer';
15+
import { _move } from './utils';
1616

1717
/**
1818
* Operation to move a range of {@link module:engine/model/item~Item model items}
@@ -184,7 +184,7 @@ export default class MoveOperation extends Operation {
184184
}
185185
}
186186

187-
const range = writer.move( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition );
187+
const range = _move( Range.createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition );
188188

189189
return {
190190
sourcePosition: this.sourcePosition,

src/model/writer.js renamed to src/model/operation/utils.js

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,36 @@
44
*/
55

66
/**
7-
* @module engine/model/writer
7+
* @module engine/model/operation/utils
88
*/
99

10-
import Node from './node';
11-
import Text from './text';
12-
import TextProxy from './textproxy';
13-
import Range from './range';
14-
import DocumentFragment from './documentfragment';
15-
import NodeList from './nodelist';
10+
import Node from '../node';
11+
import Text from '../text';
12+
import TextProxy from '../textproxy';
13+
import Range from '../range';
14+
import DocumentFragment from '../documentfragment';
15+
import NodeList from '../nodelist';
1616
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
1717

1818
/**
19-
* Contains functions used for composing model tree, grouped together under "model writer" name. Those functions
20-
* are built on top of {@link module:engine/model/node~Node node}, and it's child classes', APIs.
19+
* Contains functions used for composing model tree by {@link module:engine/model/operation~Operation operations}.
20+
* Those functions are built on top of {@link module:engine/model/node~Node node}, and it's child classes', APIs.
2121
*
22-
* Model writer API has multiple advantages and it is highly recommended to use it when changing model tree and nodes:
23-
* * model writer API {@link module:engine/model/writer~writer.normalizeNodes normalizes inserted nodes}, which means that you can insert
24-
* not only {@link module:engine/model/node~Node nodes}, but also `String`s, {@link module:engine/model/textproxy~TextProxy text proxies}
25-
* and
26-
* {@link module:engine/model/documentfragment~DocumentFragment document fragments},
27-
* * model writer API operates on {@link module:engine/model/position~Position positions}, which means that you have
28-
* better control over manipulating model tree as positions operate on offsets rather than indexes,
29-
* * model writer API automatically merges {@link module:engine/model/text~Text text nodes} with same attributes, which means
30-
* lower memory usage and better efficiency.
31-
*
32-
* @namespace writer
22+
* @protected
23+
* @namespace utils
3324
*/
34-
const writer = {
35-
insert,
36-
remove,
37-
move,
38-
setAttribute,
39-
removeAttribute,
40-
normalizeNodes
41-
};
42-
43-
export default writer;
4425

4526
/**
4627
* Inserts given nodes at given position.
4728
*
48-
* @function module:engine/model/writer~writer.insert
29+
* @protected
30+
* @function module:engine/model/operation/utils~utils.insert
4931
* @param {module:engine/model/position~Position} position Position at which nodes should be inserted.
5032
* @param {module:engine/model/node~NodeSet} nodes Nodes to insert.
5133
* @returns {module:engine/model/range~Range} Range spanning over inserted elements.
5234
*/
53-
export function insert( position, nodes ) {
54-
nodes = normalizeNodes( nodes );
35+
export function _insert( position, nodes ) {
36+
nodes = _normalizeNodes( nodes );
5537

5638
// We have to count offset before inserting nodes because they can get merged and we would get wrong offsets.
5739
const offset = nodes.reduce( ( sum, node ) => sum + node.offsetSize, 0 );
@@ -75,18 +57,19 @@ export function insert( position, nodes ) {
7557
/**
7658
* Removed nodes in given range. Only {@link module:engine/model/range~Range#isFlat flat} ranges are accepted.
7759
*
78-
* @function module:engine/model/writer~writer.remove
60+
* @protected
61+
* @function module:engine/model/operation/utils~utils.remove
7962
* @param {module:engine/model/range~Range} range Range containing nodes to remove.
8063
* @returns {Array.<module:engine/model/node~Node>}
8164
*/
82-
export function remove( range ) {
65+
export function _remove( range ) {
8366
if ( !range.isFlat ) {
8467
/**
8568
* Trying to remove a range which starts and ends in different element.
8669
*
87-
* @error model-writer-remove-range-not-flat
70+
* @error operation-utils-remove-range-not-flat
8871
*/
89-
throw new CKEditorError( 'model-writer-remove-range-not-flat: ' +
72+
throw new CKEditorError( 'operation-utils-remove-range-not-flat: ' +
9073
'Trying to remove a range which starts and ends in different element.' );
9174
}
9275

@@ -109,38 +92,42 @@ export function remove( range ) {
10992
/**
11093
* Moves nodes in given range to given target position. Only {@link module:engine/model/range~Range#isFlat flat} ranges are accepted.
11194
*
95+
* @protected
96+
* @function module:engine/model/operation/utils~utils.move
11297
* @param {module:engine/model/range~Range} sourceRange Range containing nodes to move.
11398
* @param {module:engine/model/position~Position} targetPosition Position to which nodes should be moved.
11499
* @returns {module:engine/model/range~Range} Range containing moved nodes.
115100
*/
116-
export function move( sourceRange, targetPosition ) {
101+
export function _move( sourceRange, targetPosition ) {
117102
if ( !sourceRange.isFlat ) {
118103
/**
119104
* Trying to move a range which starts and ends in different element.
120105
*
121-
* @error model-writer-move-range-not-flat
106+
* @error operation-utils-move-range-not-flat
122107
*/
123-
throw new CKEditorError( 'model-writer-move-range-not-flat: ' +
108+
throw new CKEditorError( 'operation-utils-move-range-not-flat: ' +
124109
'Trying to move a range which starts and ends in different element.' );
125110
}
126111

127-
const nodes = this.remove( sourceRange );
112+
const nodes = _remove( sourceRange );
128113

129114
// We have to fix `targetPosition` because model changed after nodes from `sourceRange` got removed and
130115
// that change might have an impact on `targetPosition`.
131116
targetPosition = targetPosition._getTransformedByDeletion( sourceRange.start, sourceRange.end.offset - sourceRange.start.offset );
132117

133-
return this.insert( targetPosition, nodes );
118+
return _insert( targetPosition, nodes );
134119
}
135120

136121
/**
137122
* Sets given attribute on nodes in given range.
138123
*
124+
* @protected
125+
* @function module:engine/model/operation/utils~utils.setAttribute
139126
* @param {module:engine/model/range~Range} range Range containing nodes that should have the attribute set.
140127
* @param {String} key Key of attribute to set.
141128
* @param {*} value Attribute value.
142129
*/
143-
export function setAttribute( range, key, value ) {
130+
export function _setAttribute( range, key, value ) {
144131
// Range might start or end in text nodes, so we have to split them.
145132
_splitNodeAtPosition( range.start );
146133
_splitNodeAtPosition( range.end );
@@ -166,24 +153,16 @@ export function setAttribute( range, key, value ) {
166153
_mergeNodesAtIndex( range.end.parent, range.end.index );
167154
}
168155

169-
/**
170-
* Removes given attribute from nodes in given range.
171-
*
172-
* @param {module:engine/model/range~Range} range Range containing nodes that should have the attribute removed.
173-
* @param {String} key Key of attribute to remove.
174-
*/
175-
export function removeAttribute( range, key ) {
176-
this.setAttribute( range, key, null );
177-
}
178-
179156
/**
180157
* Normalizes given object or an array of objects to an array of {@link module:engine/model/node~Node nodes}. See
181158
* {@link module:engine/model/node~NodeSet NodeSet} for details on how normalization is performed.
182159
*
160+
* @protected
161+
* @function module:engine/model/operation/utils~utils.normalizeNodes
183162
* @param {module:engine/model/node~NodeSet} nodes Objects to normalize.
184163
* @returns {Array.<module:engine/model/node~Node>} Normalized nodes.
185164
*/
186-
export function normalizeNodes( nodes ) {
165+
export function _normalizeNodes( nodes ) {
187166
const normalized = [];
188167

189168
if ( !( nodes instanceof Array ) ) {

tests/controller/datacontroller.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ describe( 'DataController', () => {
433433

434434
data.on( 'getSelectedContent', spy );
435435

436-
data.getSelectedContent( sel );
436+
data.getSelectedContent( sel, modelDocument.batch() );
437437

438438
expect( spy.calledOnce ).to.be.true;
439439
} );
@@ -443,7 +443,7 @@ describe( 'DataController', () => {
443443

444444
setData( modelDocument, '<paragraph>fo[ob]ar</paragraph>' );
445445

446-
const content = data.getSelectedContent( modelDocument.selection );
446+
const content = data.getSelectedContent( modelDocument.selection, modelDocument.batch() );
447447

448448
expect( stringify( content ) ).to.equal( 'ob' );
449449
} );

0 commit comments

Comments
 (0)