Escape-последовательности

Назначение escape-механизма в масках ввода

В библиотеке Inputmask символы маски интерпретируются как управляющие токены: 9 обозначает цифру, a — букву, * — буквенно-цифровой символ. Однако при построении сложных масок часто возникает необходимость использовать в шаблоне литеральные символы, которые совпадают с управляющими. Для этого применяется механизм escape-последовательностей, позволяющий явно указать, что символ должен восприниматься как обычный текст, а не как правило маскирования.

Escape-последовательности обеспечивают однозначность интерпретации шаблона и позволяют комбинировать структурные и текстовые элементы в одной маске без конфликтов.


Базовый символ экранирования

Основным символом экранирования в Inputmask выступает обратный слеш:

\ 

Он изменяет поведение следующего за ним символа, превращая его в литерал.

Пример:

Inputmask("9\9\9").mask(input);

В этом случае:

  • первый 9 — ввод цифры
  • \9 — литеральный символ «9»
  • итоговая маска: цифра + символ 9 + символ 9

Литерализация служебных символов

Некоторые символы в Inputmask зарезервированы и требуют обязательного экранирования при использовании в качестве текста:

  • 9, a, * — токены ввода
  • [ ] — группы и альтернативы
  • { } — квантификаторы
  • ( ) — группировка
  • | — альтернативные ветки
  • ? — опциональные элементы

Если необходимо вывести их как часть строки, применяется экранирование:

Inputmask("99\\a99").mask(input);

Здесь \a воспринимается как символ a, а не как правило «буква».


Экранирование обратного слеша

Сам обратный слеш также является управляющим символом и требует двойного экранирования при использовании в строковых литералах Jav * aScript:

Inputmask("9\\\\9").mask(input);

Разбор:

  • \\\\ в JavaScript → \\ в строке
  • \\ в Inputmask → литеральный \
  • итоговая маска: цифра + обратный слеш + цифра

Это один из наиболее частых источников ошибок при построении сложных масок.


Символьные блоки и текстовые сегменты

Inputmask поддерживает смешивание структурных токенов и фиксированных строк. Любой текстовый сегмент может быть экранирован по символам:

Inputmask("Tel: +7 (999) 999-99-99").mask(input);

В данном случае литералы не требуют экранирования, так как не конфликтуют с токенами.

Однако при наличии потенциально конфликтных символов экранирование становится обязательным:

Inputmask("\\+7 (999) 999-99-99").mask(input);

Здесь \+ фиксирует символ плюса как литерал.


Контекстное поведение escape-последовательностей

Escape-символ работает только в пределах строки маски. Он не влияет на:

  • динамическую генерацию маски через функцию
  • предварительную обработку строки до передачи в Inputmask
  • постобработку значения после ввода

Пример:

const mask = "9\\a9";
Inputmask(mask).mask(input);

Разбор происходит на этапе парсинга маски, после чего создаётся внутреннее представление шаблона.


Экранирование в динамических масках

При использовании функции маскирования:

Inputmask({
  mask: function () {
    return "99\\9-AAA";
  }
}).mask(input);

escape-последовательности интерпретируются так же, как и в статической строке. Это важно при генерации шаблонов на основе условий.


Конфликты с JavaScript-строками

Наиболее критичный аспект escape-последовательностей связан с двойной интерпретацией:

  1. JavaScript обрабатывает строку
  2. Inputmask обрабатывает результат

Пример:

"\\9"

Фактическое значение:

  • Jav * aScript: \9
  • Inputmask: литеральный 9

При необходимости передать обратный слеш в маску требуется учет обоих уровней:

"\\\\"

Экранирование в регулярных выражениях Inputmask

Некоторые конфигурации Inputmask используют регулярные выражения (например, в валидаторах или alias-расширениях). В этом случае escape-последовательности пересекаются с правилами RegExp.

Пример конфликта:

/\\d/

Здесь:

  • \\d в строке → \d в RegExp
  • \d означает цифру

Если этот RegExp используется внутри маски, важно учитывать, что Inputmask не обрабатывает его как текст, а передаёт в движок регулярных выражений.


Экранирование в alias-конфигурациях

Встроенные alias (например, datetime, currency, email) используют собственные правила интерпретации. При создании кастомных alias escape-последовательности применяются в тех же правилах, что и в базовой маске:

Inputmask.extendAliases({
  custom: {
    mask: "AA\\-999"
  }
});

Здесь:

  • AA — две буквы
  • \- — дефис как литерал
  • 999 — три цифры

Поведение в группах и альтернативных блоках

При использовании группировок:

Inputmask("(99\\) 999-9999").mask(input);

символ ) экранируется, чтобы не завершать группу. Без escape-последовательности шаблон интерпретировался бы некорректно.

Аналогично в альтернативных выражениях:

Inputmask("999|\\999").mask(input);

вторая ветка начинается с литерального символа 9, а не с токена.


Экранирование в числовых и валютных масках

В финансовых масках часто присутствуют символы валют и разделителей:

Inputmask("\\$ 999,999.99").mask(input);

или

Inputmask("\\€ 99.999,99").mask(input);

Здесь escape требуется для:

  • $ — в некоторых конфигурациях может интерпретироваться как спецсимвол
  • — безопасное экранирование для единообразия шаблона

Вложенные escape-последовательности в сложных шаблонах

В сложных масках с повторениями и условными блоками часто возникает необходимость комбинировать несколько уровней экранирования:

Inputmask("9\\[99\\]\\-AAA").mask(input);

Разбор:

  • \[ и \] — литеральные квадратные скобки
  • \- — литеральный дефис
  • AAA — три буквенных символа

Такие конструкции используются при форматировании идентификаторов и кодов.


Типовые ошибки при использовании escape-последовательностей

На практике наиболее частые ошибки связаны не с самой библиотекой, а с неправильным пониманием уровней экранирования:

  1. Недоэкранирование обратного слеша

    "9\9"

    приводит к неожиданной интерпретации \9

  2. Избыточное экранирование

    "\\\\9"

    создаёт лишний литеральный слеш

  3. Конфликт с RegExp использование \d без учета строкового уровня

  4. Неправильное экранирование групп потеря закрывающей скобки из-за отсутствия \)


Внутренний парсинг escape-последовательностей

При обработке маски Inputmask выполняет предварительный проход строки, в ходе которого:

  • определяется наличие \
  • следующий символ помечается как литерал
  • токенизация маски строится на основе уже «развернутой» строки
  • escape-символ удаляется из финального представления

Это означает, что escape-последовательности не существуют в рантайме как отдельные сущности — они участвуют только в этапе компиляции маски.