     public static func randomAlphanumeric(length: Int) -> String {
         let seed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
         return String((0..<length).map { _ in seed.randomElement()! })
+    }
+}
+
+// MARK: - Truncation
+
+extension String {
+    public enum TruncationPosition {
+        /// Truncate at head: `"...wxyz"`
+        case head
+        /// Truncate middle: `"ab...yz"`
+        case middle
+        /// Truncate at tail: `"abcd..."`
+        case tail
+    }
+
+    /// Truncates the string to the specified length and appends an ellipsis string
+    /// at the given truncation position.
+    ///
+    /// ```swift
+    /// let result = "This is a really long string".truncate(10)
+    /// print(result)
+    /// // "This is a ..."
+    /// ```
+    ///
+    /// - Parameters:
+    ///     - length: The maximum length of the string.
+    ///     - position: The truncation position option.
+    ///     - ellipsis: A `String` that will be appended in the truncation position.
+    public func truncate(_ length: Int, position: TruncationPosition = .tail, ellipsis: String = "...") -> String {
+        guard count > length else { return self }
+
+        switch position {
+            case .head:
+                return ellipsis + suffix(length)
+            case .middle:
+                let count = Double(length - ellipsis.count) / 2
+                let headCount = Int(ceil(count))
+                let tailCount = Int(floor(count))
+                return "\(prefix(headCount))\(ellipsis)\(suffix(tailCount))"
+            case .tail:
+                return prefix(length) + ellipsis
+        }
     }
 }
 

        do {
            let regex = try NSRegularExpression(pattern: pattern, options: [])
            let results = regex.matches(in: self, range: NSRange(startIndex..., in: self))
            let nsString = self as NSString
            return results.map {
                nsString.substring(with: $0.range)
            }

        options: NSStringDrawingOptions = .usesLineFragmentOrigin,
        constrainedToSize: CGSize
    ) -> CGSize {
        let expectedRect = nsString.boundingRect(
            with: constrainedToSize,
            options: options,
            attributes: [.font: font],
