fix(card): a search for blue no longer finds blunt
The card browser looked for a query also with every ae, oe and ue made a, o and u, so that maedchen found Mädchen: in any language, so blue found blunt, Spanish que found aquí, and ue nearly everything. A card's umlauts are written out on its side instead, beside its folded text, and a query is matched as typed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
4eb2640be6
commit
31eed85aff
2 changed files with 29 additions and 8 deletions
|
|
@ -109,7 +109,7 @@ typedef BrowsedCard = ({
|
||||||
/// `たべる` finds た.べる).
|
/// `たべる` finds た.べる).
|
||||||
String searchTextOf(Card card, List<Tag> tags) {
|
String searchTextOf(Card card, List<Tag> tags) {
|
||||||
final content = card.content;
|
final content = card.content;
|
||||||
return searchFolded(
|
return searchableText(
|
||||||
[
|
[
|
||||||
content.front.plainText,
|
content.front.plainText,
|
||||||
content.back.plainText,
|
content.back.plainText,
|
||||||
|
|
@ -126,6 +126,26 @@ String searchTextOf(Card card, List<Tag> tags) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [text] as a card's search text holds it: folded ([searchFolded]), and
|
||||||
|
/// where it has German's umlauts, folded once more with them written out,
|
||||||
|
/// so `maedchen` finds Mädchen as `madchen` does. Written out on the card's
|
||||||
|
/// side, not the query's: a query's own `ue` stays as typed, and `blue`
|
||||||
|
/// doesn't find blunt, nor Spanish `que` aquí.
|
||||||
|
String searchableText(String text) {
|
||||||
|
final folded = searchFolded(text);
|
||||||
|
final lower = text.toLowerCase();
|
||||||
|
if (!lower.contains(_umlaut)) {
|
||||||
|
return folded;
|
||||||
|
}
|
||||||
|
final written = lower
|
||||||
|
.replaceAll('ä', 'ae')
|
||||||
|
.replaceAll('ö', 'oe')
|
||||||
|
.replaceAll('ü', 'ue');
|
||||||
|
return '$folded\n${searchFolded(written)}';
|
||||||
|
}
|
||||||
|
|
||||||
|
final _umlaut = RegExp('[äöü]');
|
||||||
|
|
||||||
/// [text] as searches compare it and A–Z orders it: in lower case,
|
/// [text] as searches compare it and A–Z orders it: in lower case,
|
||||||
/// katakana as hiragana, without accents and tone marks (Latin and Greek
|
/// katakana as hiragana, without accents and tone marks (Latin and Greek
|
||||||
/// letters, pinyin's vowels), ß as ss and Greek's final sigma as σ; so
|
/// letters, pinyin's vowels), ß as ss and Greek's final sigma as σ; so
|
||||||
|
|
@ -177,18 +197,14 @@ final _bare = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Whether a card whose [searchText] is [searchTextOf] holds [query]: as
|
/// Whether a card whose [searchText] is [searchTextOf] holds [query]: as
|
||||||
/// typed, with German's umlauts written out as typed without them
|
/// typed (German's umlauts written out or not, see [searchableText]), or
|
||||||
/// (`maedchen` finds Mädchen), or romaji typed for its kana (`taberu`
|
/// romaji typed for its kana (`taberu` finds たべる).
|
||||||
/// finds たべる).
|
|
||||||
bool matchesQuery(String searchText, String query) {
|
bool matchesQuery(String searchText, String query) {
|
||||||
final typed = searchFolded(query.trim());
|
final typed = searchFolded(query.trim());
|
||||||
if (typed.isEmpty) {
|
if (typed.isEmpty) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return searchText.contains(typed) ||
|
return searchText.contains(typed) ||
|
||||||
searchText.contains(
|
|
||||||
typed.replaceAll('ae', 'a').replaceAll('oe', 'o').replaceAll('ue', 'u'),
|
|
||||||
) ||
|
|
||||||
searchText.contains(romajiToHiragana(typed, finished: true));
|
searchText.contains(romajiToHiragana(typed, finished: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ void main() {
|
||||||
test('a search finds words of any language as typed on any keyboard: '
|
test('a search finds words of any language as typed on any keyboard: '
|
||||||
'without accents, tone marks or umlauts, ß as ss, kana by romaji', () {
|
'without accents, tone marks or umlauts, ß as ss, kana by romaji', () {
|
||||||
bool finds(String text, String query) =>
|
bool finds(String text, String query) =>
|
||||||
matchesQuery(searchFolded(text), query);
|
matchesQuery(searchableText(text), query);
|
||||||
|
|
||||||
expect(finds('Straße', 'strasse'), isTrue);
|
expect(finds('Straße', 'strasse'), isTrue);
|
||||||
expect(finds('Mädchen', 'madchen'), isTrue);
|
expect(finds('Mädchen', 'madchen'), isTrue);
|
||||||
|
|
@ -18,6 +18,11 @@ void main() {
|
||||||
expect(finds('たべる', 'taberu'), isTrue);
|
expect(finds('たべる', 'taberu'), isTrue);
|
||||||
expect(finds('テレビ', 'てれび'), isTrue);
|
expect(finds('テレビ', 'てれび'), isTrue);
|
||||||
expect(finds('Haus', 'maus'), isFalse);
|
expect(finds('Haus', 'maus'), isFalse);
|
||||||
|
// Only a card's umlauts are written out, never a query's ue, oe or ae.
|
||||||
|
expect(finds('Müller', 'mueller'), isTrue);
|
||||||
|
expect(finds('blunt', 'blue'), isFalse);
|
||||||
|
expect(finds('aquí', 'que'), isFalse);
|
||||||
|
expect(finds('god', 'goed'), isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('A–Z compares letters as their bare ones: Ärger among the a, xué '
|
test('A–Z compares letters as their bare ones: Ärger among the a, xué '
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue