@webex/helper-html 3.0.0-beta.13 → 3.0.0-beta.15

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
  }
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/helper-html",
3
- "version": "3.0.0-beta.13",
3
+ "version": "3.0.0-beta.15",
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.13",
28
- "@webex/test-helper-mocha": "3.0.0-beta.13"
27
+ "@webex/test-helper-chai": "3.0.0-beta.15",
28
+ "@webex/test-helper-mocha": "3.0.0-beta.15"
29
29
  },
30
30
  "dependencies": {
31
- "@webex/helper-html": "3.0.0-beta.13",
31
+ "@webex/helper-html": "3.0.0-beta.15",
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()', () => {