parent
6922fb0d5f
commit
e945e3fe3c
@ -0,0 +1,99 @@ |
||||
/* |
||||
* remixBleach |
||||
* a minimal html sanitizer |
||||
* credits to cam@onswipe.com |
||||
*/ |
||||
import * as he from 'he' |
||||
|
||||
const remixBleach = { |
||||
|
||||
matcher: /<\/?([a-zA-Z0-9]+)*(.*?)\/?>/igm, |
||||
|
||||
whitelist: [ |
||||
'a', |
||||
'b', |
||||
'p', |
||||
'em', |
||||
'strong' |
||||
], |
||||
|
||||
analyze: function (html) { |
||||
html = String(html) || '' |
||||
|
||||
const matches = [] |
||||
let match |
||||
|
||||
// extract all tags
|
||||
while ((match = remixBleach.matcher.exec(html)) != null) { |
||||
const attrr = match[2].split(' ') |
||||
const attrs = [] |
||||
|
||||
// extract attributes from the tag
|
||||
attrr.shift() |
||||
attrr.forEach((attr) => { |
||||
attr = attr.split('=') |
||||
const attrName = attr[0] |
||||
let attrValue = attr.length > 1 ? attr.slice(1).join('=') : null |
||||
// remove quotes from attributes
|
||||
if (attrValue && attrValue.charAt(0).match(/'|"/)) attrValue = attrValue.slice(1) |
||||
if (attrValue && attrValue.charAt(attrValue.length - 1).match(/'|"/)) attrValue = attrValue.slice(0, -1) |
||||
attr = { |
||||
name: attrName, |
||||
value: attrValue |
||||
} |
||||
if (!attr.value) delete attr.value |
||||
if (attr.name) attrs.push(attr) |
||||
}) |
||||
|
||||
var tag = { |
||||
full: match[0], |
||||
name: match[1], |
||||
attr: attrs |
||||
} |
||||
|
||||
matches.push(tag) |
||||
} |
||||
|
||||
return matches |
||||
}, |
||||
|
||||
sanitize: function (html, options) { |
||||
html = String(html) || '' |
||||
options = options || {} |
||||
|
||||
const mode = options.mode || 'white' |
||||
const list = options.list || remixBleach.whitelist |
||||
|
||||
var matches = remixBleach.analyze(html) |
||||
|
||||
if ((mode === 'white' && list.indexOf('script') === -1) || |
||||
(mode === 'black' && list.indexOf('script') !== -1)) { |
||||
html = html.replace(/<script(.*?)>(.*?[\r\n])*?(.*?)(.*?[\r\n])*?<\/script>/gim, '') |
||||
} |
||||
|
||||
if ((mode === 'white' && list.indexOf('style') === -1) || |
||||
(mode === 'black' && list.indexOf('style') !== -1)) { |
||||
html = html.replace(/<style(.*?)>(.*?[\r\n])*?(.*?)(.*?[\r\n])*?<\/style>/gim, '') |
||||
} |
||||
|
||||
matches.forEach(function (tag) { |
||||
if (mode === 'white') { |
||||
if (list.indexOf(tag.name) === -1) { |
||||
html = html.replace(tag.full, '') |
||||
} |
||||
} else if (mode === 'black') { |
||||
if (list.indexOf(tag.name) !== -1) { |
||||
html = html.replace(tag.full, '') |
||||
} |
||||
} else { |
||||
throw new Error('Unknown sanitization mode "' + mode + '"') |
||||
} |
||||
}) |
||||
|
||||
if (options.encode_entities) html = he.encode(html) |
||||
|
||||
return html |
||||
} |
||||
} |
||||
|
||||
module.exports = remixBleach |
Loading…
Reference in new issue