@lyrasearch/plugin-match-highlight
Version:
Lyrasearch plugin for search match highlighting
60 lines (59 loc) • 2.49 kB
JavaScript
import { search } from '@lyrasearch/lyra';
import { normalizationCache, tokenize } from '@lyrasearch/lyra/internals';
export async function afterInsert(id) {
if (!('positions' in this)) {
Object.assign(this, {
positions: {}
});
}
recursivePositionInsertion(this, this.docs[id], id);
}
const wordRegEx = /[\p{L}0-9_'-]+/gimu;
function recursivePositionInsertion(lyra, doc, id, prefix = '', schema = lyra.schema) {
lyra.positions[id] = Object.create(null);
for (const key of Object.keys(doc)){
const isNested = typeof doc[key] === 'object';
const isSchemaNested = typeof schema[key] === 'object';
const propName = `${prefix}${key}`;
if (isNested && key in schema && isSchemaNested) {
recursivePositionInsertion(lyra, doc[key], id, propName + '.', schema[key]);
}
if (!(typeof doc[key] === 'string' && key in schema && !isSchemaNested)) {
continue;
}
lyra.positions[id][propName] = Object.create(null);
const text = doc[key];
let regExResult;
while((regExResult = wordRegEx.exec(text)) !== null){
const word = regExResult[0].toLowerCase();
const key = `${lyra.defaultLanguage}:${word}`;
let token;
if (normalizationCache.has(key)) {
token = normalizationCache.get(key);
/* c8 ignore next 4 */ } else {
[token] = tokenize(word);
normalizationCache.set(key, token);
}
if (!Array.isArray(lyra.positions[id][propName][token])) {
lyra.positions[id][propName][token] = [];
}
const start = regExResult.index;
const length = regExResult[0].length;
lyra.positions[id][propName][token].push({
start,
length
});
}
}
}
export async function searchWithHighlight(lyra, params, language) {
const result = await search(lyra, params, language);
const queryTokens = tokenize(params.term);
return result.hits.map((hit)=>Object.assign(hit, {
positions: Object.fromEntries(Object.entries(lyra.positions[hit.id]).map(([propName, tokens])=>[
propName,
Object.fromEntries(Object.entries(tokens).filter(([token])=>queryTokens.find((queryToken)=>token.startsWith(queryToken))))
]))
}));
}
//# sourceMappingURL=index.js.map