@webex/helper-html 3.0.0-beta.8 → 3.0.0-bnr.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/browsers.js CHANGED
@@ -6,10 +6,10 @@
6
6
 
7
7
  'use strict';
8
8
 
9
- module.exports = function(browsers) {
9
+ module.exports = function (browsers) {
10
10
  // For reasons as-yet unexplained, the html filter test suite hangs when run
11
11
  // on Safari/Sauce Labs
12
- Object.keys(browsers).forEach(function(key) {
12
+ Object.keys(browsers).forEach(function (key) {
13
13
  if (key.indexOf('safari') !== -1) {
14
14
  delete browsers[key];
15
15
  }
package/dist/html-base.js CHANGED
@@ -1,22 +1,20 @@
1
1
  "use strict";
2
2
 
3
3
  var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
-
5
4
  var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
6
-
7
5
  _Object$defineProperty(exports, "__esModule", {
8
6
  value: true
9
7
  });
10
-
11
8
  exports.escape = escape;
12
9
  exports.escapeSync = escapeSync;
13
-
14
10
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
15
-
16
11
  /*!
17
12
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
18
13
  */
19
- var escapeMe = /(<|>|&)/g; // escape and escapeSync probably don't both need to exist, but it seemed like a
14
+
15
+ var escapeMe = /(<|>|&)/g;
16
+
17
+ // escape and escapeSync probably don't both need to exist, but it seemed like a
20
18
  // good idea in case we ever want to for the future.
21
19
 
22
20
  /**
@@ -24,40 +22,34 @@ var escapeMe = /(<|>|&)/g; // escape and escapeSync probably don't both need to
24
22
  * @param {[type]} html
25
23
  * @returns {[type]}
26
24
  */
27
-
28
25
  function escape(html) {
29
26
  return new _promise.default(function (resolve) {
30
27
  return resolve(escapeSync(html));
31
28
  });
32
29
  }
30
+
33
31
  /**
34
32
  * Synchronously escape HTML
35
33
  * @param {[type]} html
36
34
  * @returns {[type]}
37
35
  */
38
-
39
-
40
36
  function escapeSync(html) {
41
37
  return html.replace(escapeMe, entityReplacer);
42
38
  }
39
+
43
40
  /**
44
41
  * @param {string} char
45
42
  * @private
46
43
  * @returns {string}
47
44
  */
48
-
49
-
50
45
  function entityReplacer(char) {
51
46
  switch (char) {
52
47
  case '<':
53
48
  return '&lt;';
54
-
55
49
  case '>':
56
50
  return '&gt;';
57
-
58
51
  case '&':
59
52
  return '&amp;';
60
-
61
53
  default:
62
54
  return char;
63
55
  }
@@ -1 +1 @@
1
- {"version":3,"names":["escapeMe","escape","html","resolve","escapeSync","replace","entityReplacer","char"],"sources":["html-base.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nconst escapeMe = /(<|>|&)/g;\n\n// escape and escapeSync probably don't both need to exist, but it seemed like a\n// good idea in case we ever want to for the future.\n\n/**\n * Escapes HTML\n * @param {[type]} html\n * @returns {[type]}\n */\nexport function escape(html) {\n return new Promise((resolve) => resolve(escapeSync(html)));\n}\n\n/**\n * Synchronously escape HTML\n * @param {[type]} html\n * @returns {[type]}\n */\nexport function escapeSync(html) {\n return html.replace(escapeMe, entityReplacer);\n}\n\n/**\n * @param {string} char\n * @private\n * @returns {string}\n */\nfunction entityReplacer(char) {\n switch (char) {\n case '<':\n return '&lt;';\n case '>':\n return '&gt;';\n case '&':\n return '&amp;';\n default:\n return char;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AACA;AACA;AAEA,IAAMA,QAAQ,GAAG,UAAjB,C,CAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AACO,SAASC,MAAT,CAAgBC,IAAhB,EAAsB;EAC3B,OAAO,qBAAY,UAACC,OAAD;IAAA,OAAaA,OAAO,CAACC,UAAU,CAACF,IAAD,CAAX,CAApB;EAAA,CAAZ,CAAP;AACD;AAED;AACA;AACA;AACA;AACA;;;AACO,SAASE,UAAT,CAAoBF,IAApB,EAA0B;EAC/B,OAAOA,IAAI,CAACG,OAAL,CAAaL,QAAb,EAAuBM,cAAvB,CAAP;AACD;AAED;AACA;AACA;AACA;AACA;;;AACA,SAASA,cAAT,CAAwBC,IAAxB,EAA8B;EAC5B,QAAQA,IAAR;IACE,KAAK,GAAL;MACE,OAAO,MAAP;;IACF,KAAK,GAAL;MACE,OAAO,MAAP;;IACF,KAAK,GAAL;MACE,OAAO,OAAP;;IACF;MACE,OAAOA,IAAP;EARJ;AAUD"}
1
+ {"version":3,"names":["escapeMe","escape","html","resolve","escapeSync","replace","entityReplacer","char"],"sources":["html-base.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nconst escapeMe = /(<|>|&)/g;\n\n// escape and escapeSync probably don't both need to exist, but it seemed like a\n// good idea in case we ever want to for the future.\n\n/**\n * Escapes HTML\n * @param {[type]} html\n * @returns {[type]}\n */\nexport function escape(html) {\n return new Promise((resolve) => resolve(escapeSync(html)));\n}\n\n/**\n * Synchronously escape HTML\n * @param {[type]} html\n * @returns {[type]}\n */\nexport function escapeSync(html) {\n return html.replace(escapeMe, entityReplacer);\n}\n\n/**\n * @param {string} char\n * @private\n * @returns {string}\n */\nfunction entityReplacer(char) {\n switch (char) {\n case '<':\n return '&lt;';\n case '>':\n return '&gt;';\n case '&':\n return '&amp;';\n default:\n return char;\n }\n}\n"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;;AAEA,IAAMA,QAAQ,GAAG,UAAU;;AAE3B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACO,SAASC,MAAM,CAACC,IAAI,EAAE;EAC3B,OAAO,qBAAY,UAACC,OAAO;IAAA,OAAKA,OAAO,CAACC,UAAU,CAACF,IAAI,CAAC,CAAC;EAAA,EAAC;AAC5D;;AAEA;AACA;AACA;AACA;AACA;AACO,SAASE,UAAU,CAACF,IAAI,EAAE;EAC/B,OAAOA,IAAI,CAACG,OAAO,CAACL,QAAQ,EAAEM,cAAc,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASA,cAAc,CAACC,IAAI,EAAE;EAC5B,QAAQA,IAAI;IACV,KAAK,GAAG;MACN,OAAO,MAAM;IACf,KAAK,GAAG;MACN,OAAO,MAAM;IACf,KAAK,GAAG;MACN,OAAO,OAAO;IAChB;MACE,OAAOA,IAAI;EAAC;AAElB"}
package/dist/html.js CHANGED
@@ -1,35 +1,26 @@
1
1
  "use strict";
2
2
 
3
3
  var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
-
5
4
  var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
6
-
7
5
  _Object$defineProperty(exports, "__esModule", {
8
6
  value: true
9
7
  });
10
-
11
8
  _Object$defineProperty(exports, "escape", {
12
9
  enumerable: true,
13
10
  get: function get() {
14
11
  return _htmlBase.escape;
15
12
  }
16
13
  });
17
-
18
14
  _Object$defineProperty(exports, "escapeSync", {
19
15
  enumerable: true,
20
16
  get: function get() {
21
17
  return _htmlBase.escapeSync;
22
18
  }
23
19
  });
24
-
25
20
  exports.filterSync = exports.filterEscapeSync = exports.filterEscape = exports.filter = void 0;
26
-
27
21
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
28
-
29
22
  var _curry2 = _interopRequireDefault(require("lodash/curry"));
30
-
31
23
  var _htmlBase = require("./html-base");
32
-
33
24
  /**
34
25
  * @param {Object} allowedTags
35
26
  * @param {Array<string>} allowedStyles
@@ -41,11 +32,11 @@ function noop() {
41
32
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
42
33
  args[_key] = arguments[_key];
43
34
  }
44
-
45
35
  return new _promise.default(function (resolve) {
46
36
  resolve(noopSync.apply(void 0, args));
47
37
  });
48
38
  }
39
+
49
40
  /**
50
41
  * @param {function} processCallback callback function to do additional
51
42
  * processing on node. of the form process(node)
@@ -55,12 +46,9 @@ function noop() {
55
46
  * @private
56
47
  * @returns {string}
57
48
  */
58
-
59
-
60
49
  function noopSync(processCallback, allowedTags, allowedStyles, html) {
61
50
  return html;
62
51
  }
63
-
64
52
  var filter = (0, _curry2.default)(noop, 4);
65
53
  exports.filter = filter;
66
54
  var filterSync = (0, _curry2.default)(noopSync, 4);
package/dist/html.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["noop","args","resolve","noopSync","processCallback","allowedTags","allowedStyles","html","filter","filterSync","filterEscape","filterEscapeSync"],"sources":["html.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {curry} from 'lodash';\n\nexport {escape, escapeSync} from './html-base';\n\n/**\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction noop(...args) {\n return new Promise((resolve) => {\n resolve(noopSync(...args));\n });\n}\n\n/**\n * @param {function} processCallback callback function to do additional\n * processing on node. of the form process(node)\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction noopSync(processCallback, allowedTags, allowedStyles, html) {\n return html;\n}\n\nexport const filter = curry(noop, 4);\nexport const filterSync = curry(noopSync, 4);\nexport const filterEscape = curry(noop, 4);\nexport const filterEscapeSync = curry(noopSync, 4);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,IAAT,GAAuB;EAAA,kCAANC,IAAM;IAANA,IAAM;EAAA;;EACrB,OAAO,qBAAY,UAACC,OAAD,EAAa;IAC9BA,OAAO,CAACC,QAAQ,MAAR,SAAYF,IAAZ,CAAD,CAAP;EACD,CAFM,CAAP;AAGD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,SAASE,QAAT,CAAkBC,eAAlB,EAAmCC,WAAnC,EAAgDC,aAAhD,EAA+DC,IAA/D,EAAqE;EACnE,OAAOA,IAAP;AACD;;AAEM,IAAMC,MAAM,GAAG,qBAAMR,IAAN,EAAY,CAAZ,CAAf;;AACA,IAAMS,UAAU,GAAG,qBAAMN,QAAN,EAAgB,CAAhB,CAAnB;;AACA,IAAMO,YAAY,GAAG,qBAAMV,IAAN,EAAY,CAAZ,CAArB;;AACA,IAAMW,gBAAgB,GAAG,qBAAMR,QAAN,EAAgB,CAAhB,CAAzB"}
1
+ {"version":3,"names":["noop","args","resolve","noopSync","processCallback","allowedTags","allowedStyles","html","filter","filterSync","filterEscape","filterEscapeSync"],"sources":["html.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {curry} from 'lodash';\n\nexport {escape, escapeSync} from './html-base';\n\n/**\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction noop(...args) {\n return new Promise((resolve) => {\n resolve(noopSync(...args));\n });\n}\n\n/**\n * @param {function} processCallback callback function to do additional\n * processing on node. of the form process(node)\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction noopSync(processCallback, allowedTags, allowedStyles, html) {\n return html;\n}\n\nexport const filter = curry(noop, 4);\nexport const filterSync = curry(noopSync, 4);\nexport const filterEscape = curry(noop, 4);\nexport const filterEscapeSync = curry(noopSync, 4);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAMA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,IAAI,GAAU;EAAA,kCAANC,IAAI;IAAJA,IAAI;EAAA;EACnB,OAAO,qBAAY,UAACC,OAAO,EAAK;IAC9BA,OAAO,CAACC,QAAQ,eAAIF,IAAI,CAAC,CAAC;EAC5B,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASE,QAAQ,CAACC,eAAe,EAAEC,WAAW,EAAEC,aAAa,EAAEC,IAAI,EAAE;EACnE,OAAOA,IAAI;AACb;AAEO,IAAMC,MAAM,GAAG,qBAAMR,IAAI,EAAE,CAAC,CAAC;AAAC;AAC9B,IAAMS,UAAU,GAAG,qBAAMN,QAAQ,EAAE,CAAC,CAAC;AAAC;AACtC,IAAMO,YAAY,GAAG,qBAAMV,IAAI,EAAE,CAAC,CAAC;AAAC;AACpC,IAAMW,gBAAgB,GAAG,qBAAMR,QAAQ,EAAE,CAAC,CAAC;AAAC"}
package/dist/html.shim.js CHANGED
@@ -1,43 +1,30 @@
1
1
  "use strict";
2
2
 
3
3
  var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
-
5
4
  var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
6
-
7
5
  _Object$defineProperty(exports, "__esModule", {
8
6
  value: true
9
7
  });
10
-
11
8
  _Object$defineProperty(exports, "escape", {
12
9
  enumerable: true,
13
10
  get: function get() {
14
11
  return _htmlBase.escape;
15
12
  }
16
13
  });
17
-
18
14
  _Object$defineProperty(exports, "escapeSync", {
19
15
  enumerable: true,
20
16
  get: function get() {
21
17
  return _htmlBase.escapeSync;
22
18
  }
23
19
  });
24
-
25
20
  exports.filterSync = exports.filterEscapeSync = exports.filterEscape = exports.filter = void 0;
26
-
27
21
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
28
-
29
22
  var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
30
-
31
23
  var _reduce2 = _interopRequireDefault(require("lodash/reduce"));
32
-
33
24
  var _includes2 = _interopRequireDefault(require("lodash/includes"));
34
-
35
25
  var _forEach2 = _interopRequireDefault(require("lodash/forEach"));
36
-
37
26
  var _curry2 = _interopRequireDefault(require("lodash/curry"));
38
-
39
27
  var _htmlBase = require("./html-base");
40
-
41
28
  /**
42
29
  * Some browsers don't implement {@link Element#remove()} or
43
30
  * {@link NodeList#remove()} or {@link HTMLCollection#remove()}. This wrapper
@@ -51,22 +38,19 @@ function removeNode(node) {
51
38
  node.remove();
52
39
  return;
53
40
  }
54
-
55
41
  if (node.parentElement) {
56
42
  node.parentElement.removeChild(node);
57
43
  return;
58
44
  }
59
-
60
45
  if ('length' in node) {
61
46
  for (var i = node.length - 1; i >= 0; i -= 1) {
62
47
  removeNode(node[i]);
63
48
  }
64
-
65
49
  return;
66
50
  }
67
-
68
51
  throw new Error('Could not find a way to remove node');
69
52
  }
53
+
70
54
  /**
71
55
  * @param {Object} allowedTags
72
56
  * @param {Array<string>} allowedStyles
@@ -74,17 +58,15 @@ function removeNode(node) {
74
58
  * @private
75
59
  * @returns {string}
76
60
  */
77
-
78
-
79
61
  function _filter() {
80
62
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
81
63
  args[_key] = arguments[_key];
82
64
  }
83
-
84
65
  return new _promise.default(function (resolve) {
85
66
  resolve(_filterSync.apply(void 0, args));
86
67
  });
87
68
  }
69
+
88
70
  /**
89
71
  * Curried async HTML filter.
90
72
  * @param {Object} allowedTags Map of tagName -> array of allowed attributes
@@ -92,9 +74,8 @@ function _filter() {
92
74
  * @param {string} html html to filter
93
75
  * @returns {string}
94
76
  */
95
-
96
-
97
77
  var filter = (0, _curry2.default)(_filter, 4);
78
+
98
79
  /**
99
80
  * @param {function} processCallback callback function to do additional
100
81
  * processing on node. of the form process(node)
@@ -104,63 +85,54 @@ var filter = (0, _curry2.default)(_filter, 4);
104
85
  * @private
105
86
  * @returns {string}
106
87
  */
107
-
108
88
  exports.filter = filter;
109
-
110
89
  function _filterSync(processCallback, allowedTags, allowedStyles, html) {
111
90
  if (!html || !allowedStyles || !allowedTags) {
112
91
  if (html.length === 0) {
113
92
  return html;
114
93
  }
115
-
116
94
  throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');
117
95
  }
118
-
119
96
  var doc = new DOMParser().parseFromString(html, 'text/html');
120
97
  depthFirstForEach(doc.body.childNodes, filterNode);
121
98
  processCallback(doc.body);
122
-
123
99
  if (html.indexOf('body') === 1) {
124
100
  return "<body>".concat(doc.body.innerHTML, "</body>");
125
101
  }
126
-
127
102
  return doc.body.innerHTML;
103
+
128
104
  /**
129
105
  * @param {Node} node
130
106
  * @private
131
107
  * @returns {undefined}
132
108
  */
133
-
134
109
  function filterNode(node) {
135
110
  if (!isElement(node)) {
136
111
  return;
137
112
  }
138
-
139
113
  var nodeName = node.nodeName.toLowerCase();
140
114
  var allowedTagNames = (0, _keys.default)(allowedTags);
141
115
  depthFirstForEach(node.childNodes, filterNode);
142
-
143
116
  if ((0, _includes2.default)(allowedTagNames, nodeName)) {
144
117
  var allowedAttributes = allowedTags[nodeName];
145
118
  (0, _forEach2.default)(listAttributeNames(node.attributes), function (attrName) {
146
119
  if (!(0, _includes2.default)(allowedAttributes, attrName)) {
147
120
  node.removeAttribute(attrName);
148
121
  } else if (attrName === 'href' || attrName === 'src') {
149
- var attrValue = node.attributes.getNamedItem(attrName).value.trim().toLowerCase(); // We're doing at runtime what the no-script-url rule does at compile
122
+ var attrValue = node.attributes.getNamedItem(attrName).value.trim().toLowerCase();
123
+
124
+ // We're doing at runtime what the no-script-url rule does at compile
150
125
  // time
151
126
  // eslint-disable-next-line no-script-url
152
-
153
127
  if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {
154
128
  reparent(node);
155
129
  }
156
130
  } else if (attrName === 'style') {
157
131
  var styles = node.attributes.getNamedItem('style').value.split(';').map(function (style) {
158
132
  var styleName = trim(style.split(':')[0]);
159
-
160
133
  if ((0, _includes2.default)(allowedStyles, styleName)) {
161
134
  return style;
162
135
  }
163
-
164
136
  return null;
165
137
  }).filter(function (style) {
166
138
  return Boolean(style);
@@ -173,6 +145,7 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
173
145
  }
174
146
  }
175
147
  }
148
+
176
149
  /**
177
150
  * Same as _filter, but escapes rather than removes disallowed values
178
151
  * @param {Function} processCallback
@@ -181,17 +154,15 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
181
154
  * @param {string} html
182
155
  * @returns {Promise<string>}
183
156
  */
184
-
185
-
186
157
  function _filterEscape() {
187
158
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
188
159
  args[_key2] = arguments[_key2];
189
160
  }
190
-
191
161
  return new _promise.default(function (resolve) {
192
162
  resolve(_filterEscapeSync.apply(void 0, args));
193
163
  });
194
164
  }
165
+
195
166
  /**
196
167
  * Same as _filterSync, but escapes rather than removes disallowed values
197
168
  * @param {Function} processCallback
@@ -200,62 +171,53 @@ function _filterEscape() {
200
171
  * @param {string} html
201
172
  * @returns {string}
202
173
  */
203
-
204
-
205
174
  function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
206
175
  if (!html || !allowedStyles || !allowedTags) {
207
176
  if (html.length === 0) {
208
177
  return html;
209
178
  }
210
-
211
179
  throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');
212
180
  }
213
-
214
181
  var doc = new DOMParser().parseFromString(html, 'text/html');
215
182
  depthFirstForEach(doc.body.childNodes, filterNode);
216
183
  processCallback(doc.body);
217
-
218
184
  if (html.indexOf('body') === 1) {
219
185
  return "<body>".concat(doc.body.innerHTML, "</body>");
220
186
  }
221
-
222
187
  return doc.body.innerHTML;
188
+
223
189
  /**
224
190
  * @param {Node} node
225
191
  * @private
226
192
  * @returns {undefined}
227
193
  */
228
-
229
194
  function filterNode(node) {
230
195
  if (!isElement(node)) {
231
196
  return;
232
197
  }
233
-
234
198
  depthFirstForEach(node.childNodes, filterNode);
235
199
  var nodeName = node.nodeName.toLowerCase();
236
200
  var allowedTagNames = (0, _keys.default)(allowedTags);
237
-
238
201
  if ((0, _includes2.default)(allowedTagNames, nodeName)) {
239
202
  var allowedAttributes = allowedTags[nodeName];
240
203
  (0, _forEach2.default)(listAttributeNames(node.attributes), function (attrName) {
241
204
  if (!(0, _includes2.default)(allowedAttributes, attrName)) {
242
205
  node.removeAttribute(attrName);
243
206
  } else if (attrName === 'href' || attrName === 'src') {
244
- var attrValue = node.attributes.getNamedItem(attrName).value.toLowerCase(); // We're doing at runtime what the no-script-url rule does at compile
207
+ var attrValue = node.attributes.getNamedItem(attrName).value.toLowerCase();
208
+
209
+ // We're doing at runtime what the no-script-url rule does at compile
245
210
  // time
246
211
  // eslint-disable-next-line no-script-url
247
-
248
212
  if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {
249
213
  reparent(node);
250
214
  }
251
215
  } else if (attrName === 'style') {
252
216
  var styles = node.attributes.getNamedItem('style').value.split(';').map(function (style) {
253
217
  var styleName = trim(style.split(':')[0]);
254
-
255
218
  if ((0, _includes2.default)(allowedStyles, styleName)) {
256
219
  return style;
257
220
  }
258
-
259
221
  return null;
260
222
  }).filter(function (style) {
261
223
  return Boolean(style);
@@ -268,101 +230,89 @@ function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
268
230
  }
269
231
  }
270
232
  }
233
+
271
234
  /**
272
235
  * Escapes a given html node
273
236
  * @param {Node} node
274
237
  * @returns {undefined}
275
238
  */
276
-
277
-
278
239
  function escapeNode(node) {
279
240
  var before = document.createTextNode("<".concat(node.nodeName.toLowerCase(), ">"));
280
241
  var after = document.createTextNode("</".concat(node.nodeName.toLowerCase(), ">"));
281
242
  node.parentNode.insertBefore(before, node);
282
-
283
243
  while (node.childNodes.length > 0) {
284
244
  node.parentNode.insertBefore(node.childNodes[0], node);
285
245
  }
286
-
287
246
  node.parentNode.insertBefore(after, node);
288
247
  removeNode(node);
289
248
  }
290
-
291
249
  var trimPattern = /^\s|\s$/g;
250
+
292
251
  /**
293
252
  * @param {string} str
294
253
  * @returns {string}
295
254
  */
296
-
297
255
  function trim(str) {
298
256
  return str.replace(trimPattern, '');
299
257
  }
258
+
300
259
  /**
301
260
  * @param {Node} node
302
261
  * @private
303
262
  * @returns {undefined}
304
263
  */
305
-
306
-
307
264
  function reparent(node) {
308
265
  while (node.childNodes.length > 0) {
309
266
  node.parentNode.insertBefore(node.childNodes[0], node);
310
267
  }
311
-
312
268
  removeNode(node);
313
269
  }
270
+
314
271
  /**
315
272
  * @param {NamedNodeMap} attributes
316
273
  * @private
317
274
  * @returns {Array<string>}
318
275
  */
319
-
320
-
321
276
  function listAttributeNames(attributes) {
322
277
  return (0, _reduce2.default)(attributes, function (attrNames, attr) {
323
278
  attrNames.push(attr.name);
324
279
  return attrNames;
325
280
  }, []);
326
281
  }
282
+
327
283
  /**
328
284
  * @param {Array} list
329
285
  * @param {Function} fn
330
286
  * @private
331
287
  * @returns {undefined}
332
288
  */
333
-
334
-
335
289
  function depthFirstForEach(list, fn) {
336
290
  for (var i = list.length; i >= 0; i -= 1) {
337
291
  fn(list[i]);
338
292
  }
339
293
  }
294
+
340
295
  /**
341
296
  * @param {Node} o
342
297
  * @private
343
298
  * @returns {Boolean}
344
299
  */
345
-
346
-
347
300
  function isElement(o) {
348
301
  if (!o) {
349
302
  return false;
350
303
  }
351
-
352
304
  if (o.ownerDocument === undefined) {
353
305
  return false;
354
306
  }
355
-
356
307
  if (o.nodeType !== 1) {
357
308
  return false;
358
309
  }
359
-
360
310
  if (typeof o.nodeName !== 'string') {
361
311
  return false;
362
312
  }
363
-
364
313
  return true;
365
314
  }
315
+
366
316
  /**
367
317
  * Curried HTML filter.
368
318
  * @param {Object} allowedTags Map of tagName -> array of allowed attributes
@@ -370,9 +320,8 @@ function isElement(o) {
370
320
  * @param {string} html html to filter
371
321
  * @returns {string}
372
322
  */
373
-
374
-
375
323
  var filterSync = (0, _curry2.default)(_filterSync, 4);
324
+
376
325
  /**
377
326
  * Curried HTML filter that escapes rather than removes disallowed tags
378
327
  * @param {Object} allowedTags Map of tagName -> array of allowed attributes
@@ -380,9 +329,9 @@ var filterSync = (0, _curry2.default)(_filterSync, 4);
380
329
  * @param {string} html html to filter
381
330
  * @returns {Promise<string>}
382
331
  */
383
-
384
332
  exports.filterSync = filterSync;
385
333
  var filterEscape = (0, _curry2.default)(_filterEscape, 4);
334
+
386
335
  /**
387
336
  * Curried HTML filter that escapes rather than removes disallowed tags
388
337
  * @param {Object} allowedTags Map of tagName -> array of allowed attributes
@@ -390,7 +339,6 @@ var filterEscape = (0, _curry2.default)(_filterEscape, 4);
390
339
  * @param {string} html html to filter
391
340
  * @returns {string}
392
341
  */
393
-
394
342
  exports.filterEscape = filterEscape;
395
343
  var filterEscapeSync = (0, _curry2.default)(_filterEscapeSync, 4);
396
344
  exports.filterEscapeSync = filterEscapeSync;
@@ -1 +1 @@
1
- {"version":3,"names":["removeNode","node","remove","parentElement","removeChild","i","length","Error","_filter","args","resolve","_filterSync","filter","processCallback","allowedTags","allowedStyles","html","doc","DOMParser","parseFromString","depthFirstForEach","body","childNodes","filterNode","indexOf","innerHTML","isElement","nodeName","toLowerCase","allowedTagNames","allowedAttributes","listAttributeNames","attributes","attrName","removeAttribute","attrValue","getNamedItem","value","trim","reparent","styles","split","map","style","styleName","Boolean","join","setAttribute","_filterEscape","_filterEscapeSync","escapeNode","before","document","createTextNode","after","parentNode","insertBefore","trimPattern","str","replace","attrNames","attr","push","name","list","fn","o","ownerDocument","undefined","nodeType","filterSync","filterEscape","filterEscapeSync"],"sources":["html.shim.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-env browser */\n\nimport {curry, forEach, includes, reduce} from 'lodash';\n\nexport {escape, escapeSync} from './html-base';\n\n/**\n * Some browsers don't implement {@link Element#remove()} or\n * {@link NodeList#remove()} or {@link HTMLCollection#remove()}. This wrapper\n * calls the appropriate `#remove()` method if available, or falls back to a\n * non-global-polluting polyfill.\n * @param {Element|NodeList|HTMLCollection} node\n * @returns {undefined}\n */\nfunction removeNode(node) {\n if (node.remove) {\n node.remove();\n\n return;\n }\n\n if (node.parentElement) {\n node.parentElement.removeChild(node);\n\n return;\n }\n\n if ('length' in node) {\n for (let i = node.length - 1; i >= 0; i -= 1) {\n removeNode(node[i]);\n }\n\n return;\n }\n\n throw new Error('Could not find a way to remove node');\n}\n\n/**\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction _filter(...args) {\n return new Promise((resolve) => {\n resolve(_filterSync(...args));\n });\n}\n\n/**\n * Curried async HTML filter.\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filter = curry(_filter, 4);\n\n/**\n * @param {function} processCallback callback function to do additional\n * processing on node. of the form process(node)\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction _filterSync(processCallback, allowedTags, allowedStyles, html) {\n if (!html || !allowedStyles || !allowedTags) {\n if (html.length === 0) {\n return html;\n }\n\n throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');\n }\n\n const doc = (new DOMParser()).parseFromString(html, 'text/html');\n\n depthFirstForEach(doc.body.childNodes, filterNode);\n processCallback(doc.body);\n\n if (html.indexOf('body') === 1) {\n return `<body>${doc.body.innerHTML}</body>`;\n }\n\n return doc.body.innerHTML;\n\n /**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\n function filterNode(node) {\n if (!isElement(node)) {\n return;\n }\n\n const nodeName = node.nodeName.toLowerCase();\n const allowedTagNames = Object.keys(allowedTags);\n\n depthFirstForEach(node.childNodes, filterNode);\n\n if (includes(allowedTagNames, nodeName)) {\n const allowedAttributes = allowedTags[nodeName];\n\n forEach(listAttributeNames(node.attributes), (attrName) => {\n if (!includes(allowedAttributes, attrName)) {\n node.removeAttribute(attrName);\n }\n else if (attrName === 'href' || attrName === 'src') {\n const attrValue = node.attributes.getNamedItem(attrName).value.trim().toLowerCase();\n\n // We're doing at runtime what the no-script-url rule does at compile\n // time\n // eslint-disable-next-line no-script-url\n if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {\n reparent(node);\n }\n }\n else if (attrName === 'style') {\n const styles = node\n .attributes\n .getNamedItem('style')\n .value\n .split(';')\n .map((style) => {\n const styleName = trim(style.split(':')[0]);\n\n if (includes(allowedStyles, styleName)) {\n return style;\n }\n\n return null;\n })\n .filter((style) => Boolean(style))\n .join(';');\n\n node.setAttribute('style', styles);\n }\n });\n }\n else {\n reparent(node);\n }\n }\n}\n\n/**\n * Same as _filter, but escapes rather than removes disallowed values\n * @param {Function} processCallback\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @returns {Promise<string>}\n */\nfunction _filterEscape(...args) {\n return new Promise((resolve) => {\n resolve(_filterEscapeSync(...args));\n });\n}\n\n/**\n * Same as _filterSync, but escapes rather than removes disallowed values\n * @param {Function} processCallback\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @returns {string}\n */\nfunction _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {\n if (!html || !allowedStyles || !allowedTags) {\n if (html.length === 0) {\n return html;\n }\n\n throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');\n }\n\n const doc = (new DOMParser()).parseFromString(html, 'text/html');\n\n depthFirstForEach(doc.body.childNodes, filterNode);\n processCallback(doc.body);\n\n if (html.indexOf('body') === 1) {\n return `<body>${doc.body.innerHTML}</body>`;\n }\n\n return doc.body.innerHTML;\n\n /**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\n function filterNode(node) {\n if (!isElement(node)) {\n return;\n }\n\n depthFirstForEach(node.childNodes, filterNode);\n\n const nodeName = node.nodeName.toLowerCase();\n const allowedTagNames = Object.keys(allowedTags);\n\n if (includes(allowedTagNames, nodeName)) {\n const allowedAttributes = allowedTags[nodeName];\n\n forEach(listAttributeNames(node.attributes), (attrName) => {\n if (!includes(allowedAttributes, attrName)) {\n node.removeAttribute(attrName);\n }\n else if (attrName === 'href' || attrName === 'src') {\n const attrValue = node.attributes.getNamedItem(attrName).value.toLowerCase();\n\n // We're doing at runtime what the no-script-url rule does at compile\n // time\n // eslint-disable-next-line no-script-url\n if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {\n reparent(node);\n }\n }\n else if (attrName === 'style') {\n const styles = node\n .attributes\n .getNamedItem('style')\n .value\n .split(';')\n .map((style) => {\n const styleName = trim(style.split(':')[0]);\n\n if (includes(allowedStyles, styleName)) {\n return style;\n }\n\n return null;\n })\n .filter((style) => Boolean(style))\n .join(';');\n\n node.setAttribute('style', styles);\n }\n });\n }\n else {\n escapeNode(node);\n }\n }\n}\n\n/**\n * Escapes a given html node\n * @param {Node} node\n * @returns {undefined}\n */\nfunction escapeNode(node) {\n const before = document.createTextNode(`<${node.nodeName.toLowerCase()}>`);\n const after = document.createTextNode(`</${node.nodeName.toLowerCase()}>`);\n\n node.parentNode.insertBefore(before, node);\n while (node.childNodes.length > 0) {\n node.parentNode.insertBefore(node.childNodes[0], node);\n }\n node.parentNode.insertBefore(after, node);\n\n removeNode(node);\n}\n\nconst trimPattern = /^\\s|\\s$/g;\n\n/**\n * @param {string} str\n * @returns {string}\n */\nfunction trim(str) {\n return str.replace(trimPattern, '');\n}\n\n/**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\nfunction reparent(node) {\n while (node.childNodes.length > 0) {\n node.parentNode.insertBefore(node.childNodes[0], node);\n }\n removeNode(node);\n}\n\n/**\n * @param {NamedNodeMap} attributes\n * @private\n * @returns {Array<string>}\n */\nfunction listAttributeNames(attributes) {\n return reduce(attributes, (attrNames, attr) => {\n attrNames.push(attr.name);\n\n return attrNames;\n }, []);\n}\n\n/**\n * @param {Array} list\n * @param {Function} fn\n * @private\n * @returns {undefined}\n */\nfunction depthFirstForEach(list, fn) {\n for (let i = list.length; i >= 0; i -= 1) {\n fn(list[i]);\n }\n}\n\n/**\n * @param {Node} o\n * @private\n * @returns {Boolean}\n */\nfunction isElement(o) {\n if (!o) {\n return false;\n }\n\n if (o.ownerDocument === undefined) {\n return false;\n }\n\n if (o.nodeType !== 1) {\n return false;\n }\n\n if (typeof o.nodeName !== 'string') {\n return false;\n }\n\n return true;\n}\n\n/**\n * Curried HTML filter.\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filterSync = curry(_filterSync, 4);\n\n/**\n * Curried HTML filter that escapes rather than removes disallowed tags\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {Promise<string>}\n */\nexport const filterEscape = curry(_filterEscape, 4);\n\n/**\n * Curried HTML filter that escapes rather than removes disallowed tags\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filterEscapeSync = curry(_filterEscapeSync, 4);\n"],"mappings":"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"}
1
+ {"version":3,"names":["removeNode","node","remove","parentElement","removeChild","i","length","Error","_filter","args","resolve","_filterSync","filter","processCallback","allowedTags","allowedStyles","html","doc","DOMParser","parseFromString","depthFirstForEach","body","childNodes","filterNode","indexOf","innerHTML","isElement","nodeName","toLowerCase","allowedTagNames","allowedAttributes","listAttributeNames","attributes","attrName","removeAttribute","attrValue","getNamedItem","value","trim","reparent","styles","split","map","style","styleName","Boolean","join","setAttribute","_filterEscape","_filterEscapeSync","escapeNode","before","document","createTextNode","after","parentNode","insertBefore","trimPattern","str","replace","attrNames","attr","push","name","list","fn","o","ownerDocument","undefined","nodeType","filterSync","filterEscape","filterEscapeSync"],"sources":["html.shim.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-env browser */\n\nimport {curry, forEach, includes, reduce} from 'lodash';\n\nexport {escape, escapeSync} from './html-base';\n\n/**\n * Some browsers don't implement {@link Element#remove()} or\n * {@link NodeList#remove()} or {@link HTMLCollection#remove()}. This wrapper\n * calls the appropriate `#remove()` method if available, or falls back to a\n * non-global-polluting polyfill.\n * @param {Element|NodeList|HTMLCollection} node\n * @returns {undefined}\n */\nfunction removeNode(node) {\n if (node.remove) {\n node.remove();\n\n return;\n }\n\n if (node.parentElement) {\n node.parentElement.removeChild(node);\n\n return;\n }\n\n if ('length' in node) {\n for (let i = node.length - 1; i >= 0; i -= 1) {\n removeNode(node[i]);\n }\n\n return;\n }\n\n throw new Error('Could not find a way to remove node');\n}\n\n/**\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction _filter(...args) {\n return new Promise((resolve) => {\n resolve(_filterSync(...args));\n });\n}\n\n/**\n * Curried async HTML filter.\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filter = curry(_filter, 4);\n\n/**\n * @param {function} processCallback callback function to do additional\n * processing on node. of the form process(node)\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @private\n * @returns {string}\n */\nfunction _filterSync(processCallback, allowedTags, allowedStyles, html) {\n if (!html || !allowedStyles || !allowedTags) {\n if (html.length === 0) {\n return html;\n }\n\n throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');\n }\n\n const doc = new DOMParser().parseFromString(html, 'text/html');\n\n depthFirstForEach(doc.body.childNodes, filterNode);\n processCallback(doc.body);\n\n if (html.indexOf('body') === 1) {\n return `<body>${doc.body.innerHTML}</body>`;\n }\n\n return doc.body.innerHTML;\n\n /**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\n function filterNode(node) {\n if (!isElement(node)) {\n return;\n }\n\n const nodeName = node.nodeName.toLowerCase();\n const allowedTagNames = Object.keys(allowedTags);\n\n depthFirstForEach(node.childNodes, filterNode);\n\n if (includes(allowedTagNames, nodeName)) {\n const allowedAttributes = allowedTags[nodeName];\n\n forEach(listAttributeNames(node.attributes), (attrName) => {\n if (!includes(allowedAttributes, attrName)) {\n node.removeAttribute(attrName);\n } else if (attrName === 'href' || attrName === 'src') {\n const attrValue = node.attributes.getNamedItem(attrName).value.trim().toLowerCase();\n\n // We're doing at runtime what the no-script-url rule does at compile\n // time\n // eslint-disable-next-line no-script-url\n if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {\n reparent(node);\n }\n } else if (attrName === 'style') {\n const styles = node.attributes\n .getNamedItem('style')\n .value.split(';')\n .map((style) => {\n const styleName = trim(style.split(':')[0]);\n\n if (includes(allowedStyles, styleName)) {\n return style;\n }\n\n return null;\n })\n .filter((style) => Boolean(style))\n .join(';');\n\n node.setAttribute('style', styles);\n }\n });\n } else {\n reparent(node);\n }\n }\n}\n\n/**\n * Same as _filter, but escapes rather than removes disallowed values\n * @param {Function} processCallback\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @returns {Promise<string>}\n */\nfunction _filterEscape(...args) {\n return new Promise((resolve) => {\n resolve(_filterEscapeSync(...args));\n });\n}\n\n/**\n * Same as _filterSync, but escapes rather than removes disallowed values\n * @param {Function} processCallback\n * @param {Object} allowedTags\n * @param {Array<string>} allowedStyles\n * @param {string} html\n * @returns {string}\n */\nfunction _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {\n if (!html || !allowedStyles || !allowedTags) {\n if (html.length === 0) {\n return html;\n }\n\n throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');\n }\n\n const doc = new DOMParser().parseFromString(html, 'text/html');\n\n depthFirstForEach(doc.body.childNodes, filterNode);\n processCallback(doc.body);\n\n if (html.indexOf('body') === 1) {\n return `<body>${doc.body.innerHTML}</body>`;\n }\n\n return doc.body.innerHTML;\n\n /**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\n function filterNode(node) {\n if (!isElement(node)) {\n return;\n }\n\n depthFirstForEach(node.childNodes, filterNode);\n\n const nodeName = node.nodeName.toLowerCase();\n const allowedTagNames = Object.keys(allowedTags);\n\n if (includes(allowedTagNames, nodeName)) {\n const allowedAttributes = allowedTags[nodeName];\n\n forEach(listAttributeNames(node.attributes), (attrName) => {\n if (!includes(allowedAttributes, attrName)) {\n node.removeAttribute(attrName);\n } else if (attrName === 'href' || attrName === 'src') {\n const attrValue = node.attributes.getNamedItem(attrName).value.toLowerCase();\n\n // We're doing at runtime what the no-script-url rule does at compile\n // time\n // eslint-disable-next-line no-script-url\n if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {\n reparent(node);\n }\n } else if (attrName === 'style') {\n const styles = node.attributes\n .getNamedItem('style')\n .value.split(';')\n .map((style) => {\n const styleName = trim(style.split(':')[0]);\n\n if (includes(allowedStyles, styleName)) {\n return style;\n }\n\n return null;\n })\n .filter((style) => Boolean(style))\n .join(';');\n\n node.setAttribute('style', styles);\n }\n });\n } else {\n escapeNode(node);\n }\n }\n}\n\n/**\n * Escapes a given html node\n * @param {Node} node\n * @returns {undefined}\n */\nfunction escapeNode(node) {\n const before = document.createTextNode(`<${node.nodeName.toLowerCase()}>`);\n const after = document.createTextNode(`</${node.nodeName.toLowerCase()}>`);\n\n node.parentNode.insertBefore(before, node);\n while (node.childNodes.length > 0) {\n node.parentNode.insertBefore(node.childNodes[0], node);\n }\n node.parentNode.insertBefore(after, node);\n\n removeNode(node);\n}\n\nconst trimPattern = /^\\s|\\s$/g;\n\n/**\n * @param {string} str\n * @returns {string}\n */\nfunction trim(str) {\n return str.replace(trimPattern, '');\n}\n\n/**\n * @param {Node} node\n * @private\n * @returns {undefined}\n */\nfunction reparent(node) {\n while (node.childNodes.length > 0) {\n node.parentNode.insertBefore(node.childNodes[0], node);\n }\n removeNode(node);\n}\n\n/**\n * @param {NamedNodeMap} attributes\n * @private\n * @returns {Array<string>}\n */\nfunction listAttributeNames(attributes) {\n return reduce(\n attributes,\n (attrNames, attr) => {\n attrNames.push(attr.name);\n\n return attrNames;\n },\n []\n );\n}\n\n/**\n * @param {Array} list\n * @param {Function} fn\n * @private\n * @returns {undefined}\n */\nfunction depthFirstForEach(list, fn) {\n for (let i = list.length; i >= 0; i -= 1) {\n fn(list[i]);\n }\n}\n\n/**\n * @param {Node} o\n * @private\n * @returns {Boolean}\n */\nfunction isElement(o) {\n if (!o) {\n return false;\n }\n\n if (o.ownerDocument === undefined) {\n return false;\n }\n\n if (o.nodeType !== 1) {\n return false;\n }\n\n if (typeof o.nodeName !== 'string') {\n return false;\n }\n\n return true;\n}\n\n/**\n * Curried HTML filter.\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filterSync = curry(_filterSync, 4);\n\n/**\n * Curried HTML filter that escapes rather than removes disallowed tags\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {Promise<string>}\n */\nexport const filterEscape = curry(_filterEscape, 4);\n\n/**\n * Curried HTML filter that escapes rather than removes disallowed tags\n * @param {Object} allowedTags Map of tagName -> array of allowed attributes\n * @param {Array<string>} allowedStyles Array of allowed styles\n * @param {string} html html to filter\n * @returns {string}\n */\nexport const filterEscapeSync = curry(_filterEscapeSync, 4);\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,52 +1,44 @@
1
1
  "use strict";
2
2
 
3
3
  var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
-
5
4
  _Object$defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
-
9
7
  _Object$defineProperty(exports, "escape", {
10
8
  enumerable: true,
11
9
  get: function get() {
12
10
  return _html.escape;
13
11
  }
14
12
  });
15
-
16
13
  _Object$defineProperty(exports, "escapeSync", {
17
14
  enumerable: true,
18
15
  get: function get() {
19
16
  return _html.escapeSync;
20
17
  }
21
18
  });
22
-
23
19
  _Object$defineProperty(exports, "filter", {
24
20
  enumerable: true,
25
21
  get: function get() {
26
22
  return _html.filter;
27
23
  }
28
24
  });
29
-
30
25
  _Object$defineProperty(exports, "filterEscape", {
31
26
  enumerable: true,
32
27
  get: function get() {
33
28
  return _html.filterEscape;
34
29
  }
35
30
  });
36
-
37
31
  _Object$defineProperty(exports, "filterEscapeSync", {
38
32
  enumerable: true,
39
33
  get: function get() {
40
34
  return _html.filterEscapeSync;
41
35
  }
42
36
  });
43
-
44
37
  _Object$defineProperty(exports, "filterSync", {
45
38
  enumerable: true,
46
39
  get: function get() {
47
40
  return _html.filterSync;
48
41
  }
49
42
  });
50
-
51
43
  var _html = require("./html");
52
44
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["index.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nexport {escape, escapeSync, filter, filterSync, filterEscape, filterEscapeSync} from './html';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA"}
1
+ {"version":3,"names":[],"sources":["index.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nexport {escape, escapeSync, filter, filterSync, filterEscape, filterEscapeSync} from './html';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Escapes HTML
3
+ * @param {[type]} html
4
+ * @returns {[type]}
5
+ */
6
+ export function escape(html: [type]): [type];
7
+ /**
8
+ * Synchronously escape HTML
9
+ * @param {[type]} html
10
+ * @returns {[type]}
11
+ */
12
+ export function escapeSync(html: [type]): [type];
@@ -0,0 +1,5 @@
1
+ export const filter: import("lodash").CurriedFunction1<any, string>;
2
+ export const filterSync: import("lodash").CurriedFunction4<Function, any, string[], string, string>;
3
+ export const filterEscape: import("lodash").CurriedFunction1<any, string>;
4
+ export const filterEscapeSync: import("lodash").CurriedFunction4<Function, any, string[], string, string>;
5
+ export { escape, escapeSync } from "./html-base";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Curried async HTML filter.
3
+ * @param {Object} allowedTags Map of tagName -> array of allowed attributes
4
+ * @param {Array<string>} allowedStyles Array of allowed styles
5
+ * @param {string} html html to filter
6
+ * @returns {string}
7
+ */
8
+ export const filter: import("lodash").CurriedFunction1<any, string>;
9
+ /**
10
+ * Curried HTML filter.
11
+ * @param {Object} allowedTags Map of tagName -> array of allowed attributes
12
+ * @param {Array<string>} allowedStyles Array of allowed styles
13
+ * @param {string} html html to filter
14
+ * @returns {string}
15
+ */
16
+ export const filterSync: import("lodash").CurriedFunction4<Function, any, string[], string, string>;
17
+ /**
18
+ * Curried HTML filter that escapes rather than removes disallowed tags
19
+ * @param {Object} allowedTags Map of tagName -> array of allowed attributes
20
+ * @param {Array<string>} allowedStyles Array of allowed styles
21
+ * @param {string} html html to filter
22
+ * @returns {Promise<string>}
23
+ */
24
+ export const filterEscape: import("lodash").CurriedFunction1<any, Promise<string>>;
25
+ /**
26
+ * Curried HTML filter that escapes rather than removes disallowed tags
27
+ * @param {Object} allowedTags Map of tagName -> array of allowed attributes
28
+ * @param {Array<string>} allowedStyles Array of allowed styles
29
+ * @param {string} html html to filter
30
+ * @returns {string}
31
+ */
32
+ export const filterEscapeSync: import("lodash").CurriedFunction4<Function, any, string[], string, string>;
33
+ export { escape, escapeSync } from "./html-base";
@@ -0,0 +1 @@
1
+ export { escape, escapeSync, filter, filterSync, filterEscape, filterEscapeSync } from "./html";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/helper-html",
3
- "version": "3.0.0-beta.8",
3
+ "version": "3.0.0-bnr.0",
4
4
  "description": "HTML Utiltities",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -24,11 +24,11 @@
24
24
  ]
25
25
  },
26
26
  "devDependencies": {
27
- "@webex/test-helper-chai": "3.0.0-beta.8",
28
- "@webex/test-helper-mocha": "3.0.0-beta.8"
27
+ "@webex/test-helper-chai": "3.0.0-bnr.0",
28
+ "@webex/test-helper-mocha": "3.0.0-bnr.0"
29
29
  },
30
30
  "dependencies": {
31
- "@webex/helper-html": "3.0.0-beta.8",
31
+ "@webex/helper-html": "3.0.0-bnr.0",
32
32
  "lodash": "^4.17.21"
33
33
  }
34
34
  }
package/src/html.shim.js CHANGED
@@ -80,7 +80,7 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
80
80
  throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');
81
81
  }
82
82
 
83
- const doc = (new DOMParser()).parseFromString(html, 'text/html');
83
+ const doc = new DOMParser().parseFromString(html, 'text/html');
84
84
 
85
85
  depthFirstForEach(doc.body.childNodes, filterNode);
86
86
  processCallback(doc.body);
@@ -112,8 +112,7 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
112
112
  forEach(listAttributeNames(node.attributes), (attrName) => {
113
113
  if (!includes(allowedAttributes, attrName)) {
114
114
  node.removeAttribute(attrName);
115
- }
116
- else if (attrName === 'href' || attrName === 'src') {
115
+ } else if (attrName === 'href' || attrName === 'src') {
117
116
  const attrValue = node.attributes.getNamedItem(attrName).value.trim().toLowerCase();
118
117
 
119
118
  // We're doing at runtime what the no-script-url rule does at compile
@@ -122,13 +121,10 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
122
121
  if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {
123
122
  reparent(node);
124
123
  }
125
- }
126
- else if (attrName === 'style') {
127
- const styles = node
128
- .attributes
124
+ } else if (attrName === 'style') {
125
+ const styles = node.attributes
129
126
  .getNamedItem('style')
130
- .value
131
- .split(';')
127
+ .value.split(';')
132
128
  .map((style) => {
133
129
  const styleName = trim(style.split(':')[0]);
134
130
 
@@ -144,8 +140,7 @@ function _filterSync(processCallback, allowedTags, allowedStyles, html) {
144
140
  node.setAttribute('style', styles);
145
141
  }
146
142
  });
147
- }
148
- else {
143
+ } else {
149
144
  reparent(node);
150
145
  }
151
146
  }
@@ -182,7 +177,7 @@ function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
182
177
  throw new Error('`allowedTags`, `allowedStyles`, and `html` must be provided');
183
178
  }
184
179
 
185
- const doc = (new DOMParser()).parseFromString(html, 'text/html');
180
+ const doc = new DOMParser().parseFromString(html, 'text/html');
186
181
 
187
182
  depthFirstForEach(doc.body.childNodes, filterNode);
188
183
  processCallback(doc.body);
@@ -214,8 +209,7 @@ function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
214
209
  forEach(listAttributeNames(node.attributes), (attrName) => {
215
210
  if (!includes(allowedAttributes, attrName)) {
216
211
  node.removeAttribute(attrName);
217
- }
218
- else if (attrName === 'href' || attrName === 'src') {
212
+ } else if (attrName === 'href' || attrName === 'src') {
219
213
  const attrValue = node.attributes.getNamedItem(attrName).value.toLowerCase();
220
214
 
221
215
  // We're doing at runtime what the no-script-url rule does at compile
@@ -224,13 +218,10 @@ function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
224
218
  if (attrValue.indexOf('javascript:') === 0 || attrValue.indexOf('vbscript:') === 0) {
225
219
  reparent(node);
226
220
  }
227
- }
228
- else if (attrName === 'style') {
229
- const styles = node
230
- .attributes
221
+ } else if (attrName === 'style') {
222
+ const styles = node.attributes
231
223
  .getNamedItem('style')
232
- .value
233
- .split(';')
224
+ .value.split(';')
234
225
  .map((style) => {
235
226
  const styleName = trim(style.split(':')[0]);
236
227
 
@@ -246,8 +237,7 @@ function _filterEscapeSync(processCallback, allowedTags, allowedStyles, html) {
246
237
  node.setAttribute('style', styles);
247
238
  }
248
239
  });
249
- }
250
- else {
240
+ } else {
251
241
  escapeNode(node);
252
242
  }
253
243
  }
@@ -299,11 +289,15 @@ function reparent(node) {
299
289
  * @returns {Array<string>}
300
290
  */
301
291
  function listAttributeNames(attributes) {
302
- return reduce(attributes, (attrNames, attr) => {
303
- attrNames.push(attr.name);
304
-
305
- return attrNames;
306
- }, []);
292
+ return reduce(
293
+ attributes,
294
+ (attrNames, attr) => {
295
+ attrNames.push(attr.name);
296
+
297
+ return attrNames;
298
+ },
299
+ []
300
+ );
307
301
  }
308
302
 
309
303
  /**
@@ -9,7 +9,7 @@ import {
9
9
  filter,
10
10
  filterSync,
11
11
  filterEscape,
12
- filterEscapeSync
12
+ filterEscapeSync,
13
13
  } from '@webex/helper-html';
14
14
  import {skipInNode} from '@webex/test-helper-mocha';
15
15
 
@@ -29,7 +29,7 @@ skipInNode(describe)('html', () => {
29
29
  span: ['style'],
30
30
  ul: ['style'],
31
31
  body: ['style', 'xmlns', 'xml:lang'],
32
- 'webex-mention': ['data-object-id', 'data-object-type']
32
+ 'webex-mention': ['data-object-id', 'data-object-type'],
33
33
  };
34
34
 
35
35
  const allowedStyles = [
@@ -42,7 +42,7 @@ skipInNode(describe)('html', () => {
42
42
  'margin-left',
43
43
  'margin-right',
44
44
  'text-align',
45
- 'text-decoration'
45
+ 'text-decoration',
46
46
  ];
47
47
 
48
48
  /**
@@ -58,12 +58,15 @@ skipInNode(describe)('html', () => {
58
58
  const cfilterEscapeSync = filterEscapeSync(noop, allowedTags, allowedStyles);
59
59
 
60
60
  describe('#filter()', () => {
61
- it('sanitizes trivial html', () => cfilter('<p data-test="5"><em>foo</em></p>')
62
- .then((result) => assert.deepEqual(result, '<p><em>foo</em></p>')));
61
+ it('sanitizes trivial html', () =>
62
+ cfilter('<p data-test="5"><em>foo</em></p>').then((result) =>
63
+ assert.deepEqual(result, '<p><em>foo</em></p>')
64
+ ));
63
65
  });
64
66
 
65
67
  describe('#filterSync()', () => {
66
- it('sanitizes trivial html', () => assert.deepEqual(cfilterSync('<p data-test="5"><em>foo</em></p>'), '<p><em>foo</em></p>'));
68
+ it('sanitizes trivial html', () =>
69
+ assert.deepEqual(cfilterSync('<p data-test="5"><em>foo</em></p>'), '<p><em>foo</em></p>'));
67
70
  });
68
71
 
69
72
  [
@@ -72,147 +75,154 @@ skipInNode(describe)('html', () => {
72
75
  // emptry string
73
76
  it: 'accepts blank strings',
74
77
  input: '',
75
- output: ''
78
+ output: '',
76
79
  },
77
80
  {
78
81
  it: 'allows custom tags',
79
- input: '<webex-mention data-object-id="88888888-4444-4444-4444-AAAAAAAAAAAA">John Doe</webex-mention>',
80
- output: '<webex-mention data-object-id="88888888-4444-4444-4444-AAAAAAAAAAAA">John Doe</webex-mention>'
82
+ input:
83
+ '<webex-mention data-object-id="88888888-4444-4444-4444-AAAAAAAAAAAA">John Doe</webex-mention>',
84
+ output:
85
+ '<webex-mention data-object-id="88888888-4444-4444-4444-AAAAAAAAAAAA">John Doe</webex-mention>',
81
86
  },
82
87
  {
83
88
  it: 'filters tags',
84
- input: '<p><remove-me><bar>text1<em>text2</em>text3</bar>text4</remove-me><strong>text5</strong>text6</p>',
85
- output: '<p>text1<em>text2</em>text3text4<strong>text5</strong>text6</p>'
89
+ input:
90
+ '<p><remove-me><bar>text1<em>text2</em>text3</bar>text4</remove-me><strong>text5</strong>text6</p>',
91
+ output: '<p>text1<em>text2</em>text3text4<strong>text5</strong>text6</p>',
86
92
  },
87
93
  {
88
94
  it: 'filters attributes',
89
95
  input: '<p remove="me" style="font-size:large"><em>foo</em></p>',
90
- output: /<p style="font-size:\s?large;?"><em>foo<\/em><\/p>/
96
+ output: /<p style="font-size:\s?large;?"><em>foo<\/em><\/p>/,
91
97
  },
92
98
  {
93
99
  it: 'filters styles',
94
100
  input: '<p style="color:red;remove:me;font-size:large"><em>foo</em></p>',
95
- output: /<p style="color:\s?red;\s?font-size:\s?large;?"><em>foo<\/em><\/p>/
101
+ output: /<p style="color:\s?red;\s?font-size:\s?large;?"><em>foo<\/em><\/p>/,
96
102
  },
97
103
  {
98
104
  it: 'filters child attributes',
99
105
  input: '<body><span bcd="abc" style="font-size:large"><p><em>foo</em></p></span></body>',
100
- output: /<body><span style="font-size:\s?large;?"><p><em>foo<\/em><\/p><\/span><\/body>/
106
+ output: /<body><span style="font-size:\s?large;?"><p><em>foo<\/em><\/p><\/span><\/body>/,
101
107
  },
102
108
  {
103
109
  it: 'filters disallowed attributes from allowed tags',
104
110
  input: '<strong style="font-size:large"><span>text</span></strong>',
105
- output: '<strong><span>text</span></strong>'
111
+ output: '<strong><span>text</span></strong>',
106
112
  },
107
113
  {
108
114
  it: 'filters javascript: from a href',
109
115
  input: '<p><a href="javascript:window.close(); return false">click here</a></p>',
110
- output: '<p>click here</p>'
116
+ output: '<p>click here</p>',
111
117
  },
112
118
  {
113
119
  it: 'filters javascript: from a href (mixed case)',
114
120
  input: '<p><a href="JavaScript:window.close(); return false">click here</a></p>',
115
- output: '<p>click here</p>'
121
+ output: '<p>click here</p>',
116
122
  },
117
123
  {
118
124
  it: 'filters vbscript: from a href',
119
125
  input: '<p><a href="vbscript:window.close(); return false">click here</a></p>',
120
- output: '<p>click here</p>'
126
+ output: '<p>click here</p>',
121
127
  },
122
128
  {
123
129
  it: 'filters vbscript: from a href (mixed case)',
124
130
  input: '<p><a href="VBScript:window.close(); return false">click here</a></p>',
125
- output: '<p>click here</p>'
131
+ output: '<p>click here</p>',
126
132
  },
127
133
  {
128
134
  it: 'does not filter arbitrary strings from a href',
129
135
  input: '<p><a href="window.close(); return false">click here</a></p>',
130
- output: '<p><a href="window.close(); return false">click here</a></p>'
136
+ output: '<p><a href="window.close(); return false">click here</a></p>',
131
137
  },
132
138
  {
133
139
  it: 'filters javascript: from img src',
134
140
  input: '<p><img src="javascript:window.close(); return false">foo</img>bar</p>',
135
- output: '<p>foobar</p>'
141
+ output: '<p>foobar</p>',
136
142
  },
137
143
  {
138
144
  it: 'filters javascript: from img src (mixed case)',
139
145
  input: '<p><img src="javaScript:window.close(); return false">foo</img>bar</p>',
140
- output: '<p>foobar</p>'
146
+ output: '<p>foobar</p>',
141
147
  },
142
148
  {
143
149
  it: 'filters vbscript: from img src',
144
150
  input: '<p><img src="vbscript:window.close(); return false">foo</img>bar</p>',
145
- output: '<p>foobar</p>'
151
+ output: '<p>foobar</p>',
146
152
  },
147
153
  {
148
154
  it: 'filters vbscript: from img src (mixed case)',
149
155
  input: '<p><img src="VBScript:window.close(); return false">foo</img>bar</p>',
150
- output: '<p>foobar</p>'
156
+ output: '<p>foobar</p>',
151
157
  },
152
158
  {
153
159
  it: 'does not filter arbitrary strings from img src',
154
160
  input: '<p><img src="window.close(); return false">foo</img></p>',
155
- output: '<p><img src="window.close(); return false">foo</p>'
161
+ output: '<p><img src="window.close(); return false">foo</p>',
156
162
  },
157
163
  {
158
164
  it: 'correctly cleans nested a/img tags with javscript: href/src',
159
- input: '<p><a href="javascript:window.close()">Click here<img src="http://example.com/img">bar</img></a> for something with <a href="http://www.cisco.com/">MORE<img src="javascript:window.location=`http://www.cisco.com`">of my</img>MOJO</a></p>',
160
- output: '<p>Click here<img src="http://example.com/img">bar for something with <a href="http://www.cisco.com/">MOREof myMOJO</a></p>'
165
+ input:
166
+ '<p><a href="javascript:window.close()">Click here<img src="http://example.com/img">bar</img></a> for something with <a href="http://www.cisco.com/">MORE<img src="javascript:window.location=`http://www.cisco.com`">of my</img>MOJO</a></p>',
167
+ output:
168
+ '<p>Click here<img src="http://example.com/img">bar for something with <a href="http://www.cisco.com/">MOREof myMOJO</a></p>',
161
169
  },
162
170
  {
163
171
  it: 'correctly cleans nested a/img tags with javscript: href/src, even cleverly obfuscated with whitespace',
164
- input: '<p><a href=" javascript:window.close()">Click here<img src="http://example.com/img">bar</img></a> for something with <a href="http://www.cisco.com/">MORE<img src=" javascript:window.location=`http://www.cisco.com`">of my</img>MOJO</a></p>',
165
- output: '<p>Click here<img src="http://example.com/img">bar for something with <a href="http://www.cisco.com/">MOREof myMOJO</a></p>'
172
+ input:
173
+ '<p><a href=" javascript:window.close()">Click here<img src="http://example.com/img">bar</img></a> for something with <a href="http://www.cisco.com/">MORE<img src=" javascript:window.location=`http://www.cisco.com`">of my</img>MOJO</a></p>',
174
+ output:
175
+ '<p>Click here<img src="http://example.com/img">bar for something with <a href="http://www.cisco.com/">MOREof myMOJO</a></p>',
166
176
  },
167
177
  {
168
178
  it: 'handles weirder nesting',
169
- input: '<p>text</p><div><p>text0</p><div style="font-size: large;"><span>text1</span><span>text2</span><script></script></div></div>',
170
- output: '<p>text</p><p>text0</p><span>text1</span><span>text2</span>'
179
+ input:
180
+ '<p>text</p><div><p>text0</p><div style="font-size: large;"><span>text1</span><span>text2</span><script></script></div></div>',
181
+ output: '<p>text</p><p>text0</p><span>text1</span><span>text2</span>',
171
182
  },
172
183
  {
173
184
  it: 'filters bad html from unwrapped strings',
174
185
  input: 'Hi <script></script><em style="font-size:large;">Steve</em>',
175
- output: 'Hi <em>Steve</em>'
186
+ output: 'Hi <em>Steve</em>',
176
187
  },
177
188
  {
178
189
  it: 'filters disallowed attributes from a href',
179
190
  input: '<a remove="me" href="http://www.jabber.org/"><p><em>foo</em></p></a>',
180
- output: '<a href="http://www.jabber.org/"><p><em>foo</em></p></a>'
191
+ output: '<a href="http://www.jabber.org/"><p><em>foo</em></p></a>',
181
192
  },
182
193
  {
183
194
  it: 'filters disallowed attributes from a style',
184
195
  input: '<a remove="me" style="font-size:large"><p><em>foo</em></p></a>',
185
- output: /<a style="font-size:\s?large;?"><p><em>foo<\/em><\/p><\/a>/
196
+ output: /<a style="font-size:\s?large;?"><p><em>foo<\/em><\/p><\/a>/,
186
197
  },
187
198
  {
188
199
  it: 'filters disallowed attributes from a type',
189
200
  input: '<a remove="me" type="stuff"><p><em>foo</em></p></a>',
190
- output: '<a type="stuff"><p><em>foo</em></p></a>'
201
+ output: '<a type="stuff"><p><em>foo</em></p></a>',
191
202
  },
192
203
  {
193
204
  it: 'filters disallowed attributes from img src',
194
205
  input: '<img remove="me" src="http://www.xmpp.org/images/psa-license.jpg">bar</img>',
195
- output: '<img src="http://www.xmpp.org/images/psa-license.jpg">bar'
206
+ output: '<img src="http://www.xmpp.org/images/psa-license.jpg">bar',
196
207
  },
197
208
  {
198
209
  it: 'filters disallowed attributes from img alt',
199
210
  input: '<img remove="me" alt="A License to Jabber">bar</img>',
200
- output: '<img alt="A License to Jabber">bar'
211
+ output: '<img alt="A License to Jabber">bar',
201
212
  },
202
213
  {
203
214
  it: 'filters disallowed attributes from img height',
204
215
  input: '<img remove="me" height="261">bar</img>',
205
- output: '<img height="261">bar'
216
+ output: '<img height="261">bar',
206
217
  },
207
218
  {
208
219
  it: 'filters disallowed attributes from img width',
209
220
  input: '<img remove="me" width="537">bar</img>',
210
- output: '<img width="537">bar'
211
- }
221
+ output: '<img width="537">bar',
222
+ },
212
223
  ].forEach((def) => {
213
224
  describe('#filter()', () => {
214
- it(def.it, () => cfilter(def.input)
215
- .then((out) => assert.match(out, def.output)));
225
+ it(def.it, () => cfilter(def.input).then((out) => assert.match(out, def.output)));
216
226
  });
217
227
 
218
228
  describe('#filterSync()', () => {
@@ -222,14 +232,15 @@ skipInNode(describe)('html', () => {
222
232
  });
223
233
  });
224
234
 
225
- [{
226
- it: 'escapes html',
227
- input: 'This is an <b>invalid</b> tag',
228
- output: 'This is an &lt;b&gt;invalid&lt;/b&gt; tag'
229
- }].forEach((def) => {
235
+ [
236
+ {
237
+ it: 'escapes html',
238
+ input: 'This is an <b>invalid</b> tag',
239
+ output: 'This is an &lt;b&gt;invalid&lt;/b&gt; tag',
240
+ },
241
+ ].forEach((def) => {
230
242
  describe('#escape()', () => {
231
- it(def.it, () => escape(def.input)
232
- .then((result) => assert.deepEqual(result, def.output)));
243
+ it(def.it, () => escape(def.input).then((result) => assert.deepEqual(result, def.output)));
233
244
  });
234
245
 
235
246
  describe('#escapeSync()', () => {
@@ -243,24 +254,27 @@ skipInNode(describe)('html', () => {
243
254
  {
244
255
  it: 'escapes invalid tags',
245
256
  input: '<bar>text1<em>text2</em>text3</bar>',
246
- output: '&lt;bar&gt;text1<em>text2</em>text3&lt;/bar&gt;'
257
+ output: '&lt;bar&gt;text1<em>text2</em>text3&lt;/bar&gt;',
247
258
  },
248
259
  {
249
260
  it: 'escapes deeply nested invalid tags',
250
- input: '<p><remove-me><bar>text1<em>text2</em>text3</bar>text4</remove-me><strong>text5</strong>text6</p>',
251
- output: '<p>&lt;remove-me&gt;&lt;bar&gt;text1<em>text2</em>text3&lt;/bar&gt;text4&lt;/remove-me&gt;<strong>text5</strong>text6</p>'
261
+ input:
262
+ '<p><remove-me><bar>text1<em>text2</em>text3</bar>text4</remove-me><strong>text5</strong>text6</p>',
263
+ output:
264
+ '<p>&lt;remove-me&gt;&lt;bar&gt;text1<em>text2</em>text3&lt;/bar&gt;text4&lt;/remove-me&gt;<strong>text5</strong>text6</p>',
252
265
  },
253
266
  {
254
267
  it: 'esapes special characters',
255
268
  input: '<b>&<</b>',
256
- output: '<b>&amp;&lt;</b>'
257
- }
269
+ output: '<b>&amp;&lt;</b>',
270
+ },
258
271
  ].forEach((def) => {
259
272
  describe('#filterEscape()', () => {
260
- it(def.it, () => cfilterEscape(def.input)
261
- .then((out) => {
273
+ it(def.it, () =>
274
+ cfilterEscape(def.input).then((out) => {
262
275
  assert.match(out, def.output);
263
- }));
276
+ })
277
+ );
264
278
  });
265
279
 
266
280
  describe('#filterEscapeSync()', () => {