Fix handling of mis-nested <a> tags

This commit is contained in:
Shadowfacts 2023-12-17 18:32:00 -05:00
parent 2f18ad3cf4
commit d396a800f6
2 changed files with 22 additions and 2 deletions

View File

@ -151,7 +151,7 @@ public struct AttributedStringConverter<Callbacks: AttributedStringCallbacks> {
private mutating func handleEndTag(_ name: String) { private mutating func handleEndTag(_ name: String) {
switch name { switch name {
case "a": case "a":
if case .link(.some(_)) = styleStack.last { if case .link(.some(_)) = lastStyle(.link) {
finishRun() finishRun()
} }
removeLastStyle(.link) removeLastStyle(.link)
@ -186,7 +186,8 @@ public struct AttributedStringConverter<Callbacks: AttributedStringCallbacks> {
} }
} }
// needed to correctly handle mis-nested tags // Finds the last currently-open style of the given type.
// We can't just use the last one because we need to handle mis-nested tags.
private mutating func removeLastStyle(_ type: Style.StyleType) { private mutating func removeLastStyle(_ type: Style.StyleType) {
var i = styleStack.index(before: styleStack.endIndex) var i = styleStack.index(before: styleStack.endIndex)
while i >= styleStack.startIndex { while i >= styleStack.startIndex {
@ -198,6 +199,10 @@ public struct AttributedStringConverter<Callbacks: AttributedStringCallbacks> {
} }
} }
private func lastStyle(_ type: Style.StyleType) -> Style? {
styleStack.last { $0.type == type }
}
private lazy var blockquoteParagraphStyle: NSParagraphStyle = { private lazy var blockquoteParagraphStyle: NSParagraphStyle = {
let style = configuration.paragraphStyle.mutableCopy() as! NSMutableParagraphStyle let style = configuration.paragraphStyle.mutableCopy() as! NSMutableParagraphStyle
style.headIndent = 32 style.headIndent = 32

View File

@ -119,6 +119,21 @@ final class AttributedStringConverterTests: XCTestCase {
XCTAssertEqual(convert("<strong>bold <em>both</strong> italic</em>"), result) XCTAssertEqual(convert("<strong>bold <em>both</strong> italic</em>"), result)
} }
func testMisnestedLink() {
let result = NSMutableAttributedString()
result.append(NSAttributedString(string: "hello ", attributes: [
.link: URL(string: "https://example.com")!,
.font: font,
.paragraphStyle: NSParagraphStyle.default,
]))
result.append(NSAttributedString(string: "world", attributes: [
.link: URL(string: "https://example.com")!,
.font: boldFont,
.paragraphStyle: NSParagraphStyle.default,
]))
XCTAssertEqual(convert("<a href='https://example.com'>hello <b>world</a></b>"), result)
}
func testDel() { func testDel() {
XCTAssertEqual(convert("<del>blah</del>"), NSAttributedString(string: "blah", attributes: [ XCTAssertEqual(convert("<del>blah</del>"), NSAttributedString(string: "blah", attributes: [
.font: font, .font: font,