htmlCleanup.spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import { describe, it, assert } from 'vitest'
  3. import { htmlCleanup } from '../htmlCleanup'
  4. // htmlCleanup
  5. describe('htmlCleanup utility', () => {
  6. it('removes comments', () => {
  7. const source = '<div><!--test comment--><a href="test">test</a></div>'
  8. const should = '<a href="test">test</a>'
  9. const result = htmlCleanup(source)
  10. assert.equal(result, should, source)
  11. })
  12. it('keeps text as is', () => {
  13. const source = 'some link to somewhere'
  14. const should = 'some link to somewhere'
  15. const result = htmlCleanup(source)
  16. assert.equal(result, should, source)
  17. })
  18. it('keeps lists as is', () => {
  19. const source = '<li>a</li><li>b</li>'
  20. const should = '<li>a</li><li>b</li>'
  21. const result = htmlCleanup(source)
  22. assert.equal(result, should, source)
  23. })
  24. it('removes invalid links', () => {
  25. const source = '<a href="some_link">some link to somewhere</a>'
  26. const should = 'some link to somewhere'
  27. const result = htmlCleanup(source)
  28. assert.equal(result, should, source)
  29. })
  30. it('keeps link', () => {
  31. const source = '<p><a href="some_link">some link to somewhere</a></p>'
  32. const should = '<a href="some_link">some link to somewhere</a>'
  33. const result = htmlCleanup(source)
  34. assert.equal(result, should, source)
  35. })
  36. it('removes wrapper', () => {
  37. const source = '<div><h1>some link to somewhere</h1></div>'
  38. const should = '<h1>some link to somewhere</h1>'
  39. const result = htmlCleanup(source)
  40. assert.equal(result, should, source)
  41. })
  42. // This is done on backend
  43. // source = '<div><p id="123" data-id="abc">some link to somewhere</p></div>'
  44. // should = '<p>some link to somewhere</p>'
  45. // result = htmlCleanup(source)
  46. // assert.equal(result, should, source)
  47. it('removes "small" tag', () => {
  48. const source = '<div><small>some link to somewhere</small></a>'
  49. const should = 'some link to somewhere'
  50. const result = htmlCleanup(source)
  51. assert.equal(result, should, source)
  52. })
  53. it('removes "time" tag', () => {
  54. const source = '<div><time>some link to somewhere</time></a>'
  55. const should = 'some link to somewhere'
  56. const result = htmlCleanup(source)
  57. assert.equal(result, should, source)
  58. })
  59. it('removes wrapper for several children', () => {
  60. const source = '<div><h1>some h1 for somewhere</h1><p><hr></p></div>'
  61. const should = '<h1>some h1 for somewhere</h1><p></p><hr><p></p>'
  62. const result = htmlCleanup(source)
  63. assert.equal(result, should, source)
  64. })
  65. it('removes wrapper for "br"', () => {
  66. const source = '<div><br></div>'
  67. const should = '<br>'
  68. const result = htmlCleanup(source)
  69. assert.equal(result, should, source)
  70. })
  71. it('keeps inner div', () => {
  72. const source = '<div><div class="xxx"><br></div></div>'
  73. const should = '<div class="xxx"><br></div>'
  74. const result = htmlCleanup(source)
  75. assert.equal(result, should, source)
  76. })
  77. it('removes form', () => {
  78. const source = '<div><form class="xxx">test 123</form></div>'
  79. const should = 'test 123'
  80. const result = htmlCleanup(source)
  81. assert.equal(result, should, source)
  82. })
  83. it('removes subform', () => {
  84. const source =
  85. '<div><form class="xxx">test 123</form> some other value</div>'
  86. const should = 'test 123 some other value'
  87. const result = htmlCleanup(source)
  88. assert.equal(result, should, source)
  89. })
  90. it('removes form tag and input', () => {
  91. const source =
  92. '<div><form class="xxx">test 123</form> some other value<input value="should not be shown"></div>'
  93. const should = 'test 123 some other value'
  94. const result = htmlCleanup(source)
  95. assert.equal(result, should, source)
  96. })
  97. it('removes svg', () => {
  98. const source =
  99. '<div><font size="3" color="red">This is some text!</font><svg><use xlink:href="assets/images/icons.svg#icon-status"></svg></div>'
  100. const should = '<font size="3" color="red">This is some text!</font>'
  101. const result = htmlCleanup(source)
  102. assert.equal(result, should, source)
  103. })
  104. it('removes "w" an "o" tags', () => {
  105. const source =
  106. '<div><p>some link to somewhere from word<w:sdt>abc</w:sdt></p><o:p></o:p></a>'
  107. // should = "<div><p>some link to somewhere from wordabc</p></div>"
  108. const should = '<p>some link to somewhere from wordabc</p>'
  109. const result = htmlCleanup(source)
  110. assert.equal(result, should, source)
  111. })
  112. it('clears external tags', () => {
  113. const source =
  114. '<div><div><label for="Ticket_888344_group_id">Gruppe <span>*</span></label></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div><label for="Ticket_888344_owner_id">Besitzer <span></span></label></div><div><div></div></div></div><div><div><div><svg><use xlink:href="http://localhost:3000/assets/images/icons.svg#icon-arrow-down"></use></svg></div><span></span><span></span></div></div><div><div> <label for="Ticket_888344_state_id">Status <span>*</span></label></div></div></div>\n'
  115. // should = "<div>test 123</div>"
  116. const should =
  117. '<div>Gruppe <span>*</span></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div>Besitzer <span></span></div><div><div></div></div></div><div><div><div></div><span></span><span></span></div></div><div><div> Status <span>*</span></div></div>'
  118. const result = htmlCleanup(source)
  119. assert.equal(result, should, source)
  120. })
  121. it('clears html head', () => {
  122. const source =
  123. '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">\n<html>\n<head>\n <meta http-equiv="content-type" content="text/html; charset=utf-8"/>\n <title></title>\n <meta name="generator" content="LibreOffice 4.4.7.2 (MacOSX)"/>\n <style type="text/css">\n @page { margin: 0.79in }\n p { margin-bottom: 0.1in; line-height: 120% }\n a:link { so-language: zxx }\n </style>\n</head>\n<body lang="en-US" dir="ltr">\n<p align="center" style="margin-bottom: 0in; line-height: 100%">1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%"><br/>\n\n</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">2.\nMel<font color="#800000">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">Benutzer:\nme@xxx.net</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">Passwort:\nxxx.</p>\n</body>\n</html>'
  124. const should =
  125. '\n\n\n \n \n \n \n\n\n<p align="center" style="margin-bottom: 0in; line-height: 100%">1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%"><br>\n\n</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">2.\nMel<font color="#800000">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">Benutzer:\nme@xxx.net</p>\n<p align="center" style="margin-bottom: 0in; line-height: 100%">Passwort:\nxxx.</p>\n\n'
  126. const result = htmlCleanup(source)
  127. assert.equal(result, should, source)
  128. })
  129. it('clears table', () => {
  130. const source =
  131. '<table bgcolor="green" aaa="1"><thead><tr><th colspan="2" abc="a">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>'
  132. const should =
  133. '<thead><tr><th colspan="2" abc="a">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody>'
  134. const result = htmlCleanup(source)
  135. assert.equal(result, should, source)
  136. })
  137. // strip out browser-inserted (broken) link (see https://github.com/zammad/zammad/issues/2019)
  138. // should not be possible in the new tech stack
  139. // source =
  140. // '<div><a href="https://example.com/#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}">test</a></div>'
  141. // should =
  142. // '<a href="#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}">test</a>'
  143. // result = htmlCleanup(source)
  144. // assert.equal(result, should, source)
  145. // this is done on the backend now
  146. // source =
  147. // '<table bgcolor="green" aaa="1" style="color: red"><thead><tr style="margin-top: 10px"><th colspan="2" abc="a" style="margin-top: 12px">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>'
  148. // should =
  149. // '<table bgcolor="green" style="color:red;"><thead><tr style="margin-top:10px;"><th colspan="2" style="margin-top:12px;">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>'
  150. // result = htmlCleanup(source)
  151. // result.get(0).outerHTML
  152. // // equal(result.get(0).outerHTML, should, source) / string order is different on browsers
  153. // assert.equal(result.first().attr('bgcolor'), 'green')
  154. // assert.equal(result.first().attr('style'), 'color:red;')
  155. // assert.equal(result.first().attr('aaa'), undefined)
  156. // assert.equal(result.find('tr').first().attr('style'), 'margin-top:10px;')
  157. // assert.equal(result.find('th').first().attr('colspan'), '2')
  158. // assert.equal(result.find('th').first().attr('abc'), undefined)
  159. // assert.equal(result.find('th').first().attr('style'), 'margin-top:12px;')
  160. // source =
  161. // '<table bgcolor="green" aaa="1" style="color:red; display: none;"><thead><tr><th colspan="2" abc="a">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>'
  162. // should =
  163. // '<table bgcolor="green" style="color:red;"><thead><tr><th colspan="2">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>'
  164. // result = htmlCleanup(source)
  165. // // equal(result.get(0).outerHTML, should, source) / string order is different on browsers
  166. // assert.equal(result.first().attr('bgcolor'), 'green')
  167. // assert.equal(result.first().attr('style'), 'color:red;')
  168. // assert.equal(result.first().attr('aaa'), undefined)
  169. // assert.equal(result.find('tr').first().attr('style'), undefined)
  170. // assert.equal(result.find('th').first().attr('colspan'), '2')
  171. // assert.equal(result.find('th').first().attr('abc'), undefined)
  172. // assert.equal(result.find('th').first().attr('style'), undefined)
  173. // https://github.com/zammad/zammad/issues/4445
  174. // source =
  175. // '<meta charset=\'utf-8\'><span style="color: rgb(219, 219, 220);">This is a black font colour with white background</span>'
  176. // should = '<span>This is a black font colour with white background</span>'
  177. // result = htmlCleanup(source)
  178. // assert.equal(result, should, source)
  179. // source =
  180. // '<meta charset=\'utf-8\'><div class="article-content" style="box-sizing: border-box; color: rgb(219, 219, 220); position: relative; z-index: 1; padding: 0px 55px;"><div class="bubble-gap" style="box-sizing: border-box;"><div class="internal-border" style="box-sizing: border-box; padding: 5px; border-radius: 5px; margin: -5px;"><div class="textBubble" style="box-sizing: border-box; padding: 10px 20px; background: var(--background-article-customer); border-radius: 2px; border-color: var(--border-article-customer); box-shadow: none; position: relative;"><div class="textBubble-content" id="article-content-4" data-id="4" style="box-sizing: border-box; overflow: hidden; position: relative;"><div class="richtext-content" style="box-sizing: border-box;"><div style="box-sizing: border-box;">This is a black font colour with white background</div></div></div></div></div></div></div>'
  181. // should =
  182. // '<div><div><div><div><div id="article-content-4"><div><div>This is a black font colour with white background</div></div></div></div></div></div></div>'
  183. // result = htmlCleanup(source)
  184. // assert.equal(result, should, source)
  185. })