refactor(search): avoid issue with one character keyword

closes https://github.com/CaiJimmy/hugo-theme-stack/issues/184
This commit is contained in:
Jimmy Cai 2021-12-28 23:18:59 +00:00 committed by GitHub
parent dde6a10cab
commit dda0beadcb

View File

@ -8,6 +8,11 @@ interface pageData {
matchCount: number matchCount: number
} }
interface match {
start: number,
end: number
}
/** /**
* Escape HTML tags as HTML entities * Escape HTML tags as HTML entities
* Edited from: * Edited from:
@ -53,6 +58,42 @@ class Search {
this.bindSearchForm(); this.bindSearchForm();
} }
private static processMatches(str: string, matches: match[]): string[] {
matches.sort((a, b) => {
return a.start - b.start;
});
let i = 0,
lastIndex = 0;
let resultArray: string[] = [];
while (i < matches.length) {
const item = matches[i];
if (item.start > lastIndex) {
resultArray.push(str.substring(lastIndex, item.start));
}
let j = i + 1,
end = item.end;
while (j < matches.length && matches[j].start <= end) {
end = matches[j].end;
j++;
}
resultArray.push(`<mark>${str.substring(item.start, end)}</mark>`);
i = j;
lastIndex = end;
}
resultArray.push(str.substring(lastIndex));
return resultArray;
}
private async searchKeywords(keywords: string[]) { private async searchKeywords(keywords: string[]) {
const rawData = await this.getData(); const rawData = await this.getData();
let results: pageData[] = []; let results: pageData[] = [];
@ -63,14 +104,15 @@ class Search {
}); });
for (const item of rawData) { for (const item of rawData) {
let titleMatches: match[] = [],
bodyMatches: match[] = [];
let result = { let result = {
...item, ...item,
preview: '', preview: '',
matchCount: 0 matchCount: 0
} }
let matched = false;
for (const keyword of keywords) { for (const keyword of keywords) {
if (keyword === '') continue; if (keyword === '') continue;
@ -83,35 +125,30 @@ class Search {
regex.lastIndex = 0; /// Reset regex regex.lastIndex = 0; /// Reset regex
if (titleMatch) { if (titleMatch) {
result.title = result.title.replace(regex, Search.marker); titleMatches.push({
start: titleMatch.index,
end: titleMatch.index + titleMatch[0].length
});
} }
if (titleMatch || contentMatch) { if (contentMatch) {
matched = true; bodyMatches.push({
++result.matchCount; start: contentMatch.index,
end: contentMatch.index + contentMatch[0].length
let start = 0, });
end = 100;
if (contentMatch) {
start = contentMatch.index - 20;
end = contentMatch.index + 80
if (start < 0) start = 0;
}
if (result.preview.indexOf(keyword) !== -1) {
result.preview = result.preview.replace(regex, Search.marker);
}
else {
if (start !== 0) result.preview += `[...] `;
result.preview += `${result.content.slice(start, end).replace(regex, Search.marker)} `;
}
} }
} }
if (matched) { if (titleMatches.length > 0) {
result.preview += '[...]'; result.title = Search.processMatches(result.title, titleMatches).join('');
}
console.log(bodyMatches);
if (bodyMatches.length > 0) {
result.preview = Search.processMatches(result.content, bodyMatches).join('');
}
if (titleMatches.length > 0 || bodyMatches.length > 0) {
results.push(result); results.push(result);
} }
} }