StringExtension.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // StringExtensions.swift
  3. // RichTextView
  4. //
  5. // Created by Ahmed Elkady on 2018-11-19.
  6. // Copyright © 2018 Top Hat. All rights reserved.
  7. //
  8. extension String {
  9. func replaceAppropiateZeroWidthSpaces() -> String? {
  10. let newString = self
  11. let cleanString = newString.replacingOccurrences(of: "\u{200B}", with: "\u{200D}")
  12. return cleanString
  13. }
  14. func replaceTrailingWhiteSpaceWithNonBreakingSpace() -> String {
  15. var newString = self
  16. while newString.last?.isWhitespace == true {
  17. newString = String(newString.dropLast())
  18. newString = newString.replacingCharacters(in: newString.endIndex..., with: " ")
  19. }
  20. return newString
  21. }
  22. func replaceLeadingWhiteSpaceWithNonBreakingSpace() -> String {
  23. var newString = self
  24. while newString.first?.isWhitespace == true {
  25. newString = newString.replacingCharacters(in: ...newString.startIndex, with: " ")
  26. }
  27. return newString
  28. }
  29. func getSubstring(inBetween firstTag: String, and secondTag: String) -> String? {
  30. return (self.range(of: firstTag)?.upperBound).flatMap { substringFrom in
  31. (self.range(of: secondTag, range: substringFrom..<self.endIndex)?.lowerBound).map { substringTo in
  32. String(self[substringFrom..<substringTo])
  33. }
  34. }
  35. }
  36. func getComponents(separatedBy string: String, options: CompareOptions = .regularExpression) -> [String] {
  37. var ranges = [Range<Index>]()
  38. var start = self.startIndex
  39. while let range = self.range(of: string, options: options, range: start..<self.endIndex) {
  40. if start != range.lowerBound {
  41. ranges.append(Range(uncheckedBounds: (lower: start, upper: range.lowerBound)))
  42. }
  43. ranges.append(range)
  44. start = {
  45. if range.lowerBound < range.upperBound {
  46. return range.upperBound
  47. }
  48. return self.index(range.lowerBound, offsetBy: 1, limitedBy: self.endIndex) ?? self.endIndex
  49. }()
  50. }
  51. if let lastRange = ranges.last, lastRange.upperBound < self.endIndex {
  52. ranges.append(Range(uncheckedBounds: (lower: lastRange.upperBound, upper: self.endIndex)))
  53. }
  54. if ranges.isEmpty {
  55. return [self]
  56. }
  57. return ranges.map { String(self[$0]) }
  58. }
  59. subscript(bounds: CountableClosedRange<Int>) -> String {
  60. let start = self.index(self.startIndex, offsetBy: bounds.lowerBound)
  61. let end = self.index(self.startIndex, offsetBy: bounds.upperBound)
  62. return String(self[start...end])
  63. }
  64. subscript(bounds: CountableRange<Int>) -> String {
  65. let start = self.index(self.startIndex, offsetBy: bounds.lowerBound)
  66. let end = self.index(self.startIndex, offsetBy: bounds.upperBound)
  67. return String(self[start..<end])
  68. }
  69. subscript(_ index: Int) -> String {
  70. let index = self.index(self.startIndex, offsetBy: index)
  71. return String(self[index])
  72. }
  73. // MARK: - Split String Extensions
  74. func split(atPositions positions: [Index]) -> [String] {
  75. var substrings = [String]()
  76. var start = 0
  77. var positions = positions
  78. positions.sort()
  79. positions = positions.filter { return $0 > self.startIndex && $0 < self.endIndex }
  80. while start < positions.count {
  81. let substring: String = {
  82. let startIndex = positions[start]
  83. if startIndex > self.startIndex && substrings.count == 0 {
  84. return String(self[..<startIndex])
  85. }
  86. if start == positions.count - 1 {
  87. start += 1
  88. return String(self[startIndex...])
  89. }
  90. let endIndex = positions[start + 1]
  91. start += 1
  92. return String(self[startIndex..<endIndex])
  93. }()
  94. if !substring.isEmpty {
  95. substrings.append(substring)
  96. }
  97. }
  98. if substrings.isEmpty {
  99. return [self]
  100. }
  101. return substrings
  102. }
  103. func ranges(of string: String, options: CompareOptions = .literal) -> [Range<Index>] {
  104. var result = [Range<Index>]()
  105. var start = self.startIndex
  106. while let range = self.range(of: string, options: options, range: start..<self.endIndex) {
  107. result.append(range)
  108. start = {
  109. if range.lowerBound < range.upperBound {
  110. return range.upperBound
  111. }
  112. return self.index(range.lowerBound, offsetBy: 1, limitedBy: self.endIndex) ?? self.endIndex
  113. }()
  114. }
  115. return result
  116. }
  117. }