in packages/roosterjs-editor-dom/lib/htmlSanitizer/HtmlSanitizer.ts [175:241]
private processNode(node: Node, currentStyle: StringMap, context: Object) {
const nodeType = node.nodeType;
const isElement = nodeType == NodeType.Element;
const isText = nodeType == NodeType.Text;
const isFragment = nodeType == NodeType.DocumentFragment;
const isComment = nodeType == NodeType.Comment;
let shouldKeep = false;
if (isElement) {
const tag = getTagOfNode(node);
const callback = this.elementCallbacks[tag];
let replacement = this.tagReplacements[tag.toLowerCase()];
if (replacement === undefined) {
replacement = this.unknownTagReplacement;
}
if (callback) {
shouldKeep = callback(node as HTMLElement, context);
} else if (tag.indexOf(':') > 0) {
shouldKeep = true;
} else if (tag == replacement || replacement == '*') {
shouldKeep = true;
} else if (replacement && /^[a-zA-Z][\w\-]*$/.test(replacement)) {
node = changeElementTag(node as HTMLElement, replacement);
shouldKeep = true;
}
} else if (isText) {
const whiteSpace = currentStyle['white-space'];
shouldKeep =
whiteSpace == 'pre' ||
whiteSpace == 'pre-line' ||
whiteSpace == 'pre-wrap' ||
!/^[\r\n]*$/g.test(node.nodeValue);
} else if (isFragment) {
shouldKeep = true;
} else if (isComment) {
shouldKeep = this.preserveHtmlComments;
} else {
shouldKeep = false;
}
if (!shouldKeep) {
node.parentNode.removeChild(node);
} else if (
isText &&
(currentStyle['white-space'] == 'pre' || currentStyle['white-space'] == 'pre-wrap')
) {
node.nodeValue = node.nodeValue.replace(/^ /gm, '\u00A0').replace(/ {2}/g, ' \u00A0');
} else if (isElement || isFragment) {
let thisStyle = cloneObject(currentStyle);
let element = <HTMLElement>node;
if (isElement) {
this.processAttributes(element, context);
this.preprocessCss(element, thisStyle);
this.processCss(element, thisStyle, context);
}
let child: Node = element.firstChild;
let next: Node;
for (; child; child = next) {
next = child.nextSibling;
this.processNode(child, thisStyle, context);
}
}
}