/** * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md. */ /* globals Range, DocumentFragment, HTMLElement, document, Text */ /* bender-tags: view, domconverter, browser-only */ import ViewText from '/ckeditor5/engine/view/text.js'; import ViewElement from '/ckeditor5/engine/view/element.js'; import ViewContainerElement from '/ckeditor5/engine/view/containerelement.js'; import ViewAttributeElement from '/ckeditor5/engine/view/attributeelement.js'; import DomConverter from '/ckeditor5/engine/view/domconverter.js'; import ViewDocumentFragment from '/ckeditor5/engine/view/documentfragment.js'; import { INLINE_FILLER, INLINE_FILLER_LENGTH, isBlockFiller } from '/ckeditor5/engine/view/filler.js'; import { parse } from '/ckeditor5/engine/dev-utils/view.js'; import createElement from '/ckeditor5/utils/dom/createelement.js'; describe( 'DomConverter', () => { let converter; before( () => { converter = new DomConverter(); } ); describe( 'viewToDom', () => { it( 'should create tree of DOM elements from view elements', () => { const viewImg = new ViewElement( 'img' ); const viewText = new ViewText( 'foo' ); const viewP = new ViewElement( 'p' ); viewP.setAttribute( 'class', 'foo' ); viewP.appendChildren( viewImg ); viewP.appendChildren( viewText ); const domImg = document.createElement( 'img' ); converter.bindElements( domImg, viewImg ); const domP = converter.viewToDom( viewP, document ); expect( domP ).to.be.an.instanceof( HTMLElement ); expect( domP.tagName ).to.equal( 'P' ); expect( domP.getAttribute( 'class' ) ).to.equal( 'foo' ); expect( domP.attributes.length ).to.equal( 1 ); expect( domP.childNodes.length ).to.equal( 2 ); expect( domP.childNodes[ 0 ].tagName ).to.equal( 'IMG' ); expect( domP.childNodes[ 1 ].data ).to.equal( 'foo' ); expect( converter.getCorrespondingView( domP ) ).not.to.equal( viewP ); expect( converter.getCorrespondingView( domP.childNodes[ 0 ] ) ).to.equal( viewImg ); } ); it( 'should create tree of DOM elements from view elements and bind elements', () => { const viewImg = new ViewElement( 'img' ); const viewText = new ViewText( 'foo' ); const viewP = new ViewElement( 'p' ); viewP.setAttribute( 'class', 'foo' ); viewP.appendChildren( viewImg ); viewP.appendChildren( viewText ); const domP = converter.viewToDom( viewP, document, { bind: true } ); expect( domP ).to.be.an.instanceof( HTMLElement ); expect( domP.tagName ).to.equal( 'P' ); expect( domP.getAttribute( 'class' ) ).to.equal( 'foo' ); expect( domP.attributes.length ).to.equal( 1 ); expect( domP.childNodes.length ).to.equal( 2 ); expect( domP.childNodes[ 0 ].tagName ).to.equal( 'IMG' ); expect( domP.childNodes[ 1 ].data ).to.equal( 'foo' ); expect( converter.getCorrespondingView( domP ) ).to.equal( viewP ); expect( converter.getCorrespondingView( domP.childNodes[ 0 ] ) ).to.equal( viewP.getChild( 0 ) ); } ); it( 'should support unicode', () => { const viewText = new ViewText( 'நிலைக்கு' ); const viewP = new ViewElement( 'p', null, viewText ); const domP = converter.viewToDom( viewP, document, { bind: true } ); expect( domP.childNodes.length ).to.equal( 1 ); expect( domP.childNodes[ 0 ].data ).to.equal( 'நிலைக்கு' ); expect( converter.getCorrespondingView( domP ) ).to.equal( viewP ); expect( converter.getCorrespondingView( domP.childNodes[ 0 ] ) ).to.equal( viewP.getChild( 0 ) ); } ); it( 'should create tree of DOM elements from view element without children', () => { const viewImg = new ViewElement( 'img' ); const viewText = new ViewText( 'foo' ); const viewP = new ViewElement( 'p' ); viewP.setAttribute( 'class', 'foo' ); viewP.appendChildren( viewImg ); viewP.appendChildren( viewText ); const domImg = document.createElement( 'img' ); converter.bindElements( domImg, viewImg ); const domP = converter.viewToDom( viewP, document, { withChildren: false } ); expect( domP ).to.be.an.instanceof( HTMLElement ); expect( domP.tagName ).to.equal( 'P' ); expect( domP.getAttribute( 'class' ) ).to.equal( 'foo' ); expect( domP.attributes.length ).to.equal( 1 ); expect( domP.childNodes.length ).to.equal( 0 ); expect( converter.getCorrespondingView( domP ) ).not.to.equal( viewP ); } ); it( 'should create DOM document fragment from view document fragment and bind elements', () => { const viewImg = new ViewElement( 'img' ); const viewText = new ViewText( 'foo' ); const viewFragment = new ViewDocumentFragment(); viewFragment.appendChildren( viewImg ); viewFragment.appendChildren( viewText ); const domFragment = converter.viewToDom( viewFragment, document, { bind: true } ); expect( domFragment ).to.be.an.instanceof( DocumentFragment ); expect( domFragment.childNodes.length ).to.equal( 2 ); expect( domFragment.childNodes[ 0 ].tagName ).to.equal( 'IMG' ); expect( domFragment.childNodes[ 1 ].data ).to.equal( 'foo' ); expect( converter.getCorrespondingView( domFragment ) ).to.equal( viewFragment ); expect( converter.getCorrespondingView( domFragment.childNodes[ 0 ] ) ).to.equal( viewFragment.getChild( 0 ) ); } ); it( 'should create DOM document fragment from view document without children', () => { const viewImg = new ViewElement( 'img' ); const viewText = new ViewText( 'foo' ); const viewFragment = new ViewDocumentFragment(); viewFragment.appendChildren( viewImg ); viewFragment.appendChildren( viewText ); const domImg = document.createElement( 'img' ); converter.bindElements( domImg, viewImg ); const domFragment = converter.viewToDom( viewFragment, document, { withChildren: false } ); expect( domFragment ).to.be.an.instanceof( DocumentFragment ); expect( domFragment.childNodes.length ).to.equal( 0 ); expect( converter.getCorrespondingView( domFragment ) ).not.to.equal( viewFragment ); } ); it( 'should return already bind document fragment', () => { const domFragment = document.createDocumentFragment(); const viewFragment = new ViewDocumentFragment(); converter.bindDocumentFragments( domFragment, viewFragment ); const domFragment2 = converter.viewToDom( viewFragment, document ); expect( domFragment2 ).to.equal( domFragment ); } ); it( 'should create DOM text node from view text node', () => { const viewTextNode = new ViewText( 'foo' ); const domTextNode = converter.viewToDom( viewTextNode, document ); expect( domTextNode ).to.be.instanceof( Text ); expect( domTextNode.data ).to.equal( 'foo' ); } ); describe( 'it should convert spaces to ', () => { it( 'at the beginning of each container element', () => { const viewDiv = new ViewContainerElement( 'div', null, [ new ViewContainerElement( 'p', null, new ViewText( ' foo' ) ), new ViewContainerElement( 'p', null, new ViewText( 'bar' ) ), new ViewContainerElement( 'p', null, new ViewText( ' xxx' ) ) ] ); const domDiv = converter.viewToDom( viewDiv, document ); expect( domDiv.innerHTML ).to.equal( '
foo
bar
xxx
' ); } ); it( 'at the end of each container element', () => { const viewDiv = new ViewContainerElement( 'div', null, [ new ViewContainerElement( 'p', null, new ViewText( 'foo ' ) ), new ViewContainerElement( 'p', null, new ViewText( 'bar' ) ), new ViewContainerElement( 'p', null, new ViewText( 'xxx ' ) ) ] ); const domDiv = converter.viewToDom( viewDiv, document ); expect( domDiv.innerHTML ).to.equal( 'foo
bar
xxx
' ); } ); it( 'when there are multiple spaces next to each other or between attribute elements', () => { const viewDiv = new ViewContainerElement( 'div', null, [ new ViewText( 'x x x x ' ), new ViewAttributeElement( 'b', null, new ViewText( ' x ' ) ), new ViewAttributeElement( 'i', null, new ViewAttributeElement( 'b', null, new ViewAttributeElement( 'u' , null, new ViewText( ' x' ) ) ) ) ] ); const domDiv = converter.viewToDom( viewDiv, document ); expect( domDiv.innerHTML ).to.equal( 'x x x x x x' ); } ); it( 'all together', () => { const viewDiv = new ViewContainerElement( 'div', null, [ new ViewContainerElement( 'p', null, [ new ViewText( ' x x x x ' ), new ViewAttributeElement( 'b', null, new ViewText( ' x ' ) ), new ViewAttributeElement( 'i', null, new ViewAttributeElement( 'b', null, new ViewAttributeElement( 'u' , null, new ViewText( ' x ' ) ) ) ) ] ), new ViewContainerElement( 'p', null, new ViewText( ' x ' ) ) ] ); const domDiv = converter.viewToDom( viewDiv, document ); expect( domDiv.innerHTML ).to.equal( 'x x x x x x
x
' ); } ); } ); } ); describe( 'viewChildrenToDom', () => { it( 'should convert children', () => { const viewP = parse( '