search target fix

This commit is contained in:
gosangam
2026-06-02 00:42:26 +05:30
parent 8a8ce24479
commit 0352cb2003
+34 -16
View File
@@ -206,28 +206,46 @@ export function extractMatchedTextFromSnippet(
const firstStart = first.index ?? 0;
const lastEnd = (last.index ?? 0) + last[0].length;
const span = snippetHtml.slice(firstStart, lastEnd);
const plain = normalizeQuotes(
decodeSnippetEntities(span.replace(/<[^>]*>/g, ""))
// Marked-span text — just the tokens Typesense highlighted.
const markedSpan = snippetHtml.slice(firstStart, lastEnd);
const markedPlain = normalizeQuotes(
decodeSnippetEntities(markedSpan.replace(/<[^>]*>/g, ""))
.replace(/\s+/g, " ")
.trim(),
);
if (!plain) return null;
// Full-snippet text — includes Typesense's surrounding context. Typesense
// snippets are direct slices of the source field, so the surrounding text
// exists verbatim in the destination page. Using it as the prefix makes
// single-token matches (e.g. `<mark>Therefore</mark> material senses...`)
// land on the *correct* occurrence on the destination page rather than the
// first instance of that token alphabetically.
const fullPlain = normalizeQuotes(
decodeSnippetEntities(snippetHtml.replace(/<[^>]*>/g, ""))
.replace(/\s+/g, " ")
// strip leading/trailing ellipsis Typesense sometimes adds
.replace(/^(?:…|\.{3,})\s*/, "")
.replace(/\s*(?:…|\.{3,})$/, "")
.trim(),
);
// If the span between first and last mark is unreasonably long
// (e.g. snippet has marks at far ends of a long passage), fall back to
// just the first marked term — that's still a real match in the doc.
if (plain.length > 200) {
const firstPlain = normalizeQuotes(
decodeSnippetEntities(first[1].replace(/<[^>]*>/g, ""))
.replace(/\s+/g, " ")
.trim(),
);
return firstPlain || null;
// Pick the best candidate:
// - if the marked span alone is already ≥6 words, it's a multi-token phrase
// and is specific enough — use it.
// - otherwise prefer the full snippet (more context = more uniquely placed),
// capped at 200 chars to keep URLs sane.
// - fall back to marked span if the full snippet is empty / unusable.
const markedWordCount = markedPlain
? markedPlain.split(/\s+/).filter(Boolean).length
: 0;
if (markedWordCount >= 6) {
return markedPlain || null;
}
return plain;
if (fullPlain && fullPlain.length <= 200) {
return fullPlain;
}
return markedPlain || null;
}
// Decode the HTML entities Typesense commonly emits in match snippets.