opening.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict'
  2. var is = require('unist-util-is')
  3. var element = require('hast-util-is-element')
  4. var before = require('./util/siblings').before
  5. var first = require('./util/first')
  6. var place = require('./util/place')
  7. var whiteSpaceLeft = require('./util/white-space-left')
  8. var closing = require('./closing')
  9. var omission = require('./omission')
  10. var own = {}.hasOwnProperty
  11. var uniqueHeadMetadata = ['title', 'base']
  12. var meta = ['meta', 'link', 'script', 'style', 'template']
  13. var tableContainers = ['thead', 'tbody']
  14. var tableRow = 'tr'
  15. module.exports = omission({
  16. html: html,
  17. head: head,
  18. body: body,
  19. colgroup: colgroup,
  20. tbody: tbody
  21. })
  22. /* Whether to omit `<html>`. */
  23. function html(node) {
  24. var head = first(node)
  25. return !head || !is('comment', head)
  26. }
  27. /* Whether to omit `<head>`. */
  28. function head(node) {
  29. var children = node.children
  30. var length = children.length
  31. var map = {}
  32. var index = -1
  33. var child
  34. var name
  35. while (++index < length) {
  36. child = children[index]
  37. name = child.tagName
  38. if (element(child, uniqueHeadMetadata)) {
  39. if (own.call(map, name)) {
  40. return false
  41. }
  42. map[name] = true
  43. }
  44. }
  45. return Boolean(length)
  46. }
  47. /* Whether to omit `<body>`. */
  48. function body(node) {
  49. var head = first(node, true)
  50. return (
  51. !head ||
  52. (!is('comment', head) && !whiteSpaceLeft(head) && !element(head, meta))
  53. )
  54. }
  55. /* Whether to omit `<colgroup>`.
  56. * The spec describes some logic for the opening tag,
  57. * but it’s easier to implement in the closing tag, to
  58. * the same effect, so we handle it there instead. */
  59. function colgroup(node, index, parent) {
  60. var prev = before(parent, index)
  61. var head = first(node, true)
  62. /* Previous colgroup was already omitted. */
  63. if (element(prev, 'colgroup') && closing(prev, place(parent, prev), parent)) {
  64. return false
  65. }
  66. return head && element(head, 'col')
  67. }
  68. /* Whether to omit `<tbody>`. */
  69. function tbody(node, index, parent) {
  70. var prev = before(parent, index)
  71. var head = first(node)
  72. /* Previous table section was already omitted. */
  73. if (
  74. element(prev, tableContainers) &&
  75. closing(prev, place(parent, prev), parent)
  76. ) {
  77. return false
  78. }
  79. return head && element(head, tableRow)
  80. }