Skip to content

Commit

Permalink
Merge branch 'release/4.2.0' into versions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeehut committed Apr 14, 2024
2 parents 0a66272 + bd2394c commit 7ef8da8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 1 deletion.
Binary file added Images/FreelanceKit.webp
Binary file not shown.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,28 @@ I extracted most of this library from these Indie apps (rate them with 5 stars t
</td>
<td>
<a href="https://apps.apple.com/app/apple-store/id6476773066?pt=549314&ct=github.com&mt=8">
<strong>String Catalog Translator</strong>
<strong>TranslateKit: App Localizer</strong>
</a>
<br />
Simple drag & drop translation of String Catalog files with support for 4 machine translation services.
</td>
<td>Mac</td>
</tr>
<tr>
<td>
<a href="https://apps.apple.com/app/apple-store/id6480134993?pt=549314&ct=github.com&mt=8">
<img src="https://raw.githubusercontent.com/FlineDev/HandySwift/main/Images/FreelanceKit.webp" width="64" />
</a>
</td>
<td>
<a href="https://apps.apple.com/app/apple-store/id6480134993?pt=549314&ct=github.com&mt=8">
<strong>FreelanceKit: Time Tracking</strong>
</a>
<br />
Simple & affordable time tracking with a native experience for all  devices. iCloud sync & CSV export included.
</td>
<td>iPhone, iPad, Mac, Vision</td>
</tr>
<tr>
<td>
<a href="https://apps.apple.com/app/apple-store/id6472669260?pt=549314&ct=github.com&mt=8">
Expand Down
39 changes: 39 additions & 0 deletions Sources/HandySwift/Extensions/StringExt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,45 @@ extension String {

return plainString
}

/// Splits the String into word tokens that are folded for case-insensitive, diacritics-insensitive, and width-insensitive operations such as search.
/// This is particularly useful for string normalization in search queries, where the goal is to match strings regardless of their case, diacritics, or full-width/half-width characters.
///
/// - Parameter locale: Optional. The locale to use for the folding operation. If `nil`, the system's current locale is used. This affects the folding behavior, especially for diacritics.
/// - Returns: An array of normalized, tokenized strings.
///
/// ## Example:
/// ```
/// let sentence = "Café au lait"
/// let tokens = sentence.tokenized()
/// print(tokens) // Output: ["cafe", "au", "lait"]
/// ```
public func tokenized(locale: Locale? = nil) -> [String] {
self.components(separatedBy: .whitespacesAndNewlines).map { word in
word.folding(options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive], locale: locale)
}
}

/// Splits both the current string and the search text into word tokens and performs a case-insensitive, diacritics-insensitive search.
/// It matches the start of each token in the search text with the tokens in the current string, making it suitable for prefix-based search queries.
///
/// - Parameters:
/// - searchText: The text to search for within this String.
/// - locale: Optional. The locale to use for the insensitivity folding operation. If `nil`, the system's current locale is used. This can impact how characters are folded for comparison.
/// - Returns: `true` if all tokens from the search text are prefixes of any token in this String; otherwise, `false`.
///
/// ## Example:
/// ```
/// let text = "Terms and Conditions"
/// let searchResult = text.matchesTokenizedPrefixes(in: "ter con")
/// print(searchResult) // Output: true
/// ```
public func matchesTokenizedPrefixes(in searchText: String, locale: Locale? = nil) -> Bool {
let tokens = self.tokenized(locale: locale)
return searchText.tokenized(locale: locale).allSatisfy { searchToken in
tokens.contains { $0.hasPrefix(searchToken) }
}
}
}
#endif

Expand Down
2 changes: 2 additions & 0 deletions Sources/HandySwift/HandySwift.docc/Essentials/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ func downloadPuzzle(from url: URL) async throws -> Puzzle {
- ``Swift/String/randomElements(count:)``
- ``Swift/String/encrypted(key:)``
- ``Swift/String/decrypted(key:)``
- ``Swift/String/tokenized(locale:)``
- ``Swift/String/matchesTokenizedPrefixes(in:locale:)``

### StringProtocol

Expand Down

0 comments on commit 7ef8da8

Please sign in to comment.