diff --git a/package.json b/package.json
index 56535501..60d040b9 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"test": "npm run lint-errors && npm run just-test-in-node",
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
"just-test": "karma start --config karma.conf.js",
- "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
+ "just-test-in-node": "mocha --require test/setup.js --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
"just-check-coverage": "nyc npm run just-test-in-node",
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
@@ -48,6 +48,7 @@
"core-js": "^2.5.1",
"css.escape": "1.5.1",
"deep-extend": "0.4.1",
+ "dompurify": "^1.0.4",
"expect": "1.20.2",
"getbase": "^2.8.2",
"ieee754": "^1.1.8",
@@ -80,7 +81,6 @@
"redux-logger": "*",
"remarkable": "^1.7.1",
"reselect": "2.5.3",
- "sanitize-html": "^1.14.1",
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
@@ -119,6 +119,7 @@
"file-loader": "0.11.2",
"git-describe": "^4.0.1",
"imports-loader": "0.7.1",
+ "jsdom": "^11.10.0",
"json-loader": "0.5.4",
"json-server": "^0.11.0",
"karma": "^1.7.0",
diff --git a/src/core/components/providers/markdown.jsx b/src/core/components/providers/markdown.jsx
index 4952a326..aac227fa 100644
--- a/src/core/components/providers/markdown.jsx
+++ b/src/core/components/providers/markdown.jsx
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import Remarkable from "remarkable"
-import sanitize from "sanitize-html"
+import DomPurify from "dompurify"
import cx from "classnames"
// eslint-disable-next-line no-useless-escape
@@ -40,20 +40,8 @@ Markdown.propTypes = {
export default Markdown
-const sanitizeOptions = {
- allowedTags: sanitize.defaults.allowedTags.concat([ "h1", "h2", "img", "span" ]),
- allowedAttributes: {
- ...sanitize.defaults.allowedAttributes,
- "img": sanitize.defaults.allowedAttributes.img.concat(["title"]),
- "td": [ "colspan" ],
- "*": [ "class" ]
- },
- allowedSchemesByTag: { img: [ "http", "https", "data" ] },
- textFilter: function(text) {
- return text.replace(/"/g, "\"")
- }
-}
-
export function sanitizer(str) {
- return sanitize(str, sanitizeOptions)
+ return DomPurify.sanitize(str, {
+ ADD_ATTR: ["target"]
+ })
}
diff --git a/test/components/markdown.js b/test/components/markdown.js
index cf208510..ebf765bc 100644
--- a/test/components/markdown.js
+++ b/test/components/markdown.js
@@ -16,19 +16,19 @@ describe("Markdown component", function() {
it("allows td elements with colspan attrib", function() {
const str = `
`
const el = render()
- expect(el.html()).toEqual(``)
+ expect(el.html()).toEqual(``)
})
it("allows image elements", function() {
const str = ``
const el = render()
- expect(el.html()).toEqual(`
\n
`)
+ expect(el.html()).toEqual(`
\n
`)
})
-
+
it("allows image elements with https scheme", function() {
const str = ``
const el = render()
- expect(el.html()).toEqual(`
\n
`)
+ expect(el.html()).toEqual(`
\n
`)
})
it("allows image elements with data scheme", function() {
@@ -52,7 +52,7 @@ describe("Markdown component", function() {
it("allows links", function() {
const str = `[Link](https://example.com/)`
const el = render()
- expect(el.html()).toEqual(``)
+ expect(el.html()).toEqual(``)
})
})
@@ -60,13 +60,13 @@ describe("Markdown component", function() {
it("allows image elements", function() {
const str = ``
const el = render()
- expect(el.html()).toEqual(``)
+ expect(el.html()).toEqual(``)
})
it("allows image elements with https scheme", function() {
const str = ``
const el = render()
- expect(el.html()).toEqual(``)
+ expect(el.html()).toEqual(``)
})
it("allows image elements with data scheme", function() {
diff --git a/test/setup.js b/test/setup.js
new file mode 100644
index 00000000..49d8d1d1
--- /dev/null
+++ b/test/setup.js
@@ -0,0 +1,23 @@
+const { JSDOM } = require("jsdom")
+const win = require("core/window")
+
+const jsdom = new JSDOM("")
+const { window } = jsdom
+
+function copyProps(src, target) {
+ const props = Object.getOwnPropertyNames(src)
+ .filter(prop => typeof target[prop] === "undefined")
+ .reduce((result, prop) => ({
+ ...result,
+ [prop]: Object.getOwnPropertyDescriptor(src, prop),
+ }), {})
+ Object.defineProperties(target, props)
+}
+
+global.window = window
+global.document = window.document
+global.navigator = {
+ userAgent: "node.js",
+}
+copyProps(win, window) // use UI's built-in window wrapper
+copyProps(window, global)