mergeAttributes.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: view, browser-only */
  6. import { mergeAttributes } from 'ckeditor5/engine/view/writer.js';
  7. import ContainerElement from 'ckeditor5/engine/view/containerelement.js';
  8. import Text from 'ckeditor5/engine/view/text.js';
  9. import Position from 'ckeditor5/engine/view/position.js';
  10. import { stringify, parse } from 'ckeditor5/engine/dev-utils/view.js';
  11. describe( 'writer', () => {
  12. /**
  13. * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
  14. * test merge position.
  15. *
  16. * @param {String} input
  17. * @param {String} expected
  18. */
  19. function test( input, expected ) {
  20. const { view, selection } = parse( input );
  21. const newPosition = mergeAttributes( selection.getFirstPosition() );
  22. expect( stringify( view, newPosition, { showType: true, showPriority: true } ) ).to.equal( expected );
  23. }
  24. describe( 'mergeAttributes', () => {
  25. it( 'should not merge if inside text node', () => {
  26. test( '<container:p>fo{}bar</container:p>', '<container:p>fo{}bar</container:p>' );
  27. } );
  28. it( 'should not merge if between containers', () => {
  29. test(
  30. '<container:div><container:p>foo</container:p>[]<container:p>bar</container:p></container:div>',
  31. '<container:div><container:p>foo</container:p>[]<container:p>bar</container:p></container:div>'
  32. );
  33. } );
  34. it( 'should return same position when inside empty container', () => {
  35. test(
  36. '<container:p>[]</container:p>',
  37. '<container:p>[]</container:p>'
  38. );
  39. } );
  40. it( 'should not merge when position is placed at the beginning of the container', () => {
  41. test(
  42. '<container:p>[]<attribute:b view-priority="1"></attribute:b></container:p>',
  43. '<container:p>[]<attribute:b view-priority="1"></attribute:b></container:p>'
  44. );
  45. } );
  46. it( 'should not merge when position is placed at the end of the container', () => {
  47. test(
  48. '<container:p><attribute:b view-priority="1"></attribute:b>[]</container:p>',
  49. '<container:p><attribute:b view-priority="1"></attribute:b>[]</container:p>'
  50. );
  51. } );
  52. it( 'should merge when placed between two text nodes', () => {
  53. // <p>foobar</p> -> <p>foo|bar</p>
  54. const t1 = new Text( 'foo' );
  55. const t2 = new Text( 'bar' );
  56. const p = new ContainerElement( 'p', null, [ t1, t2 ] );
  57. const position = new Position( p, 1 );
  58. const newPosition = mergeAttributes( position );
  59. expect( stringify( p, newPosition ) ).to.equal( '<p>foo{}bar</p>' );
  60. } );
  61. it( 'should merge when placed between similar attribute nodes', () => {
  62. test(
  63. '<container:p>' +
  64. '<attribute:b view-priority="1" foo="bar">baz</attribute:b>[]<attribute:b view-priority="1" foo="bar">qux</attribute:b>' +
  65. '</container:p>',
  66. '<container:p><attribute:b view-priority="1" foo="bar">baz{}qux</attribute:b></container:p>'
  67. );
  68. } );
  69. it( 'should not merge when placed between non-similar attribute nodes', () => {
  70. test(
  71. '<container:p>' +
  72. '<attribute:b view-priority="1" foo="bar"></attribute:b>[]<attribute:b view-priority="1" foo="baz"></attribute:b>' +
  73. '</container:p>',
  74. '<container:p>' +
  75. '<attribute:b view-priority="1" foo="bar"></attribute:b>[]<attribute:b view-priority="1" foo="baz"></attribute:b>' +
  76. '</container:p>'
  77. );
  78. } );
  79. it( 'should not merge when placed between similar attribute nodes with different priority', () => {
  80. test(
  81. '<container:p>' +
  82. '<attribute:b view-priority="1" foo="bar"></attribute:b>[]<attribute:b view-priority="2" foo="bar"></attribute:b>' +
  83. '</container:p>',
  84. '<container:p>' +
  85. '<attribute:b view-priority="1" foo="bar"></attribute:b>[]<attribute:b view-priority="2" foo="bar"></attribute:b>' +
  86. '</container:p>'
  87. );
  88. } );
  89. it( 'should merge attribute nodes and their contents if possible', () => {
  90. test(
  91. '<container:p>' +
  92. '<attribute:b view-priority="1" foo="bar">foo</attribute:b>[]<attribute:b view-priority="1" foo="bar">bar</attribute:b>' +
  93. '</container:p>',
  94. '<container:p><attribute:b view-priority="1" foo="bar">foo{}bar</attribute:b></container:p>'
  95. );
  96. } );
  97. it( 'should remove empty attributes after merge #1', () => {
  98. test(
  99. '<container:p><attribute:b>[]</attribute:b></container:p>',
  100. '<container:p>[]</container:p>'
  101. );
  102. } );
  103. it( 'should remove empty attributes after merge #2', () => {
  104. test(
  105. '<container:p><attribute:b>foo</attribute:b><attribute:i>[]</attribute:i><attribute:b>bar</attribute:b></container:p>',
  106. '<container:p><attribute:b view-priority="10">foo{}bar</attribute:b></container:p>'
  107. );
  108. } );
  109. it( 'should remove empty attributes after merge #3', () => {
  110. test(
  111. '<container:p><attribute:b></attribute:b><attribute:i>[]</attribute:i><attribute:b></attribute:b></container:p>',
  112. '<container:p>[]</container:p>'
  113. );
  114. } );
  115. it( 'should not merge when placed between EmptyElements', () => {
  116. test(
  117. '<container:p><empty:img></empty:img>[]<empty:img></empty:img></container:p>',
  118. '<container:p><empty:img></empty:img>[]<empty:img></empty:img></container:p>'
  119. );
  120. } );
  121. } );
  122. } );