lists.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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 { testDataProcessor } from '../_utils/utils';
  6. import MarkdownDataProcessor from '../../src/gfmdataprocessor';
  7. import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';
  8. import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document';
  9. import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap';
  10. describe( 'GFMDataProcessor', () => {
  11. describe( 'lists', () => {
  12. it( 'should process tight asterisks', () => {
  13. testDataProcessor(
  14. '* item 1\n' +
  15. '* item 2\n' +
  16. '* item 3',
  17. // GitHub renders it as (notice spaces before list items)
  18. // <ul>
  19. // <li> item 1</li>
  20. // <li> item 2</li>
  21. // <li> item 3</li>
  22. // </ul>
  23. '<ul><li>item 1</li><li>item 2</li><li>item 3</li></ul>',
  24. // List will be normalized to 3-space representation.
  25. '* item 1\n' +
  26. '* item 2\n' +
  27. '* item 3'
  28. );
  29. } );
  30. it( 'should process loose asterisks', () => {
  31. testDataProcessor(
  32. '* item 1\n' +
  33. '\n' +
  34. '* item 2\n' +
  35. '\n' +
  36. '* item 3',
  37. // Loose lists are rendered with with paragraph inside.
  38. '<ul>' +
  39. '<li>' +
  40. '<p>item 1</p>' +
  41. '</li>' +
  42. '<li>' +
  43. '<p>item 2</p>' +
  44. '</li>' +
  45. '<li>' +
  46. '<p>item 3</p>' +
  47. '</li>' +
  48. '</ul>',
  49. // List will be normalized to 3-space representation.
  50. '* item 1\n' +
  51. '\n' +
  52. '* item 2\n' +
  53. '\n' +
  54. '* item 3'
  55. );
  56. } );
  57. it( 'should process tight pluses', () => {
  58. testDataProcessor(
  59. '+ item 1\n' +
  60. '+ item 2\n' +
  61. '+ item 3',
  62. '<ul>' +
  63. '<li>item 1</li>' +
  64. '<li>item 2</li>' +
  65. '<li>item 3</li>' +
  66. '</ul>',
  67. // List will be normalized to asterisks, 3-space representation.
  68. '* item 1\n' +
  69. '* item 2\n' +
  70. '* item 3'
  71. );
  72. } );
  73. it( 'should process loose pluses', () => {
  74. testDataProcessor(
  75. '+ item 1\n' +
  76. '\n' +
  77. '+ item 2\n' +
  78. '\n' +
  79. '+ item 3',
  80. '<ul>' +
  81. '<li>' +
  82. '<p>item 1</p>' +
  83. '</li>' +
  84. '<li>' +
  85. '<p>item 2</p>' +
  86. '</li>' +
  87. '<li>' +
  88. '<p>item 3</p>' +
  89. '</li>' +
  90. '</ul>',
  91. // List will be normalized to asterisks, 3-space representation.
  92. '* item 1\n' +
  93. '\n' +
  94. '* item 2\n' +
  95. '\n' +
  96. '* item 3'
  97. );
  98. } );
  99. it( 'should process tight minuses', () => {
  100. testDataProcessor(
  101. '- item 1\n' +
  102. '- item 2\n' +
  103. '- item 3',
  104. '<ul>' +
  105. '<li>item 1</li>' +
  106. '<li>item 2</li>' +
  107. '<li>item 3</li>' +
  108. '</ul>',
  109. // List will be normalized to asterisks, 3-space representation.
  110. '* item 1\n' +
  111. '* item 2\n' +
  112. '* item 3'
  113. );
  114. } );
  115. it( 'should process loose minuses', () => {
  116. testDataProcessor(
  117. '- item 1\n' +
  118. '\n' +
  119. '- item 2\n' +
  120. '\n' +
  121. '- item 3',
  122. '<ul>' +
  123. '<li>' +
  124. '<p>item 1</p>' +
  125. '</li>' +
  126. '<li>' +
  127. '<p>item 2</p>' +
  128. '</li>' +
  129. '<li>' +
  130. '<p>item 3</p>' +
  131. '</li>' +
  132. '</ul>',
  133. // List will be normalized to asterisks, 3-space representation.
  134. '* item 1\n' +
  135. '\n' +
  136. '* item 2\n' +
  137. '\n' +
  138. '* item 3'
  139. );
  140. } );
  141. it( 'should process ordered list with tabs', () => {
  142. testDataProcessor(
  143. '1. item 1\n' +
  144. '2. item 2\n' +
  145. '3. item 3',
  146. '<ol>' +
  147. '<li>item 1</li>' +
  148. '<li>item 2</li>' +
  149. '<li>item 3</li>' +
  150. '</ol>',
  151. // List will be normalized to 2-space representation.
  152. '1. item 1\n' +
  153. '2. item 2\n' +
  154. '3. item 3'
  155. );
  156. } );
  157. it( 'should process ordered list with spaces', () => {
  158. testDataProcessor(
  159. '1. item 1\n' +
  160. '2. item 2\n' +
  161. '3. item 3',
  162. '<ol>' +
  163. '<li>item 1</li>' +
  164. '<li>item 2</li>' +
  165. '<li>item 3</li>' +
  166. '</ol>',
  167. // List will be normalized to 2-space representation.
  168. '1. item 1\n' +
  169. '2. item 2\n' +
  170. '3. item 3'
  171. );
  172. } );
  173. it( 'should process loose ordered list with tabs', () => {
  174. testDataProcessor(
  175. '1. item 1\n' +
  176. '\n' +
  177. '2. item 2\n' +
  178. '\n' +
  179. '3. item 3',
  180. '<ol>' +
  181. '<li>' +
  182. '<p>item 1</p>' +
  183. '</li>' +
  184. '<li>' +
  185. '<p>item 2</p>' +
  186. '</li>' +
  187. '<li>' +
  188. '<p>item 3</p>' +
  189. '</li>' +
  190. '</ol>',
  191. // List will be normalized to 2-space representation.
  192. '1. item 1\n' +
  193. '\n' +
  194. '2. item 2\n' +
  195. '\n' +
  196. '3. item 3'
  197. );
  198. } );
  199. it( 'should process loose ordered list with spaces', () => {
  200. testDataProcessor(
  201. '1. item 1\n' +
  202. '\n' +
  203. '2. item 2\n' +
  204. '\n' +
  205. '3. item 3',
  206. '<ol>' +
  207. '<li>' +
  208. '<p>item 1</p>' +
  209. '</li>' +
  210. '<li>' +
  211. '<p>item 2</p>' +
  212. '</li>' +
  213. '<li>' +
  214. '<p>item 3</p>' +
  215. '</li>' +
  216. '</ol>',
  217. // List will be normalized to 2-space representation.
  218. '1. item 1\n' +
  219. '\n' +
  220. '2. item 2\n' +
  221. '\n' +
  222. '3. item 3'
  223. );
  224. } );
  225. it( 'should process nested and mixed lists', () => {
  226. testDataProcessor(
  227. '1. First\n' +
  228. '2. Second:\n' +
  229. ' * Fee\n' +
  230. ' * Fie\n' +
  231. ' * Foe\n' +
  232. '3. Third',
  233. '<ol>' +
  234. '<li>First</li>' +
  235. '<li>Second:' +
  236. '<ul>' +
  237. '<li>Fee</li>' +
  238. '<li>Fie</li>' +
  239. '<li>Foe</li>' +
  240. '</ul>' +
  241. '</li>' +
  242. '<li>Third</li>' +
  243. '</ol>',
  244. // All lists will be normalized after converting back.
  245. '1. First\n' +
  246. '2. Second:\n' +
  247. ' * Fee\n' +
  248. ' * Fie\n' +
  249. ' * Foe\n' +
  250. '3. Third'
  251. );
  252. } );
  253. it( 'should process nested and mixed loose lists', () => {
  254. testDataProcessor(
  255. '1. First\n' +
  256. '\n' +
  257. '2. Second:\n' +
  258. ' * Fee\n' +
  259. ' * Fie\n' +
  260. ' * Foe\n' +
  261. '\n' +
  262. '3. Third',
  263. '<ol>' +
  264. '<li>' +
  265. '<p>First</p>' +
  266. '</li>' +
  267. '<li>' +
  268. '<p>Second:</p>' +
  269. '<ul>' +
  270. '<li>Fee</li>' +
  271. '<li>Fie</li>' +
  272. '<li>Foe</li>' +
  273. '</ul>' +
  274. '</li>' +
  275. '<li>' +
  276. '<p>Third</p>' +
  277. '</li>' +
  278. '</ol>',
  279. // All lists will be normalized after converting back.
  280. '1. First\n' +
  281. '\n' +
  282. '2. Second:\n' +
  283. '\n' +
  284. ' * Fee\n' +
  285. ' * Fie\n' +
  286. ' * Foe\n' +
  287. '3. Third'
  288. );
  289. } );
  290. it( 'should create same bullet from different list indicators', () => {
  291. testDataProcessor(
  292. '* test\n' +
  293. '+ test\n' +
  294. '- test',
  295. '<ul>' +
  296. '<li>test</li>' +
  297. '<li>test</li>' +
  298. '<li>test</li>' +
  299. '</ul>',
  300. // After converting back list items will be unified.
  301. '* test\n' +
  302. '* test\n' +
  303. '* test'
  304. );
  305. } );
  306. } );
  307. describe( 'todo lists', () => {
  308. it( 'should process todo lists', () => {
  309. testDataProcessor(
  310. '* [ ] Item 1\n' +
  311. '* [x] Item 2',
  312. '<ul>' +
  313. '<li><input disabled="" type="checkbox"></input>Item 1</li>' +
  314. '<li><input checked="" disabled="" type="checkbox"></input>Item 2</li>' +
  315. '</ul>' );
  316. } );
  317. it( 'should process the HTML produced by the todo list feature', () => {
  318. const viewDocument = new ViewDocument( new StylesProcessor() );
  319. const htmlDataProcessor = new HtmlDataProcessor( viewDocument );
  320. const mdDataProcessor = new MarkdownDataProcessor( viewDocument );
  321. const viewFragment = htmlDataProcessor.toView(
  322. '<ul class="todo-list">' +
  323. '<li><label class="todo-list__label">' +
  324. '<input type="checkbox" disabled="disabled">' +
  325. '<span class="todo-list__label__description">Item 1</span>' +
  326. '</label></li>' +
  327. '<li><label class="todo-list__label">' +
  328. '<input type="checkbox" disabled="disabled" checked="checked">' +
  329. '<span class="todo-list__label__description">Item 2</span>' +
  330. '</label></li>' +
  331. '</ul>'
  332. );
  333. expect( mdDataProcessor.toData( viewFragment ) ).to.equal(
  334. '* [ ] Item 1\n' +
  335. '* [x] Item 2'
  336. );
  337. } );
  338. } );
  339. } );