/** * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md. */ /* bender-tags: treeview */ 'use strict'; import Writer from '/ckeditor5/engine/treeview/writer.js'; import ContainerElement from '/ckeditor5/engine/treeview/containerelement.js'; import AttributeElement from '/ckeditor5/engine/treeview/attributeelement.js'; import Position from '/ckeditor5/engine/treeview/position.js'; import Range from '/ckeditor5/engine/treeview/range.js'; import Text from '/ckeditor5/engine/treeview/text.js'; import utils from '/tests/engine/treeview/writer/_utils/utils.js'; import CKEditorError from '/ckeditor5/utils/ckeditorerror.js'; describe( 'Writer', () => { const create = utils.create; const test = utils.test; let writer; beforeEach( () => { writer = new Writer(); } ); describe( 'unwrap', () => { it( 'should do nothing on collapsed ranges', () => { const description = { instanceOf: ContainerElement, name: 'p', children: [ { instanceOf: Text, data: 'foo', rangeStart: 1, rangeEnd: 1 } ] }; const created = create( writer, description ); const newRange = writer.unwrap( created.range, new ContainerElement( 'b' ), 1 ); test( writer, newRange, created.node, description ); } ); it( 'should do nothing on single text node', () => { //

[{foobar}]

const description = { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: Text, data: 'foobar' } ] }; const created = create( writer, description ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, description ); } ); it( 'should throw error when range placed in two containers', () => { const container1 = new ContainerElement( 'p' ); const container2 = new ContainerElement( 'p' ); const range = new Range( new Position( container1, 0 ), new Position( container2, 1 ) ); const b = new ContainerElement( 'b' ); expect( () => { writer.unwrap( range, b, 1 ); } ).to.throw( CKEditorError, 'treeview-writer-invalid-range-container' ); } ); it( 'should unwrap single node', () => { //

[{foobar}]

->

[{foobar}]

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ); } ); it( 'should not unwrap attributes with different priorities #1', () => { //

[{foobar}]

->

[{foobar}]

// Unwrapped with but using different priority. const description = { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ] }; const created = create( writer, description ); const b = new ContainerElement( 'b' ); b.priority = 2; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, description ); } ); it( 'should not unwrap attributes with different priorities #2', () => { //

[{foo}{bar}{baz}]

->

[{foo}bar{baz}]

// around `bar` has different priority than others. const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'baz' } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 2; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: Text, data: 'baz' } ] } ); } ); it( 'should unwrap part of the node', () => { //

[{baz}{foo]bar}

->

[{bazfoo}]{bar}

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, children: [ { instanceOf: Text, data: 'baz' }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'foobar', rangeEnd: 3 } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: Text, data: 'bazfoo' }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] } ] } ); } ); it( 'should unwrap nested attributes', () => { //

[{foobar}]

->

[{foobar}]

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ); } ); it( 'should merge unwrapped nodes #1', () => { //

{foo}[{bar}]{bom}

->

{foo[bar]bom}

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 1, rangeEnd: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: Text, data: 'bom' } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', children: [ { instanceOf: Text, data: 'foobarbom', rangeStart: 3, rangeEnd: 6 } ] } ); } ); it( 'should merge unwrapped nodes #2', () => { //

{foo}{bar}[{bazqux}]

->

{foo}{bar[bazqux}]

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 2, rangeEnd: 3, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bazqux' } ] } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeEnd: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'barbazqux', rangeStart: 3 } ] } ] } ); } ); it( 'should merge unwrapped nodes #3', () => { //

{foo}{bar}[{baz]qux}

->

{foo}{bar[baz}]{qux}

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bazqux', rangeEnd: 3 } ] } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeEnd: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'barbaz', rangeStart: 3 } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'qux' } ] } ] } ] } ); } ); it( 'should merge unwrapped nodes #4', () => { //

{foo}{bar}[{baz}]qux

->

{foo}{bar[baz]qux}

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 2, rangeEnd: 3, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'baz' } ] } ] }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'qux' } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'barbazqux', rangeStart: 3, rangeEnd: 6 } ] } ] } ); } ); it( 'should merge unwrapped nodes #5', () => { //

[{foo}{bar}{baz}]

->

[{foobarbaz}]

const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'foo' } ] } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] } ] }, { instanceOf: AttributeElement, name: 'b', priority: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'baz' } ] } ] } ] } ); const b = new ContainerElement( 'b' ); b.priority = 1; const newRange = writer.unwrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'foobarbaz' } ] } ] } ); } ); it( 'should unwrap mixed ranges #1', () => { //

[{foo}]

->

[{foo}]

{ //

[{foo]}

->

[{foo}]