 
 
     // MARK: - Getting format identifiers
-
+    
+    private let formatterIdentifiersMap: [FormattingIdentifier: AttributeFormatter] = [
+        .bold: BoldFormatter(),
+        .italic: ItalicFormatter(),
+        .underline: UnderlineFormatter(),
+        .strikethrough: StrikethroughFormatter(),
+        .link: LinkFormatter(),
+        .orderedlist: TextListFormatter(style: .ordered),
+        .unorderedlist: TextListFormatter(style: .unordered),
+        .blockquote: BlockquoteFormatter()
+    ]
 
     /// Get a list of format identifiers spanning the specified range as a String array.
     ///

        return textStorage.attribute(NSAttachmentAttributeName, at: index, effectiveRange: nil) as? TextAttachment
    }


    /// Check if the bold attribute spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func boldFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = BoldFormatter()
        return formatter.present(in: storage, at: range)
    }


    /// Check if the italic attribute spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func italicFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = ItalicFormatter()
        return formatter.present(in: storage, at: range)
    }


    /// Check if the underline attribute spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func underlineFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = UnderlineFormatter()        
        return formatter.present(in: storage, at: range)
    }


    /// Check if the strikethrough attribute spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func strikethroughFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = StrikethroughFormatter()
        return formatter.present(in: storage, at: range)
    }

    /// Check if the link attribute spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func linkFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = LinkFormatter()
        return formatter.present(in: storage, at: range)
    }


    /// Check if an ordered list spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func orderedListFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = TextListFormatter(style: .ordered)
        return formatter.present(in: storage, at: range)
    }


    /// Check if an unordered list spans the specified range.
    ///
    /// - Parameter range: The NSRange to inspect.
    ///
    /// - Returns: True if the attribute spans the entire range.
    ///
    open func unorderedListFormattingSpansRange(_ range: NSRange) -> Bool {
        let formatter = TextListFormatter(style: .unordered)
        return formatter.present(in: storage, at: range)
    }


    /// Returns an NSURL if the specified range as attached a link attribute
    ///

    open func formatIdentifiersForTypingAttributes() -> [FormattingIdentifier] {
        var identifiers = [FormattingIdentifier]()

        for (key, formatter) in formatterIdentifiersMap {
            if formatter.present(in: typingAttributes) {
                identifiers.append(key)
            }
        }

        return identifiers
