 
 struct Typographizer {
 
-    enum TypographizerTokenResult: String {
+    enum Result: String {
         case openingSingle = "opening-single"
         case closingSingle = "closing-single"
         case openingDouble = "opening-double"
         case closingDouble = "closing-double"
-        case apostrophe = "apostrophe"
+        case apostrophe
         case enDash = "en-dash"
         // Unchanged text because it doesn’t contain the trigger characters:
-        case unchanged = "unchanged"
+        case unchanged
         // It’s one of the trigger characters but didn’t need changing:
-        case ignored = "ignored"
+        case ignored
         // Was skipped because it was either an HTML tag, or a pair of tags with protected text in between:
-        case skipped = "skipped"
-    }
-    
-    struct TypographizerToken {
-        let result: TypographizerTokenResult
+        case skipped
+    }
+    
+    struct Token {
+        let result: Result
         let text: String
         
-        init(_ result: TypographizerTokenResult, _ text: String) {
+        init(_ result: Result, _ text: String) {
             self.result = result
             self.text = text
         }

                bufferedScalar = ch
                break loop
            default:
                self.previousScalar = ch
                tokenText.unicodeScalars.append(ch)
            }
        }
        return TypographizerToken(.unchanged, tokenText)
    }
    
    // MARK: Fixable Token (quote, apostrophe, hyphen)
    
    private mutating func fixableToken(_ first: UnicodeScalar) throws -> TypographizerToken {
        var tokenText = String(first)
        
        let nextScalar = self.nextScalar()
        self.bufferedScalar = nextScalar
        
        var fixingResult: TypographizerTokenResult = .ignored
        
        switch first {
        case "\"":
            if let previousScalar = self.previousScalar,
                let nextScalar = nextScalar {
                if CharacterSet.whitespacesAndNewlines.contains(previousScalar) || self.openingBracketsArray.contains(previousScalar) {
                    tokenText = self.openingDoubleQuote
                    fixingResult = .openingDouble
                } else if CharacterSet.whitespacesAndNewlines.contains(nextScalar) || CharacterSet.punctuationCharacters.contains(nextScalar) {
                    tokenText = self.closingDoubleQuote
                    fixingResult = .closingDouble
                } else {
                    tokenText = self.closingDoubleQuote
                    fixingResult = .closingDouble
                }
            } else {
                if previousScalar == nil {
                    // The last character of a string:
                    tokenText = self.openingDoubleQuote
                    fixingResult = .openingDouble
                } else {
                    // The first character of a string:
                    tokenText = self.closingDoubleQuote
                    fixingResult = .closingDouble
                }
            }
            
        case "'":
            if let previousScalar = self.previousScalar,
                let nextScalar = nextScalar {
                
                if CharacterSet.whitespacesAndNewlines.contains(previousScalar)
                    || CharacterSet.punctuationCharacters.contains(previousScalar) && !CharacterSet.whitespacesAndNewlines.contains(nextScalar)
                {
                    tokenText = self.openingSingleQuote
                    fixingResult = .openingSingle
                } else if CharacterSet.whitespacesAndNewlines.contains(nextScalar) || CharacterSet.punctuationCharacters.contains(nextScalar) {
                    tokenText = self.closingSingleQuote
                    fixingResult = .closingSingle
                } else {
                    tokenText = self.apostrophe
                    fixingResult = .apostrophe
                }
            } else {
                if previousScalar == nil {
                    // The first character of a string:
                    tokenText = self.openingSingleQuote
                    fixingResult = .openingSingle
                } else {
                    // The last character of a string:
                    tokenText = self.closingSingleQuote
                    fixingResult = .closingSingle
                }
            }
        case "-":
            if let previousScalar = self.previousScalar,
                let nextScalar = nextScalar,
                CharacterSet.whitespacesAndNewlines.contains(previousScalar)
                && CharacterSet.whitespacesAndNewlines.contains(nextScalar)
            {
                tokenText = self.enDash
                fixingResult = .enDash
            }
        default: ()
        }
        
        self.previousScalar = tokenText.unicodeScalars.last
        
        #if DEBUG
            if self.isDebugModeEnabled && self.isHTML {
                tokenText = "<span class=\"typographizer-debug typographizer-debug--\(fixingResult.rawValue)\">\(tokenText)</span>"
            }
        #endif
        return TypographizerToken(fixingResult, tokenText)
    }
    
}

                tokenText.unicodeScalars.append(ch)
            }
        }
        return Token(.skipped, tokenText)
    }
    
    private mutating func fastForwardToClosingTag(_ tag: String) -> String {
