UNPKG

@bitrix24/b24ui-nuxt

Version:

Bitrix24 UI-Kit for developing web applications REST API for NUXT & VUE

85 lines (84 loc) 2.5 kB
const htmlEscapes = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }; 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); } }