|
@@ -1,7 +1,28 @@
|
|
|
import Foundation
|
|
import Foundation
|
|
|
|
|
|
|
|
|
|
+enum WordLimit: Sendable {
|
|
|
|
|
+ nonisolated static func message(maxWords: Int) -> String {
|
|
|
|
|
+ "Maximum \(maxWords) words allowed."
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nonisolated static func apply(_ text: String, maxWords: Int) -> (text: String, exceeded: Bool) {
|
|
|
|
|
+ guard text.wordCount > maxWords else { return (text, false) }
|
|
|
|
|
+ return (text.truncated(toMaxWords: maxWords), true)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nonisolated static func applyImported(
|
|
|
|
|
+ _ text: String,
|
|
|
|
|
+ maxWords: Int,
|
|
|
|
|
+ setError: (String?) -> Void
|
|
|
|
|
+ ) -> String {
|
|
|
|
|
+ let (limited, exceeded) = apply(text, maxWords: maxWords)
|
|
|
|
|
+ setError(exceeded ? message(maxWords: maxWords) : nil)
|
|
|
|
|
+ return limited
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
extension String {
|
|
extension String {
|
|
|
- var wordCount: Int {
|
|
|
|
|
|
|
+ nonisolated var wordCount: Int {
|
|
|
let trimmed = trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let trimmed = trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
guard !trimmed.isEmpty else { return 0 }
|
|
guard !trimmed.isEmpty else { return 0 }
|
|
|
return trimmed
|
|
return trimmed
|
|
@@ -10,7 +31,7 @@ extension String {
|
|
|
.count
|
|
.count
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- func truncated(toMaxWords maxWords: Int) -> String {
|
|
|
|
|
|
|
+ nonisolated func truncated(toMaxWords maxWords: Int) -> String {
|
|
|
guard maxWords > 0 else { return "" }
|
|
guard maxWords > 0 else { return "" }
|
|
|
guard wordCount > maxWords else { return self }
|
|
guard wordCount > maxWords else { return self }
|
|
|
|
|
|
|
@@ -35,23 +56,4 @@ extension String {
|
|
|
|
|
|
|
|
return self
|
|
return self
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- static func wordLimitExceededMessage(maxWords: Int) -> String {
|
|
|
|
|
- "Maximum \(maxWords) words allowed."
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- func applyingWordLimit(maxWords: Int) -> (text: String, exceeded: Bool) {
|
|
|
|
|
- guard wordCount > maxWords else { return (self, false) }
|
|
|
|
|
- return (truncated(toMaxWords: maxWords), true)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- static func importedApplyingWordLimit(
|
|
|
|
|
- _ text: String,
|
|
|
|
|
- maxWords: Int,
|
|
|
|
|
- setError: (String?) -> Void
|
|
|
|
|
- ) -> String {
|
|
|
|
|
- let (limited, exceeded) = text.applyingWordLimit(maxWords: maxWords)
|
|
|
|
|
- setError(exceeded ? wordLimitExceededMessage(maxWords: maxWords) : nil)
|
|
|
|
|
- return limited
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|