diff --git a/Sources/HTMLStreamer/AttributedStringConverter.swift b/Sources/HTMLStreamer/AttributedStringConverter.swift
index eb3c7e1..d2f3170 100644
--- a/Sources/HTMLStreamer/AttributedStringConverter.swift
+++ b/Sources/HTMLStreamer/AttributedStringConverter.swift
@@ -151,7 +151,7 @@ public struct AttributedStringConverter {
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 {
}
}
- // 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 {
}
}
+ 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
diff --git a/Tests/HTMLStreamerTests/AttributedStringConverterTests.swift b/Tests/HTMLStreamerTests/AttributedStringConverterTests.swift
index fda40fb..14e2d3d 100644
--- a/Tests/HTMLStreamerTests/AttributedStringConverterTests.swift
+++ b/Tests/HTMLStreamerTests/AttributedStringConverterTests.swift
@@ -119,6 +119,21 @@ final class AttributedStringConverterTests: XCTestCase {
XCTAssertEqual(convert("bold both italic"), 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("hello world"), result)
+ }
+
func testDel() {
XCTAssertEqual(convert("blah"), NSAttributedString(string: "blah", attributes: [
.font: font,