Skip to content

Commit f4fd107

Browse files
authored
Fix regex match substring by range when string includes emojis (#1279)
1 parent dc76428 commit f4fd107

3 files changed

Lines changed: 20 additions & 18 deletions

File tree

Zotero/Controllers/ISBNParser.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ final class ISBNParser {
2121
var isbns: [String] = []
2222

2323
for match in matches {
24-
let startIndex = cleanedString.index(cleanedString.startIndex, offsetBy: match.range.lowerBound)
25-
let endIndex = cleanedString.index(cleanedString.startIndex, offsetBy: match.range.upperBound)
26-
let isbn = cleanedString[startIndex..<endIndex].replacingOccurrences(of: #"\s+"#, with: "", options: .regularExpression, range: nil)
24+
guard let range = Range(match.range, in: cleanedString) else { continue }
25+
let isbn = cleanedString[range].replacingOccurrences(of: #"\s+"#, with: "", options: .regularExpression, range: nil)
2726

2827
if isbn.count == 10 ? self.validate(isbn10: isbn) : self.validate(isbn13: isbn) {
2928
isbns.append(isbn)

Zotero/Scenes/Detail/Items/ViewModels/BaseItemsActionHandler.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,26 @@ class BaseItemsActionHandler: BackgroundDbProcessingActionHandler {
7676
}
7777

7878
var components: [String] = []
79-
for (idx, match) in matches.enumerated() {
80-
if match.range.lowerBound > 0 {
81-
let lowerBound = idx == 0 ? 0 : matches[idx - 1].range.upperBound
82-
let precedingRange = normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: lowerBound)..<normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: match.range.lowerBound)
83-
let precedingComponents = separateComponents(from: String(normalizedSearchTerm[precedingRange]))
79+
var previousMatchEnd = normalizedSearchTerm.startIndex
80+
for match in matches {
81+
guard let matchRange = Range(match.range, in: normalizedSearchTerm) else { continue }
82+
83+
if matchRange.lowerBound > previousMatchEnd {
84+
let precedingComponents = separateComponents(from: String(normalizedSearchTerm[previousMatchEnd..<matchRange.lowerBound]))
8485
components.append(contentsOf: precedingComponents)
8586
}
8687

87-
let upperBound = normalizedSearchTerm[normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: (match.range.upperBound - 1))] == "\"" ? match.range.upperBound - 1 : match.range.upperBound
88-
let range = normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: (match.range.lowerBound + 1))..<normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: upperBound)
89-
components.append(String(normalizedSearchTerm[range]))
88+
// Strip the opening quote, and the closing quote if present
89+
var innerStart = normalizedSearchTerm.index(after: matchRange.lowerBound)
90+
let innerEnd = normalizedSearchTerm[normalizedSearchTerm.index(before: matchRange.upperBound)] == "\"" ? normalizedSearchTerm.index(before: matchRange.upperBound) : matchRange.upperBound
91+
if innerStart > innerEnd { innerStart = innerEnd }
92+
components.append(String(normalizedSearchTerm[innerStart..<innerEnd]))
93+
94+
previousMatchEnd = matchRange.upperBound
9095
}
9196

92-
if let match = matches.last, match.range.upperBound != (normalizedSearchTerm.count - 1) {
93-
let lastRange = normalizedSearchTerm.index(normalizedSearchTerm.startIndex, offsetBy: match.range.upperBound)..<normalizedSearchTerm.endIndex
94-
let lastComponents = separateComponents(from: String(normalizedSearchTerm[lastRange]))
97+
if previousMatchEnd < normalizedSearchTerm.endIndex {
98+
let lastComponents = separateComponents(from: String(normalizedSearchTerm[previousMatchEnd..<normalizedSearchTerm.endIndex]))
9599
components.append(contentsOf: lastComponents)
96100
}
97101

Zotero/Scenes/Detail/Lookup/ViewModels/ManualLookupActionHandler.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ final class ManualLookupActionHandler: ViewModelActionHandler {
5252
}
5353

5454
private func getResults(withExpression expression: NSRegularExpression, from text: String) -> [String] {
55-
return expression.matches(in: text, range: NSRange(text.startIndex..., in: text)).map { result in
56-
let startIndex = text.index(text.startIndex, offsetBy: result.range.lowerBound)
57-
let endIndex = text.index(text.startIndex, offsetBy: result.range.upperBound)
58-
return String(text[startIndex..<endIndex])
55+
return expression.matches(in: text, range: NSRange(text.startIndex..., in: text)).compactMap { result in
56+
guard let range = Range(result.range, in: text) else { return nil }
57+
return String(text[range])
5958
}
6059
}
6160
}

0 commit comments

Comments
 (0)