Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandr-dukhovnyy committed Oct 3, 2022
0 parents commit fde5431
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
59 changes: 59 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -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 = `
<script> fetch('google.com', { mode: 'no-cors' }) </script>
<<div></div>img src="1" onerror="alert(1)">
<img src="1" onerror="alert(1)">
<b>Bold</b>
<b class="red">Bold</b>
<b class="red" onclick="alert(1)">Bold</b>
<p data-some="123" data-some-else="321">123</p>
<div></div>
`;

const safeString = sanitizer.sanitize(dangerString);

console.log(safeString);

/*
&lt;img src="1" onerror="alert(1)"&gt;
<b>Bold</b>
<b class="red">Bold</b>
<b class="red">Bold</b>
<p data-some="123">123</p>
*/
```

## 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).
51 changes: 51 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -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;
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -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"
}

0 comments on commit fde5431

Please sign in to comment.