nowjs-core
Version:
NowCanDo Javascript Core [nowjs-core] is a library written by TypeScript code maintains under Apache 2.0 licence
126 lines (125 loc) • 3.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../index");
const DEFAULT_ALLOWED_TAGS = [
'h3',
'h4',
'h5',
'h6',
'blockquote',
'p',
'a',
'ul',
'ol',
'nl',
'li',
'b',
'i',
'strong',
'em',
'strike',
'code',
'hr',
'br',
'div',
'table',
'thead',
'caption',
'tbody',
'tr',
'th',
'td',
'pre',
];
const DEFAULT_ALLOWED_ATTRIBUTES = {
a: ['href', 'name', 'target'],
img: ['src'],
};
const DEFAULT_SELFCLOSING = ['img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta'];
const DEFAULT_ALLOWED_SCHEMAS = ['http', 'https', 'ftp', 'mailto'];
const HTML_TAG_REGEX = /^\<.+\>/gim;
const HTML_TAG_ATTRIBUTE_REGEX = /(([a-zA-Z0-9]+)\=\"([a-zA-Z0-9]+)\")+/gim;
class HtmlSanitizer extends index_1.SanitizerBase {
constructor(options) {
super('HtmlSanitizer');
this.options = options;
this.options = this.options || {};
this.options.AllowedAttributes = this.options.AllowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES;
this.options.AllowedTags = this.options.AllowedTags || DEFAULT_ALLOWED_TAGS;
this.options.AllowedSchemes = this.options.AllowedSchemes || DEFAULT_ALLOWED_SCHEMAS;
}
sanitize(value) {
if (!value) {
return Promise.resolve(value);
}
const allowedTags = (this.options.AllowedTags || DEFAULT_ALLOWED_TAGS).join('|');
const selfcloseTags = (this.options.SelfClosingTags || DEFAULT_SELFCLOSING).join('|');
this.tagRegex = new RegExp(`^((\<(${allowedTags})\\s*([a-zA-Z0-9\"\=\\s]*\\s*)\>)(.*)\<\/(${allowedTags})\\s*\>)|(<!--[\\s\\S]*?-->)|((\<(${selfcloseTags})\\s*\/\>))$`, 'gmi');
if (this.options.AllowedAttributes) {
this.tagAttrRegex = {};
}
for (const item in this.options.AllowedAttributes) {
const attrs = this.options.AllowedAttributes[item];
this.tagAttrRegex[item] = [];
}
return Promise.resolve(this.sanitizeInnerText(value, ''));
}
sanitizeInnerText(value, parentValue) {
const results = [];
const tags = this.getTagParts(value);
if (!tags) {
return this.hasTag(value) ? '' : value;
}
if (tags[3] && tags[3] === tags[6]) {
let tagst = '';
if (tags[4]) {
tagst = `<${tags[3]} ${this.sanitizeTagAttributes(tags[3], tags[4])} >`;
}
else {
tagst = `<${tags[3]}>`;
}
const innerText = this.sanitizeInnerText(tags[5], tags[2]);
const tagText = `${tagst}${innerText}</${tags[6]}>`;
results.push(tagText);
}
return results.join('');
}
hasTag(value) {
return HTML_TAG_REGEX.test(value);
}
sanitizeTagAttributes(value, tag) {
const results = [];
HTML_TAG_ATTRIBUTE_REGEX.lastIndex = 0;
let attrs;
while ((attrs = this.getTagAttributeParts(value, tag))) {
results.push(attrs[1]);
}
return results.join(' ');
}
getTagAttributeParts(tag, value) {
if (this.tagAttrRegex && tag && this.tagAttrRegex[tag]) {
return this.tagAttrRegex[tag].exec(value);
}
else if (tag && HTML_TAG_ATTRIBUTE_REGEX) {
return HTML_TAG_ATTRIBUTE_REGEX.exec(value);
}
else {
return [];
}
}
getTagParts(value) {
this.tagRegex.lastIndex = 0;
return this.tagRegex.exec(value);
}
escapeHtml(s) {
if (typeof s !== 'string') {
s = s + '';
}
return s
.replace(/\&/g, '&')
.replace(/</g, '<')
.replace(/\>/g, '>')
.replace(/\"/g, '"');
}
}
exports.HtmlSanitizer = HtmlSanitizer;