Блок задач

5. Один класс

Темы
Сложность 6

Задача «Шаблонизатор Mustache»

Реализовать шаблонизатор для подмножества языка шаблонов Mustache.

Шаблон представляет собой текст, содержащий в себе специальные синтаксические конструкции, позволяющие вставлять в него значения переменных, а также включать/исключать некоторые куски в зависимости от переменных. Применяя шаблон к определённому набору значений переменных (контексту), получаем результирующий текст.

Описание языка шаблонов

Вставка переменных

Пример простейшего шаблона:

Hello {{name}}!

Если переменная name равна World, то, применяя шаблон, получаем:

Hello World!

Таким образом, конструкция {{имяпеременной}} позволяет вставлять значения переменных. Следующий шаблон содержит ссылки на две переменных:

Hello {{name}} from {{whom}}.
Условное включение

Условимся считать, что любая несуществующая переменная или переменная, содержащая пустую строку, имеет значение ЛОЖЬ, а переменная с любым другим значением – ИСТИНА.

Тогда шаблон

{{#hi}Привет, {{name}}!{{/hi}}
{{#bye}Пока, {{name}}!{{/bye}}

в случае, когда истинны обе переменных hi и bye, выведет две строки. Для name = Вася:

Привет, Вася!
Пока, Вася!

Если переменная bye ложна, то одна строка будет пустой:

Привет, Вася!

Если обе переменных ложны, то вывод будет пустым.

Mustache также поддерживает инверсию условия:

{{#love}}
I love you!
{{/love}}
{{^love}}
I hate you!
{{/love}}

Здесь условный блок, начинающийся с {{^love}}, сработает, если значение переменной love ложно.

Комментарии
Привет, {{! игнорируемый текст}}Вася!

Превратится в

Привет, Вася!

Задание

Требуется реализовать шаблонизатор, позволяющий генерировать текст на основе шаблона с подстановкой переменных.

Обработка ошибок (неверный синтаксис шаблона) должна производиться с помощью исключений.

Неподдерживаемые возможности Mustache

HTML-эскейпинг. {{{name}}} и {{& name}}.

Массивы

{{#people}}
  <b>{{name}}</b>
{{/people}}

Будет выводить значение name для каждого элемента из массива people.

Вложенные переменные

{{#person?}}
  Hi {{name}}!
{{/person?}}

Включения блоков

<h2>Names</h2>
{{#names}}
  {{> user}}
{{/names}}

Изменение символов-разделителей

* {{default_tags}}
{{=<% %>=}}
* <% erb_style_tags %>
<%={{ }}=%>
* {{ default_tags_again }}