| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- import {
- downcastElementToElement, downcastAttributeToElement, downcastAttributeToAttribute, downcastMarkerToElement, downcastMarkerToHighlight
- } from '../../src/conversion/downcast-helpers';
- import Conversion from '../../src/conversion/conversion';
- import EditingController from '../../src/controller/editingcontroller';
- import Model from '../../src/model/model';
- import ModelRange from '../../src/model/range';
- import ViewContainerElement from '../../src/view/containerelement';
- import ViewAttributeElement from '../../src/view/attributeelement';
- import ViewUIElement from '../../src/view/uielement';
- import { stringify } from '../../src/dev-utils/view';
- describe( 'downcast-helpers', () => {
- let conversion, model, modelRoot, viewRoot;
- beforeEach( () => {
- model = new Model();
- const modelDoc = model.document;
- modelRoot = modelDoc.createRoot();
- const controller = new EditingController( model );
- // Set name of view root the same as dom root.
- // This is a mock of attaching view root to dom root.
- controller.view.getRoot()._name = 'div';
- viewRoot = controller.view.getRoot();
- conversion = new Conversion();
- conversion.register( 'downcast', [ controller.downcastDispatcher ] );
- } );
- describe( 'downcastElementToElement', () => {
- it( 'config.view is a string', () => {
- const helper = downcastElementToElement( { model: 'paragraph', view: 'p' } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'paragraph', modelRoot, 0 );
- } );
- expectResult( '<p></p>' );
- } );
- it( 'can be overwritten using priority', () => {
- const helperA = downcastElementToElement( { model: 'paragraph', view: 'p' } );
- const helperB = downcastElementToElement( { model: 'paragraph', view: 'foo' }, 'high' );
- conversion.for( 'downcast' ).add( helperA ).add( helperB );
- model.change( writer => {
- writer.insertElement( 'paragraph', modelRoot, 0 );
- } );
- expectResult( '<foo></foo>' );
- } );
- it( 'config.view is an element instance', () => {
- const helper = downcastElementToElement( {
- model: 'paragraph',
- view: new ViewContainerElement( 'p' )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'paragraph', modelRoot, 0 );
- } );
- expectResult( '<p></p>' );
- } );
- it( 'config.view is a view element definition', () => {
- const helper = downcastElementToElement( {
- model: 'fancyParagraph',
- view: {
- name: 'p',
- class: 'fancy'
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'fancyParagraph', modelRoot, 0 );
- } );
- expectResult( '<p class="fancy"></p>' );
- } );
- it( 'config.view is a function', () => {
- const helper = downcastElementToElement( {
- model: 'heading',
- view: modelElement => new ViewContainerElement( 'h' + modelElement.getAttribute( 'level' ) )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'heading', { level: 2 }, modelRoot, 0 );
- } );
- expectResult( '<h2></h2>' );
- } );
- } );
- describe( 'downcastAttributeToElement', () => {
- it( 'config.view is a string', () => {
- const helper = downcastAttributeToElement( 'bold', { view: 'strong' } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
- } );
- expectResult( '<strong>foo</strong>' );
- } );
- it( 'can be overwritten using priority', () => {
- const helperA = downcastAttributeToElement( 'bold', { view: 'strong' } );
- const helperB = downcastAttributeToElement( 'bold', { view: 'b' }, 'high' );
- conversion.for( 'downcast' ).add( helperA ).add( helperB );
- model.change( writer => {
- writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
- } );
- expectResult( '<b>foo</b>' );
- } );
- it( 'config.view is an element instance', () => {
- const helper = downcastAttributeToElement( 'bold', {
- view: new ViewAttributeElement( 'strong' )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
- } );
- expectResult( '<strong>foo</strong>' );
- } );
- it( 'config.view is a view element definition', () => {
- const helper = downcastAttributeToElement( 'bold', {
- view: {
- name: 'span',
- class: 'bold'
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { bold: true }, modelRoot, 0 );
- } );
- expectResult( '<span class="bold">foo</span>' );
- } );
- it( 'config.view is a view element definition, model attribute value specified', () => {
- const helper = downcastAttributeToElement( 'styled', {
- model: 'dark',
- view: {
- name: 'span',
- class: [ 'styled', 'styled-dark' ]
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { styled: 'dark' }, modelRoot, 0 );
- } );
- expectResult( '<span class="styled styled-dark">foo</span>' );
- model.change( writer => {
- writer.setAttribute( 'styled', 'xyz', modelRoot.getChild( 0 ) );
- } );
- expectResult( 'foo' );
- } );
- it( 'multiple config items', () => {
- const helper = downcastAttributeToElement( 'fontSize', [
- {
- model: 'big',
- view: {
- name: 'span',
- style: {
- 'font-size': '1.2em'
- }
- }
- },
- {
- model: 'small',
- view: {
- name: 'span',
- style: {
- 'font-size': '0.8em'
- }
- }
- }
- ] );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { fontSize: 'big' }, modelRoot, 0 );
- } );
- expectResult( '<span style="font-size:1.2em">foo</span>' );
- model.change( writer => {
- writer.setAttribute( 'fontSize', 'small', modelRoot.getChild( 0 ) );
- } );
- expectResult( '<span style="font-size:0.8em">foo</span>' );
- model.change( writer => {
- writer.removeAttribute( 'fontSize', modelRoot.getChild( 0 ) );
- } );
- expectResult( 'foo' );
- } );
- it( 'config.view is a function', () => {
- const helper = downcastAttributeToElement( 'bold', {
- view: attributeValue => new ViewAttributeElement( 'span', { style: 'font-weight:' + attributeValue } )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', { bold: '500' }, modelRoot, 0 );
- } );
- expectResult( '<span style="font-weight:500">foo</span>' );
- } );
- } );
- describe( 'downcastAttributeToAttribute', () => {
- beforeEach( () => {
- conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'image', view: 'img' } ) );
- } );
- it( 'config not set', () => {
- const helper = downcastAttributeToAttribute( 'src' );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { src: 'foo.jpg' }, modelRoot, 0 );
- } );
- expectResult( '<img src="foo.jpg"></img>' );
- } );
- it( 'config.view is a string', () => {
- const helper = downcastAttributeToAttribute( 'source', { view: 'src' } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { source: 'foo.jpg' }, modelRoot, 0 );
- } );
- expectResult( '<img src="foo.jpg"></img>' );
- } );
- it( 'can be overwritten using priority', () => {
- const helperA = downcastAttributeToAttribute( 'source', { view: 'href' } );
- const helperB = downcastAttributeToAttribute( 'source', { view: 'src' }, 'high' );
- conversion.for( 'downcast' ).add( helperA ).add( helperB );
- model.change( writer => {
- writer.insertElement( 'image', { source: 'foo.jpg' }, modelRoot, 0 );
- } );
- expectResult( '<img src="foo.jpg"></img>' );
- } );
- it( 'config.view is an object', () => {
- const helper = downcastAttributeToAttribute( 'stylish', { view: { key: 'class', value: 'styled' } } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { stylish: true }, modelRoot, 0 );
- } );
- expectResult( '<img class="styled"></img>' );
- } );
- it( 'config.view is an object, model attribute value specified', () => {
- const helper = downcastAttributeToAttribute( 'styled', {
- model: 'dark',
- view: {
- key: 'class',
- value: 'styled-dark styled'
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { styled: 'dark' }, modelRoot, 0 );
- } );
- expectResult( '<img class="styled styled-dark"></img>' );
- model.change( writer => {
- writer.setAttribute( 'styled', 'xyz', modelRoot.getChild( 0 ) );
- } );
- expectResult( '<img></img>' );
- } );
- it( 'multiple config items', () => {
- const helper = downcastAttributeToAttribute( 'styled', [
- {
- model: 'dark',
- view: {
- key: 'class',
- value: 'styled-dark'
- }
- },
- {
- model: 'light',
- view: {
- key: 'class',
- value: 'styled-light'
- }
- }
- ] );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { styled: 'dark' }, modelRoot, 0 );
- } );
- expectResult( '<img class="styled-dark"></img>' );
- model.change( writer => {
- writer.setAttribute( 'styled', 'light', modelRoot.getChild( 0 ) );
- } );
- expectResult( '<img class="styled-light"></img>' );
- model.change( writer => {
- writer.setAttribute( 'styled', 'xyz', modelRoot.getChild( 0 ) );
- } );
- expectResult( '<img></img>' );
- } );
- it( 'config.view is a function', () => {
- const helper = downcastAttributeToAttribute( 'styled', {
- view: attributeValue => ( { key: 'class', value: 'styled-' + attributeValue } )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertElement( 'image', { styled: 'pull-out' }, modelRoot, 0 );
- } );
- expectResult( '<img class="styled-pull-out"></img>' );
- } );
- } );
- describe( 'downcastMarkerToElement', () => {
- it( 'config.view is a string', () => {
- const helper = downcastMarkerToElement( { model: 'search', view: 'marker-search' } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) );
- } );
- expectResult( 'f<marker-search></marker-search>o<marker-search></marker-search>o' );
- } );
- it( 'can be overwritten using priority', () => {
- const helperA = downcastMarkerToElement( { model: 'search', view: 'marker-search' } );
- const helperB = downcastMarkerToElement( { model: 'search', view: 'search' }, 'high' );
- conversion.for( 'downcast' ).add( helperA ).add( helperB );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) );
- } );
- expectResult( 'f<search></search>o<search></search>o' );
- } );
- it( 'config.view is an element instance', () => {
- const helper = downcastMarkerToElement( {
- model: 'search',
- view: new ViewUIElement( 'span', { 'data-marker': 'search' } )
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) );
- } );
- expectResult( 'f<span data-marker="search"></span>o<span data-marker="search"></span>o' );
- } );
- it( 'config.view is a view element definition', () => {
- const helper = downcastMarkerToElement( {
- model: 'search',
- view: {
- name: 'span',
- attribute: {
- 'data-marker': 'search'
- }
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) );
- } );
- expectResult( 'f<span data-marker="search"></span>o<span data-marker="search"></span>o' );
- } );
- it( 'config.view is a function', () => {
- const helper = downcastMarkerToElement( {
- model: 'search',
- view: data => {
- return new ViewUIElement( 'span', { 'data-marker': 'search', 'data-start': data.isOpening } );
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'search', ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 ) );
- } );
- expectResult( 'f<span data-marker="search" data-start="true"></span>o<span data-marker="search" data-start="false"></span>o' );
- } );
- } );
- describe( 'downcastMarkerToHighlight', () => {
- it( 'config.view is a highlight descriptor', () => {
- const helper = downcastMarkerToHighlight( { model: 'comment', view: { class: 'comment' } } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'comment', ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ) );
- } );
- expectResult( '<span class="comment">foo</span>' );
- } );
- it( 'can be overwritten using priority', () => {
- const helperA = downcastMarkerToHighlight( { model: 'comment', view: { class: 'comment' } } );
- const helperB = downcastMarkerToHighlight( { model: 'comment', view: { class: 'new-comment' } }, 'high' );
- conversion.for( 'downcast' ).add( helperA ).add( helperB );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'comment', ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ) );
- } );
- expectResult( '<span class="new-comment">foo</span>' );
- } );
- it( 'config.view is a function', () => {
- const helper = downcastMarkerToHighlight( {
- model: 'comment',
- view: data => {
- const commentType = data.markerName.split( ':' )[ 1 ];
- return {
- class: [ 'comment', 'comment-' + commentType ]
- };
- }
- } );
- conversion.for( 'downcast' ).add( helper );
- model.change( writer => {
- writer.insertText( 'foo', modelRoot, 0 );
- writer.setMarker( 'comment:abc', ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 ) );
- } );
- expectResult( '<span class="comment comment-abc">foo</span>' );
- } );
- } );
- function expectResult( string ) {
- expect( stringify( viewRoot, null, { ignoreRoot: true } ) ).to.equal( string );
- }
- } );
|