@bitrix24/b24ui-nuxt
Version:
Bitrix24 UI-Kit for developing web applications REST API for NUXT & VUE
85 lines (84 loc) • 2.5 kB
JavaScript
const htmlEscapes = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
function escapeHTML(str) {
return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
}
function isAlreadyEscaped(str) {
return /&(?:amp|lt|gt|quot|#39);/.test(str);
}
function sanitize(str) {
if (isAlreadyEscaped(str)) {
return str;
}
return escapeHTML(str);
}
function truncateHTMLFromStart(html, maxLength) {
let truncated = "";
let totalLength = 0;
let insideTag = false;
for (let i = html.length - 1; i >= 0; i--) {
if (html[i] === ">") {
insideTag = true;
} else if (html[i] === "<") {
insideTag = false;
truncated = html[i] + truncated;
continue;
}
if (!insideTag) {
totalLength++;
}
if (totalLength <= maxLength) {
truncated = html[i] + truncated;
} else {
truncated = "..." + truncated;
break;
}
}
return truncated;
}
export function highlight(item, searchTerm, forceKey, omitKeys, useTokenSearch) {
const tokens = useTokenSearch ? searchTerm.match(/[\p{L}\p{M}\p{N}_]+/gu) || [] : [];
const minTokenLength = tokens.length > 0 ? Math.min(...tokens.map((t) => t.length)) : searchTerm.length;
function generateHighlightedText(value, indices = []) {
value = value || "";
let content = "";
let nextUnhighlightedRegionStartingIndex = 0;
indices.forEach((region) => {
if (region.length === 2 && region[0] === region[1]) {
return;
}
const lastIndiceNextIndex = region[1] + 1;
const isMatched = lastIndiceNextIndex - region[0] >= minTokenLength;
content += [
sanitize(value.substring(nextUnhighlightedRegionStartingIndex, region[0])),
isMatched && `<mark>`,
sanitize(value.substring(region[0], lastIndiceNextIndex)),
isMatched && "</mark>"
].filter(Boolean).join("");
nextUnhighlightedRegionStartingIndex = lastIndiceNextIndex;
});
content += sanitize(value.substring(nextUnhighlightedRegionStartingIndex));
const markIndex = content.indexOf("<mark>");
if (markIndex !== -1) {
content = truncateHTMLFromStart(content, content.length - markIndex);
}
return content;
}
if (!item.matches?.length) {
return;
}
for (const match of item.matches) {
if (forceKey && match.key !== forceKey) {
continue;
}
if (omitKeys?.includes(match.key)) {
continue;
}
return generateHighlightedText(match.value, match.indices);
}
}