UNPKG

@risadams/docusaurus-lunr-search

Version:
157 lines (148 loc) 5.95 kB
/* Aloglia DocSearch Adapter for Lunr.js ==================================== Written by: Praveen N github: praveenn77 */ import lunr from "@generated/lunr.client"; lunr.tokenizer.separator = /[\s\-/]+/; class LunrSearchAdapter { constructor(searchDocs, searchIndex, baseUrl = '/', maxHits) { this.searchDocs = searchDocs; this.lunrIndex = lunr.Index.load(searchIndex); this.baseUrl = baseUrl; this.maxHits = maxHits; } getLunrResult(input) { return this.lunrIndex.query(function (query) { const tokens = lunr.tokenizer(input); query.term(tokens, { boost: 10 }); query.term(tokens, { wildcard: lunr.Query.wildcard.TRAILING }); }); } getHit(doc, formattedTitle, formattedContent) { return { hierarchy: { lvl0: doc.pageTitle || doc.title, lvl1: doc.type === 0 ? null : doc.title }, url: doc.url, version: doc.version, _snippetResult: formattedContent ? { content: { value: formattedContent, matchLevel: "full" } } : null, _highlightResult: { hierarchy: { lvl0: { value: doc.type === 0 ? formattedTitle || doc.title : doc.pageTitle, }, lvl1: doc.type === 0 ? null : { value: formattedTitle || doc.title } } } }; } getTitleHit(doc, position, length) { const start = position[0]; const end = position[0] + length; let formattedTitle = doc.title.substring(0, start) + '<span class="algolia-docsearch-suggestion--highlight">' + doc.title.substring(start, end) + '</span>' + doc.title.substring(end, doc.title.length); return this.getHit(doc, formattedTitle) } getKeywordHit(doc, position, length) { const start = position[0]; const end = position[0] + length; let formattedTitle = doc.title + '<br /><i>Keywords: ' + doc.keywords.substring(0, start) + '<span class="algolia-docsearch-suggestion--highlight">' + doc.keywords.substring(start, end) + '</span>' + doc.keywords.substring(end, doc.keywords.length) + '</i>' return this.getHit(doc, formattedTitle) } getContentHit(doc, position) { const start = position[0]; const end = position[0] + position[1]; let previewStart = start; let previewEnd = end; let ellipsesBefore = true; let ellipsesAfter = true; for (let k = 0; k < 3; k++) { const nextSpace = doc.content.lastIndexOf(' ', previewStart - 2); const nextDot = doc.content.lastIndexOf('.', previewStart - 2); if ((nextDot > 0) && (nextDot > nextSpace)) { previewStart = nextDot + 1; ellipsesBefore = false; break; } if (nextSpace < 0) { previewStart = 0; ellipsesBefore = false; break; } previewStart = nextSpace + 1; } for (let k = 0; k < 10; k++) { const nextSpace = doc.content.indexOf(' ', previewEnd + 1); const nextDot = doc.content.indexOf('.', previewEnd + 1); if ((nextDot > 0) && (nextDot < nextSpace)) { previewEnd = nextDot; ellipsesAfter = false; break; } if (nextSpace < 0) { previewEnd = doc.content.length; ellipsesAfter = false; break; } previewEnd = nextSpace; } let preview = doc.content.substring(previewStart, start); if (ellipsesBefore) { preview = '... ' + preview; } preview += '<span class="algolia-docsearch-suggestion--highlight">' + doc.content.substring(start, end) + '</span>'; preview += doc.content.substring(end, previewEnd); if (ellipsesAfter) { preview += ' ...'; } return this.getHit(doc, null, preview); } search(input) { return new Promise((resolve, rej) => { const results = this.getLunrResult(input); const hits = []; results.length > this.maxHits && (results.length = this.maxHits); this.titleHitsRes = [] this.contentHitsRes = [] results.forEach(result => { const doc = this.searchDocs[result.ref]; const { metadata } = result.matchData; for (let i in metadata) { if (metadata[i].title) { if (!this.titleHitsRes.includes(result.ref)) { const position = metadata[i].title.position[0] hits.push(this.getTitleHit(doc, position, input.length)); this.titleHitsRes.push(result.ref); } } else if (metadata[i].content) { const position = metadata[i].content.position[0] hits.push(this.getContentHit(doc, position)) } else if (metadata[i].keywords) { const position = metadata[i].keywords.position[0] hits.push(this.getKeywordHit(doc, position, input.length)); this.titleHitsRes.push(result.ref); } } }); hits.length > this.maxHits && (hits.length = this.maxHits); resolve(hits); }); } } export default LunrSearchAdapter;