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) {
switch name {
case "a":
if case .link(.some(_)) = styleStack.last {
if case .link(.some(_)) = lastStyle(.link) {
finishRun()
}
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) {
var i = styleStack.index(before: styleStack.endIndex)
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 = {
let style = configuration.paragraphStyle.mutableCopy() as! NSMutableParagraphStyle
style.headIndent = 32

View File

@ -119,6 +119,21 @@ final class AttributedStringConverterTests: XCTestCase {
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() {
XCTAssertEqual(convert("<del>blah</del>"), NSAttributedString(string: "blah", attributes: [
.font: font,