| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- import {InvalidArgumentError} from '../errors/index.js';
- /**
- * Преобразует SQL LIKE-шаблон в объект RegExp.
- *
- * Экранирует специальные символы регулярных выражений,
- * чтобы они обрабатывались как обычные символы, и преобразует
- * SQL wildcards (% и _) в их эквиваленты в регулярных выражениях.
- *
- * @param {string} pattern
- * @param {boolean} isCaseInsensitive
- * @returns {RegExp}
- */
- export function likeToRegexp(pattern, isCaseInsensitive = false) {
- if (typeof pattern !== 'string') {
- throw new InvalidArgumentError(
- 'The first argument of `likeToRegexp` ' +
- 'should be a String, but %v was given.',
- pattern,
- );
- }
- // символы, которые имеют специальное значение
- // в RegExp и должны быть экранированы
- const regexSpecials = '-[]{}()*+?.\\^$|';
- let regexString = '';
- let isEscaping = false;
- // экранирование
- for (const char of pattern) {
- if (isEscaping) {
- // предыдущий символ был '\', значит текущий символ - литерал
- regexString += regexSpecials.includes(char) ? `\\${char}` : char;
- isEscaping = false;
- } else if (char === '\\') {
- // символ экранирования, следующий символ будет литералом
- isEscaping = true;
- } else if (char === '%') {
- // SQL wildcard: любое количество любых символов
- regexString += '.*';
- } else if (char === '_') {
- // SQL wildcard: ровно один любой символ
- regexString += '.';
- } else if (regexSpecials.includes(char)) {
- // экранирование других специальных символов RegExp
- regexString += `\\${char}`;
- } else {
- // обычный символ
- regexString += char;
- }
- }
- // если строка заканчивается на экранирующий символ,
- // считаем его литералом.
- if (isEscaping) {
- regexString += '\\\\';
- }
- const flags = isCaseInsensitive ? 'i' : '';
- return new RegExp(`^${regexString}$`, flags);
- }
|