 
 // MARK: Private Functions
 
-/** Remove duplicated coloring ranges.
- 
- This sanitization will reduce performance time of `applyHighlights:highlights:layoutManager:` significantly.
- Adding temporary attribute to a layoutManager is quite sluggish,
- so we want to remove useless highlighting ranges as many as possible beforehand.
- */
+private extension String {
+    
+    /// find and return ranges of passed-in substring with the given range of receiver.
+    func ranges(of substring: String, range searchRange: NSRange) -> [NSRange] {
+        
+        var ranges = [NSRange]()
+        
+        var location = searchRange.location
+        while location != NSNotFound {
+            let range = (self as NSString).range(of: substring, options: .literal, range: NSRange(location..<searchRange.upperBound))
+            location = range.upperBound
+            
+            guard range.location != NSNotFound else { break }
+            guard !self.isCharacterEscaped(at: range.location) else { continue }
+            
+            ranges.append(range)
+        }
+        
+        return ranges
+    }
+    
+}
+
+
+
+/// Remove duplicated coloring ranges.
+///
+/// This sanitization will reduce performance time of `applyHighlights:highlights:layoutManager:` significantly.
+/// Adding temporary attribute to a layoutManager is quite sluggish,
+/// so we want to remove useless highlighting ranges as many as possible beforehand.
 private func sanitize(highlights: [SyntaxType: [NSRange]]) -> [SyntaxType: [NSRange]] {
     
     var sanitizedHighlights = [SyntaxType: [NSRange]]()

        var sanitizedRanges = [NSRange]()
        
        for range in ranges {
            if !highlightedIndexes.contains(in: range) {
                sanitizedRanges.append(range)
                highlightedIndexes.add(in: range)
            }
        }
        
        if !sanitizedRanges.isEmpty {
            sanitizedHighlights[type] = sanitizedRanges
        }
    }
    
    return sanitizedHighlights

    
    // MARK: Private Methods
    
    /// extract ranges of quoted texts as well as comments in the parse range
    private func extractCommentsWithQuotes() -> [SyntaxType: [NSRange]] {
        
        var positions = [QuoteCommentItem]()
        
        if let delimiters = self.blockCommentDelimiters {
            for range in self.string!.ranges(of: delimiters.begin, range: self.parseRange) {
                positions.append(QuoteCommentItem(kind: QuoteCommentItem.Kind.blockComment, role: .begin, range: range))
            }
            for range in self.string!.ranges(of: delimiters.end, range: self.parseRange) {
                positions.append(QuoteCommentItem(kind: QuoteCommentItem.Kind.blockComment, role: .end, range: range))
            }
        }
        
        if let delimiter = self.inlineCommentDelimiter {
            for range in self.string!.ranges(of: delimiter, range: self.parseRange) {
                let lineRange = (self.string! as NSString).lineRange(for: range)
                let endRange = NSRange(location: lineRange.upperBound, length: 0)
                
