UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

84 lines (83 loc) 2.81 kB
"use client"; //#region packages/@mantine/core/src/components/Highlight/highlighter/highlighter.ts function escapeRegex(value) { return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&"); } function foldAccents(text) { return text.normalize("NFD").replace(/\p{M}/gu, ""); } function foldAccentsWithMap(text) { let folded = ""; const map = []; let i = 0; while (i < text.length) { const cp = text.codePointAt(i); const cpStr = String.fromCodePoint(cp); const foldedCp = foldAccents(cpStr); for (let j = 0; j < foldedCp.length; j += 1) map.push(i); folded += foldedCp; i += cpStr.length; } map.push(text.length); return { folded, map }; } function getAccentInsensitiveChunks(value, re) { const { folded, map } = foldAccentsWithMap(value); const chunks = []; let lastOrigEnd = 0; let match; while ((match = re.exec(folded)) !== null) { const foldedStart = match.index; const foldedEnd = foldedStart + match[0].length; const origStart = map[foldedStart]; const origEnd = map[foldedEnd]; if (origStart > lastOrigEnd) chunks.push({ chunk: value.slice(lastOrigEnd, origStart), highlighted: false }); chunks.push({ chunk: value.slice(origStart, origEnd), highlighted: true }); lastOrigEnd = origEnd; if (match[0].length === 0) re.lastIndex += 1; } if (lastOrigEnd < value.length) chunks.push({ chunk: value.slice(lastOrigEnd), highlighted: false }); return chunks.filter(({ chunk }) => chunk); } function highlighter(value, _highlight, options = {}) { if (_highlight == null) return [{ chunk: value, highlighted: false }]; const { wholeWord = false, caseInsensitive = true, accentInsensitive = true } = options; const prepareTerm = (term) => accentInsensitive ? foldAccents(escapeRegex(term)) : escapeRegex(term); const highlight = Array.isArray(_highlight) ? _highlight.map(prepareTerm) : prepareTerm(_highlight); if (!(Array.isArray(highlight) ? highlight.filter((part) => part.trim().length > 0).length > 0 : highlight.trim() !== "")) return [{ chunk: value, highlighted: false }]; const matcher = typeof highlight === "string" ? highlight.trim() : highlight.filter((part) => part.trim().length !== 0).map((part) => part.trim()).sort((a, b) => b.length - a.length).join("|"); const pattern = wholeWord ? `(?<![\\p{L}\\p{N}_])(${matcher})(?![\\p{L}\\p{N}_])` : `(${matcher})`; const flags = [ "g", caseInsensitive ? "i" : "", wholeWord ? "u" : "" ].join(""); const re = new RegExp(pattern, flags); if (accentInsensitive) return getAccentInsensitiveChunks(value, re); return value.split(re).map((part, index) => ({ chunk: part, highlighted: index % 2 === 1 })).filter(({ chunk }) => chunk); } //#endregion exports.foldAccents = foldAccents; exports.highlighter = highlighter; //# sourceMappingURL=highlighter.cjs.map