8
0

insert.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 Element from '/ckeditor5/engine/treeview/element.js';
  9. import Position from '/ckeditor5/engine/treeview/position.js';
  10. import Text from '/ckeditor5/engine/treeview/text.js';
  11. import utils from '/tests/engine/treeview/writer/_utils/utils.js';
  12. describe( 'Writer', () => {
  13. const create = utils.create;
  14. const test = utils.test;
  15. let writer;
  16. beforeEach( () => {
  17. writer = new Writer();
  18. } );
  19. describe( 'insert', () => {
  20. it( 'should return collapsed range in insertion position when using empty array', () => {
  21. // <p>{foo|bar}</p> -> <p>{foo[]bar}</p>
  22. const created = create( writer, {
  23. instanceOf: Element,
  24. name: 'p',
  25. children: [
  26. { instanceOf: Text, data: 'foobar', position: 3 }
  27. ]
  28. } );
  29. const newRange = writer.insert( created.position, [] );
  30. test( writer, newRange, created.node, {
  31. instanceOf: Element,
  32. name: 'p',
  33. children: [
  34. { instanceOf: Text, data: 'foobar', rangeStart: 3, rangeEnd: 3 }
  35. ]
  36. } );
  37. } );
  38. it( 'should insert text into another text node #1', () => {
  39. // <p>{foo|bar}</p> insert {baz}
  40. // <p>{foo[baz]bar}</p>
  41. const created = create( writer, {
  42. instanceOf: Element,
  43. name: 'p',
  44. children: [
  45. { instanceOf: Text, data: 'foobar', position: 3 }
  46. ]
  47. } );
  48. const newRange = writer.insert( created.position, new Text( 'baz' ) );
  49. test( writer, newRange, created.node, {
  50. instanceOf: Element,
  51. name: 'p',
  52. children: [
  53. { instanceOf: Text, data: 'foobazbar', rangeStart: 3, rangeEnd: 6 }
  54. ]
  55. } );
  56. } );
  57. it( 'should insert text into another text node #2', () => {
  58. // <p>{foobar|}</p> insert {baz}
  59. // <p>{foobar[baz}]</p>
  60. const created = create( writer, {
  61. instanceOf: Element,
  62. name: 'p',
  63. children: [
  64. { instanceOf: Text, data: 'foobar', position: 6 }
  65. ]
  66. } );
  67. const newRange = writer.insert( created.position, new Text( 'baz' ) );
  68. test( writer, newRange, created.node, {
  69. instanceOf: Element,
  70. name: 'p',
  71. rangeEnd: 1,
  72. children: [
  73. { instanceOf: Text, data: 'foobarbaz', rangeStart: 6 }
  74. ]
  75. } );
  76. } );
  77. it( 'should insert text into another text node #3', () => {
  78. // <p>{|foobar}</p> insert {baz}
  79. // <p>[{baz]foobar}</p>
  80. const created = create( writer, {
  81. instanceOf: Element,
  82. name: 'p',
  83. children: [
  84. { instanceOf: Text, data: 'foobar', position: 0 }
  85. ]
  86. } );
  87. const newRange = writer.insert( created.position, new Text( 'baz' ) );
  88. test( writer, newRange, created.node, {
  89. instanceOf: Element,
  90. name: 'p',
  91. rangeStart: 0,
  92. children: [
  93. { instanceOf: Text, data: 'bazfoobar', rangeEnd: 3 }
  94. ]
  95. } );
  96. } );
  97. it( 'should break attributes when inserting into text node', () => {
  98. // <p>{foo|bar}</p> insert <b>{baz}</b>
  99. // <p>{foo}[<b>baz</b>]{bar}</p>
  100. const created = create( writer, {
  101. instanceOf: Element,
  102. name: 'p',
  103. children: [
  104. { instanceOf: Text, data: 'foobar', position: 3 }
  105. ]
  106. } );
  107. const toInsert = create( writer, {
  108. instanceOf: Element,
  109. name: 'b',
  110. priority: 1,
  111. children: [
  112. { instanceOf: Text, data: 'baz' }
  113. ]
  114. } );
  115. const newRange = writer.insert( created.position, toInsert.node );
  116. test( writer, newRange, created.node, {
  117. instanceOf: Element,
  118. name: 'p',
  119. rangeStart: 1,
  120. rangeEnd: 2,
  121. children: [
  122. { instanceOf: Text, data: 'foo' },
  123. {
  124. instanceOf: Element,
  125. name: 'b',
  126. priority: 1,
  127. children: [
  128. { instanceOf: Text, data: 'baz' }
  129. ]
  130. },
  131. { instanceOf: Text, data: 'bar' }
  132. ]
  133. } );
  134. } );
  135. it( 'should merge text ndoes', () => {
  136. // <p>|{foobar}</p> insert {baz}
  137. // <p>[{baz]foobar}</p>
  138. const created = create( writer, {
  139. instanceOf: Element,
  140. name: 'p',
  141. position: 0,
  142. children: [
  143. { instanceOf: Text, data: 'foobar' }
  144. ]
  145. } );
  146. const newRange = writer.insert( created.position, new Text( 'baz' ) );
  147. test( writer, newRange, created.node, {
  148. instanceOf: Element,
  149. name: 'p',
  150. rangeStart: 0,
  151. children: [
  152. { instanceOf: Text, data: 'bazfoobar', rangeEnd: 3 }
  153. ]
  154. } );
  155. } );
  156. it( 'should merge same attribute nodes', () => {
  157. // <p><b>{foo|bar}</b></p> insert <b>{baz}</b>
  158. // <p><b>{foo[baz]bar}</b></p>
  159. const created = create( writer, {
  160. instanceOf: Element,
  161. name: 'p',
  162. children: [
  163. {
  164. instanceOf: Element,
  165. name: 'b',
  166. priority: 1,
  167. children: [
  168. { instanceOf: Text, data: 'foobar', position: 3 }
  169. ]
  170. }
  171. ]
  172. } );
  173. const toInsert = create( writer, {
  174. instanceOf: Element,
  175. name: 'b',
  176. priority: 1,
  177. children: [
  178. { instanceOf: Text, data: 'baz' }
  179. ]
  180. } );
  181. const newRange = writer.insert( created.position, toInsert.node );
  182. test( writer, newRange, created.node, {
  183. instanceOf: Element,
  184. name: 'p',
  185. children: [
  186. {
  187. instanceOf: Element,
  188. name: 'b',
  189. priority: 1,
  190. children: [
  191. { instanceOf: Text, data: 'foobazbar', rangeStart: 3, rangeEnd: 6 }
  192. ]
  193. }
  194. ]
  195. } );
  196. } );
  197. it( 'should not merge different attributes', () => {
  198. // <p><b>{foo|bar}</b></p> insert <b>{baz}</b> ( different priority )
  199. // <p><b>{foo}</b>[<b>{baz}</b>]<b>{bar}</b></p>
  200. const created = create( writer, {
  201. instanceOf: Element,
  202. name: 'p',
  203. children: [
  204. {
  205. instanceOf: Element,
  206. name: 'b',
  207. priority: 1,
  208. children: [
  209. { instanceOf: Text, data: 'foobar', position: 3 }
  210. ]
  211. }
  212. ]
  213. } );
  214. const toInsert = create( writer, {
  215. instanceOf: Element,
  216. name: 'b',
  217. priority: 2,
  218. children: [
  219. { instanceOf: Text, data: 'baz' }
  220. ]
  221. } );
  222. const newRange = writer.insert( created.position, toInsert.node );
  223. test( writer, newRange, created.node, {
  224. instanceOf: Element,
  225. name: 'p',
  226. rangeStart: 1,
  227. rangeEnd: 2,
  228. children: [
  229. {
  230. instanceOf: Element,
  231. name: 'b',
  232. priority: 1,
  233. children: [
  234. { instanceOf: Text, data: 'foo' }
  235. ]
  236. },
  237. {
  238. instanceOf: Element,
  239. name: 'b',
  240. priority: 2,
  241. children: [
  242. { instanceOf: Text, data: 'baz' }
  243. ]
  244. },
  245. {
  246. instanceOf: Element,
  247. name: 'b',
  248. priority: 1,
  249. children: [
  250. { instanceOf: Text, data: 'bar' }
  251. ]
  252. }
  253. ]
  254. } );
  255. } );
  256. it( 'should allow to insert multiple nodes', () => {
  257. // <p>|</p> insert <b>{foo}</b>{bar}
  258. // <p>[<b>{foo}</b>{bar}]</p>
  259. const root = new Element( 'p' );
  260. const toInsert = create( writer, {
  261. instanceOf: Element,
  262. name: 'fake',
  263. children: [
  264. {
  265. instanceOf: Element,
  266. name: 'b',
  267. priority: 1,
  268. children: [
  269. { instanceOf: Text, data: 'foo' }
  270. ]
  271. },
  272. { instanceOf: Text, data: 'bar' }
  273. ]
  274. } ).node.getChildren();
  275. const position = new Position( root, 0 );
  276. const newRange = writer.insert( position, toInsert );
  277. test( writer, newRange, root, {
  278. instanceOf: Element,
  279. name: 'p',
  280. rangeStart: 0,
  281. rangeEnd: 2,
  282. children: [
  283. {
  284. instanceOf: Element,
  285. name: 'b',
  286. priority: 1,
  287. children: [
  288. { instanceOf: Text, data: 'foo' }
  289. ]
  290. },
  291. { instanceOf: Text, data: 'bar' }
  292. ]
  293. } );
  294. } );
  295. it( 'should merge after inserting multiple nodes', () => {
  296. // <p><b>{qux}</b>|{baz}</p> insert <b>{foo}</b>{bar}
  297. // <p><b>{qux[foo}</b>{bar]baz}</p>
  298. const created = create( writer, {
  299. instanceOf: Element,
  300. name: 'p',
  301. position: 1,
  302. children: [
  303. {
  304. instanceOf: Element,
  305. name: 'b',
  306. priority: 1,
  307. children: [
  308. { instanceOf: Text, data: 'qux' }
  309. ]
  310. },
  311. { instanceOf: Text, data: 'baz' }
  312. ]
  313. } );
  314. const toInsert = create( writer, {
  315. instanceOf: Element,
  316. name: 'fake',
  317. children: [
  318. {
  319. instanceOf: Element,
  320. name: 'b',
  321. priority: 1,
  322. children: [
  323. { instanceOf: Text, data: 'foo' }
  324. ]
  325. },
  326. { instanceOf: Text, data: 'bar' }
  327. ]
  328. } ).node.getChildren();
  329. const newRange = writer.insert( created.position, toInsert );
  330. test( writer, newRange, created.node, {
  331. instanceOf: Element,
  332. name: 'p',
  333. children: [
  334. {
  335. instanceOf: Element,
  336. name: 'b',
  337. priority: 1,
  338. children: [
  339. { instanceOf: Text, data: 'quxfoo', rangeStart: 3 }
  340. ]
  341. },
  342. { instanceOf: Text, data: 'barbaz', rangeEnd: 3 }
  343. ]
  344. } );
  345. } );
  346. } );
  347. } );