8
0

tablewalker.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
  6. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  7. import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
  8. import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  9. import TableEditing from '../src/tableediting';
  10. import { modelTable } from './_utils/utils';
  11. import TableWalker from '../src/tablewalker';
  12. describe( 'TableWalker', () => {
  13. let editor, model, doc, root;
  14. beforeEach( () => {
  15. return ModelTestEditor.create( { plugins: [ Paragraph, TableEditing ] } )
  16. .then( newEditor => {
  17. editor = newEditor;
  18. model = editor.model;
  19. doc = model.document;
  20. root = doc.getRoot( 'main' );
  21. } );
  22. } );
  23. function testWalker( tableData, expected, options, skip ) {
  24. setData( model, modelTable( tableData ) );
  25. const walker = new TableWalker( root.getChild( 0 ), options );
  26. if ( skip !== undefined ) {
  27. walker.skipRow( skip );
  28. }
  29. const result = [ ...walker ];
  30. const formattedResult = result.map( tableSlot => {
  31. const { cell, row, column, isAnchor, cellWidth, cellHeight, cellAnchorRow, cellAnchorColumn } = tableSlot;
  32. return {
  33. row,
  34. column,
  35. data: cell && cell.getChild( 0 ).getChild( 0 ).data,
  36. index: tableSlot.getPositionBefore().offset,
  37. ...( cellAnchorRow != row ? { anchorRow: cellAnchorRow } : null ),
  38. ...( cellAnchorColumn != column ? { anchorColumn: cellAnchorColumn } : null ),
  39. ...( isAnchor ? { isAnchor } : null ),
  40. ...( cellWidth > 1 ? { width: cellWidth } : null ),
  41. ...( cellHeight > 1 ? { height: cellHeight } : null )
  42. };
  43. } );
  44. expect( formattedResult ).to.deep.equal( expected );
  45. }
  46. it( 'should iterate over a table', () => {
  47. // +----+----+
  48. // | 00 | 01 |
  49. // +----+----+
  50. // | 10 | 11 |
  51. // +----+----+
  52. testWalker( [
  53. [ '00', '01' ],
  54. [ '10', '11' ]
  55. ], [
  56. { row: 0, column: 0, index: 0, data: '00', isAnchor: true },
  57. { row: 0, column: 1, index: 1, data: '01', isAnchor: true },
  58. { row: 1, column: 0, index: 0, data: '10', isAnchor: true },
  59. { row: 1, column: 1, index: 1, data: '11', isAnchor: true }
  60. ] );
  61. } );
  62. it( 'should properly output column indexes of a table that has col-spans', () => {
  63. // +----+----+----+
  64. // | 00 | 13 |
  65. // +----+----+----+
  66. testWalker( [
  67. [ { colspan: 2, contents: '00' }, '13' ]
  68. ], [
  69. { row: 0, column: 0, index: 0, data: '00', isAnchor: true, width: 2 },
  70. { row: 0, column: 2, index: 1, data: '13', isAnchor: true }
  71. ] );
  72. } );
  73. it( 'should properly output column indexes of a table that has row-spans', () => {
  74. // +----+----+----+
  75. // | 00 | 02 |
  76. // + +----+
  77. // | | 12 |
  78. // + +----+
  79. // | | 22 |
  80. // +----+----+----+
  81. // | 30 | 31 | 32 |
  82. // +----+----+----+
  83. testWalker( [
  84. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  85. [ '12' ],
  86. [ '22' ],
  87. [ '30', '31', '32' ]
  88. ], [
  89. { row: 0, column: 0, index: 0, data: '00', isAnchor: true, width: 2, height: 3 },
  90. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  91. { row: 1, column: 2, index: 0, data: '12', isAnchor: true },
  92. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  93. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  94. { row: 3, column: 1, index: 1, data: '31', isAnchor: true },
  95. { row: 3, column: 2, index: 2, data: '32', isAnchor: true }
  96. ] );
  97. } );
  98. it( 'should properly output column indexes of a table that has multiple row-spans', () => {
  99. // +----+----+----+
  100. // | 11 | 12 | 13 |
  101. // + +----+----+
  102. // | | 22 | 23 |
  103. // + + +----+
  104. // | | | 33 |
  105. // +----+----+----+
  106. // | 41 | 42 | 43 |
  107. // +----+----+----+
  108. testWalker( [
  109. [ { rowspan: 3, contents: '11' }, '12', '13' ],
  110. [ { rowspan: 2, contents: '22' }, '23' ],
  111. [ '33' ],
  112. [ '41', '42', '43' ]
  113. ], [
  114. { row: 0, column: 0, index: 0, data: '11', isAnchor: true, height: 3 },
  115. { row: 0, column: 1, index: 1, data: '12', isAnchor: true },
  116. { row: 0, column: 2, index: 2, data: '13', isAnchor: true },
  117. { row: 1, column: 1, index: 0, data: '22', isAnchor: true, height: 2 },
  118. { row: 1, column: 2, index: 1, data: '23', isAnchor: true },
  119. { row: 2, column: 2, index: 0, data: '33', isAnchor: true },
  120. { row: 3, column: 0, index: 0, data: '41', isAnchor: true },
  121. { row: 3, column: 1, index: 1, data: '42', isAnchor: true },
  122. { row: 3, column: 2, index: 2, data: '43', isAnchor: true }
  123. ] );
  124. } );
  125. describe( 'option.startRow', () => {
  126. it( 'should start iterating from given row but with cell spans properly calculated', () => {
  127. // +----+----+----+
  128. // | 11 | 13 |
  129. // + +----+
  130. // | | 23 |
  131. // + +----+
  132. // | | 33 |
  133. // +----+----+----+
  134. // | 41 | 42 | 43 |
  135. // +----+----+----+
  136. testWalker( [
  137. [ { colspan: 2, rowspan: 3, contents: '11' }, '13' ],
  138. [ '23' ],
  139. [ '33' ],
  140. [ '41', '42', '43' ]
  141. ], [
  142. { row: 2, column: 2, index: 0, data: '33', isAnchor: true },
  143. { row: 3, column: 0, index: 0, data: '41', isAnchor: true },
  144. { row: 3, column: 1, index: 1, data: '42', isAnchor: true },
  145. { row: 3, column: 2, index: 2, data: '43', isAnchor: true }
  146. ], { startRow: 2 } );
  147. } );
  148. it( 'should start iterating from given row, includeAllSlots = true', () => {
  149. // +----+----+----+
  150. // | 11 | 13 |
  151. // + +----+
  152. // | | 23 |
  153. // + +----+
  154. // | | 33 |
  155. // +----+----+----+
  156. // | 41 | 42 | 43 |
  157. // +----+----+----+
  158. testWalker( [
  159. [ { colspan: 2, rowspan: 3, contents: '11' }, '13' ],
  160. [ '23' ],
  161. [ '33' ],
  162. [ '41', '42', '43' ]
  163. ], [
  164. { row: 2, column: 0, index: 0, data: '11', width: 2, height: 3, anchorRow: 0 },
  165. { row: 2, column: 1, index: 0, data: '11', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  166. { row: 2, column: 2, index: 0, data: '33', isAnchor: true },
  167. { row: 3, column: 0, index: 0, data: '41', isAnchor: true },
  168. { row: 3, column: 1, index: 1, data: '42', isAnchor: true },
  169. { row: 3, column: 2, index: 2, data: '43', isAnchor: true }
  170. ], { startRow: 2, includeAllSlots: true } );
  171. } );
  172. } );
  173. describe( 'option.endRow', () => {
  174. it( 'should stop iterating after given row but with cell spans properly calculated', () => {
  175. // +----+----+----+
  176. // | 11 | 13 |
  177. // + +----+
  178. // | | 23 |
  179. // + +----+
  180. // | | 33 |
  181. // +----+----+----+
  182. // | 41 | 42 | 43 |
  183. // +----+----+----+
  184. testWalker( [
  185. [ { colspan: 2, rowspan: 3, contents: '11' }, '13' ],
  186. [ '23' ],
  187. [ '33' ],
  188. [ '41', '42', '43' ]
  189. ], [
  190. { row: 0, column: 0, index: 0, data: '11', isAnchor: true, width: 2, height: 3 },
  191. { row: 0, column: 2, index: 1, data: '13', isAnchor: true },
  192. { row: 1, column: 2, index: 0, data: '23', isAnchor: true },
  193. { row: 2, column: 2, index: 0, data: '33', isAnchor: true }
  194. ], { endRow: 2 } );
  195. } );
  196. it( 'should iterate over given row only', () => {
  197. // +----+----+----+
  198. // | 11 | 13 |
  199. // + +----+
  200. // | | 23 |
  201. // + +----+
  202. // | | 33 |
  203. // +----+----+----+
  204. // | 41 | 42 | 43 |
  205. // +----+----+----+
  206. testWalker( [
  207. [ { colspan: 2, rowspan: 3, contents: '11' }, '13' ],
  208. [ '23' ],
  209. [ '33' ],
  210. [ '41', '42', '43' ]
  211. ], [
  212. { row: 0, column: 0, index: 0, data: '11', isAnchor: true, width: 2, height: 3 },
  213. { row: 0, column: 2, index: 1, data: '13', isAnchor: true }
  214. ], { endRow: 0 } );
  215. } );
  216. it( 'should stop iterating after given row, includeAllSlots = true', () => {
  217. // +----+----+----+
  218. // | 11 | 13 |
  219. // + +----+
  220. // | | 23 |
  221. // + +----+
  222. // | | 33 |
  223. // +----+----+----+
  224. // | 41 | 42 | 43 |
  225. // +----+----+----+
  226. testWalker( [
  227. [ { colspan: 2, rowspan: 3, contents: '11' }, '13' ],
  228. [ '23' ],
  229. [ '33' ],
  230. [ '41', '42', '43' ]
  231. ], [
  232. { row: 0, column: 0, index: 0, data: '11', width: 2, height: 3, isAnchor: true },
  233. { row: 0, column: 1, index: 0, data: '11', width: 2, height: 3, anchorColumn: 0 },
  234. { row: 0, column: 2, index: 1, data: '13', isAnchor: true },
  235. { row: 1, column: 0, index: 0, data: '11', width: 2, height: 3, anchorRow: 0 },
  236. { row: 1, column: 1, index: 0, data: '11', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  237. { row: 1, column: 2, index: 0, data: '23', isAnchor: true }
  238. ], { endRow: 1, includeAllSlots: true } );
  239. } );
  240. } );
  241. describe( 'options.row', () => {
  242. it( 'should iterate given row', () => {
  243. // +----+----+----+
  244. // | 00 | 02 |
  245. // + +----+
  246. // | | 12 |
  247. // + +----+
  248. // | | 22 |
  249. // +----+----+----+
  250. // | 30 | 31 | 32 |
  251. // +----+----+----+
  252. testWalker( [
  253. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  254. [ '12' ],
  255. [ '22' ],
  256. [ '30', '31', '32' ]
  257. ], [
  258. { row: 1, column: 2, index: 0, data: '12', isAnchor: true }
  259. ], { row: 1 } );
  260. } );
  261. it( 'should iterate given row, includeAllSlots = true', () => {
  262. // +----+----+----+
  263. // | 00 | 02 |
  264. // + +----+
  265. // | | 12 |
  266. // + +----+
  267. // | | 22 |
  268. // +----+----+----+
  269. // | 30 | 31 | 32 |
  270. // +----+----+----+
  271. testWalker( [
  272. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  273. [ '12' ],
  274. [ '22' ],
  275. [ '30', '31', '32' ]
  276. ], [
  277. { row: 1, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  278. { row: 1, column: 1, index: 0, data: '00', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  279. { row: 1, column: 2, index: 0, data: '12', isAnchor: true }
  280. ], { row: 1, includeAllSlots: true } );
  281. } );
  282. } );
  283. describe( 'options.startColumn', () => {
  284. it( 'should not return the slots before startColumn', () => {
  285. // +----+----+----+
  286. // | 00 | 02 |
  287. // + +----+
  288. // | | 12 |
  289. // + +----+
  290. // | | 22 |
  291. // +----+----+----+
  292. // | 30 | 31 | 32 |
  293. // +----+----+----+
  294. testWalker( [
  295. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  296. [ '12' ],
  297. [ '22' ],
  298. [ '30', '31', '32' ]
  299. ], [
  300. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  301. { row: 1, column: 2, index: 0, data: '12', isAnchor: true },
  302. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  303. { row: 3, column: 1, index: 1, data: '31', isAnchor: true },
  304. { row: 3, column: 2, index: 2, data: '32', isAnchor: true }
  305. ], { startColumn: 1 } );
  306. } );
  307. it( 'should not return the slots before startColumn, includeAllSlots = true', () => {
  308. // +----+----+----+
  309. // | 00 | 02 |
  310. // + +----+
  311. // | | 12 |
  312. // + +----+
  313. // | | 22 |
  314. // +----+----+----+
  315. // | 30 | 31 | 32 |
  316. // +----+----+----+
  317. testWalker( [
  318. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  319. [ '12' ],
  320. [ '22' ],
  321. [ '30', '31', '32' ]
  322. ], [
  323. { row: 0, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0 },
  324. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  325. { row: 1, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  326. { row: 1, column: 2, index: 0, data: '12', isAnchor: true },
  327. { row: 2, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  328. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  329. { row: 3, column: 1, index: 1, data: '31', isAnchor: true },
  330. { row: 3, column: 2, index: 2, data: '32', isAnchor: true }
  331. ], { startColumn: 1, includeAllSlots: true } );
  332. } );
  333. } );
  334. describe( 'options.endColumn', () => {
  335. it( 'should not return the slots after endColumn', () => {
  336. // +----+----+----+
  337. // | 00 | 02 |
  338. // + +----+
  339. // | | 12 |
  340. // + +----+
  341. // | | 22 |
  342. // +----+----+----+
  343. // | 30 | 31 | 32 |
  344. // +----+----+----+
  345. testWalker( [
  346. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  347. [ '12' ],
  348. [ '22' ],
  349. [ '30', '31', '32' ]
  350. ], [
  351. { row: 0, column: 0, index: 0, data: '00', isAnchor: true, width: 2, height: 3 },
  352. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  353. { row: 3, column: 1, index: 1, data: '31', isAnchor: true }
  354. ], { endColumn: 1 } );
  355. } );
  356. it( 'should not return the slots after endColumn, includeAllSlots = true', () => {
  357. // +----+----+----+
  358. // | 00 | 02 |
  359. // + +----+
  360. // | | 12 |
  361. // + +----+
  362. // | | 22 |
  363. // +----+----+----+
  364. // | 30 | 31 | 32 |
  365. // +----+----+----+
  366. testWalker( [
  367. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  368. [ '12' ],
  369. [ '22' ],
  370. [ '30', '31', '32' ]
  371. ], [
  372. { row: 0, column: 0, index: 0, data: '00', width: 2, height: 3, isAnchor: true },
  373. { row: 0, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0 },
  374. { row: 1, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  375. { row: 1, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  376. { row: 2, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  377. { row: 2, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  378. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  379. { row: 3, column: 1, index: 1, data: '31', isAnchor: true }
  380. ], { endColumn: 1, includeAllSlots: true } );
  381. } );
  382. } );
  383. describe( 'options.column', () => {
  384. it( 'should return the slots from given column', () => {
  385. // +----+----+----+
  386. // | 00 | 02 |
  387. // + +----+
  388. // | | 12 |
  389. // + +----+
  390. // | | 22 |
  391. // +----+----+----+
  392. // | 30 | 31 | 32 |
  393. // +----+----+----+
  394. testWalker( [
  395. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  396. [ '12' ],
  397. [ '22' ],
  398. [ '30', '31', '32' ]
  399. ], [
  400. { row: 3, column: 1, index: 1, data: '31', isAnchor: true }
  401. ], { column: 1 } );
  402. } );
  403. it( 'should return the slots from given column, includeAllSlots = true', () => {
  404. // +----+----+----+
  405. // | 00 | 02 |
  406. // + +----+
  407. // | | 12 |
  408. // + +----+
  409. // | | 22 |
  410. // +----+----+----+
  411. // | 30 | 31 | 32 |
  412. // +----+----+----+
  413. testWalker( [
  414. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  415. [ '12' ],
  416. [ '22' ],
  417. [ '30', '31', '32' ]
  418. ], [
  419. { row: 0, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0 },
  420. { row: 1, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  421. { row: 2, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0, anchorRow: 0 },
  422. { row: 3, column: 1, index: 1, data: '31', isAnchor: true }
  423. ], { column: 1, includeAllSlots: true } );
  424. } );
  425. } );
  426. describe( 'option.includeAllSlots', () => {
  427. it( 'should output spanned cells at the end of a table', () => {
  428. // +----+----+
  429. // | 00 | 01 |
  430. // +----+ +
  431. // | 10 | |
  432. // +----+----+
  433. testWalker( [
  434. [ '00', { rowspan: 2, contents: '01' } ],
  435. [ '10' ]
  436. ], [
  437. { row: 0, column: 0, index: 0, data: '00', isAnchor: true },
  438. { row: 0, column: 1, index: 1, data: '01', isAnchor: true, height: 2 },
  439. { row: 1, column: 0, index: 0, data: '10', isAnchor: true },
  440. { row: 1, column: 1, index: 1, data: '01', anchorRow: 0, height: 2 }
  441. ], { includeAllSlots: true } );
  442. } );
  443. it( 'should output spanned cells', () => {
  444. // +----+----+----+
  445. // | 00 | 02 |
  446. // + +----+
  447. // | | 12 |
  448. // + +----+
  449. // | | 22 |
  450. // +----+----+----+
  451. // | 30 | 31 |
  452. // +----+----+----+
  453. testWalker( [
  454. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  455. [ '12' ],
  456. [ '22' ],
  457. [ '30', { colspan: 2, contents: '31' } ]
  458. ], [
  459. { row: 0, column: 0, index: 0, data: '00', width: 2, height: 3, isAnchor: true },
  460. { row: 0, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0 },
  461. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  462. { row: 1, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  463. { row: 1, column: 1, index: 0, data: '00', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  464. { row: 1, column: 2, index: 0, data: '12', isAnchor: true },
  465. { row: 2, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  466. { row: 2, column: 1, index: 0, data: '00', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  467. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  468. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  469. { row: 3, column: 1, index: 1, data: '31', width: 2, isAnchor: true },
  470. { row: 3, column: 2, index: 1, data: '31', width: 2, anchorColumn: 1 }
  471. ], { includeAllSlots: true } );
  472. } );
  473. it( 'should output rowspanned cells at the end of a table row', () => {
  474. // +----+----+
  475. // | 00 | 01 |
  476. // +----+ +
  477. // | 10 | |
  478. // +----+----+
  479. testWalker( [
  480. [ '00', { rowspan: 2, contents: '01' } ],
  481. [ '10' ]
  482. ], [
  483. { row: 0, column: 0, index: 0, data: '00', isAnchor: true },
  484. { row: 0, column: 1, index: 1, data: '01', isAnchor: true, height: 2 },
  485. { row: 1, column: 0, index: 0, data: '10', isAnchor: true },
  486. { row: 1, column: 1, index: 1, data: '01', anchorRow: 0, height: 2 }
  487. ], { includeAllSlots: true } );
  488. } );
  489. it( 'should work with startRow & endRow options', () => {
  490. // +----+----+----+
  491. // | 00 | 02 |
  492. // + +----+
  493. // | | 12 |
  494. // + +----+
  495. // | | 22 |
  496. // +----+----+----+
  497. // | 30 | 31 | 32 |
  498. // +----+----+----+
  499. testWalker( [
  500. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  501. [ '12' ],
  502. [ '22' ],
  503. [ '30', '31', '32' ]
  504. ], [
  505. { row: 1, column: 0, index: 0, data: '00', anchorRow: 0, width: 2, height: 3 },
  506. { row: 1, column: 1, index: 0, data: '00', anchorRow: 0, width: 2, height: 3, anchorColumn: 0 },
  507. { row: 1, column: 2, index: 0, data: '12', isAnchor: true },
  508. { row: 2, column: 0, index: 0, data: '00', anchorRow: 0, width: 2, height: 3 },
  509. { row: 2, column: 1, index: 0, data: '00', anchorRow: 0, width: 2, height: 3, anchorColumn: 0 },
  510. { row: 2, column: 2, index: 0, data: '22', isAnchor: true }
  511. ], { includeAllSlots: true, startRow: 1, endRow: 2 } );
  512. } );
  513. it( 'should output row-spanned cells at the end of a table row with startRow & endRow options', () => {
  514. // +----+----+
  515. // | 00 | 01 |
  516. // +----+ +
  517. // | 10 | |
  518. // +----+----+
  519. // | 20 | 21 |
  520. // +----+----+
  521. testWalker( [
  522. [ '00', { rowspan: 2, contents: '01' } ],
  523. [ '10' ],
  524. [ '20', '21' ]
  525. ], [
  526. { row: 0, column: 0, index: 0, data: '00', isAnchor: true },
  527. { row: 0, column: 1, index: 1, data: '01', isAnchor: true, height: 2 },
  528. { row: 1, column: 0, index: 0, data: '10', isAnchor: true },
  529. { row: 1, column: 1, index: 1, data: '01', anchorRow: 0, height: 2 }
  530. ], { startRow: 0, endRow: 1, includeAllSlots: true } );
  531. } );
  532. } );
  533. describe( '#skipRow()', () => {
  534. it( 'should skip row', () => {
  535. // +----+----+----+
  536. // | 00 | 02 |
  537. // + +----+
  538. // | | 12 |
  539. // + +----+
  540. // | | 22 |
  541. // +----+----+----+
  542. // | 30 | 31 | 32 |
  543. // +----+----+----+
  544. testWalker( [
  545. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  546. [ '12' ],
  547. [ '22' ],
  548. [ '30', '31', '32' ]
  549. ], [
  550. { row: 0, column: 0, index: 0, data: '00', isAnchor: true, width: 2, height: 3 },
  551. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  552. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  553. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  554. { row: 3, column: 1, index: 1, data: '31', isAnchor: true },
  555. { row: 3, column: 2, index: 2, data: '32', isAnchor: true }
  556. ], {}, 1 );
  557. } );
  558. it( 'should skip row, includeAllSlots = true', () => {
  559. // +----+----+----+
  560. // | 00 | 02 |
  561. // + +----+
  562. // | | 12 |
  563. // + +----+
  564. // | | 22 |
  565. // +----+----+----+
  566. // | 30 | 31 | 32 |
  567. // +----+----+----+
  568. testWalker( [
  569. [ { colspan: 2, rowspan: 3, contents: '00' }, '02' ],
  570. [ '12' ],
  571. [ '22' ],
  572. [ '30', '31', '32' ]
  573. ], [
  574. { row: 0, column: 0, index: 0, data: '00', width: 2, height: 3, isAnchor: true },
  575. { row: 0, column: 1, index: 0, data: '00', width: 2, height: 3, anchorColumn: 0 },
  576. { row: 0, column: 2, index: 1, data: '02', isAnchor: true },
  577. { row: 2, column: 0, index: 0, data: '00', width: 2, height: 3, anchorRow: 0 },
  578. { row: 2, column: 1, index: 0, data: '00', width: 2, height: 3, anchorRow: 0, anchorColumn: 0 },
  579. { row: 2, column: 2, index: 0, data: '22', isAnchor: true },
  580. { row: 3, column: 0, index: 0, data: '30', isAnchor: true },
  581. { row: 3, column: 1, index: 1, data: '31', isAnchor: true },
  582. { row: 3, column: 2, index: 2, data: '32', isAnchor: true }
  583. ], { includeAllSlots: true }, 1 );
  584. } );
  585. } );
  586. it( 'should throw error if walker value old api used', () => {
  587. setData( model, modelTable( [
  588. [ 'a' ]
  589. ] ) );
  590. const walker = new TableWalker( root.getChild( 0 ) );
  591. const { value } = walker.next();
  592. expect( () => value.isSpanned ).to.throw( CKEditorError, 'tablewalker-improper-api-usage' );
  593. expect( () => value.colspan ).to.throw( CKEditorError, 'tablewalker-improper-api-usage' );
  594. expect( () => value.rowspan ).to.throw( CKEditorError, 'tablewalker-improper-api-usage' );
  595. expect( () => value.cellIndex ).to.throw( CKEditorError, 'tablewalker-improper-api-usage' );
  596. } );
  597. } );