From 949729574fffc7bcfd2e4013cd914ddc2cf727ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Maa=C3=9F?= <mathias.maass@uni-leipzig.de> Date: Tue, 19 Feb 2019 09:56:01 +0100 Subject: [PATCH] Create <SanitizedHtml/> component. Part of #1854 --- .../src/components/SanitizedHtml.test.js | 25 ++++++++++++++++ package.json | 1 + src/components/SanitizedHtml.js | 30 +++++++++++++++++++ src/lib/htmlRules.js | 7 +++++ 4 files changed, 63 insertions(+) create mode 100644 __tests__/src/components/SanitizedHtml.test.js create mode 100644 src/components/SanitizedHtml.js create mode 100644 src/lib/htmlRules.js diff --git a/__tests__/src/components/SanitizedHtml.test.js b/__tests__/src/components/SanitizedHtml.test.js new file mode 100644 index 000000000..c630c0f73 --- /dev/null +++ b/__tests__/src/components/SanitizedHtml.test.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import SanitizedHtml from '../../../src/components/SanitizedHtml'; + +const wrapper = shallow( + <SanitizedHtml + htmlString="<script>doBadThings()</script><b>Don't worry!</b>" + ruleSet="basic" + />, +); + +describe('SanitizedHtml', () => { + it('should render needed elements', () => { + expect(wrapper.find('span').length).toBe(1); + }); + + it('should pass correct class name to root element', () => { + expect(wrapper.find('span').first().props().className).toBe('mirador-third-party-html'); + }); + + it('should pass sanitized html string to dangerouslySetInnerHTML attribute', () => { + expect(wrapper.find('span').first().props().dangerouslySetInnerHTML) + .toEqual({ __html: "<b>Don't worry!</b>" }); + }); +}); diff --git a/package.json b/package.json index a145b2942..7e05e1af0 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "classnames": "^2.2.6", "css-ns": "^1.2.2", "deepmerge": "^3.1.0", + "dompurify": "^1.0.9", "i18next": "^14.0.1", "intersection-observer": "^0.5.1", "manifesto.js": "^3.0.9", diff --git a/src/components/SanitizedHtml.js b/src/components/SanitizedHtml.js new file mode 100644 index 000000000..299bf2eab --- /dev/null +++ b/src/components/SanitizedHtml.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { sanitize } from 'dompurify'; +import ns from '../config/css-ns'; +import htmlRules from '../lib/htmlRules'; + +/** +*/ +class SanitizedHtml extends Component { + /** + */ + render() { + const { htmlString, ruleSet } = this.props; + return ( + <span + className={ns('third-party-html')} + dangerouslySetInnerHTML={{ // eslint-disable-line react/no-danger + __html: sanitize(htmlString, htmlRules[ruleSet]), + }} + /> + ); + } +} + +SanitizedHtml.propTypes = { + ruleSet: PropTypes.string.isRequired, + htmlString: PropTypes.string.isRequired, +}; + +export default SanitizedHtml; diff --git a/src/lib/htmlRules.js b/src/lib/htmlRules.js new file mode 100644 index 000000000..ca5b95dd9 --- /dev/null +++ b/src/lib/htmlRules.js @@ -0,0 +1,7 @@ + +const basic = { + ALLOWED_TAGS: ['a', 'b', 'br', 'i', 'img', 'p', 'span', 'strong', 'em', 'ul', 'ol', 'li'], + ALLOWED_ATTR: ['href', 'target', 'src', 'alt', 'dir'], +}; + +export default { basic }; -- GitLab