8
0

wrapposition.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: treeview */
  6. 'use strict';
  7. import Writer from '/ckeditor5/engine/treeview/writer.js';
  8. import Text from '/ckeditor5/engine/treeview/text.js';
  9. import Element from '/ckeditor5/engine/treeview/element.js';
  10. import ContainerElement from '/ckeditor5/engine/treeview/containerelement.js';
  11. import AttributeElement from '/ckeditor5/engine/treeview/attributeelement.js';
  12. import Position from '/ckeditor5/engine/treeview/position.js';
  13. import utils from '/tests/engine/treeview/writer/_utils/utils.js';
  14. import { DEFAULT_PRIORITY } from '/ckeditor5/engine/treeview/attributeelement.js';
  15. import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
  16. describe( 'wrapPosition', () => {
  17. const create = utils.create;
  18. const test = utils.test;
  19. let writer;
  20. beforeEach( () => {
  21. writer = new Writer();
  22. } );
  23. it( 'should throw error when element is not instance of AttributeElement', () => {
  24. const container = new ContainerElement( 'p', null, new Text( 'foo' ) );
  25. const position = new Position( container, 0 );
  26. const b = new Element( 'b' );
  27. expect( () => {
  28. writer.wrapPosition( position, b );
  29. } ).to.throw( CKEditorError, 'treeview-writer-wrap-invalid-attribute' );
  30. } );
  31. it( 'should wrap position at the beginning of text node', () => {
  32. // <p>{|foobar}</p>
  33. // wrap with <b>
  34. // <p><b>|<b>{foobar}</p>
  35. const description = {
  36. instanceOf: ContainerElement,
  37. name: 'p',
  38. children: [
  39. { instanceOf: Text, data: 'foobar', position: 0 }
  40. ]
  41. };
  42. const created = create( writer, description );
  43. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  44. test( writer, newPosition, created.node, {
  45. instanceOf: ContainerElement,
  46. name: 'p',
  47. children: [
  48. { instanceOf: AttributeElement, name: 'b', position: 0 },
  49. { instanceOf: Text, data: 'foobar' }
  50. ]
  51. } );
  52. } );
  53. it( 'should wrap position inside text node', () => {
  54. // <p>{foo|bar}</p>
  55. // wrap with <b>
  56. // <p>{foo}<b>|</b>{bar}</p>
  57. const description = {
  58. instanceOf: ContainerElement,
  59. name: 'p',
  60. children: [
  61. { instanceOf: Text, data: 'foobar', position: 3 }
  62. ]
  63. };
  64. const created = create( writer, description );
  65. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  66. test( writer, newPosition, created.node, {
  67. instanceOf: ContainerElement,
  68. name: 'p',
  69. children: [
  70. { instanceOf: Text, data: 'foo' },
  71. { instanceOf: AttributeElement, name: 'b', position: 0 },
  72. { instanceOf: Text, data: 'bar' }
  73. ]
  74. } );
  75. } );
  76. it( 'should wrap position at the end of text node', () => {
  77. // <p>{foobar|}</p>
  78. // wrap with <b>
  79. // <p>{foobar}<b>|</b></p>
  80. const description = {
  81. instanceOf: ContainerElement,
  82. name: 'p',
  83. children: [
  84. { instanceOf: Text, data: 'foobar', position: 6 }
  85. ]
  86. };
  87. const created = create( writer, description );
  88. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  89. test( writer, newPosition, created.node, {
  90. instanceOf: ContainerElement,
  91. name: 'p',
  92. children: [
  93. { instanceOf: Text, data: 'foobar' },
  94. { instanceOf: AttributeElement, name: 'b', position: 0 }
  95. ]
  96. } );
  97. } );
  98. it( 'should merge with existing attributes #1', () => {
  99. // <p><b>{foo}</b>|</p>
  100. // wrap with <b>
  101. // <p><b>{foo|}</b></p>
  102. const description = {
  103. instanceOf: ContainerElement,
  104. name: 'p',
  105. position: 1,
  106. children: [
  107. {
  108. instanceOf: AttributeElement,
  109. name: 'b',
  110. children: [
  111. { instanceOf: Text, data: 'foobar' }
  112. ]
  113. }
  114. ]
  115. };
  116. const created = create( writer, description );
  117. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  118. test( writer, newPosition, created.node, {
  119. instanceOf: ContainerElement,
  120. name: 'p',
  121. children: [
  122. {
  123. instanceOf: AttributeElement,
  124. name: 'b',
  125. priority: DEFAULT_PRIORITY,
  126. children: [
  127. { instanceOf: Text, data: 'foobar', position: 6 }
  128. ]
  129. }
  130. ]
  131. } );
  132. } );
  133. it( 'should merge with existing attributes #2', () => {
  134. // <p>|<b>{foo}</b></p>
  135. // wrap with <b>
  136. // <p><b>{|foo}</b></p>
  137. const description = {
  138. instanceOf: ContainerElement,
  139. name: 'p',
  140. position: 0,
  141. children: [
  142. {
  143. instanceOf: AttributeElement,
  144. name: 'b',
  145. children: [
  146. { instanceOf: Text, data: 'foobar' }
  147. ]
  148. }
  149. ]
  150. };
  151. const created = create( writer, description );
  152. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  153. test( writer, newPosition, created.node, {
  154. instanceOf: ContainerElement,
  155. name: 'p',
  156. children: [
  157. {
  158. instanceOf: AttributeElement,
  159. name: 'b',
  160. priority: DEFAULT_PRIORITY,
  161. children: [
  162. { instanceOf: Text, data: 'foobar', position: 0 }
  163. ]
  164. }
  165. ]
  166. } );
  167. } );
  168. it( 'should wrap when inside nested attributes', () => {
  169. // <p><b>{foo|bar}</b></p>
  170. // wrap with <u>
  171. // <p><b>{foo}</b><u><b>|</b></u><b>{bar}</b></p>
  172. const description = {
  173. instanceOf: ContainerElement,
  174. name: 'p',
  175. children: [
  176. {
  177. instanceOf: AttributeElement,
  178. name: 'b',
  179. children: [
  180. { instanceOf: Text, data: 'foobar', position: 3 }
  181. ]
  182. }
  183. ]
  184. };
  185. const created = create( writer, description );
  186. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'u' ) );
  187. test( writer, newPosition, created.node, {
  188. instanceOf: ContainerElement,
  189. name: 'p',
  190. children: [
  191. {
  192. instanceOf: AttributeElement,
  193. name: 'b',
  194. children: [
  195. { instanceOf: Text, data: 'foo' }
  196. ]
  197. },
  198. {
  199. instanceOf: AttributeElement,
  200. name: 'u',
  201. children: [
  202. { instanceOf: AttributeElement, name: 'b', children: [] }
  203. ]
  204. },
  205. {
  206. instanceOf: AttributeElement,
  207. name: 'b',
  208. children: [
  209. { instanceOf: Text, data: 'bar' }
  210. ]
  211. }
  212. ]
  213. } );
  214. } );
  215. it( 'should merge when wrapping between same attribute', () => {
  216. // <p><b>{foo}</b>|<b>{bar}</b></p>
  217. // wrap with <b>
  218. // <p><b>{foo|bar}</b></p>
  219. const description = {
  220. instanceOf: ContainerElement,
  221. name: 'p',
  222. position: 1,
  223. children: [
  224. {
  225. instanceOf: AttributeElement,
  226. name: 'b',
  227. children: [
  228. { instanceOf: Text, data: 'foo' }
  229. ]
  230. },
  231. {
  232. instanceOf: AttributeElement,
  233. name: 'b',
  234. children: [
  235. { instanceOf: Text, data: 'bar' }
  236. ]
  237. }
  238. ]
  239. };
  240. const created = create( writer, description );
  241. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  242. test( writer, newPosition, created.node, {
  243. instanceOf: ContainerElement,
  244. name: 'p',
  245. children: [
  246. {
  247. instanceOf: AttributeElement,
  248. name: 'b',
  249. children: [
  250. { instanceOf: Text, data: 'foobar', position: 3 }
  251. ]
  252. }
  253. ]
  254. } );
  255. } );
  256. it( 'should return same position when inside same attribute', () => {
  257. // <p><b>{foobar}|</b></p>
  258. // wrap with <b>
  259. // <p><b>{foobar|}</b></p>
  260. const description = {
  261. instanceOf: ContainerElement,
  262. name: 'p',
  263. children: [
  264. {
  265. instanceOf: AttributeElement,
  266. name: 'b',
  267. position: 1,
  268. children: [
  269. { instanceOf: Text, data: 'foobar' }
  270. ]
  271. }
  272. ]
  273. };
  274. const created = create( writer, description );
  275. const newPosition = writer.wrapPosition( created.position, new AttributeElement( 'b' ) );
  276. test( writer, newPosition, created.node, {
  277. instanceOf: ContainerElement,
  278. name: 'p',
  279. children: [
  280. {
  281. instanceOf: AttributeElement,
  282. name: 'b',
  283. children: [
  284. { instanceOf: Text, data: 'foobar', position: 6 }
  285. ]
  286. }
  287. ]
  288. } );
  289. } );
  290. } );