From 847144d228d07c46e047e78e53ad74aa81342d8c Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 24 Feb 2026 16:54:37 +0900 Subject: [PATCH] WIP: generate matchspans for word search results --- .../word_search/word_search_match_span.dart | 23 +++++++++++++++++++ .../word_search/word_search_result.dart | 22 ++++++++++++++---- lib/search/word_search/word_search.dart | 4 ++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 lib/models/word_search/word_search_match_span.dart diff --git a/lib/models/word_search/word_search_match_span.dart b/lib/models/word_search/word_search_match_span.dart new file mode 100644 index 0000000..6aa6f9d --- /dev/null +++ b/lib/models/word_search/word_search_match_span.dart @@ -0,0 +1,23 @@ +enum WordSearchMatchSpanType { kanji, kana, sense } + +/// +class WordSearchMatchSpan { + /// Which type of item that this span is meant for. + final WordSearchMatchSpanType spanType; + + /// + final int index; + + /// The start of the span (inclusive) + final int start; + + /// The end of the span (inclusive) + final int end; + + WordSearchMatchSpan({ + required this.spanType, + required this.index, + required this.start, + required this.end, + }); +} diff --git a/lib/models/word_search/word_search_result.dart b/lib/models/word_search/word_search_result.dart index 261dc22..72cea49 100644 --- a/lib/models/word_search/word_search_result.dart +++ b/lib/models/word_search/word_search_result.dart @@ -1,9 +1,11 @@ import 'package:jadb/models/common/jlpt_level.dart'; import 'package:jadb/models/jmdict/jmdict_kanji_info.dart'; import 'package:jadb/models/jmdict/jmdict_reading_info.dart'; +import 'package:jadb/models/word_search/word_search_match_span.dart'; import 'package:jadb/models/word_search/word_search_ruby.dart'; import 'package:jadb/models/word_search/word_search_sense.dart'; import 'package:jadb/models/word_search/word_search_sources.dart'; +import 'package:jadb/search/word_search/word_search.dart'; /// A class representing a single dictionary entry from a word search. class WordSearchResult { @@ -34,11 +36,15 @@ class WordSearchResult { /// A class listing the sources used to make up the data for this word search result. final WordSearchSources sources; - // TODO: Create a list containing pointers to the matched parts of the word (either kanjiInfo, readingInfo, senses), - // as well as spans for the subpart of the string that matched. This will be used for highlighting, and displaying - // alternative kanji/kana forms later on. + /// A list of spans, specifying which part of this word result matched the search keyword. + /// + /// Note that this is considered ephemeral data - it does not originate from the dictionary, + /// and unlike the rest of the class it varies based on external information (the searchword). + /// It will *NOT* be exported to JSON, but can be reinferred by invoking [inferMatchSpans] with + /// the original searchword. + List? matchSpans; - const WordSearchResult({ + WordSearchResult({ required this.score, required this.entryId, required this.isCommon, @@ -48,6 +54,7 @@ class WordSearchResult { required this.senses, required this.jlptLevel, required this.sources, + this.matchSpans, }); Map toJson() => { @@ -97,6 +104,13 @@ class WordSearchResult { sources: WordSearchSources.empty(), ); + void inferMatchSpans( + String searchword, { + SearchMode searchMode = SearchMode.Auto, + }) { + throw UnimplementedError(); + } + String _formatJapaneseWord(WordSearchRuby word) => word.furigana == null ? word.base : '${word.base} (${word.furigana})'; diff --git a/lib/search/word_search/word_search.dart b/lib/search/word_search/word_search.dart index 1d7d8ed..86a8ce9 100644 --- a/lib/search/word_search/word_search.dart +++ b/lib/search/word_search/word_search.dart @@ -52,6 +52,10 @@ Future?> searchWordWithDbConnection( linearWordQueryData: linearWordQueryData, ); + for (final resultEntry in result) { + resultEntry.inferMatchSpans(word, searchMode: searchMode); + } + return result; }