#pagebreak(weak: true) #set text(size: 13pt) #align(center, text([Документация к New York Transit Line (набросок для своих)], size: 30pt)) #let Heading(c, d) = { heading(c, depth: d, numbering: "1."); } #let bold(txt) = text(txt, weight: "bold") #Heading([Интродакшн], 1) New York Transit Line - это система шаблонов. Она рассчитана под html, но в теории может использоваться для чего угодно. Чтобы её использовать нужно завести папку с нашим кодом nytl (здесь и далее я называю кодом html код и html код вперемешку с nytl инструкциями). Допустим папка называется `nytl_dir`. Нужно создать объект `nytl::Templater`, настроить, обновить его, и можно уже "рендерить" наши странички (выбрать какой-то один элемент, объявленный в `nytl_dir` и передать ему какие-то аргументы) ```cpp nytl::Templater t{{{nytl_dir}}}; t.update(); json::JSON var1; json::JSON var2; std::string result = t.render(el_name, {&var1, &var2}); ``` Элемент - это функция, возвращающая код. Элемент может принимать json::JSON аргументы (весь nytl базируется на libjsonincpp) аргументы и другие элементы как аргументы. У него есть чётко заданная сигнатура. Элементы идентифицируются по имени: Имя состоит из нескольких "лексических имён" (Непустых последовательностей букв, цифр, дефисов, подчеркиваний, не начинающихся с цифры), разделённых точками. "лексическое имя" не может быть одним подчёркиванием. Все "части" имени символа кроме подследнего символизируют путь до файла с символом (от папки `nytl_dir`). Последняя часть идентифицирует элемент ВНУТРИ этого файла. NYTL индексирует файлы следующим образом: `nytl::Templater` получает объект `nytl::TemplaterSettings` (назовём его `settings`) и он содержит два важных поля: `settings.det.postfix_rule_for_element_cont` ( по дефолту `".nytl.html"` ) и `settings.det.postfix_rule_for_static_files` (по дефолту `.html`). Сначала темплейтер смотрит, оканчивается ли имя файла на `settings.det.postfix_rule_for_element_cont`, если да, то от имени отбрасывается постфикс, составляется имя самого файла (вместо / ставятся точки) и далее nytl парсит файл согласно обычному nytl синтаксису (где файл - это набор элементов). Если первый постфикс не подходит, проверяется второй (`settings.det.postfix_rule_for_static_files`), если подходит то файл не парсится, а всё его содержимое прямо запихивается в один элемент с именем как у файла. Если оба правила не применимы, ничего не происходит. #Heading([Синтаксис], 1) #Heading([ELDEF], 2) Файл nytl (Который скорее всего будет иметь расширение .nytl.html) состоит из объявления элементов, в которые входит: - Название элемента относительно файла (одно лексическое имя). Если в качестве относительного имени файла выбрано main, имя элемента становится равным имени фала. - Сигнатура элемента. Нужна чисто чтобы меньше путаться. - Содержиое элемента, где КОД намешан с NYTL ИНСТРУКЦИЯМИ. Nytl инструкции всегда находятся в так называемых "волшебных блоках". Они начинаются со строки `settings.magic_block_start` и заканчиваются на `settings.magic_block_end`. По дефолту волшебный блок таков: `{% ... %}`. Объявление элемента выглядит так: ``` {% ELDEF element-name type-of-arg-1 arg-1-name type-of-arg-2 arg-2-name ... %} ... Содержимое элемента {% ENDELDEF %} ``` Здесь я обозначил `ELDEF` и `ENDELDEF` большими буквами, поскольку это ключевое слово (имя оператора). Для них регистр не важен, но мне кажется так писать их красивее. Аргументов может быть сколько угодно в сигнатуре. Имя аргумента "это лексическое имя". Если оно равно `"_"`, то аргументу как бы не присваевается переменная. _Это как в Go_. Тип аргумента это либо `JSON`, либо `EL()` (регистр не важен). В скобках для типа `EL` надо указать сигнатуру желанного элемента. Она состоит из списка типо аргументов (как в объявлении элемента, но без имён переменных). Пример: `EL(EL() EL(JSON EL(EL) EL(EL() JSON EL()) EL()) JSON EL(EL(EL(EL(JSON)) JSON EL(EL()))))`. Это корректный тип. Внутри элемента мы можем прямо писать _[html]_код и можно добавить специальные инструкции (конечно же, в волшебных блоках), что бы добавить сложное поведение. #Heading([NYTL выражения (внутри волшебных блоков)], 2) Сперва нужно познакомиться с "nytl expressions". Начинаются они с имени переменной. Это может быть локальная переменная, а может быть имя пакета с самого высокого уровня (так я называю фалы и саб-директории в корневой директории nytl). Оно тоже должно быть "лексическим именем". Оно не может быть `"_"`. Объявление локальной переменной (хотя нет в них ничего переменного, в nytl все переменные константы) может "закрыть собой" имя пакета верхнего уровня. Они приоритетнее. Выражение может состоять из одного такого имени. Но к выражению можно приписать "доступ к члену": $<"expr"> = <"expr">.<"us integer">$ (это доступ по индексу), $<"expr"> = <"expr">.<"lexical name">$ (это доступ по ключу), $<"expr"> = <"expr">[ <"expr"> ]$ (это доступ по значению (которое является результатом выполениея выражения)) Доступ по ключу может проиходить для элемента (для взятия пакета элементов / элемента из пакета элементов). Это работает именно так, как ты подумал. Так же доступ по ключу может обращаться к члену JSON-словаря. Доступ по индексу обращается к члену JSON-массива. Доступ по выражению может делать всё это, но нужно чтобы тип результата выполнения выражения-ключа подходил для задумываемой операции. Если это ещё не стало понятно: переменные это либо JSON, либо элемент (либо пакет - часть пути для элемента, отражающий папочную структуру `nytl_dir`). Пример nytl выражения: `boba.aboba.biba[bibina.0.222[din.don].zavletayu.v_tvoy_dom ][ odichal.vizovi.sebe-vracha]` #Heading([Вкрапления nytl инструкций], 2) #Heading([PUT], 3) Синтаксис оператора PUT: `{% PUT ... %}` (ключевое слово PUT регстронечувствительно). Оператор `PUT` вызвает какой-то элемент. Какой - определяется первым переданным выражением. Следуюущие выражения указывают передаваемые аргументы. Есть ряд "встроенных элементов", определяемых самим nytl: - `jsinsert`. Тип: `EL(JSON)`. Напрямую вставляет сериализованный JS-объект в код. Полезно если нужно через тег ```html