tablepropertiesediting.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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 VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
  6. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  7. import TableEditing from '../../src/tableediting';
  8. import TablePropertiesEditing from '../../src/tableproperties/tablepropertiesediting';
  9. import TableBorderColorCommand from '../../src/tableproperties/commands/tablebordercolorcommand';
  10. import TableBorderStyleCommand from '../../src/tableproperties/commands/tableborderstylecommand';
  11. import TableBorderWidthCommand from '../../src/tableproperties/commands/tableborderwidthcommand';
  12. import TableAlignmentCommand from '../../src/tableproperties/commands/tablealignmentcommand';
  13. import TableWidthCommand from '../../src/tableproperties/commands/tablewidthcommand';
  14. import TableHeightCommand from '../../src/tableproperties/commands/tableheightcommand';
  15. import TableBackgroundColorCommand from '../../src/tableproperties/commands/tablebackgroundcolorcommand';
  16. import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  17. import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
  18. import { assertTableStyle, assertTRBLAttribute } from '../_utils/utils';
  19. describe( 'table properties', () => {
  20. describe( 'TablePropertiesEditing', () => {
  21. let editor, model;
  22. beforeEach( () => {
  23. return VirtualTestEditor
  24. .create( {
  25. plugins: [ TablePropertiesEditing, Paragraph, TableEditing ]
  26. } )
  27. .then( newEditor => {
  28. editor = newEditor;
  29. model = editor.model;
  30. } );
  31. } );
  32. afterEach( () => {
  33. editor.destroy();
  34. } );
  35. it( 'should have pluginName', () => {
  36. expect( TablePropertiesEditing.pluginName ).to.equal( 'TablePropertiesEditing' );
  37. } );
  38. it( 'adds tableBorderColor command', () => {
  39. expect( editor.commands.get( 'tableBorderColor' ) ).to.be.instanceOf( TableBorderColorCommand );
  40. } );
  41. it( 'adds tableBorderStyle command', () => {
  42. expect( editor.commands.get( 'tableBorderStyle' ) ).to.be.instanceOf( TableBorderStyleCommand );
  43. } );
  44. it( 'adds tableBorderWidth command', () => {
  45. expect( editor.commands.get( 'tableBorderWidth' ) ).to.be.instanceOf( TableBorderWidthCommand );
  46. } );
  47. it( 'adds tableAlignment command', () => {
  48. expect( editor.commands.get( 'tableAlignment' ) ).to.be.instanceOf( TableAlignmentCommand );
  49. } );
  50. it( 'adds tableWidth command', () => {
  51. expect( editor.commands.get( 'tableWidth' ) ).to.be.instanceOf( TableWidthCommand );
  52. } );
  53. it( 'adds tableHeight command', () => {
  54. expect( editor.commands.get( 'tableHeight' ) ).to.be.instanceOf( TableHeightCommand );
  55. } );
  56. it( 'adds tableBackgroundColor command', () => {
  57. expect( editor.commands.get( 'tableBackgroundColor' ) ).to.be.instanceOf( TableBackgroundColorCommand );
  58. } );
  59. describe( 'border', () => {
  60. it( 'should set proper schema rules', () => {
  61. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'borderColor' ) ).to.be.true;
  62. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'borderStyle' ) ).to.be.true;
  63. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'borderWidth' ) ).to.be.true;
  64. } );
  65. describe( 'upcast conversion', () => {
  66. it( 'should upcast border shorthand', () => {
  67. editor.setData( '<table style="border:1px solid #f00"><tr><td>foo</td></tr></table>' );
  68. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  69. assertTRBLAttribute( table, 'borderColor', '#f00' );
  70. assertTRBLAttribute( table, 'borderStyle', 'solid' );
  71. assertTRBLAttribute( table, 'borderWidth', '1px' );
  72. } );
  73. it( 'should upcast border-color shorthand', () => {
  74. editor.setData( '<table style="border-color:#f00"><tr><td>foo</td></tr></table>' );
  75. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  76. assertTRBLAttribute( table, 'borderColor', '#f00' );
  77. } );
  78. it( 'should upcast border-style shorthand', () => {
  79. editor.setData( '<table style="border-style:ridge"><tr><td>foo</td></tr></table>' );
  80. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  81. assertTRBLAttribute( table, 'borderStyle', 'ridge' );
  82. } );
  83. it( 'should upcast border-width shorthand', () => {
  84. editor.setData( '<table style="border-width:1px"><tr><td>foo</td></tr></table>' );
  85. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  86. assertTRBLAttribute( table, 'borderWidth', '1px' );
  87. } );
  88. it( 'should upcast border-top shorthand', () => {
  89. editor.setData( '<table style="border-top:1px solid #f00"><tr><td>foo</td></tr></table>' );
  90. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  91. assertTRBLAttribute( table, 'borderColor', '#f00', null, null, null );
  92. assertTRBLAttribute( table, 'borderStyle', 'solid', null, null, null );
  93. assertTRBLAttribute( table, 'borderWidth', '1px', null, null, null );
  94. } );
  95. it( 'should upcast border-right shorthand', () => {
  96. editor.setData( '<table style="border-right:1px solid #f00"><tr><td>foo</td></tr></table>' );
  97. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  98. assertTRBLAttribute( table, 'borderColor', null, '#f00', null, null );
  99. assertTRBLAttribute( table, 'borderStyle', null, 'solid', null, null );
  100. assertTRBLAttribute( table, 'borderWidth', null, '1px', null, null );
  101. } );
  102. it( 'should upcast border-bottom shorthand', () => {
  103. editor.setData( '<table style="border-bottom:1px solid #f00"><tr><td>foo</td></tr></table>' );
  104. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  105. assertTRBLAttribute( table, 'borderColor', null, null, '#f00', null );
  106. assertTRBLAttribute( table, 'borderStyle', null, null, 'solid', null );
  107. assertTRBLAttribute( table, 'borderWidth', null, null, '1px', null );
  108. } );
  109. it( 'should upcast border-left shorthand', () => {
  110. editor.setData( '<table style="border-left:1px solid #f00"><tr><td>foo</td></tr></table>' );
  111. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  112. assertTRBLAttribute( table, 'borderColor', null, null, null, '#f00' );
  113. assertTRBLAttribute( table, 'borderStyle', null, null, null, 'solid' );
  114. assertTRBLAttribute( table, 'borderWidth', null, null, null, '1px' );
  115. } );
  116. it( 'should upcast border-top-* styles', () => {
  117. editor.setData(
  118. '<table style="border-top-width:1px;border-top-style:solid;border-top-color:#f00"><tr><td>foo</td></tr></table>'
  119. );
  120. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  121. assertTRBLAttribute( table, 'borderColor', '#f00', null, null, null );
  122. assertTRBLAttribute( table, 'borderStyle', 'solid', null, null, null );
  123. assertTRBLAttribute( table, 'borderWidth', '1px', null, null, null );
  124. } );
  125. it( 'should upcast border-right-* styles', () => {
  126. editor.setData(
  127. '<table style="border-right-width:1px;border-right-style:solid;border-right-color:#f00">' +
  128. '<tr>' +
  129. '<td>foo</td>' +
  130. '</tr>' +
  131. '</table>'
  132. );
  133. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  134. assertTRBLAttribute( table, 'borderColor', null, '#f00', null, null );
  135. assertTRBLAttribute( table, 'borderStyle', null, 'solid', null, null );
  136. assertTRBLAttribute( table, 'borderWidth', null, '1px', null, null );
  137. } );
  138. it( 'should upcast border-bottom-* styles', () => {
  139. editor.setData(
  140. '<table style="border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#f00">' +
  141. '<tr>' +
  142. '<td>foo</td>' +
  143. '</tr>' +
  144. '</table>'
  145. );
  146. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  147. assertTRBLAttribute( table, 'borderColor', null, null, '#f00', null );
  148. assertTRBLAttribute( table, 'borderStyle', null, null, 'solid', null );
  149. assertTRBLAttribute( table, 'borderWidth', null, null, '1px', null );
  150. } );
  151. it( 'should upcast border-left-* styles', () => {
  152. editor.setData(
  153. '<table style="border-left-width:1px;border-left-style:solid;border-left-color:#f00"><tr><td>foo</td></tr></table>'
  154. );
  155. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  156. assertTRBLAttribute( table, 'borderColor', null, null, null, '#f00' );
  157. assertTRBLAttribute( table, 'borderStyle', null, null, null, 'solid' );
  158. assertTRBLAttribute( table, 'borderWidth', null, null, null, '1px' );
  159. } );
  160. } );
  161. describe( 'downcast conversion', () => {
  162. let table;
  163. beforeEach( () => {
  164. table = createEmptyTable();
  165. } );
  166. it( 'should consume converted item borderColor attribute', () => {
  167. editor.conversion.for( 'downcast' )
  168. .add( dispatcher => dispatcher.on( 'attribute:borderColor:table', ( evt, data, conversionApi ) => {
  169. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  170. } ) );
  171. model.change( writer => writer.setAttribute( 'borderColor', '#f00', table ) );
  172. } );
  173. it( 'should be overridable', () => {
  174. editor.conversion.for( 'downcast' )
  175. .add( dispatcher => dispatcher.on( 'attribute:borderColor:table', ( evt, data, conversionApi ) => {
  176. conversionApi.consumable.consume( data.item, evt.name );
  177. }, { priority: 'high' } ) );
  178. model.change( writer => writer.setAttribute( 'borderColor', '#f00', table ) );
  179. assertTableStyle( editor, '' );
  180. } );
  181. it( 'should downcast borderColor attribute (same top, right, bottom, left)', () => {
  182. model.change( writer => writer.setAttribute( 'borderColor', {
  183. top: '#f00',
  184. right: '#f00',
  185. bottom: '#f00',
  186. left: '#f00'
  187. }, table ) );
  188. assertTableStyle( editor, 'border-bottom:#f00;border-left:#f00;border-right:#f00;border-top:#f00;' );
  189. } );
  190. it( 'should downcast borderColor attribute (different top, right, bottom, left)', () => {
  191. model.change( writer => writer.setAttribute( 'borderColor', {
  192. top: '#f00',
  193. right: 'hsla(0, 100%, 50%, 0.5)',
  194. bottom: 'deeppink',
  195. left: 'rgb(255, 0, 0)'
  196. }, table ) );
  197. assertTableStyle( editor,
  198. 'border-bottom:deeppink;' +
  199. 'border-left:rgb(255, 0, 0);' +
  200. 'border-right:hsla(0, 100%, 50%, 0.5);' +
  201. 'border-top:#f00;'
  202. );
  203. } );
  204. it( 'should consume converted item borderStyle attribute', () => {
  205. editor.conversion.for( 'downcast' )
  206. .add( dispatcher => dispatcher.on( 'attribute:borderStyle:table', ( evt, data, conversionApi ) => {
  207. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  208. } ) );
  209. model.change( writer => writer.setAttribute( 'borderStyle', 'solid', table ) );
  210. } );
  211. it( 'should be overridable', () => {
  212. editor.conversion.for( 'downcast' )
  213. .add( dispatcher => dispatcher.on( 'attribute:borderStyle:table', ( evt, data, conversionApi ) => {
  214. conversionApi.consumable.consume( data.item, evt.name );
  215. }, { priority: 'high' } ) );
  216. model.change( writer => writer.setAttribute( 'borderStyle', 'solid', table ) );
  217. assertTableStyle( editor, '' );
  218. } );
  219. it( 'should downcast borderStyle attribute (same top, right, bottom, left)', () => {
  220. model.change( writer => writer.setAttribute( 'borderStyle', {
  221. top: 'solid',
  222. right: 'solid',
  223. bottom: 'solid',
  224. left: 'solid'
  225. }, table ) );
  226. assertTableStyle( editor, 'border-bottom:solid;border-left:solid;border-right:solid;border-top:solid;' );
  227. } );
  228. it( 'should downcast borderStyle attribute (different top, right, bottom, left)', () => {
  229. model.change( writer => writer.setAttribute( 'borderStyle', {
  230. top: 'solid',
  231. right: 'ridge',
  232. bottom: 'dotted',
  233. left: 'dashed'
  234. }, table ) );
  235. assertTableStyle( editor, 'border-bottom:dotted;border-left:dashed;border-right:ridge;border-top:solid;' );
  236. } );
  237. it( 'should consume converted item borderWidth attribute', () => {
  238. editor.conversion.for( 'downcast' )
  239. .add( dispatcher => dispatcher.on( 'attribute:borderWidth:table', ( evt, data, conversionApi ) => {
  240. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  241. } ) );
  242. model.change( writer => writer.setAttribute( 'borderWidth', '2px', table ) );
  243. } );
  244. it( 'should be overridable', () => {
  245. editor.conversion.for( 'downcast' )
  246. .add( dispatcher => dispatcher.on( 'attribute:borderWidth:table', ( evt, data, conversionApi ) => {
  247. conversionApi.consumable.consume( data.item, evt.name );
  248. }, { priority: 'high' } ) );
  249. model.change( writer => writer.setAttribute( 'borderWidth', '2px', table ) );
  250. assertTableStyle( editor, '' );
  251. } );
  252. it( 'should downcast borderWidth attribute (same top, right, bottom, left)', () => {
  253. model.change( writer => writer.setAttribute( 'borderWidth', {
  254. top: '42px',
  255. right: '.1em',
  256. bottom: '1337rem',
  257. left: 'thick'
  258. }, table ) );
  259. assertTableStyle( editor, 'border-bottom:1337rem;border-left:thick;border-right:.1em;border-top:42px;' );
  260. } );
  261. it( 'should downcast borderWidth attribute (different top, right, bottom, left)', () => {
  262. model.change( writer => writer.setAttribute( 'borderWidth', {
  263. top: '42px',
  264. right: '42px',
  265. bottom: '42px',
  266. left: '42px'
  267. }, table ) );
  268. assertTableStyle( editor, 'border-bottom:42px;border-left:42px;border-right:42px;border-top:42px;' );
  269. } );
  270. it( 'should downcast borderColor, borderStyle and borderWidth attributes together (same top, right, bottom, left)', () => {
  271. model.change( writer => {
  272. writer.setAttribute( 'borderColor', {
  273. top: '#f00',
  274. right: '#f00',
  275. bottom: '#f00',
  276. left: '#f00'
  277. }, table );
  278. writer.setAttribute( 'borderStyle', {
  279. top: 'solid',
  280. right: 'solid',
  281. bottom: 'solid',
  282. left: 'solid'
  283. }, table );
  284. writer.setAttribute( 'borderWidth', {
  285. top: '42px',
  286. right: '42px',
  287. bottom: '42px',
  288. left: '42px'
  289. }, table );
  290. } );
  291. assertTableStyle( editor,
  292. 'border-bottom:42px solid #f00;' +
  293. 'border-left:42px solid #f00;' +
  294. 'border-right:42px solid #f00;' +
  295. 'border-top:42px solid #f00;'
  296. );
  297. } );
  298. it(
  299. 'should downcast borderColor, borderStyle and borderWidth attributes together (different top, right, bottom, left)',
  300. () => {
  301. model.change( writer => {
  302. writer.setAttribute( 'borderColor', {
  303. top: '#f00',
  304. right: 'hsla(0, 100%, 50%, 0.5)',
  305. bottom: 'deeppink',
  306. left: 'rgb(255, 0, 0)'
  307. }, table );
  308. writer.setAttribute( 'borderStyle', {
  309. top: 'solid',
  310. right: 'ridge',
  311. bottom: 'dotted',
  312. left: 'dashed'
  313. }, table );
  314. writer.setAttribute( 'borderWidth', {
  315. top: '42px',
  316. right: '.1em',
  317. bottom: '1337rem',
  318. left: 'thick'
  319. }, table );
  320. } );
  321. assertTableStyle( editor,
  322. 'border-bottom:1337rem dotted deeppink;' +
  323. 'border-left:thick dashed rgb(255, 0, 0);' +
  324. 'border-right:.1em ridge hsla(0, 100%, 50%, 0.5);' +
  325. 'border-top:42px solid #f00;'
  326. );
  327. }
  328. );
  329. describe( 'change attribute', () => {
  330. beforeEach( () => {
  331. model.change( writer => {
  332. writer.setAttribute( 'borderColor', {
  333. top: '#f00',
  334. right: '#f00',
  335. bottom: '#f00',
  336. left: '#f00'
  337. }, table );
  338. writer.setAttribute( 'borderStyle', {
  339. top: 'solid',
  340. right: 'solid',
  341. bottom: 'solid',
  342. left: 'solid'
  343. }, table );
  344. writer.setAttribute( 'borderWidth', {
  345. top: '42px',
  346. right: '42px',
  347. bottom: '42px',
  348. left: '42px'
  349. }, table );
  350. } );
  351. } );
  352. it( 'should downcast borderColor attribute change', () => {
  353. model.change( writer => writer.setAttribute( 'borderColor', {
  354. top: 'deeppink',
  355. right: 'deeppink',
  356. bottom: 'deeppink',
  357. left: 'deeppink'
  358. }, table ) );
  359. assertTableStyle( editor,
  360. 'border-bottom:42px solid deeppink;' +
  361. 'border-left:42px solid deeppink;' +
  362. 'border-right:42px solid deeppink;' +
  363. 'border-top:42px solid deeppink;'
  364. );
  365. } );
  366. it( 'should downcast borderStyle attribute change', () => {
  367. model.change( writer => writer.setAttribute( 'borderStyle', {
  368. top: 'ridge',
  369. right: 'ridge',
  370. bottom: 'ridge',
  371. left: 'ridge'
  372. }, table ) );
  373. assertTableStyle( editor,
  374. 'border-bottom:42px ridge #f00;' +
  375. 'border-left:42px ridge #f00;' +
  376. 'border-right:42px ridge #f00;' +
  377. 'border-top:42px ridge #f00;'
  378. );
  379. } );
  380. it( 'should downcast borderWidth attribute change', () => {
  381. model.change( writer => writer.setAttribute( 'borderWidth', {
  382. top: 'thick',
  383. right: 'thick',
  384. bottom: 'thick',
  385. left: 'thick'
  386. }, table ) );
  387. assertTableStyle( editor,
  388. 'border-bottom:thick solid #f00;' +
  389. 'border-left:thick solid #f00;' +
  390. 'border-right:thick solid #f00;' +
  391. 'border-top:thick solid #f00;'
  392. );
  393. } );
  394. it( 'should downcast borderColor attribute removal', () => {
  395. model.change( writer => writer.removeAttribute( 'borderColor', table ) );
  396. assertTableStyle( editor,
  397. 'border-bottom:42px solid;' +
  398. 'border-left:42px solid;' +
  399. 'border-right:42px solid;' +
  400. 'border-top:42px solid;'
  401. );
  402. } );
  403. it( 'should downcast borderStyle attribute removal', () => {
  404. model.change( writer => writer.removeAttribute( 'borderStyle', table ) );
  405. assertTableStyle( editor,
  406. 'border-bottom:42px #f00;' +
  407. 'border-left:42px #f00;' +
  408. 'border-right:42px #f00;' +
  409. 'border-top:42px #f00;'
  410. );
  411. } );
  412. it( 'should downcast borderWidth attribute removal', () => {
  413. model.change( writer => writer.removeAttribute( 'borderWidth', table ) );
  414. assertTableStyle( editor,
  415. 'border-bottom:solid #f00;' +
  416. 'border-left:solid #f00;' +
  417. 'border-right:solid #f00;' +
  418. 'border-top:solid #f00;'
  419. );
  420. } );
  421. it( 'should downcast borderColor, borderStyle and borderWidth attributes removal', () => {
  422. model.change( writer => {
  423. writer.removeAttribute( 'borderColor', table );
  424. writer.removeAttribute( 'borderStyle', table );
  425. writer.removeAttribute( 'borderWidth', table );
  426. } );
  427. assertEqualMarkup(
  428. editor.getData(),
  429. '<figure class="table"><table><tbody><tr><td>foo</td></tr></tbody></table></figure>'
  430. );
  431. } );
  432. } );
  433. } );
  434. } );
  435. describe( 'background color', () => {
  436. it( 'should set proper schema rules', () => {
  437. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'backgroundColor' ) ).to.be.true;
  438. } );
  439. describe( 'upcast conversion', () => {
  440. it( 'should upcast background-color', () => {
  441. editor.setData( '<table style="background-color:#f00"><tr><td>foo</td></tr></table>' );
  442. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  443. expect( table.getAttribute( 'backgroundColor' ) ).to.equal( '#f00' );
  444. } );
  445. it( 'should upcast from background shorthand', () => {
  446. editor.setData( '<table style="background:#f00 center center"><tr><td>foo</td></tr></table>' );
  447. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  448. expect( table.getAttribute( 'backgroundColor' ) ).to.equal( '#f00' );
  449. } );
  450. } );
  451. describe( 'downcast conversion', () => {
  452. let table;
  453. beforeEach( () => {
  454. table = createEmptyTable();
  455. } );
  456. it( 'should consume converted item', () => {
  457. editor.conversion.for( 'downcast' )
  458. .add( dispatcher => dispatcher.on( 'attribute:backgroundColor:table', ( evt, data, conversionApi ) => {
  459. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  460. } ) );
  461. model.change( writer => writer.setAttribute( 'backgroundColor', '#f00', table ) );
  462. } );
  463. it( 'should be overridable', () => {
  464. editor.conversion.for( 'downcast' )
  465. .add( dispatcher => dispatcher.on( 'attribute:backgroundColor:table', ( evt, data, conversionApi ) => {
  466. conversionApi.consumable.consume( data.item, evt.name );
  467. }, { priority: 'high' } ) );
  468. model.change( writer => writer.setAttribute( 'backgroundColor', '#f00', table ) );
  469. assertTableStyle( editor, '' );
  470. } );
  471. it( 'should downcast backgroundColor', () => {
  472. model.change( writer => writer.setAttribute( 'backgroundColor', '#f00', table ) );
  473. assertTableStyle( editor, 'background-color:#f00;' );
  474. } );
  475. } );
  476. } );
  477. describe( 'width', () => {
  478. it( 'should set proper schema rules', () => {
  479. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'width' ) ).to.be.true;
  480. } );
  481. describe( 'upcast conversion', () => {
  482. it( 'should upcast width', () => {
  483. editor.setData( '<table style="width:1337px"><tr><td>foo</td></tr></table>' );
  484. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  485. expect( table.getAttribute( 'width' ) ).to.equal( '1337px' );
  486. } );
  487. } );
  488. describe( 'downcast conversion', () => {
  489. let table;
  490. beforeEach( () => {
  491. table = createEmptyTable();
  492. } );
  493. it( 'should consume converted item', () => {
  494. editor.conversion.for( 'downcast' )
  495. .add( dispatcher => dispatcher.on( 'attribute:width:table', ( evt, data, conversionApi ) => {
  496. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  497. } ) );
  498. model.change( writer => writer.setAttribute( 'width', '400px', table ) );
  499. } );
  500. it( 'should be overridable', () => {
  501. editor.conversion.for( 'downcast' )
  502. .add( dispatcher => dispatcher.on( 'attribute:width:table', ( evt, data, conversionApi ) => {
  503. conversionApi.consumable.consume( data.item, evt.name );
  504. }, { priority: 'high' } ) );
  505. model.change( writer => writer.setAttribute( 'width', '400px', table ) );
  506. assertTableStyle( editor, '' );
  507. } );
  508. it( 'should downcast width', () => {
  509. model.change( writer => writer.setAttribute( 'width', '1337px', table ) );
  510. assertTableStyle( editor, 'width:1337px;' );
  511. } );
  512. } );
  513. } );
  514. describe( 'height', () => {
  515. it( 'should set proper schema rules', () => {
  516. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'height' ) ).to.be.true;
  517. } );
  518. describe( 'upcast conversion', () => {
  519. it( 'should upcast height', () => {
  520. editor.setData( '<table style="height:1337px"><tr><td>foo</td></tr></table>' );
  521. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  522. expect( table.getAttribute( 'height' ) ).to.equal( '1337px' );
  523. } );
  524. } );
  525. describe( 'downcast conversion', () => {
  526. let table;
  527. beforeEach( () => {
  528. table = createEmptyTable();
  529. } );
  530. it( 'should downcast height', () => {
  531. model.change( writer => writer.setAttribute( 'height', '1337px', table ) );
  532. assertTableStyle( editor, 'height:1337px;' );
  533. } );
  534. it( 'should consume converted item', () => {
  535. editor.conversion.for( 'downcast' )
  536. .add( dispatcher => dispatcher.on( 'attribute:height:table', ( evt, data, conversionApi ) => {
  537. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  538. } ) );
  539. model.change( writer => writer.setAttribute( 'height', '400px', table ) );
  540. } );
  541. it( 'should be overridable', () => {
  542. editor.conversion.for( 'downcast' )
  543. .add( dispatcher => dispatcher.on( 'attribute:height:table', ( evt, data, conversionApi ) => {
  544. conversionApi.consumable.consume( data.item, evt.name );
  545. }, { priority: 'high' } ) );
  546. model.change( writer => writer.setAttribute( 'height', '400px', table ) );
  547. assertTableStyle( editor, '' );
  548. } );
  549. } );
  550. } );
  551. describe( 'alignment', () => {
  552. it( 'should set proper schema rules', () => {
  553. expect( model.schema.checkAttribute( [ '$root', 'table' ], 'alignment' ) ).to.be.true;
  554. } );
  555. describe( 'upcast conversion', () => {
  556. it( 'should upcast style="float:right;margin-right:0" to right value', () => {
  557. editor.setData( '<table style="float:right;margin-right:0"><tr><td>foo</td></tr></table>' );
  558. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  559. expect( table.getAttribute( 'alignment' ) ).to.equal( 'right' );
  560. } );
  561. it( 'should upcast style="margin-left:0;float:left;" to left value', () => {
  562. editor.setData( '<table style="margin-left:0;float:left;"><tr><td>foo</td></tr></table>' );
  563. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  564. expect( table.getAttribute( 'alignment' ) ).to.equal( 'left' );
  565. } );
  566. it( 'should upcast style="margin-left:auto;margin-right:auto" to center value', () => {
  567. editor.setData( '<table style="margin-left:auto;margin-right:auto"><tr><td>foo</td></tr></table>' );
  568. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  569. expect( table.getAttribute( 'alignment' ) ).to.equal( 'center' );
  570. } );
  571. it( 'should not upcast style="float:right;margin-right:23px" to right value (non-zero margin)', () => {
  572. editor.setData( '<table style="float:right;margin-right:23px"><tr><td>foo</td></tr></table>' );
  573. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  574. expect( table.hasAttribute( 'alignment' ) ).to.be.false;
  575. } );
  576. it( 'should upcast align=right attribute', () => {
  577. editor.setData( '<table align="right"><tr><td>foo</td></tr></table>' );
  578. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  579. expect( table.getAttribute( 'alignment' ) ).to.equal( 'right' );
  580. } );
  581. it( 'should upcast align=left attribute', () => {
  582. editor.setData( '<table align="left"><tr><td>foo</td></tr></table>' );
  583. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  584. expect( table.getAttribute( 'alignment' ) ).to.equal( 'left' );
  585. } );
  586. it( 'should upcast align=center attribute', () => {
  587. editor.setData( '<table align="center"><tr><td>foo</td></tr></table>' );
  588. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  589. expect( table.getAttribute( 'alignment' ) ).to.equal( 'center' );
  590. } );
  591. it( 'should discard align=justify attribute', () => {
  592. editor.setData( '<table align="justify"><tr><td>foo</td></tr></table>' );
  593. const table = model.document.getRoot().getNodeByPath( [ 0 ] );
  594. expect( table.hasAttribute( 'alignment' ) ).to.be.false;
  595. } );
  596. } );
  597. describe( 'downcast conversion', () => {
  598. let table;
  599. beforeEach( () => {
  600. table = createEmptyTable();
  601. } );
  602. it( 'should consume converted item', () => {
  603. editor.conversion.for( 'downcast' )
  604. .add( dispatcher => dispatcher.on( 'attribute:alignment:table', ( evt, data, conversionApi ) => {
  605. expect( conversionApi.consumable.consume( data.item, evt.name ) ).to.be.false;
  606. } ) );
  607. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  608. } );
  609. it( 'should be overridable', () => {
  610. editor.conversion.for( 'downcast' )
  611. .add( dispatcher => dispatcher.on( 'attribute:alignment:table', ( evt, data, conversionApi ) => {
  612. conversionApi.consumable.consume( data.item, evt.name );
  613. }, { priority: 'highest' } ) );
  614. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  615. assertTableStyle( editor, '' );
  616. } );
  617. it( 'should downcast right alignment', () => {
  618. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  619. assertTableStyle( editor, null, 'float:right;margin-right:0;' );
  620. } );
  621. it( 'should downcast left alignment', () => {
  622. model.change( writer => writer.setAttribute( 'alignment', 'left', table ) );
  623. assertTableStyle( editor, null, 'float:left;margin-left:0;' );
  624. } );
  625. it( 'should downcast centered alignment', () => {
  626. model.change( writer => writer.setAttribute( 'alignment', 'center', table ) );
  627. assertTableStyle( editor, null, 'margin-left:auto;margin-right:auto;' );
  628. } );
  629. it( 'should downcast changed alignment (center -> right)', () => {
  630. model.change( writer => writer.setAttribute( 'alignment', 'center', table ) );
  631. assertTableStyle( editor, null, 'margin-left:auto;margin-right:auto;' );
  632. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  633. assertTableStyle( editor, null, 'float:right;margin-right:0;' );
  634. } );
  635. it( 'should downcast changed alignment (right -> center)', () => {
  636. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  637. assertTableStyle( editor, null, 'float:right;margin-right:0;' );
  638. model.change( writer => writer.setAttribute( 'alignment', 'center', table ) );
  639. assertTableStyle( editor, null, 'margin-left:auto;margin-right:auto;' );
  640. } );
  641. it( 'should downcast removed alignment (from center)', () => {
  642. model.change( writer => writer.setAttribute( 'alignment', 'center', table ) );
  643. assertTableStyle( editor, null, 'margin-left:auto;margin-right:auto;' );
  644. model.change( writer => writer.removeAttribute( 'alignment', table ) );
  645. assertTableStyle( editor );
  646. } );
  647. it( 'should downcast removed alignment (from right)', () => {
  648. model.change( writer => writer.setAttribute( 'alignment', 'right', table ) );
  649. assertTableStyle( editor, null, 'float:right;margin-right:0;' );
  650. model.change( writer => writer.removeAttribute( 'alignment', table ) );
  651. assertTableStyle( editor );
  652. } );
  653. } );
  654. } );
  655. function createEmptyTable() {
  656. setModelData(
  657. model,
  658. '<table headingRows="0" headingColumns="0">' +
  659. '<tableRow>' +
  660. '<tableCell>' +
  661. '<paragraph>foo</paragraph>' +
  662. '</tableCell>' +
  663. '</tableRow>' +
  664. '</table>'
  665. );
  666. return model.document.getRoot().getNodeByPath( [ 0 ] );
  667. }
  668. } );
  669. } );