Mark code blocks with a special attribute and strip away links from them.
This commit is contained in:
@@ -31,6 +31,7 @@ extension NSAttributedString.Key {
|
||||
static let MatrixEventOnRoomID: NSAttributedString.Key = .init(rawValue: EventOnRoomIDAttribute.name)
|
||||
static let MatrixEventOnRoomAlias: NSAttributedString.Key = .init(rawValue: EventOnRoomAliasAttribute.name)
|
||||
static let MatrixAllUsersMention: NSAttributedString.Key = .init(rawValue: AllUsersMentionAttribute.name)
|
||||
static let CodeBlock: NSAttributedString.Key = .init(rawValue: CodeBlockAttribute.name)
|
||||
}
|
||||
|
||||
struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
|
||||
@@ -85,6 +85,7 @@ struct AttributedStringBuilderV2: AttributedStringBuilderProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// swiftlint:disable:next function_body_length
|
||||
func attributedString(from element: Element, preserveFormatting: Bool,
|
||||
listTag: String?,
|
||||
listIndex: inout Int,
|
||||
@@ -162,15 +163,17 @@ struct AttributedStringBuilderV2: AttributedStringBuilderProtocol {
|
||||
let preserveFormatting = preserveFormatting || tag == "pre"
|
||||
content = attributedString(from: childElement, preserveFormatting: preserveFormatting, listTag: listTag, listIndex: &childIndex, indentLevel: indentLevel)
|
||||
content.setFontPreservingSymbolicTraits(UIFont.monospacedSystemFont(ofSize: UIFont.systemFontSize, weight: .regular))
|
||||
content.addAttribute(.CodeBlock, value: true, range: NSRange(location: 0, length: content.length))
|
||||
content.addAttribute(.backgroundColor, value: UIColor.compound._bgCodeBlock as Any, range: NSRange(location: 0, length: content.length))
|
||||
|
||||
// Don't allow identifiers in code blocks
|
||||
// Don't allow identifiers or links in code blocks
|
||||
content.removeAttribute(.MatrixRoomID, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.MatrixRoomAlias, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.MatrixUserID, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.MatrixEventOnRoomID, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.MatrixEventOnRoomAlias, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.MatrixAllUsersMention, range: NSRange(location: 0, length: content.length))
|
||||
content.removeAttribute(.link, range: NSRange(location: 0, length: content.length))
|
||||
|
||||
case "hr":
|
||||
content = NSMutableAttributedString(string: "\n")
|
||||
@@ -295,9 +298,15 @@ struct AttributedStringBuilderV2: AttributedStringBuilderProtocol {
|
||||
|
||||
// Sort the links by length so the longest one always takes priority
|
||||
matches.sorted { $0.range.length > $1.range.length }.forEach { [attributedString] match in
|
||||
// Don't highlight links within codeblocks
|
||||
let isInCodeBlock = attributedString.attribute(.CodeBlock, at: match.range.location, effectiveRange: nil) != nil
|
||||
if isInCodeBlock {
|
||||
return
|
||||
}
|
||||
|
||||
var hasLink = false
|
||||
attributedString.enumerateAttribute(.link, in: match.range, options: []) { value, _, stop in
|
||||
if value != nil {
|
||||
if value != nil, !isInCodeBlock {
|
||||
hasLink = true
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
@@ -62,6 +62,11 @@ enum AllUsersMentionAttribute: AttributedStringKey {
|
||||
static let name = "MXAllUsersMentionAttribute"
|
||||
}
|
||||
|
||||
enum CodeBlockAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
static let name = "MXCodeBlockAttribute"
|
||||
}
|
||||
|
||||
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||
extension AttributeScopes {
|
||||
struct ElementXAttributes: AttributeScope {
|
||||
@@ -77,6 +82,8 @@ extension AttributeScopes {
|
||||
|
||||
let allUsersMention: AllUsersMentionAttribute
|
||||
|
||||
let codeBlock: CodeBlockAttribute
|
||||
|
||||
let swiftUI: SwiftUIAttributes
|
||||
let uiKit: UIKitAttributes
|
||||
}
|
||||
|
||||
@@ -89,7 +89,8 @@ enum HTMLFixtures: String, CaseIterable {
|
||||
Followed by some plain code blocks</br>
|
||||
<code>Hello, world!</code>
|
||||
<code><b>Hello</b>, <i>world!</i></code>
|
||||
<code><b>Hello</b>, <a href="https://www.matrix.org">world!</a></code>
|
||||
<code><a href="https://www.matrix.org">This link should not be interpreted as such</a></code>
|
||||
<code>And this https://www.matrix.org should be not highlighted</code>
|
||||
"""
|
||||
case .unorderedList:
|
||||
"""
|
||||
|
||||
@@ -590,10 +590,6 @@ class AttributedStringBuilderV1Tests: XCTestCase {
|
||||
}
|
||||
|
||||
func testURLsAreIgnoredInCode() {
|
||||
if AttributedStringBuilder.useNextGenHTMLParser {
|
||||
return
|
||||
}
|
||||
|
||||
var htmlString = "<pre><code>test https://matrix.org test</code></pre>"
|
||||
var attributedStringFromHTML = attributedStringBuilder.fromHTML(htmlString)
|
||||
XCTAssert(attributedStringFromHTML?.runs.count == 1)
|
||||
@@ -606,10 +602,6 @@ class AttributedStringBuilderV1Tests: XCTestCase {
|
||||
}
|
||||
|
||||
func testHyperlinksAreIgnoredInCode() {
|
||||
if AttributedStringBuilder.useNextGenHTMLParser {
|
||||
return
|
||||
}
|
||||
|
||||
let htmlString = "<pre><code>test <a href=\"https://matrix.org\">matrix</a> test</code></pre>"
|
||||
let attributedStringFromHTML = attributedStringBuilder.fromHTML(htmlString)
|
||||
XCTAssertNil(attributedStringFromHTML?.link)
|
||||
@@ -619,11 +611,7 @@ class AttributedStringBuilderV1Tests: XCTestCase {
|
||||
let htmlString = "<pre><code>test https://matrix.org/#/@test:matrix.org test</code></pre>"
|
||||
let attributedString = attributedStringBuilder.fromHTML(htmlString)
|
||||
|
||||
if AttributedStringBuilder.useNextGenHTMLParser {
|
||||
XCTAssert(attributedString?.runs.count == 3)
|
||||
} else {
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
}
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
|
||||
XCTAssertNil(attributedString?.attachment)
|
||||
}
|
||||
@@ -632,11 +620,7 @@ class AttributedStringBuilderV1Tests: XCTestCase {
|
||||
let htmlString = "<pre><code>Hey @some.user.ceriu:matrix.org</code></pre>"
|
||||
let attributedString = attributedStringBuilder.fromHTML(htmlString)
|
||||
|
||||
if AttributedStringBuilder.useNextGenHTMLParser {
|
||||
XCTAssert(attributedString?.runs.count == 2)
|
||||
} else {
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
}
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
|
||||
XCTAssertNil(attributedString?.attachment)
|
||||
}
|
||||
@@ -645,11 +629,7 @@ class AttributedStringBuilderV1Tests: XCTestCase {
|
||||
let htmlString = "<pre><code>test @room test</code></pre>"
|
||||
let attributedString = attributedStringBuilder.fromHTML(htmlString)
|
||||
|
||||
if AttributedStringBuilder.useNextGenHTMLParser {
|
||||
XCTAssert(attributedString?.runs.count == 3)
|
||||
} else {
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
}
|
||||
XCTAssert(attributedString?.runs.count == 1)
|
||||
|
||||
XCTAssertNil(attributedString?.attachment)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user