aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/core-utils/renderer/html.ts
blob: 877f2ec5505dff05f4a584396551df158de3dddf (plain) (blame)
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
export function getDefaultSanitizeOptions () {
  return {
    allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
    allowedSchemes: [ 'http', 'https' ],
    allowedAttributes: {
      'a': [ 'href', 'class', 'target', 'rel' ],
      '*': [ 'data-*' ]
    },
    transformTags: {
      a: (tagName: string, attribs: any) => {
        let rel = 'noopener noreferrer'
        if (attribs.rel === 'me') rel += ' me'

        return {
          tagName,
          attribs: Object.assign(attribs, {
            target: '_blank',
            rel
          })
        }
      }
    }
  }
}

export function getTextOnlySanitizeOptions () {
  return {
    allowedTags: [] as string[]
  }
}

export function getCustomMarkupSanitizeOptions (additionalAllowedTags: string[] = []) {
  const base = getDefaultSanitizeOptions()

  return {
    allowedTags: [
      ...base.allowedTags,
      ...additionalAllowedTags,
      'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img'
    ],
    allowedSchemes: [
      ...base.allowedSchemes,

      'mailto'
    ],
    allowedAttributes: {
      ...base.allowedAttributes,

      'img': [ 'src', 'alt' ],
      '*': [ 'data-*', 'style' ]
    }
  }
}

// Thanks: https://stackoverflow.com/a/12034334
export function escapeHTML (stringParam: string) {
  if (!stringParam) return ''

  const entityMap = {
    '&': '&',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    '\'': '&#39;',
    '/': '&#x2F;',
    '`': '&#x60;',
    '=': '&#x3D;'
  }

  return String(stringParam).replace(/[&<>"'`=/]/g, s => entityMap[s])
}