|
|
@@ -1,6 +1,6 @@
|
|
|
/**
|
|
|
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
|
|
- * For licensing, see LICENSE.md.
|
|
|
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
@@ -444,7 +444,8 @@ export default class DowncastWriter {
|
|
|
* @error view-writer-break-non-container-element
|
|
|
*/
|
|
|
throw new CKEditorError(
|
|
|
- 'view-writer-break-non-container-element: Trying to break an element which is not a container element.'
|
|
|
+ 'view-writer-break-non-container-element: Trying to break an element which is not a container element.',
|
|
|
+ this.document
|
|
|
);
|
|
|
}
|
|
|
|
|
|
@@ -454,7 +455,7 @@ export default class DowncastWriter {
|
|
|
*
|
|
|
* @error view-writer-break-root
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-break-root: Trying to break root element.' );
|
|
|
+ throw new CKEditorError( 'view-writer-break-root: Trying to break root element.', this.document );
|
|
|
}
|
|
|
|
|
|
if ( position.isAtStart ) {
|
|
|
@@ -577,7 +578,7 @@ export default class DowncastWriter {
|
|
|
* @error view-writer-merge-containers-invalid-position
|
|
|
*/
|
|
|
throw new CKEditorError( 'view-writer-merge-containers-invalid-position: ' +
|
|
|
- 'Element before and after given position cannot be merged.' );
|
|
|
+ 'Element before and after given position cannot be merged.', this.document );
|
|
|
}
|
|
|
|
|
|
const lastChild = prev.getChild( prev.childCount - 1 );
|
|
|
@@ -612,7 +613,7 @@ export default class DowncastWriter {
|
|
|
nodes = isIterable( nodes ) ? [ ...nodes ] : [ nodes ];
|
|
|
|
|
|
// Check if nodes to insert are instances of AttributeElements, ContainerElements, EmptyElements, UIElements or Text.
|
|
|
- validateNodesToInsert( nodes );
|
|
|
+ validateNodesToInsert( nodes, this.document );
|
|
|
|
|
|
const container = getParentContainer( position );
|
|
|
|
|
|
@@ -622,7 +623,7 @@ export default class DowncastWriter {
|
|
|
*
|
|
|
* @error view-writer-invalid-position-container
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-invalid-position-container' );
|
|
|
+ throw new CKEditorError( 'view-writer-invalid-position-container', this.document );
|
|
|
}
|
|
|
|
|
|
const insertionPosition = this._breakAttributes( position, true );
|
|
|
@@ -665,7 +666,7 @@ export default class DowncastWriter {
|
|
|
remove( rangeOrItem ) {
|
|
|
const range = rangeOrItem instanceof Range ? rangeOrItem : Range._createOn( rangeOrItem );
|
|
|
|
|
|
- validateRangeContainer( range );
|
|
|
+ validateRangeContainer( range, this.document );
|
|
|
|
|
|
// If range is collapsed - nothing to remove.
|
|
|
if ( range.isCollapsed ) {
|
|
|
@@ -705,7 +706,7 @@ export default class DowncastWriter {
|
|
|
* @param {module:engine/view/element~Element} element Element to remove.
|
|
|
*/
|
|
|
clear( range, element ) {
|
|
|
- validateRangeContainer( range );
|
|
|
+ validateRangeContainer( range, this.document );
|
|
|
|
|
|
// Create walker on given range.
|
|
|
// We walk backward because when we remove element during walk it modifies range end position.
|
|
|
@@ -809,10 +810,10 @@ export default class DowncastWriter {
|
|
|
*/
|
|
|
wrap( range, attribute ) {
|
|
|
if ( !( attribute instanceof AttributeElement ) ) {
|
|
|
- throw new CKEditorError( 'view-writer-wrap-invalid-attribute' );
|
|
|
+ throw new CKEditorError( 'view-writer-wrap-invalid-attribute', this.document );
|
|
|
}
|
|
|
|
|
|
- validateRangeContainer( range );
|
|
|
+ validateRangeContainer( range, this.document );
|
|
|
|
|
|
if ( !range.isCollapsed ) {
|
|
|
// Non-collapsed range. Wrap it with the attribute element.
|
|
|
@@ -854,10 +855,10 @@ export default class DowncastWriter {
|
|
|
*
|
|
|
* @error view-writer-unwrap-invalid-attribute
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-unwrap-invalid-attribute' );
|
|
|
+ throw new CKEditorError( 'view-writer-unwrap-invalid-attribute', this.document );
|
|
|
}
|
|
|
|
|
|
- validateRangeContainer( range );
|
|
|
+ validateRangeContainer( range, this.document );
|
|
|
|
|
|
// If range is collapsed - nothing to unwrap.
|
|
|
if ( range.isCollapsed ) {
|
|
|
@@ -1093,7 +1094,7 @@ export default class DowncastWriter {
|
|
|
// <p><span class="bar">abc</span></p> --> <p><span class="foo bar">abc</span></p>
|
|
|
//
|
|
|
if ( isAttribute && this._wrapAttributeElement( wrapElement, child ) ) {
|
|
|
- wrapPositions.push( new Position( parent, i ) );
|
|
|
+ wrapPositions.push( new Position( parent, i ) );
|
|
|
}
|
|
|
//
|
|
|
// Wrap the child if it is not an attribute element or if it is an attribute element that should be inside
|
|
|
@@ -1113,7 +1114,7 @@ export default class DowncastWriter {
|
|
|
parent._insertChild( i, newAttribute );
|
|
|
this._addToClonedElementsGroup( newAttribute );
|
|
|
|
|
|
- wrapPositions.push( new Position( parent, i ) );
|
|
|
+ wrapPositions.push( new Position( parent, i ) );
|
|
|
}
|
|
|
//
|
|
|
// If other nested attribute is found and it wasn't wrapped (see above), continue wrapping inside it.
|
|
|
@@ -1489,7 +1490,7 @@ export default class DowncastWriter {
|
|
|
const rangeStart = range.start;
|
|
|
const rangeEnd = range.end;
|
|
|
|
|
|
- validateRangeContainer( range );
|
|
|
+ validateRangeContainer( range, this.document );
|
|
|
|
|
|
// Break at the collapsed position. Return new collapsed range.
|
|
|
if ( range.isCollapsed ) {
|
|
|
@@ -1534,7 +1535,7 @@ export default class DowncastWriter {
|
|
|
*
|
|
|
* @error view-writer-cannot-break-empty-element
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-cannot-break-empty-element' );
|
|
|
+ throw new CKEditorError( 'view-writer-cannot-break-empty-element', this.document );
|
|
|
}
|
|
|
|
|
|
// If position is placed inside UIElement - throw an exception as we cannot break inside.
|
|
|
@@ -1544,7 +1545,7 @@ export default class DowncastWriter {
|
|
|
*
|
|
|
* @error view-writer-cannot-break-ui-element
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-cannot-break-ui-element' );
|
|
|
+ throw new CKEditorError( 'view-writer-cannot-break-ui-element', this.document );
|
|
|
}
|
|
|
|
|
|
// There are no attributes to break and text nodes breaking is not forced.
|
|
|
@@ -1571,40 +1572,41 @@ export default class DowncastWriter {
|
|
|
const newPosition = new Position( positionParent.parent, positionParent.index + 1 );
|
|
|
|
|
|
return this._breakAttributes( newPosition, forceSplitText );
|
|
|
- } else
|
|
|
- // <p>foo<b><u>{}bar</u></b></p>
|
|
|
- // <p>foo<b>[]<u>bar</u></b></p>
|
|
|
- // <p>foo{}<b><u>bar</u></b></p>
|
|
|
- if ( positionOffset === 0 ) {
|
|
|
- const newPosition = new Position( positionParent.parent, positionParent.index );
|
|
|
+ } else {
|
|
|
+ // <p>foo<b><u>{}bar</u></b></p>
|
|
|
+ // <p>foo<b>[]<u>bar</u></b></p>
|
|
|
+ // <p>foo{}<b><u>bar</u></b></p>
|
|
|
+ if ( positionOffset === 0 ) {
|
|
|
+ const newPosition = new Position( positionParent.parent, positionParent.index );
|
|
|
|
|
|
- return this._breakAttributes( newPosition, forceSplitText );
|
|
|
- }
|
|
|
- // <p>foo<b><u>b{}ar</u></b></p>
|
|
|
- // <p>foo<b><u>b[]ar</u></b></p>
|
|
|
- // <p>foo<b><u>b</u>[]<u>ar</u></b></p>
|
|
|
- // <p>foo<b><u>b</u></b>[]<b><u>ar</u></b></p>
|
|
|
- else {
|
|
|
- const offsetAfter = positionParent.index + 1;
|
|
|
+ return this._breakAttributes( newPosition, forceSplitText );
|
|
|
+ }
|
|
|
+ // <p>foo<b><u>b{}ar</u></b></p>
|
|
|
+ // <p>foo<b><u>b[]ar</u></b></p>
|
|
|
+ // <p>foo<b><u>b</u>[]<u>ar</u></b></p>
|
|
|
+ // <p>foo<b><u>b</u></b>[]<b><u>ar</u></b></p>
|
|
|
+ else {
|
|
|
+ const offsetAfter = positionParent.index + 1;
|
|
|
|
|
|
- // Break element.
|
|
|
- const clonedNode = positionParent._clone();
|
|
|
+ // Break element.
|
|
|
+ const clonedNode = positionParent._clone();
|
|
|
|
|
|
- // Insert cloned node to position's parent node.
|
|
|
- positionParent.parent._insertChild( offsetAfter, clonedNode );
|
|
|
- this._addToClonedElementsGroup( clonedNode );
|
|
|
+ // Insert cloned node to position's parent node.
|
|
|
+ positionParent.parent._insertChild( offsetAfter, clonedNode );
|
|
|
+ this._addToClonedElementsGroup( clonedNode );
|
|
|
|
|
|
- // Get nodes to move.
|
|
|
- const count = positionParent.childCount - positionOffset;
|
|
|
- const nodesToMove = positionParent._removeChildren( positionOffset, count );
|
|
|
+ // Get nodes to move.
|
|
|
+ const count = positionParent.childCount - positionOffset;
|
|
|
+ const nodesToMove = positionParent._removeChildren( positionOffset, count );
|
|
|
|
|
|
- // Move nodes to cloned node.
|
|
|
- clonedNode._appendChild( nodesToMove );
|
|
|
+ // Move nodes to cloned node.
|
|
|
+ clonedNode._appendChild( nodesToMove );
|
|
|
|
|
|
- // Create new position to work on.
|
|
|
- const newPosition = new Position( positionParent.parent, offsetAfter );
|
|
|
+ // Create new position to work on.
|
|
|
+ const newPosition = new Position( positionParent.parent, offsetAfter );
|
|
|
|
|
|
- return this._breakAttributes( newPosition, forceSplitText );
|
|
|
+ return this._breakAttributes( newPosition, forceSplitText );
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1825,7 +1827,8 @@ function mergeTextNodes( t1, t2 ) {
|
|
|
//
|
|
|
// @param Iterable.<module:engine/view/text~Text|module:engine/view/attributeelement~AttributeElement
|
|
|
// |module:engine/view/containerelement~ContainerElement> nodes
|
|
|
-function validateNodesToInsert( nodes ) {
|
|
|
+// @param {Object} errorContext
|
|
|
+function validateNodesToInsert( nodes, errorContext ) {
|
|
|
for ( const node of nodes ) {
|
|
|
if ( !validNodesToInsert.some( ( validNode => node instanceof validNode ) ) ) { // eslint-disable-line no-use-before-define
|
|
|
/**
|
|
|
@@ -1836,11 +1839,11 @@ function validateNodesToInsert( nodes ) {
|
|
|
*
|
|
|
* @error view-writer-insert-invalid-node
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-insert-invalid-node' );
|
|
|
+ throw new CKEditorError( 'view-writer-insert-invalid-node', errorContext );
|
|
|
}
|
|
|
|
|
|
if ( !node.is( 'text' ) ) {
|
|
|
- validateNodesToInsert( node.getChildren() );
|
|
|
+ validateNodesToInsert( node.getChildren(), errorContext );
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -1860,7 +1863,8 @@ function isContainerOrFragment( node ) {
|
|
|
// Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when validation fails.
|
|
|
//
|
|
|
// @param {module:engine/view/range~Range} range
|
|
|
-function validateRangeContainer( range ) {
|
|
|
+// @param {Object} errorContext
|
|
|
+function validateRangeContainer( range, errorContext ) {
|
|
|
const startContainer = getParentContainer( range.start );
|
|
|
const endContainer = getParentContainer( range.end );
|
|
|
|
|
|
@@ -1872,7 +1876,8 @@ function validateRangeContainer( range ) {
|
|
|
*
|
|
|
* @error view-writer-invalid-range-container
|
|
|
*/
|
|
|
- throw new CKEditorError( 'view-writer-invalid-range-container' );
|
|
|
+
|
|
|
+ throw new CKEditorError( 'view-writer-invalid-range-container', errorContext );
|
|
|
}
|
|
|
}
|
|
|
|