html.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. exports.test_data = {
  2. default_options: [
  3. { name: "indent_size", value: "4" },
  4. { name: "indent_char", value: "' '" },
  5. { name: "indent_with_tabs", value: "false" },
  6. { name: "preserve_newlines", value: "true" },
  7. { name: "jslint_happy", value: "false" },
  8. { name: "keep_array_indentation", value: "false" },
  9. { name: "brace_style", value: "'collapse'" },
  10. { name: "extra_liners", value: "['html', 'head', '/html']" }
  11. ],
  12. groups: [{
  13. name: "End With Newline",
  14. description: "",
  15. matrix: [
  16. {
  17. options: [
  18. { name: "end_with_newline", value: "true" }
  19. ],
  20. eof: '\\n'
  21. }, {
  22. options: [
  23. { name: "end_with_newline", value: "false" }
  24. ],
  25. eof: ''
  26. }
  27. ],
  28. tests: [
  29. { fragment: true, input: '', output: '{{eof}}' },
  30. { fragment: true, input: '<div></div>', output: '<div></div>{{eof}}' },
  31. // { fragment: true, input: ' \n\n<div></div>\n\n\n\n', output: ' <div></div>{{eof}}' },
  32. { fragment: true, input: '\n', output: '{{eof}}' }
  33. ],
  34. }, {
  35. name: "Custom Extra Liners (empty)",
  36. description: "",
  37. matrix: [
  38. {
  39. options: [
  40. { name: "extra_liners", value: "[]" }
  41. ]
  42. },
  43. ],
  44. tests: [
  45. {
  46. fragment: true,
  47. input: '<html><head><meta></head><body><div><p>x</p></div></body></html>',
  48. output: '<html>\n<head>\n <meta>\n</head>\n<body>\n <div>\n <p>x</p>\n </div>\n</body>\n</html>'
  49. }
  50. ],
  51. }, {
  52. name: "Custom Extra Liners (default)",
  53. description: "",
  54. matrix: [
  55. {
  56. options: [
  57. { name: "extra_liners", value: "null" }
  58. ]
  59. },
  60. ],
  61. tests: [
  62. {
  63. fragment: true,
  64. input: '<html><head></head><body></body></html>',
  65. output: '<html>\n\n<head></head>\n\n<body></body>\n\n</html>'
  66. }
  67. ],
  68. }, {
  69. name: "Custom Extra Liners (p, string)",
  70. description: "",
  71. matrix: [
  72. {
  73. options: [
  74. { name: "extra_liners", value: "'p,/p'" }
  75. ]
  76. },
  77. ],
  78. tests: [
  79. {
  80. fragment: true,
  81. input: '<html><head><meta></head><body><div><p>x</p></div></body></html>',
  82. output: '<html>\n<head>\n <meta>\n</head>\n<body>\n <div>\n\n <p>x\n\n </p>\n </div>\n</body>\n</html>'
  83. }
  84. ],
  85. }, {
  86. name: "Custom Extra Liners (p)",
  87. description: "",
  88. matrix: [
  89. {
  90. options: [
  91. { name: "extra_liners", value: "['p', '/p']" }
  92. ]
  93. },
  94. ],
  95. tests: [
  96. {
  97. fragment: true,
  98. input: '<html><head><meta></head><body><div><p>x</p></div></body></html>',
  99. output: '<html>\n<head>\n <meta>\n</head>\n<body>\n <div>\n\n <p>x\n\n </p>\n </div>\n</body>\n</html>'
  100. }
  101. ],
  102. }, {
  103. name: "Attribute Wrap",
  104. description: "Wraps attributes inside of html tags",
  105. matrix: [
  106. {
  107. options: [
  108. { name: "wrap_attributes", value: "'force'" }
  109. ],
  110. eof: '\\n',
  111. indent_attr: ' ',
  112. over80: '\\n'
  113. }, {
  114. options: [
  115. { name: "wrap_attributes", value: "'force'" },
  116. { name: "wrap_line_length", value: "80" }
  117. ],
  118. eof: '\\n',
  119. indent_attr: ' ',
  120. over80: '\\n'
  121. }, {
  122. options: [
  123. { name: "wrap_attributes", value: "'force'" },
  124. { name: "wrap_attributes_indent_size", value: "8" },
  125. ],
  126. eof: '\\n',
  127. indent_attr: ' ',
  128. over80: '\\n'
  129. }, {
  130. options: [
  131. { name: "wrap_attributes", value: "'auto'" },
  132. { name: "wrap_line_length", value: "80" }
  133. ],
  134. eof: ' ',
  135. indent_attr: '',
  136. over80: '\\n'
  137. }, {
  138. options: [
  139. { name: "wrap_attributes", value: "'auto'" },
  140. { name: "wrap_line_length", value: "0" }
  141. ],
  142. eof: ' ',
  143. indent_attr: '',
  144. over80: ' '
  145. }
  146. ],
  147. tests: [
  148. {
  149. fragment: true,
  150. input: '<div attr0 attr1="123" data-attr2="hello t here">This is some text</div>',
  151. output: '<div attr0{{eof}}{{indent_attr}}attr1="123"{{eof}}{{indent_attr}}data-attr2="hello t here">This is some text</div>'
  152. },
  153. {
  154. fragment: true,
  155. input: '<div lookatthissuperduperlongattributenamewhoahcrazy0="true" attr0 attr1="123" data-attr2="hello t here" heymanimreallylongtoowhocomesupwiththesenames="false">This is some text</div>',
  156. output: '<div lookatthissuperduperlongattributenamewhoahcrazy0="true"{{eof}}{{indent_attr}}attr0{{eof}}{{indent_attr}}attr1="123"{{eof}}{{indent_attr}}data-attr2="hello t here"{{over80}}{{indent_attr}}heymanimreallylongtoowhocomesupwiththesenames="false">This is some text</div>'
  157. },
  158. {
  159. fragment: true,
  160. input: '<img attr0 attr1="123" data-attr2="hello t here"/>',
  161. output: '<img attr0{{eof}}{{indent_attr}}attr1="123"{{eof}}{{indent_attr}}data-attr2="hello t here" />'
  162. }
  163. ]
  164. }, {
  165. name: "Handlebars Indenting Off",
  166. description: "Test handlebar behavior when indenting is off",
  167. template: "^^^ $$$",
  168. options: [
  169. { name: "indent_handlebars", value: "false" }
  170. ],
  171. tests: [
  172. { fragment: true,
  173. input_:
  174. '{{#if 0}}\n' +
  175. ' <div>\n' +
  176. ' </div>\n' +
  177. '{{/if}}',
  178. output:
  179. '{{#if 0}}\n' +
  180. '<div>\n' +
  181. '</div>\n' +
  182. '{{/if}}' },
  183. { fragment: true,
  184. input_:
  185. '<div>\n' +
  186. '{{#each thing}}\n' +
  187. ' {{name}}\n' +
  188. '{{/each}}\n' +
  189. '</div>',
  190. output:
  191. '<div>\n' +
  192. ' {{#each thing}} {{name}} {{/each}}\n' +
  193. '</div>'}
  194. ]
  195. }, {
  196. name: "Handlebars Indenting On",
  197. description: "Test handlebar formatting",
  198. template: "^^^ $$$",
  199. matrix: [
  200. {
  201. options: [
  202. { name: "indent_handlebars", value: "true" }
  203. ],
  204. content: '{{field}}'
  205. }, {
  206. options: [
  207. { name: "indent_handlebars", value: "true" }
  208. ],
  209. content: '{{! comment}}'
  210. }, {
  211. options: [
  212. { name: "indent_handlebars", value: "true" }
  213. ],
  214. content: '{pre{{field1}} {{field2}} {{field3}}post'
  215. }
  216. , {
  217. options: [
  218. { name: "indent_handlebars", value: "true" }
  219. ],
  220. content: '{{! \\n mult-line\\ncomment \\n with spacing\\n}}'
  221. }
  222. ],
  223. tests: [
  224. { fragment: true, unchanged: '{{page-title}}' },
  225. { fragment: true, unchanged: '{{#if 0}}{{/if}}' },
  226. { fragment: true, unchanged: '{{#if 0}}^^^content$$${{/if}}' },
  227. { fragment: true, unchanged: '{{#if 0}}\n{{/if}}' },
  228. { fragment: true,
  229. input_: '{{#if words}}{{/if}}',
  230. output: '{{#if words}}{{/if}}' },
  231. { fragment: true,
  232. input_: '{{#if words}}^^^content$$${{/if}}',
  233. output: '{{#if words}}^^^content$$${{/if}}' },
  234. { fragment: true,
  235. input_: '{{#if words}}^^^content$$${{/if}}',
  236. output: '{{#if words}}^^^content$$${{/if}}' },
  237. { fragment: true,
  238. unchanged:
  239. '{{#if 1}}\n' +
  240. ' <div>\n' +
  241. ' </div>\n' +
  242. '{{/if}}' },
  243. { fragment: true,
  244. input_:
  245. '{{#if 1}}\n' +
  246. '<div>\n' +
  247. '</div>\n' +
  248. '{{/if}}',
  249. output:
  250. '{{#if 1}}\n' +
  251. ' <div>\n' +
  252. ' </div>\n' +
  253. '{{/if}}' },
  254. { fragment: true,
  255. unchanged:
  256. '<div>\n' +
  257. ' {{#if 1}}\n' +
  258. ' {{/if}}\n' +
  259. '</div>' },
  260. { fragment: true,
  261. input_:
  262. '<div>\n' +
  263. '{{#if 1}}\n' +
  264. '{{/if}}\n' +
  265. '</div>',
  266. output:
  267. '<div>\n' +
  268. ' {{#if 1}}\n' +
  269. ' {{/if}}\n' +
  270. '</div>' },
  271. { fragment: true,
  272. input_:
  273. '{{#if}}\n' +
  274. '{{#each}}\n' +
  275. '{{#if}}\n' +
  276. '^^^content$$$\n' +
  277. '{{/if}}\n' +
  278. '{{#if}}\n' +
  279. '^^^content$$$\n' +
  280. '{{/if}}\n' +
  281. '{{/each}}\n' +
  282. '{{/if}}',
  283. output:
  284. '{{#if}}\n' +
  285. ' {{#each}}\n' +
  286. ' {{#if}}\n' +
  287. ' ^^^content$$$\n' +
  288. ' {{/if}}\n' +
  289. ' {{#if}}\n' +
  290. ' ^^^content$$$\n' +
  291. ' {{/if}}\n' +
  292. ' {{/each}}\n' +
  293. '{{/if}}' },
  294. { fragment: true, unchanged: '{{#if 1}}\n' +
  295. ' <div>\n' +
  296. ' </div>\n' +
  297. '{{/if}}' },
  298. // Test {{else}} aligned with {{#if}} and {{/if}}
  299. { fragment: true,
  300. input_:
  301. '{{#if 1}}\n' +
  302. ' ^^^content$$$\n' +
  303. ' {{else}}\n' +
  304. ' ^^^content$$$\n' +
  305. '{{/if}}',
  306. output:
  307. '{{#if 1}}\n' +
  308. ' ^^^content$$$\n' +
  309. '{{else}}\n' +
  310. ' ^^^content$$$\n' +
  311. '{{/if}}' },
  312. { fragment: true,
  313. input_:
  314. '{{#if 1}}\n' +
  315. ' {{else}}\n' +
  316. ' {{/if}}',
  317. output:
  318. '{{#if 1}}\n' +
  319. '{{else}}\n' +
  320. '{{/if}}' },
  321. { fragment: true,
  322. input_:
  323. '{{#if thing}}\n' +
  324. '{{#if otherthing}}\n' +
  325. ' ^^^content$$$\n' +
  326. ' {{else}}\n' +
  327. '^^^content$$$\n' +
  328. ' {{/if}}\n' +
  329. ' {{else}}\n'+
  330. '^^^content$$$\n' +
  331. '{{/if}}',
  332. output:
  333. '{{#if thing}}\n' +
  334. ' {{#if otherthing}}\n' +
  335. ' ^^^content$$$\n' +
  336. ' {{else}}\n' +
  337. ' ^^^content$$$\n' +
  338. ' {{/if}}\n' +
  339. '{{else}}\n'+
  340. ' ^^^content$$$\n' +
  341. '{{/if}}' },
  342. // Test {{}} inside of <> tags, which should be separated by spaces
  343. // for readability, unless they are inside a string.
  344. { fragment: true,
  345. input_: '<div{{somestyle}}></div>',
  346. output: '<div {{somestyle}}></div>' },
  347. { fragment: true,
  348. input_: '<div{{#if test}}class="foo"{{/if}}>^^^content$$$</div>',
  349. output: '<div {{#if test}} class="foo" {{/if}}>^^^content$$$</div>' },
  350. { fragment: true,
  351. input_: '<div{{#if thing}}{{somestyle}}class="{{class}}"{{else}}class="{{class2}}"{{/if}}>^^^content$$$</div>',
  352. output: '<div {{#if thing}} {{somestyle}} class="{{class}}" {{else}} class="{{class2}}" {{/if}}>^^^content$$$</div>' },
  353. { fragment: true,
  354. input_: '<span{{#if condition}}class="foo"{{/if}}>^^^content$$$</span>',
  355. output: '<span {{#if condition}} class="foo" {{/if}}>^^^content$$$</span>' },
  356. { fragment: true,
  357. unchanged: '<div unformatted="{{#if}}^^^content$$${{/if}}">^^^content$$$</div>' },
  358. { fragment: true,
  359. unchanged: '<div unformatted="{{#if }} ^^^content$$${{/if}}">^^^content$$$</div>' },
  360. // Quotes found inside of Handlebars expressions inside of quoted
  361. // strings themselves should not be considered string delimiters.
  362. { fragment: true,
  363. unchanged: '<div class="{{#if thingIs "value"}}^^^content$$${{/if}}"></div>' },
  364. { fragment: true,
  365. unchanged: '<div class="{{#if thingIs \\\'value\\\'}}^^^content$$${{/if}}"></div>' },
  366. { fragment: true,
  367. unchanged: '<div class=\\\'{{#if thingIs "value"}}^^^content$$${{/if}}\\\'></div>' },
  368. { fragment: true,
  369. unchanged: '<div class=\\\'{{#if thingIs \\\'value\\\'}}^^^content$$${{/if}}\\\'></div>' }
  370. ],
  371. }, {
  372. name: "Unclosed html elements",
  373. description: "Unclosed elements should not indent",
  374. options: [],
  375. tests: [
  376. { fragment: true, unchanged: '<source>\n<source>' },
  377. { fragment: true, unchanged: '<br>\n<br>' },
  378. { fragment: true, unchanged: '<input>\n<input>' },
  379. { fragment: true, unchanged: '<meta>\n<meta>' },
  380. { fragment: true, unchanged: '<link>\n<link>' }
  381. ]
  382. }, {
  383. name: "Unformatted tags",
  384. description: "Unformatted tag behavior",
  385. options: [],
  386. tests: [
  387. { fragment: true, unchanged: '<ol>\n <li>b<pre>c</pre></li>\n</ol>' },
  388. { fragment: true, unchanged: '<ol>\n <li>b<code>c</code></li>\n</ol>' },
  389. ]
  390. }, {
  391. name: "Php formatting",
  392. description: "Php (<?php ... ?>) treated as comments.",
  393. options: [],
  394. tests: [
  395. { fragment: true, unchanged: '<h1 class="content-page-header"><?=$view["name"]; ?></h1>' },
  396. { fragment: true, unchanged:
  397. [
  398. '<?php',
  399. 'for($i = 1; $i <= 100; $i++;) {',
  400. ' #count to 100!',
  401. ' echo($i . "</br>");',
  402. '}',
  403. '?>'
  404. ]
  405. },
  406. ]
  407. }, {
  408. name: "underscore.js formatting",
  409. description: "underscore.js templates (<% ... %>) treated as comments.",
  410. options: [],
  411. tests: [
  412. { fragment: true, unchanged:
  413. [
  414. '<div class="col-sm-9">',
  415. ' <textarea id="notes" class="form-control" rows="3">',
  416. ' <%= notes %>',
  417. ' </textarea>',
  418. '</div>'
  419. ]
  420. },
  421. ]
  422. }, {
  423. name: "Indent with tabs",
  424. description: "Use one tab instead of several spaces for indentation",
  425. template: "^^^ $$$",
  426. options: [
  427. { name: "indent_with_tabs", value: "true" }
  428. ],
  429. tests: [
  430. { fragment: true,
  431. input_:
  432. '<div>\n' +
  433. '<div>\n' +
  434. '</div>\n' +
  435. '</div>',
  436. output:
  437. '<div>\n' +
  438. '\t<div>\n' +
  439. '\t</div>\n' +
  440. '</div>' }
  441. ]
  442. }, {
  443. name: "Indent without tabs",
  444. description: "Use several spaces for indentation",
  445. template: "^^^ $$$",
  446. options: [
  447. { name: "indent_with_tabs", value: "false" }
  448. ],
  449. tests: [
  450. { fragment: true,
  451. input_:
  452. '<div>\n' +
  453. '<div>\n' +
  454. '</div>\n' +
  455. '</div>',
  456. output:
  457. '<div>\n' +
  458. ' <div>\n' +
  459. ' </div>\n' +
  460. '</div>' }
  461. ]
  462. }, {
  463. name: "New Test Suite"
  464. }],
  465. };