| 25 | |
| 26 | let uid = 0; |
| 27 | const processNode = (node: Node, settings: DomParserSettings, schema: Schema, scope: Namespace.NamespaceType, evt?: UponSanitizeElementHookEvent): void => { |
| 28 | const validate = settings.validate; |
| 29 | const specialElements = schema.getSpecialElements(); |
| 30 | |
| 31 | if (node.nodeType === NodeTypes.COMMENT) { |
| 32 | // Pad conditional comments if they aren't allowed |
| 33 | if (!settings.allow_conditional_comments && /^\[if/i.test(node.nodeValue ?? '')) { |
| 34 | node.nodeValue = ' ' + node.nodeValue; |
| 35 | } |
| 36 | |
| 37 | if (settings.sanitize && settings.allow_html_in_comments && Type.isString(node.nodeValue)) { |
| 38 | node.nodeValue = KeepHtmlComments.encodeData(node.nodeValue); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | const lcTagName = evt?.tagName ?? node.nodeName.toLowerCase(); |
| 43 | |
| 44 | if (scope !== 'html' && schema.isValid(scope)) { |
| 45 | if (Type.isNonNullable(evt)) { |
| 46 | evt.allowedTags[lcTagName] = true; |
| 47 | } |
| 48 | return; |
| 49 | } |
| 50 | |
| 51 | // Just leave non-elements such as text and comments up to dompurify |
| 52 | if (node.nodeType !== NodeTypes.ELEMENT || lcTagName === 'body') { |
| 53 | return; |
| 54 | } |
| 55 | |
| 56 | // Construct the sugar element wrapper |
| 57 | const element = SugarElement.fromDom(node) as SugarElement<Element>; |
| 58 | |
| 59 | if (settings.sanitize) { |
| 60 | // TINY-9655: Preserve the content of script and style tags if they are valid elements in the schema |
| 61 | const shouldKeepContent = (ElementType.isScript(element) && schema.isValid('script')) || (ElementType.isStyle(element) && schema.isValid('style')); |
| 62 | if (shouldKeepContent) { |
| 63 | Optional.from(TextContent.get(element)).each((content) => Attribute.set(element, 'data-mce-tmp', content)); |
| 64 | } |
| 65 | |
| 66 | // TINY-9655: Clear innerHTML of script and iframe tags to prevent DOMPurify from removing them entirely |
| 67 | const shouldClearContent = ElementType.isIframe(element) && schema.isValid('iframe'); |
| 68 | if (shouldKeepContent || shouldClearContent) { |
| 69 | Remove.empty(element); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | // Determine if we're dealing with an internal attribute |
| 74 | const isInternalElement = Attribute.has(element, internalElementAttr); |
| 75 | |
| 76 | // Cleanup bogus elements |
| 77 | const bogus = Attribute.get(element, 'data-mce-bogus'); |
| 78 | if (!isInternalElement && Type.isString(bogus)) { |
| 79 | if (bogus === 'all') { |
| 80 | Remove.remove(element); |
| 81 | } else { |
| 82 | Remove.unwrap(element); |
| 83 | } |
| 84 | return; |