closing.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. 'use strict'
  2. var is = require('unist-util-is')
  3. var element = require('hast-util-is-element')
  4. var whiteSpaceLeft = require('./util/white-space-left')
  5. var after = require('./util/siblings').after
  6. var omission = require('./omission')
  7. var optionGroup = 'optgroup'
  8. var options = ['option'].concat(optionGroup)
  9. var dataListItem = ['dt', 'dd']
  10. var listItem = 'li'
  11. var menuContent = ['menuitem', 'hr', 'menu']
  12. var ruby = ['rp', 'rt']
  13. var tableContainer = ['tbody', 'tfoot']
  14. var tableRow = 'tr'
  15. var tableCell = ['td', 'th']
  16. var confusingParagraphParent = [
  17. 'a',
  18. 'audio',
  19. 'del',
  20. 'ins',
  21. 'map',
  22. 'noscript',
  23. 'video'
  24. ]
  25. var clearParagraphSibling = [
  26. 'address',
  27. 'article',
  28. 'aside',
  29. 'blockquote',
  30. 'details',
  31. 'div',
  32. 'dl',
  33. 'fieldset',
  34. 'figcaption',
  35. 'figure',
  36. 'footer',
  37. 'form',
  38. 'h1',
  39. 'h2',
  40. 'h3',
  41. 'h4',
  42. 'h5',
  43. 'h6',
  44. 'header',
  45. 'hgroup',
  46. 'hr',
  47. 'main',
  48. 'menu',
  49. 'nav',
  50. 'ol',
  51. 'p',
  52. 'pre',
  53. 'section',
  54. 'table',
  55. 'ul'
  56. ]
  57. module.exports = omission({
  58. html: html,
  59. head: headOrColgroupOrCaption,
  60. body: body,
  61. p: p,
  62. li: li,
  63. dt: dt,
  64. dd: dd,
  65. rt: rubyElement,
  66. rp: rubyElement,
  67. optgroup: optgroup,
  68. option: option,
  69. menuitem: menuitem,
  70. colgroup: headOrColgroupOrCaption,
  71. caption: headOrColgroupOrCaption,
  72. thead: thead,
  73. tbody: tbody,
  74. tfoot: tfoot,
  75. tr: tr,
  76. td: cells,
  77. th: cells
  78. })
  79. /* Macro for `</head>`, `</colgroup>`, and `</caption>`. */
  80. function headOrColgroupOrCaption(node, index, parent) {
  81. var next = after(parent, index, true)
  82. return !next || (!is('comment', next) && !whiteSpaceLeft(next))
  83. }
  84. /* Whether to omit `</html>`. */
  85. function html(node, index, parent) {
  86. var next = after(parent, index)
  87. return !next || !is('comment', next)
  88. }
  89. /* Whether to omit `</body>`. */
  90. function body(node, index, parent) {
  91. var next = after(parent, index)
  92. return !next || !is('comment', next)
  93. }
  94. /* Whether to omit `</p>`. */
  95. function p(node, index, parent) {
  96. var next = after(parent, index)
  97. return next
  98. ? element(next, clearParagraphSibling)
  99. : !parent || !element(parent, confusingParagraphParent)
  100. }
  101. /* Whether to omit `</li>`. */
  102. function li(node, index, parent) {
  103. var next = after(parent, index)
  104. return !next || element(next, listItem)
  105. }
  106. /* Whether to omit `</dt>`. */
  107. function dt(node, index, parent) {
  108. var next = after(parent, index)
  109. return next && element(next, dataListItem)
  110. }
  111. /* Whether to omit `</dd>`. */
  112. function dd(node, index, parent) {
  113. var next = after(parent, index)
  114. return !next || element(next, dataListItem)
  115. }
  116. /* Whether to omit `</rt>` or `</rp>`. */
  117. function rubyElement(node, index, parent) {
  118. var next = after(parent, index)
  119. return !next || element(next, ruby)
  120. }
  121. /* Whether to omit `</optgroup>`. */
  122. function optgroup(node, index, parent) {
  123. var next = after(parent, index)
  124. return !next || element(next, optionGroup)
  125. }
  126. /* Whether to omit `</option>`. */
  127. function option(node, index, parent) {
  128. var next = after(parent, index)
  129. return !next || element(next, options)
  130. }
  131. /* Whether to omit `</menuitem>`. */
  132. function menuitem(node, index, parent) {
  133. var next = after(parent, index)
  134. return !next || element(next, menuContent)
  135. }
  136. /* Whether to omit `</thead>`. */
  137. function thead(node, index, parent) {
  138. var next = after(parent, index)
  139. return next && element(next, tableContainer)
  140. }
  141. /* Whether to omit `</tbody>`. */
  142. function tbody(node, index, parent) {
  143. var next = after(parent, index)
  144. return !next || element(next, tableContainer)
  145. }
  146. /* Whether to omit `</tfoot>`. */
  147. function tfoot(node, index, parent) {
  148. return !after(parent, index)
  149. }
  150. /* Whether to omit `</tr>`. */
  151. function tr(node, index, parent) {
  152. var next = after(parent, index)
  153. return !next || element(next, tableRow)
  154. }
  155. /* Whether to omit `</td>` or `</th>`. */
  156. function cells(node, index, parent) {
  157. var next = after(parent, index)
  158. return !next || element(next, tableCell)
  159. }