English | Pусский
Рендеринг дерева шаблонов, использующих API
- Готовность к релизу 1.0: 95%
- Задачи до релиза:
- актуализировать документацию
- решить вопрос хранения имени метода
content
В проекте apisite шаблоны оперируют только данными HTTP-запроса и результатами вызовов методов API. В следствие того, что для страниц не требуется индивидуальная подготовка данных, необходим универсальный роутер между адресами страниц и их шаблонами. Библиотека apitpl посвящена решению этой задачи.
Примечания.
В данном документе
- термином "шаблон" обозначен файл в синтаксисе html/template
Библиотека работает с деревом каталогов, содержащих шаблоны трех типов:
- страницы (pages) - шаблоны, формирующие контент страницы (по пути к файлу формируется URL страницы)
- макеты (layouts) - шаблоны, состоящие из общих для всех страниц элементов (шапки, подвала и т.п.), в которые помещается контент (кроме этой вставки, шаблон может быть обычной HTML-страницей)
- включения (includes) - блоки, которые могут использоваться в страницах и макетах
См. также: Пример дерева шаблонов
- разделение шаблонов по типам на основе префикса или суффикса имени файла
- поддержка работы с шаблонами из встроенной файловой системы
- рендеринг страниц и макетов с использованием инклюдов, с однократным парсингом или парсингом по запросу (флаг
ParseAlways(true)) - роутинг для net/http и роутинг для gin-gonic/gin
Библиотека разделена на следующие части:
- apitpl - код формирования страницы из шаблона (выполняется в два этапа - формирование контента и сборка страницы по макеты с включением в него контента)
- lookupfs - получение из файловой системы (обычной или встроенной) списков шаблонов
- samplemeta - пример метаданных, которые могут передаваться из шаблона контента в шаблон макета
- ginapitpl - интеграция функционала apitpl в gin (код оформлен модулем, чтобы его зависимости не попали в остальные части), для тестов и примеров этот модуль имеет свои копии samplemeta
Формирование страницы из шаблона выполняется в два шага:
- формирование контента
- формирование страницы по макету с использованием контента
Такое разделение преследует следующие цели:
- процесс формирования контента может быть прерван вызовом исключения и при работе с макетом этот контент не будет использован (например, будет выведено описание этого исключения)
- процесс формирования контента может быть прерван с возвратом переадресации, в этом случае макет не будет использован и ответом сервера станет переадресация
- при формировании контента можно в любой момент изменить макет, который будет использован на шаге 2
При этом на сам шаблон страницы не накладывается никаких ограничений, это может быть как golang template так и блок HTML разметки. Потенциально, это позволит включать шаблоны страниц в другие страницы (если это понадобится, но такое еще не реализовано).
Получение списка файлов для каждого из трех типов шаблонов имеет следующие особенности:
- разделение на типы может производиться по префиксу (например,
ROOT/(pages|layouts|includes)/...) или по суффиксу (например,ROOT/PATH/name(|.layout|.include).tmpl) - доступ к файлам производится через интерфейс lookupfs.FileSystem и поддерживается работа как с обычной так и со встроенной файловой системой
По имени файла шаблона формируется имя, по которому на него можно ссылаться директивой {{template}} и использовать в роутинге HTTP-сервера. Для этого с именем файла производятся действия:
- перевод абсолютного пути к файлу в относительный путь от корня дерева шаблонов
- удаление расширения файла
- конвертация разделителей каталогов текущей ОС в
/ - замена всех подстрок
/__на/:(':' используется в gin для обозначения параметров запроса) - удаление начального
/(если имя не состоит только из него)
Для случая, когда шаблон страницы не должен включаться в роутинг, используется параметр конфигурации HidePrefix (default:"."), такие шаблоны предназначены для прямых вызовов из кода (например, pages/.404.tmpl).
См. также:
- Примеры с разделением по префиксу и суффиксу
- Пример работы с обычной ФС
- Пример работы с встроенной ФС
При формировании контента может быть создан не только он сам (т.е., фактически, тестовая строка), но и некоторые метаданные (например, заголовок страницы, имя макета, список JS-файлов для включения и т.п). Для передачи этой информации из страницы в макет используется объект структуры, соответствующей интерфейсу apitpl.MetaData. Этот объект создается при каждом запросе страницы и интерфейс содержит только три метода:
SetError(error)- вызывается внутри apitpl при возникновении необработаннной ошибки выполнения шаблона страницыError() error- позволяет получить эту ошибкуLayout()- имя макета, который будет вызван на шаге 2
Библиотека содержит базовый пример такой структуры - samplemeta.
В ginapitpl интерфейс ginapitpl.MetaData дополнен функциями для формирования заголовка HTTP-ответа:
Status() int- статусContentType() string- тип контентаLocation() string- URL для переадресации
Пример реализации структуры - ginapitpl/samplemeta.
- https://stackoverflow.com/questions/42747183/how-to-render-templates-to-multiple-layouts-in-go
- https://medium.com/@leeprovoost/dealing-with-go-template-errors-at-runtime-1b429e8b854a
The MIT License (MIT), see LICENSE.
Copyright (c) 2019 Aleksei Kovrizhkin [email protected]