                 guard let url = value as? URL else { return }
 
                 links = "href='\(url.absoluteString)'"
+                self.hasParsedLinks = true
             default:
                 assertionFailure("did not handle \(key)")
             }

        case span
        case a

        func openTag(with attributes: String? = nil) -> String {
            if let attributes = attributes {
                return "<\(self.rawValue) \(attributes)>"
            } else {
                return "<\(self.rawValue)>"
            }
        }

        func closeTag() -> String {
            return "</\(self.rawValue)>"
        }
    }

    let defaultName: Name
    var attributes: [NSAttributedStringKey: Any]
    let ignoreParagraphStyles: Bool

    mutating func addAttributes(_ attributes: [NSAttributedStringKey: Any]?) {
        attributes?.forEach { (key, value) in
            self.attributes[key] = value
        }
    }

    func makeOpenTag() -> String {
        guard !self.attributes.isEmpty else { return self.defaultName.openTag() }

        var styles: [String: String] = [:]
        var cocoaStyles: [String: String] = [:]

                                                    } else {
                                                        guard let range = Range(nsrange, in: attributedString.string) else { return }

                                                        var tag = HTMLTag(defaultName: .span, attributes: attributes, ignoreParagraphStyles: true)
                                                        paragraphContent += tag.parseOpenTag()
                                                        paragraphContent += String(attributedString.string[range]).htmlEscaped
                                                        paragraphContent += tag.makeCloseTag()
                                                    }
            })

            html += paragraphTag.parseOpenTag() + paragraphContent + paragraphTag.makeCloseTag()
        }

        return html
