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

Commit

Permalink
Merge pull request #1693 from ckeditor/cf/2435
Browse files Browse the repository at this point in the history
Feature: `Model#insertContent()` will return a range affected by the insertion.
In `Model#deleteContent()`, added `doNotAutoparagraph` flag to `options`.
`Position` and `LivePosition` static creators should handle `stickiness` param.
Closes #1689. Closes #1688.
  • Loading branch information
Piotr Jasiun committed Mar 7, 2019
2 parents d539b9d + 285634b commit f4e4644
Show file tree
Hide file tree
Showing 9 changed files with 685 additions and 164 deletions.
13 changes: 13 additions & 0 deletions src/model/liveposition.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export default class LivePosition extends Position {
* @method module:engine/model/liveposition~LivePosition._createAfter
* @see module:engine/model/position~Position._createAfter
* @param {module:engine/model/node~Node} node
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']
* @returns {module:engine/model/liveposition~LivePosition}
*/

Expand All @@ -97,6 +98,18 @@ export default class LivePosition extends Position {
* @method module:engine/model/liveposition~LivePosition._createBefore
* @see module:engine/model/position~Position._createBefore
* @param {module:engine/model/node~Node} node
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']
* @returns {module:engine/model/liveposition~LivePosition}
*/

/**
* @static
* @protected
* @method module:engine/model/liveposition~LivePosition._createAt
* @see module:engine/model/position~Position._createAt
* @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition
* @param {Number|'end'|'before'|'after'} [offset]
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']
* @returns {module:engine/model/liveposition~LivePosition}
*/

Expand Down
17 changes: 16 additions & 1 deletion src/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,12 @@ export default class Model {
* The selection into which the content should be inserted. If not provided the current model document selection will be used.
* @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] To be used when a model item was passed as `selectable`.
* This param defines a position in relation to that item.
* @returns {module:engine/model/range~Range} Range which contains all the performed changes. This is a range that, if removed,
* would return the model to the state before the insertion. If no changes were preformed by `insertContent`, returns a range collapsed
* at the insertion position.
*/
insertContent( content, selectable, placeOrOffset ) {
insertContent( this, content, selectable, placeOrOffset );
return insertContent( this, content, selectable, placeOrOffset );
}

/**
Expand Down Expand Up @@ -373,6 +376,18 @@ export default class Model {
*
* * `<paragraph>^</paragraph>` with the option disabled (`doNotResetEntireContent == false`)
* * `<heading1>^</heading1>` with enabled (`doNotResetEntireContent == true`)
*
* @param {Boolean} [options.doNotAutoparagraph=false] Whether to create a paragraph if after content deletion selection is moved
* to a place where text cannot be inserted.
*
* For example `<paragraph>x</paragraph>[<image src="foo.jpg"></image>]` will become:
*
* * `<paragraph>x</paragraph><paragraph>[]</paragraph>` with the option disabled (`doNotAutoparagraph == false`)
* * `<paragraph>x[]</paragraph>` with the option enabled (`doNotAutoparagraph == true`).
*
* **Note:** if there is no valid position for the selection, the paragraph will always be created:
*
* `[<image src="foo.jpg"></image>]` -> `<paragraph>[]</paragraph>`.
*/
deleteContent( selection, options ) {
deleteContent( this, selection, options );
Expand Down
27 changes: 14 additions & 13 deletions src/model/position.js
Original file line number Diff line number Diff line change
Expand Up @@ -828,11 +828,13 @@ export default class Position {
* * {@link module:engine/model/position~Position._createAfter}.
*
* @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when the
* first parameter is a {@link module:engine/model/item~Item model item}.
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness. Used only when the
* first parameter is a {@link module:engine/model/item~Item model item}.
* @protected
*/
static _createAt( itemOrPosition, offset ) {
static _createAt( itemOrPosition, offset, stickiness = 'toNone' ) {
if ( itemOrPosition instanceof Position ) {
return new Position( itemOrPosition.root, itemOrPosition.path, itemOrPosition.stickiness );
} else {
Expand All @@ -841,9 +843,9 @@ export default class Position {
if ( offset == 'end' ) {
offset = node.maxOffset;
} else if ( offset == 'before' ) {
return this._createBefore( node );
return this._createBefore( node, stickiness );
} else if ( offset == 'after' ) {
return this._createAfter( node );
return this._createAfter( node, stickiness );
} else if ( offset !== 0 && !offset ) {
/**
* {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`}
Expand All @@ -869,18 +871,19 @@ export default class Position {

path.push( offset );

return new this( node.root, path );
return new this( node.root, path, stickiness );
}
}

/**
* Creates a new position, after given {@link module:engine/model/item~Item model item}.
*
* @param {module:engine/model/item~Item} item Item after which the position should be placed.
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.
* @returns {module:engine/model/position~Position}
* @protected
*/
static _createAfter( item ) {
static _createAfter( item, stickiness ) {
if ( !item.parent ) {
/**
* You can not make a position after a root element.
Expand All @@ -891,17 +894,18 @@ export default class Position {
throw new CKEditorError( 'model-position-after-root: You cannot make a position after root.', { root: item } );
}

return this._createAt( item.parent, item.endOffset );
return this._createAt( item.parent, item.endOffset, stickiness );
}

/**
* Creates a new position, before the given {@link module:engine/model/item~Item model item}.
*
* @param {module:engine/model/item~Item} item Item before which the position should be placed.
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.
* @returns {module:engine/model/position~Position}
* @protected
*/
static _createBefore( item ) {
static _createBefore( item, stickiness ) {
if ( !item.parent ) {
/**
* You can not make a position before a root element.
Expand All @@ -912,7 +916,7 @@ export default class Position {
throw new CKEditorError( 'model-position-before-root: You cannot make a position before root.', { root: item } );
}

return this._createAt( item.parent, item.startOffset );
return this._createAt( item.parent, item.startOffset, stickiness );
}

/**
Expand Down Expand Up @@ -943,10 +947,7 @@ export default class Position {
);
}

const pos = new Position( doc.getRoot( json.root ), json.path );
pos.stickiness = json.stickiness;

return pos;
return new Position( doc.getRoot( json.root ), json.path, json.stickiness );
}
}

Expand Down
48 changes: 35 additions & 13 deletions src/model/utils/deletecontent.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ import DocumentSelection from '../documentselection';
*
* * `<paragraph>^</paragraph>` with the option disabled (`doNotResetEntireContent == false`)
* * `<heading>^</heading>` with enabled (`doNotResetEntireContent == true`).
*
* @param {Boolean} [options.doNotAutoparagraph=false] Whether to create a paragraph if after content deletion selection is moved
* to a place where text cannot be inserted.
*
* For example `<paragraph>x</paragraph>[<image src="foo.jpg"></image>]` will become:
*
* * `<paragraph>x</paragraph><paragraph>[]</paragraph>` with the option disabled (`doNotAutoparagraph == false`)
* * `<paragraph>x[]</paragraph>` with the option enabled (`doNotAutoparagraph == true`).
*
* **Note:** if there is no valid position for the selection, the paragraph will always be created:
*
* `[<image src="foo.jpg"></image>]` -> `<paragraph>[]</paragraph>`.
*/
export default function deleteContent( model, selection, options = {} ) {
if ( selection.isCollapsed ) {
Expand Down Expand Up @@ -79,7 +91,7 @@ export default function deleteContent( model, selection, options = {} ) {
if ( !options.leaveUnmerged ) {
mergeBranches( writer, startPos, endPos );

// TMP this will be replaced with a postifxer.
// TMP this will be replaced with a postfixer.
// We need to check and strip disallowed attributes in all nested nodes because after merge
// some attributes could end up in a path where are disallowed.
//
Expand All @@ -88,16 +100,20 @@ export default function deleteContent( model, selection, options = {} ) {
schema.removeDisallowedAttributes( startPos.parent.getChildren(), writer );
}

if ( selection instanceof DocumentSelection ) {
writer.setSelection( startPos );
} else {
selection.setTo( startPos );
}
collapseSelectionAt( writer, selection, startPos );

// 4. Autoparagraphing.
// 4. Add a paragraph to set selection in it.
// Check if a text is allowed in the new container. If not, try to create a new paragraph (if it's allowed here).
if ( shouldAutoparagraph( schema, startPos ) ) {
insertParagraph( writer, startPos, selection );
// If auto-paragraphing is off, find the closest valid selection range and collapse the selection there.
// If there is no valid selection range, create paragraph anyway and set selection there.
const validSelectionRange = schema.getNearestSelectionRange( startPos );

if ( options.doNotAutoparagraph && validSelectionRange ) {
collapseSelectionAt( writer, selection, validSelectionRange );
} else {
insertParagraph( writer, startPos, selection );
}
}

endPos.detach();
Expand Down Expand Up @@ -195,11 +211,7 @@ function insertParagraph( writer, position, selection ) {

writer.insert( paragraph, position );

if ( selection instanceof DocumentSelection ) {
writer.setSelection( paragraph, 0 );
} else {
selection.setTo( paragraph, 0 );
}
collapseSelectionAt( writer, selection, writer.createPositionAt( paragraph, 0 ) );
}

function replaceEntireContentWithParagraph( writer, selection ) {
Expand Down Expand Up @@ -228,3 +240,13 @@ function shouldEntireContentBeReplacedWithParagraph( schema, selection ) {

return schema.checkChild( limitElement, 'paragraph' );
}

// Helper function that sets the selection. Depending whether given `selection` is a document selection or not,
// uses a different method to set it.
function collapseSelectionAt( writer, selection, positionOrRange ) {
if ( selection instanceof DocumentSelection ) {
writer.setSelection( positionOrRange );
} else {
selection.setTo( positionOrRange );
}
}
Loading

0 comments on commit f4e4644

Please sign in to comment.