UNPKG

@lyrasearch/plugin-match-highlight

Version:
60 lines (59 loc) 2.49 kB
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