# All files / src/util sanitizer.js

97.3% Statements 36/37
86.36% Branches 19/22
100% Functions 4/4
97.22% Lines 35/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128

    3x

    3x

    3x

    3x

    3x
    270x

    270x
    269x
    1x

    268x

    6x

    1x
    1x
    1x

    3x

    70x
    1x

    69x
    1x

    68x
    68x
    68x
    68x

    68x
    211x
    211x

    211x
    2x

    2x

    209x
    209x

    209x
    270x
    1x

    68x

     /**
     * --------------------------------------------------------------------------
     * Bootstrap (v5.0.0-alpha1): util/sanitizer.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
     * --------------------------------------------------------------------------
     */

    const uriAttrs = [
      'background',
      'cite',
      'href',
      'itemtype',
      'longdesc',
      'poster',
      'src',
      'xlink:href'
    ]

    const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i

    /**
     * A pattern that recognizes a commonly useful subset of URLs that are safe.
     *
     * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
     */
    const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi

    /**
     * A pattern that matches safe data URLs. Only matches image, video and audio types.
     *
     * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
     */
    const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i

    const allowedAttribute = (attr, allowedAttributeList) => {
      const attrName = attr.nodeName.toLowerCase()

      if (allowedAttributeList.indexOf(attrName) !== -1) {
        if (uriAttrs.indexOf(attrName) !== -1) {
          return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
        }

        return true
      }

      const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp)

      // Check if a regular expression validates the attribute.
      for (let i = 0, len = regExp.length; i < len; i++) {
        Eif (attrName.match(regExp[i])) {
          return true
        }
      }

      return false
    }

    export const DefaultWhitelist = {
      // Global attributes allowed on any supplied element below.
      '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
      a: ['target', 'href', 'title', 'rel'],
      area: [],
      b: [],
      br: [],
      col: [],
      code: [],
      div: [],
      em: [],
      hr: [],
      h1: [],
      h2: [],
      h3: [],
      h4: [],
      h5: [],
      h6: [],
      i: [],
      img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
      li: [],
      ol: [],
      p: [],
      pre: [],
      s: [],
      small: [],
      span: [],
      sub: [],
      sup: [],
      strong: [],
      u: [],
      ul: []
    }

    export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
      if (!unsafeHtml.length) {
        return unsafeHtml
      }

      if (sanitizeFn && typeof sanitizeFn === 'function') {
        return sanitizeFn(unsafeHtml)
      }

      const domParser = new window.DOMParser()
      const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
      const whitelistKeys = Object.keys(whiteList)
      const elements = [].concat(...createdDocument.body.querySelectorAll('*'))

      for (let i = 0, len = elements.length; i < len; i++) {
        const el = elements[i]
        const elName = el.nodeName.toLowerCase()

        if (whitelistKeys.indexOf(elName) === -1) {
          el.parentNode.removeChild(el)

          continue
        }

        const attributeList = [].concat(...el.attributes)
        const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])

        attributeList.forEach(attr => {
          if (!allowedAttribute(attr, whitelistedAttributes)) {
            el.removeAttribute(attr.nodeName)
          }
        })
      }

      return createdDocument.body.innerHTML
    }