             attributes[NSAttachmentAttributeName] = attachment
         }
 
-        if node.isNodeType(.ol) {
-            let formatter = TextListFormatter(style: .ordered)
-            attributes = formatter.apply(to: attributes)
-        }
-
-        if node.isNodeType(.ul) {
-            let formatter = TextListFormatter(style: .unordered)
-            attributes = formatter.apply(to: attributes)
+        for (key, formatter) in elementToFormattersMap {
+            if node.isNodeType(key) {
+                attributes = formatter.apply(to: attributes);
+            }
         }
 
         return attributes
     }
 
-    // MARK: - Font
-
-    fileprivate func fontDescriptor(forNode node: ElementNode, withBaseFontDescriptor fontDescriptor: UIFontDescriptor) -> UIFontDescriptor {
-        let traits = symbolicTraits(forNode: node, withBaseSymbolicTraits: fontDescriptor.symbolicTraits)
-
-        return fontDescriptor.withSymbolicTraits(traits)!
-    }
-
-    /// Gets a list of symbolic traits representing the specified node.
-    ///
-    /// - Parameters:
-    ///     - node: the node to get the traits from.
-    ///
-    /// - Returns: the requested symbolic traits.
-    ///
-    fileprivate func symbolicTraits(forNode node: ElementNode, withBaseSymbolicTraits baseTraits: UIFontDescriptorSymbolicTraits) -> UIFontDescriptorSymbolicTraits {
-
-        var traits = baseTraits
-
-        if isBold(node) {
-            traits.insert(.traitBold)
-        }
-
-        if isItalic(node) {
-            traits.insert(.traitItalic)
-        }
-
-        return traits
-    }
-
-    // MARK: - Node Style Checks
-
-    fileprivate func isLink(_ node: ElementNode) -> Bool {
-        return node.name == StandardElementType.a.rawValue
-    }
-
-    fileprivate func isBold(_ node: ElementNode) -> Bool {
-        return StandardElementType.b.equivalentNames.contains(node.name)
-    }
-
-    fileprivate func isItalic(_ node: ElementNode) -> Bool {
-        return StandardElementType.i.equivalentNames.contains(node.name)
-    }
-
-    fileprivate func isStrikedThrough(_ node: ElementNode) -> Bool {
-        return StandardElementType.s.equivalentNames.contains(node.name)
-    }
-
-    fileprivate func isUnderlined(_ node: ElementNode) -> Bool {
-        return node.name == StandardElementType.u.rawValue
-    }
-
-    fileprivate func isBlockquote(_ node: ElementNode) -> Bool {
-        return node.name == StandardElementType.blockquote.rawValue
-    }
-
-    fileprivate func isImage(_ node: ElementNode) -> Bool {
-        return node.name == StandardElementType.img.rawValue
-    }    
+    public let elementToFormattersMap: [StandardElementType: AttributeFormatter] = [
+        .ol: TextListFormatter(style: .ordered),
+        .ul: TextListFormatter(style: .unordered),
+        .blockquote: BlockquoteFormatter(),
+        .strong: BoldFormatter(),
+        .em: ItalicFormatter(),
+        .u: UnderlineFormatter(),
+        .del: StrikethroughFormatter()
+    ]
 }

            attributes[NSLinkAttributeName] = linkURL as AnyObject?
        }

        if isStrikedThrough(node) {
            attributes[NSStrikethroughStyleAttributeName] = NSUnderlineStyle.styleSingle.rawValue as AnyObject?
        }

        if isUnderlined(node) {
            attributes[NSUnderlineStyleAttributeName] = NSUnderlineStyle.styleSingle.rawValue as AnyObject?
        }

        if isBlockquote(node) {
            let formatter = BlockquoteFormatter()
            attributes = formatter.apply(to: attributes)
        }

        if isImage(node) {
            let url: URL?

            if let urlString = node.valueForStringAttribute(named: "src") {


        var attributes = inheritedAttributes

        if node.isNodeType(.a) {
            let linkURL: String

            if let attributeIndex = node.attributes.index(where: { $0.name == HTMLLinkAttribute.Href.rawValue }),
