/** * @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 Element from '/ckeditor5/engine/treeview/element.js'; import ContainerElement from '/ckeditor5/engine/treeview/containerelement.js'; import AttributeElement from '/ckeditor5/engine/treeview/attributeelement.js'; import { DEFAULT_PRIORITY } 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( 'wrap', () => { 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.wrap( created.range, new AttributeElement( 'b' ) ); test( writer, newRange, created.node, description ); } ); it( 'wraps single text node', () => { //
[{foobar}]
// wrap //[{foobar}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ); const b = new AttributeElement( 'b' ); const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ); } ); it( 'should throw error when element is not instance of AttributeElement', () => { const container = new ContainerElement( 'p', null, new Text( 'foo' ) ); const range = new Range( new Position( container, 0 ), new Position( container, 1 ) ); const b = new Element( 'b' ); expect( () => { writer.wrap( range, b ); } ).to.throw( CKEditorError, 'treeview-writer-wrap-invalid-attribute' ); } ); 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 AttributeElement( 'b' ); expect( () => { writer.wrap( range, b, 1 ); } ).to.throw( CKEditorError, 'treeview-writer-invalid-range-container' ); } ); it( 'wraps part of a single text node #1', () => { //[{foo]bar}
// wrap with //[{foo}]{bar}
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, children: [ { instanceOf: Text, data: 'foobar', rangeEnd: 3 } ] } ); const b = new AttributeElement( 'b' ); const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: Text, data: 'bar' } ] } ); } ); it( 'wraps part of a single text node #2', () => { //{[foo]bar}
// wrap with //[{foo}]{bar}
const created = create( writer, { instanceOf: ContainerElement, name: 'p', children: [ { instanceOf: Text, data: 'foobar', rangeStart: 0, rangeEnd: 3 } ] } ); const b = new AttributeElement( 'b' ); const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: Text, data: 'bar' } ] } ); } ); it( 'wraps part of a single text node #3', () => { //{foo[bar]}
// wrap with //{foo}[{bar}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', children: [ { instanceOf: Text, data: 'foobar', rangeStart: 3, rangeEnd: 6 } ] } ); const b = new AttributeElement( 'b' ); const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 1, rangeEnd: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'bar' } ] } ] } ); } ); it( 'should not wrap inside nested containers', () => { //{baz}
]{baz}
][{foobar}]
// wrap with that has higher priority than //[{foobar}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'u', priority: 1, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ); const b = new AttributeElement( 'b' ); b.priority = 2; const newRange = writer.wrap( 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: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'foobar' } ] } ] } ] } ); } ); it( 'merges wrapped nodes #1', () => { //[{foo}{bar}{baz}]
// wrap with //[{foobarbaz}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: Text, data: 'bar' }, { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'baz' } ] } ] } ); const b = new AttributeElement( 'b' ); const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foobarbaz' } ] } ] } ); } ); it( 'merges wrapped nodes #2', () => { //{foo}[{bar]baz}
// wrap with //{foo[bar}]{baz}
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: Text, data: 'barbaz', rangeEnd: 3 } ] } ); const newRange = writer.wrap( created.range, new AttributeElement( 'b' ) ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foobar', rangeStart: 3 } ] }, { instanceOf: Text, data: 'baz' } ] } ); } ); it( 'merges wrapped nodes #3', () => { //{foobar}[{baz}]
// wrap with //{foobar[baz}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 1, rangeEnd: 2, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foobar' } ] }, { instanceOf: Text, data: 'baz', rangeEnd: 3 } ] } ); const newRange = writer.wrap( created.range, new AttributeElement( 'b' ) ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foobarbaz', rangeStart: 6 } ] } ] } ); } ); it( 'merges wrapped nodes #4', () => { //[{foo}{bar}]{baz}
// wrap with //[{foo}{bar}]{baz}
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 2, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'i', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: Text, data: 'baz' } ] } ); const newRange = writer.wrap( created.range, new AttributeElement( 'b' ) ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'i', priority: DEFAULT_PRIORITY, children: [ { instanceOf: Text, data: 'bar' } ] } ] }, { instanceOf: Text, data: 'baz' } ] } ); } ); it( 'merges wrapped nodes #5', () => { //[{foo}{bar}{baz}]
// wrap with , that has higher priority than //[{foo}{bar}{baz}]
const created = create( writer, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: Text, data: 'foo' }, { instanceOf: AttributeElement, name: 'i', priority: 1, children: [ { instanceOf: Text, data: 'bar' } ] }, { instanceOf: Text, data: 'baz' } ] } ); const b = new AttributeElement( 'b' ); b.priority = 2; const newRange = writer.wrap( created.range, b ); test( writer, newRange, created.node, { instanceOf: ContainerElement, name: 'p', rangeStart: 0, rangeEnd: 3, children: [ { instanceOf: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'foo' } ] }, { instanceOf: AttributeElement, name: 'i', priority: 1, children: [ { instanceOf: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'bar' } ] } ] }, { instanceOf: AttributeElement, name: 'b', priority: 2, children: [ { instanceOf: Text, data: 'baz' } ] } ] } ); } ); } ); } );