79 lines
3.2 KiB
Swift
79 lines
3.2 KiB
Swift
//
|
|
// Copyright 2022 New Vector Ltd
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import DTCoreText
|
|
import Foundation
|
|
|
|
public extension DTHTMLElement {
|
|
/// Sanitize the element using the given parameters.
|
|
/// - Parameters:
|
|
/// - allowedHTMLTags: An array of tags that are allowed. All other tags will be removed.
|
|
/// - font: The default font to use when resetting the content of any unsupported tags.
|
|
/// - imageHandler: An optional image handler to be run on `img` tags (if allowed) to update the `src` attribute.
|
|
@objc func sanitize(font: UIFont) {
|
|
if let name = name, !Self.allowedHTMLTags.contains(name) {
|
|
// This is an unsupported tag.
|
|
// Remove any attachments to fix rendering.
|
|
textAttachment = nil
|
|
|
|
// If the element has plain text content show that,
|
|
// otherwise prevent the tag from displaying.
|
|
if let stringContent = attributedString()?.string,
|
|
!stringContent.isEmpty,
|
|
let element = DTTextHTMLElement(name: nil, attributes: nil) {
|
|
element.setText(stringContent)
|
|
removeAllChildNodes()
|
|
addChildNode(element)
|
|
|
|
if let parent = parent() {
|
|
element.inheritAttributes(from: parent)
|
|
} else {
|
|
fontDescriptor = DTCoreTextFontDescriptor()
|
|
fontDescriptor.fontFamily = font.familyName
|
|
fontDescriptor.fontName = font.fontName
|
|
fontDescriptor.pointSize = font.pointSize
|
|
paragraphStyle = DTCoreTextParagraphStyle.default()
|
|
|
|
element.inheritAttributes(from: self)
|
|
}
|
|
element.interpretAttributes()
|
|
|
|
} else if let parent = parent() {
|
|
parent.removeChildNode(self)
|
|
} else {
|
|
didOutput = true
|
|
}
|
|
|
|
} else {
|
|
// This element is a supported tag, but it may contain children that aren't,
|
|
// so santize all child nodes to ensure correct tags.
|
|
if let childNodes = childNodes as? [DTHTMLElement] {
|
|
childNodes.forEach { $0.sanitize(font: font) }
|
|
}
|
|
}
|
|
}
|
|
|
|
private static var allowedHTMLTags = {
|
|
["font", // custom to matrix for IRC-style font coloring
|
|
"del", // for markdown
|
|
"body", // added internally by DTCoreText
|
|
"mx-reply",
|
|
"h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "p", "a", "ul", "ol",
|
|
"nl", "li", "b", "i", "u", "strong", "em", "strike", "code", "hr", "br", "div",
|
|
"table", "thead", "caption", "tbody", "tr", "th", "td", "pre"]
|
|
}()
|
|
}
|