Программы
Авиасимулятор
Видеокодек
Шаблонизатор
Архиватор
Компилятор
Видеомонтажка



Если обнаружите в тексте страницы ошибку, выделите ее мышкой и нажмите Ctrl-Enter.

Perl Templating System

Кратко.
Шаблонизатор Perl Templating System - движок сайта, написанный на Perl, позволяющий создавать сайты при помощи шаблонов, способных содержать вставки Perl-кода в HTML. С помощью данного шаблонизатора можно легко выделить общие части страниц в шаблон, отделить конечные данные от представления и от кода, а в статичный HTML добавить динамику а-ля PHP, но только на Perl.
Весь этот сайт построен именно на данном движке.

Причины.
Писалось все чисто для себя, поэтому движок ни на что не претендует и не пытается конкурировать с другими подобными системами. Просто был с одной стороны некоторый интерес к Web-программированию (отдельное спасибо за идеи dklab.ru), а с другой стороны хотелось иметь инструмент, позволяющий держать общие части страниц сайта в одном месте, чтобы проще было над сайтом работать. Также хотелось некоторой динамики, но не через CGI, и тут идея embedded Perl оказалась самой подходящей. Perl был выбран по той простой причине, что с ним я знаком, и он мне нравится, а с PHP я не знаком, и знакомиться нет никакого желания.

Следствия.
Получился очень простой, но довольно функциональный и эффективный движок. Состоит всего из одного файла размером в 2,5 килобайта. Не использует никаких модулей, разве что Time::HiRes для замера своей скорости, но это фича необязательная. Помимо подстановки данных в шаблоны занимается выполнением встроенного в HTML Perl-кода, а также делает всю работу по кэшированию.

Идеология.
Основная эксплуатируемая идея - древовидность сайта. С одной стороны, данные распределены по дереву каталогов сайта: главная страница в корне, каталоги-разделы, подкаталоги-подразделы, конечные файлы - конечные данные. С другой стороны, выдаваемая пользователю HTML-страница тоже представляет из себя дерево. Причем, чаще всего, соседние листья-страницы в дереве каталогов для пользователя выглядят очень похоже, имея почти одинаковое оформление (включая служебные данные, заголовки, шапку, меню..), и различаясь лишь самими конечными данными. Соответсвенно, логично вынести их общую часть в один файл, а в него уже в нужном месте включать только конечные данные. Сделать так можно не только в пределах одного каталога, но и в пределах всего дерева, объединяя узлы дерева одной глубины. В результате получим самый общий каркас всего сайта в корне, содержащий самые общие элементы (теги meta, head, body..) и указания, куда вставить данные разделов. Для каждого раздела тоже будет такой каркас, описывающий уже не всю страницу, а только ту часть, которая будет вставлена в каркас (шаблон) более высокого уровня. Шаблон раздела содержит общие для раздела части и указания, куда вставить данные с более низких уровней и т.д. В конце дерева лежат уже только конечные данные без оформления.

Основное преимущество такого представления - каждый элемент сайта описывается только в одном месте. Чтобы что-то поменять, достаточно изменить это в одном месте, и изменение отразится на всем поддереве, т.е. на всех страницах, содержащих данный элемент.

Второе преимущество в том, что в отличие от SSI, где обычно страница-лист включает в себя данные из верхних узлов дерева, и приходится шапку и подвал хранить в разных файлах, здесь наоборот, верхние узлы включают в себя данные из нижних. В результате все открывающие и закрывающие тэги всегда находятся в одном файле, что существенно упрощает верстку.

Причем понятно, что шаблон (каркас) должен уметь включать не один блок (данные более низкого уровня, или большей глубины), а несколько. Это нужно по меньшей мере для того, чтобы изменять title при переходе на разные страницы. Поэтому, каждый файл с данными - как листы (конечные данные), так и промежуточные узлы (шаблоны) - может содержать не один блок, включаемый шаблонами более высоких уровней, а несколько блоков.

Спрашивается, а как быть, если какая-то страница, или даже некоторое дерево страниц, должна выглядеть совсем иначе, нежели это предполагает главный каркас страницы? Ответ простой: можно сделать независимое поддерево. Т.к. эти страницы все равно находятся на сайте, то они образуют некоторое поддерево в дереве каталогов. Достаточно объявить узел, являющийся корневым для данного поддерева, корнем. Тогда именно он будет считаться каркасом всей страницы, и будут обрабатываться данные только в пределах этого поддерева. В предельном случае можно иметь одну-единственную страницу, которая сама себе является корнем.

Как это выглядит.
Все общие части страниц для каждого каталога объединяются в шаблон - файл с именем default.htpl. В корне сайта лежит главный шаблон - каркас всего сайта. Он является самым обычным HTML-файлом, у которого в первой строке стоит специальный комментарий <!--params(root)-->. Это признак корня. Точно такой же признак можно поставить на любом шаблоне, если нужно сделать независимое поддерево. После него идет обычный HTML, в котором в тех местах, где должны быть какие-то блоки с данными, стоят имена этих блоков, заключенные в знаки "%" (например, %blосkname%). В файлах-шаблонах узлов дерева и в конечных файлах содержатся именованные блоки. Соответвенно, при обработке шаблона, вместо %blосkname% будет подставлено содержимое блока с именем blосkname. Определяется такой блок очень просто:

