UNPKG

react-bootstrap-typeahead

Version:
46 lines (43 loc) 1.72 kB
import invariant from 'invariant'; import stripDiacritics from './stripDiacritics'; var CASE_INSENSITIVE = 'i'; var COMBINING_MARKS = /[\u0300-\u036F]/; // Export for testing. export function escapeStringRegexp(str) { !(typeof str === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, '`escapeStringRegexp` expected a string.') : invariant(false) : void 0; // Escape characters with special meaning either inside or outside character // sets. Use a simple backslash escape when it’s always valid, and a \unnnn // escape when the simpler form would be disallowed by Unicode patterns’ // stricter grammar. return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d'); } export default function getMatchBounds(subject, str) { var search = new RegExp(escapeStringRegexp(stripDiacritics(str)), CASE_INSENSITIVE); var matches = search.exec(stripDiacritics(subject)); if (!matches) { return null; } var start = matches.index; var matchLength = matches[0].length; // Account for combining marks, which changes the indices. if (COMBINING_MARKS.test(subject)) { // Starting at the beginning of the subject string, check for the number of // combining marks and increment the start index whenever one is found. for (var ii = 0; ii <= start; ii++) { if (COMBINING_MARKS.test(subject[ii])) { start += 1; } } // Similarly, increment the length of the match string if it contains a // combining mark. for (var _ii = start; _ii <= start + matchLength; _ii++) { if (COMBINING_MARKS.test(subject[_ii])) { matchLength += 1; } } } return { end: start + matchLength, start: start }; }