 
         return leafs
     }
-
-
-    ///
-    ///
-    private func lineAttachmentToNode(_ lineAttachment: LineAttachment) -> ElementNode {
-        return ElementNode(type: .hr, attributes: [], children: [])
-    }
-
-
-    ///
-    ///
-    private func commentAttachmentToNode(_ attachment: CommentAttachment) -> CommentNode {
+}
+
+
+// MARK: - Style Extraction
+//
+private extension NSAttributedStringToNodes {
+
+    ///
+    ///
+    func enumerateParagraphNodes(in style: ParagraphStyle, block: ((ElementNode) -> Void)) {
+        if style.blockquote != nil {
+            block( ElementNode(type: .blockquote) )
+        }
+
+        if style.htmlParagraph != nil {
+            block( ElementNode(type: .p) )
+        }
+
+        if style.headerLevel > 0 {
+            let header = DOMString.elementTypeForHeaderLevel(style.headerLevel) ?? .h1
+            block( ElementNode(type: header) )
+        }
+
+        for list in style.textLists {
+            if list.style == .ordered {
+                block( ElementNode(type: .ol) )
+            } else {
+                block( ElementNode(type: .ul) )
+            }
+        }
+
+        if !style.textLists.isEmpty {
+            block( ElementNode(type: .li) )
+        }
+    }
+
+
+    ///
+    ///
+    func enumerateStyleNodes(in attributes: [String: Any], block: ((ElementNode) -> Void)) {
+        for (key, value) in attributes {
+            switch key {
+            case NSFontAttributeName:
+                guard let font = value as? UIFont else {
+                    break
+                }
+
+                if font.containsTraits(.traitBold) == true {
+                    block( ElementNode(type: .b) )
+                }
+
+                if font.containsTraits(.traitItalic) == true {
+                    block( ElementNode(type: .i) )
+                }
+
+            case NSLinkAttributeName:
+                guard let url = value as? URL else {
+                    break
+                }
+
+                let source = StringAttribute(name: "href", value: url.absoluteString)
+                block( ElementNode(type: .a, attributes: [source]) )
+
+            case NSStrikethroughStyleAttributeName:
+                block( ElementNode(type: .strike) )
+
+            case NSUnderlineStyleAttributeName:
+                block( ElementNode(type: .u) )
+
+            default:
+                break
+            }
+        }
+    }
+}
+
+
+// MARK: - Leaf Nodes
+//
+private extension NSAttributedStringToNodes {
+
+    ///
+    ///
+    func lineAttachmentToNode(_ lineAttachment: LineAttachment) -> ElementNode {
+        return ElementNode(type: .hr)
+    }
+
+
+    ///
+    ///
+    func commentAttachmentToNode(_ attachment: CommentAttachment) -> CommentNode {
         return CommentNode(text: attachment.text)
     }
 
 
     ///
     ///
-    private func htmlAttachmentToNode(_ attachment: HTMLAttachment) -> [Node] {
+    func htmlAttachmentToNode(_ attachment: HTMLAttachment) -> [Node] {
         let converter = Libxml2.In.HTMLConverter()
 
         guard let rootNode = try? converter.convert(attachment.rawHTML),
             let firstChild = rootNode.children.first
-        else {
-            return textToNode(attachment.rawHTML)
+            else {
+                return textToNode(attachment.rawHTML)
         }
 
         guard rootNode.children.count == 1 else {

}


// MARK: - Leaf Nodes
//
private extension NSAttributedStringToNodes {

    ///
    ///
    func leafNodes(from attrString: NSAttributedString) -> [Node] {
        let attachment = attrString.attribute(NSAttachmentAttributeName, at: 0, effectiveRange: nil) as? NSTextAttachment
        var leafs = [Node]()



        paragraph.enumerateAttributes(in: paragraph.rangeOfEntireString, options: []) { (attrs, range, _) in

            let substring = paragraph.attributedSubstring(from: range)
            let leaves = createLeafNodes(from: substring)
            let nodes = createStyleNodes(from: attrs, leaves: leaves)

            children.append(contentsOf: nodes)
        }

        guard let paragraphElement = createParagraphElement(from: paragraph, children: children) else {
            return children
        }

