feat(frontend): search results show deleted, edited and earlier version marks with highlighted words, filter chips live in the url, results load on scroll
This commit is contained in:
1 parent
d45c96c259
commit
9a6bd8a714
15 files changed
+1430
-228
No files matched your search
@@ -0,0 +1,58 @@
|
||||
export interface Segment {
|
||||
hit: boolean;
|
||||
text: string;
|
||||
}
|
||||
|
||||
const WORD = /[\p{L}\p{N}_]+/gu;
|
||||
const SPACE = /\s/;
|
||||
const PREFIX_MIN = 3;
|
||||
const REACH = 20;
|
||||
const LEAD = 10;
|
||||
|
||||
function fold(word: string): string {
|
||||
return word.toLowerCase().replaceAll("ё", "е");
|
||||
}
|
||||
|
||||
function matches(word: string, terms: string[]): boolean {
|
||||
const folded = fold(word);
|
||||
return terms.some((term) =>
|
||||
term.length >= PREFIX_MIN ? folded.startsWith(term) : folded === term
|
||||
);
|
||||
}
|
||||
|
||||
function windowed(text: string, terms: string[]): string {
|
||||
for (const match of text.matchAll(WORD)) {
|
||||
if (!matches(match[0], terms)) {
|
||||
continue;
|
||||
}
|
||||
if (match.index <= REACH) {
|
||||
return text;
|
||||
}
|
||||
let start = match.index - LEAD;
|
||||
while (start > 0 && !SPACE.test(text[start - 1])) {
|
||||
start -= 1;
|
||||
}
|
||||
return `…${text.slice(start)}`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function highlight(text: string, terms: string[]): Segment[] {
|
||||
const shown = windowed(text, terms);
|
||||
const segments: Segment[] = [];
|
||||
let last = 0;
|
||||
for (const match of shown.matchAll(WORD)) {
|
||||
if (!matches(match[0], terms)) {
|
||||
continue;
|
||||
}
|
||||
if (match.index > last) {
|
||||
segments.push({ hit: false, text: shown.slice(last, match.index) });
|
||||
}
|
||||
segments.push({ hit: true, text: match[0] });
|
||||
last = match.index + match[0].length;
|
||||
}
|
||||
if (last < shown.length) {
|
||||
segments.push({ hit: false, text: shown.slice(last) });
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
Reference in new issue
Block a user