export default function textSearch(content, queries) {
if (content.length === 0 || queries.length === 0) {
return content;
}
const contentLower = content.toLowerCase();
const normalizedQueries = queries
.map((query) => query.toLowerCase())
.filter((query) => query.length > 0)
.sort((a, b) => b.length - a.length);
if (normalizedQueries.length === 0) {
return content;
}
const rawRanges = [];
for (const query of normalizedQueries) {
const qLen = query.length;
let i = 0;
while (i <= content.length - qLen) {
const end = i + qLen;
if (contentLower.slice(i, end) === query) {
rawRanges.push([i, end]);
i += qLen;
} else {
i++;
}
}
}
if (rawRanges.length === 0) {
return content;
}
rawRanges.sort((a, b) => {
if (a[0] !== b[0]) {
return a[0] - b[0];
}
return a[1] - b[1];
});
const mergedRanges = [rawRanges[0]];
for (let j = 1; j < rawRanges.length; j++) {
const [start, end] = rawRanges[j];
const last = mergedRanges[mergedRanges.length - 1];
if (start <= last[1]) {
last[1] = Math.max(last[1], end);
} else {
mergedRanges.push([start, end]);
}
}
let result = '';
let cursor = 0;
for (const [start, end] of mergedRanges) {
result += content.slice(cursor, start);
result += `<b>${content.slice(start, end)}</b>`;
cursor = end;
}
result += content.slice(cursor);
return result;
}