diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..32e98fc --- /dev/null +++ b/README.MD @@ -0,0 +1,59 @@ +# purify-html + +![size](https://img.shields.io/github/languages/code-size/Aleksandr-JS-Developer/purify-html?style=flat-square) + +A minimalistic library for sanitizing strings so that they can be safely used as HTML. + +The main idea is to use the browser API to parse, parse and modify the DOM. + +## Install + +```bash +npm install purify-html +``` + +## Usage + +```javascript +import Sanitizer from 'purify-html'; + +const allowedTags = [ + { name: 'br' }, + { name: 'b', attributes: ['class'] }, + { name: 'p', attributes: ['data-some'] }, +]; + +const sanitizer = new Sanitizer(allowedTags); + +const dangerString = ` + + + <
img src="1" onerror="alert(1)"> + + + Bold + Bold + Bold +

123

+
+`; + +const safeString = sanitizer.sanitize(dangerString); + +console.log(safeString); + +/* + <img src="1" onerror="alert(1)"> + + + Bold + Bold + Bold +

123

+ +*/ +``` + +## Browser support + +Although browser support is already over 95%, the specification for DOMParser is not yet fully established. [More details](https://caniuse.com/mdn-api_domparser_parsefromstring_html). diff --git a/index.js b/index.js new file mode 100644 index 0000000..3da8c06 --- /dev/null +++ b/index.js @@ -0,0 +1,51 @@ +class Sanitizer { + constructor(allowedTags = []) { + this.allowedTags = allowedTags.reduce((acc, curr) => { + const name = curr.name; + delete curr.name; + + acc[name] = curr; + + return acc; + }, {}); + this.whiteList = Object.keys(this.allowedTags); + + this.sanitize.bind(this); + } + sanitize(str) { + const wrapper = new DOMParser() + .parseFromString(str, 'text/html') + .querySelector('body'); + + const allItems = wrapper.querySelectorAll('*'); + + allItems.forEach((tag) => { + const name = tag.tagName.toLowerCase(); + + if (this.whiteList.includes(name)) { + const tagConfig = this.allowedTags[name]; + + if (tagConfig.attributes !== undefined) { + for (let i = 0; i < tag.attributes.length; i++) { + const attr = tag.attributes[i]; + + if (!tagConfig.attributes.includes(attr.name)) { + tag.removeAttribute(attr.name); + } + } + } else { + for (let i = 0; i < tag.attributes.length; i++) { + tag.removeAttribute(tag.attributes[i].name); + } + } + } else { + tag.insertAdjacentHTML('afterend', this.sanitize(tag.innerHTML)); + tag.remove(); + } + }); + + return wrapper.innerHTML; + } +} + +module.exports = Sanitizer; diff --git a/package.json b/package.json new file mode 100644 index 0000000..dbea121 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "purify-html", + "version": "1.0.1", + "description": "A minimalistic library for sanitizing strings so that they can be safely used as HTML.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Aleksandr-JS-Developer/purify-html.git" + }, + "keywords": [ + "html-sanitize", + "sanitize" + ], + "author": "alex-js-dev", + "license": "MIT", + "files": [ + "index.js" + ], + "bugs": { + "url": "https://github.com/Aleksandr-JS-Developer/purify-html/issues" + }, + "homepage": "https://github.com/Aleksandr-JS-Developer/purify-html#readme" +}