<!--tеxtblосk(blосkname)-->
Тело блока - HTML-код, который тоже может содержать произвольное число указаний вставить другие блоки (типа %blосkname2% или %anоthеrthing%).
<!--endblосk-->
Кроме того, любой блок может содержать код на Perl. Делается это способом, похожим на РНР - код помещается в конструкцию <? ?>:
Here goes our environment:
<pre>
<? foreach $key (keys %ENV) { ?>
$key = $ENV{$key}<br>
<? } ?>
</pre>
Но, в отличие от РНР, чтобы вставить значение переменной, можно просто написать ее имя прямо в HTML-тексте, никаких конструкций <?= ?> не надо.
Для того, чтобы уметь выделять текущий выбранный раздел в меню, и вообще реагировать на выбор пользователя, при выполнении кода для каждого шаблона определена переменная $Chosen, содержащая имя выбранного каталога или файла.
Из соображений эффективности блоки сделаны двух типов - содержащие Perl-код и не содержащие. Это сделано для того, чтобы не тратить время на трансляцию и выполнение тех кусков, которые код не содержат. Блок, не содержащий код, описывается конструкцией <!--tеxtblосk(blосkname)-->, а блок, содержащий Perl-код, описывается конструкцией <!--pеrlblосk(blосkname)-->. Заканчиваются они одинаково.

Чтобы превратить исходную HTML-страничку сайта в шаблон или конечный документ, достаточно расставить в ней эти комментарии - границы блоков. В результате она остается полноценной HTML-страницей, ее можно редактировать любыми способами. После всех редакций можно убрать из нее все, что находится за пределами блоков, - теперь это уже лишняя информация. Тэг title считается блоком с именем title. Т.е. чтобы описать блок title не нужно городить огород из конструкций начала и конца блока, нужно просто оставить как был исходный тэг.

В первой строке файла могут быть указаны его параметры. Они описываются конструкцией <!--params()-->, где в скобках могут быть указаны следующие ключи:
nocache - данный узел и все поддерево под ним не кэшируется
root - данный шаблон является корневым
perl - используется там, где указан root. Означает, что корневой шаблон содержит код на Perl
Примеры:
<!--params(root perl)-->
<!--params(perl, root)-->
<!--params(nocache)-->
Строка с параметрами "съедается" движком и пользователю не выводится. Поэтому она не мешает иметь в первой строке страницы тэг DOCTYPE.

Как это работает.
При запросе какого-то конечного HTML-документа (адреса всех страниц остаются как были) управление передается шаблонизатору. Он читает запрашиваемый файл и разбирает его на блоки. Блоки, содержащие код, выполняются, превращаясь в текстовые (уже с результатами работы). Затем происходит подстановка блоков в конструкции %% (т.е. можно вставлять блоки, описанные даже в этом же файле). Потом шаблонизатор находит шаблон default.htpl в том же каталоге, где находится запрашиваемый документ. Также разбирает на блоки, выполняет, подставляет. Потом находит шаблон в каталоге уровнем выше. Опять разбирает на блоки, выполняет, подставляет. И так в цикле до тех пор, пока не наткнется на шаблон с пометкой root. Он уже не содержит блоков, т.к. является одним большим блоком - корневым. Он выполняется (если надо) и происходит подстановка. В результате получается итоговая страница, которая и выдается пользователю.

Уже после выдачи пользователю она записывается в кэш, при условии, что ни в одном из файлов обработанной цепочки не было параметра nocache. При следующем запросе этого документа, при наличии его в кэше, шаблонизатор сначала сравнивает дату файла в кэше с датами всех файлов цепочки (т.е. конечных данных и шаблонов), и если кэшированный файл создан позже, то он сразу выдается пользователю. Т.е. все ограничивается чтением одного-единственного файла, никакой обработки.

Как это установить.
Достаточно поместить файл-движок в каталог, где лежат все CGI-скрипты, а в корень сайта в .htaccess прописать его в качестве обработчика HTML-файлов. Кроме этого, надо в корне сайта создать каталог с именем cache.

Скачать архив с шаблонизатором и сайтом-примером (3 кб).

Вопросы.
-Можно ли тут обрабатывать GET и POST запросы?
-Да, если документ содержит блоки с кодом, и к этому документу обращаются с запросом, то код чувствует себя как обычный CGI - в переменных окружения есть вся необходимая информация.

-А где же обещанное отделение кода от данных?
-Предлагается выносить весь код (обрабатывающий данные, но сам ничего не выводящий, а сохраняющий результат в переменные) в отдельные файлы, а в шаблоне делать <? do "code.pl"; ?>, после чего просто ставить в шаблоне имена переменных с результатами. Да, это придется делать вручную, но все равно это лучше, чем выводить HTML из CGI-скрипта.


© Dee Mon, 2004-2010.