Технология VITRAGE
Один из витражей города Иркутска
О модуле
· Что такое VITRAGE
· История модуля
· Загрузить модуль
· Документация целиком
· Загрузить документацию в формате MS Word
· Слово автора
· English version
 
Теория
· Компиляция и установка
· Идеология VITRAGE
· Оптимизация HTML
· Создание виртуальных хостов
· Создание структуры доменов
· Ваш собственный язык гипертекстовой разметки
 
Практика
· Немного о стилях парсинга
· Примеры использования
· Работающие сайты
· Хостинги
· Вопросы и ответы
· Задать вопрос
· E-mail
 
Исходный код
· VHTML-код этой страницы (в новом окне)
· VHTML-код файла vitrage (в новом окне)
 
· Введение. Что такое VITRAGE

VITRAGE (читается "витрАж") - это модуль расширения популярного веб-сервера Apache, предназначенный для решения нескольких задач, основные из которых - это:

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

2) Оптимизация "на лету" передаваемого пользователю HTML-кода посредством удаления избыточных пробелов и пустых строк, неоправданно увеличивающих загружаемые пользователем страницы: каждая страница, обработанная модулем, содержит только действительно необходимую информацию.

3) Манипуляция виртуальными хостами (доменами).

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

Используя VITRAGE, веб-разработчик получает в свои руки инструмент, который сократит время, затрачиваемое на HTML-форматирование страниц (логическую разметку) и позволит писать HTML-документы на практически обычном, "естественном" языке.

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

Для создания первичного образа данного средства веб-разработки автор VITRAGE рекомендует рассматривать его как чрезвычайно расширенную технологию SSI (Server Side Includes), известную многим. В отличие от SSI, однако, VITRAGE гораздо более мощен и "естественен" для HTML-верстки.

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

Стек-ориентрированный язык Primitive, названный так из-за ярко выраженной и ограниченной сферы применения, изначально был частью текстового редактора The Textra Edit (for Windows), который разрабатывал (исключительно в познавательных и самообразовательных целях) все тот же автор. В VITRAGE для обеспечения возможности простой обработки числовых и строковых данных вошла еще более упрощенная версия Primitive.
 

· Компиляция и установка

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

Прежде всего, стоит заметить, что данный модуль (в том виде, в котором он существует в настоящее время), скорее всего, не будет работать со второй версией веб-сервера Apache, которая уже начала распространяться. Во второй версии разработчики Apache внесли значительные изменения в Apache API и в саму идеологию создания модулей. Версия VITRAGE для Apache 2.x, вероятно, будет когда-нибудь создана, а пока речь идет об Apache 1.3.x. На данный момент у автора не возникало никаких проблем с компиляцией и установкой модуля для всех версий Apache 1.3.x.

К сожалению, автор имеет возможность комментировать установку модуля только для Apache под Linux, но это ограничение не представляется автору принципиальным.

Итак, начнем с ситуации, когда модуль еще не скомпилирован и представляет собой файл mod_vitrage.c. Вообще говоря, компиляция модуля VITRAGE аналогична компиляции прочих модулей для Apache: используется gcc с указанием того, что подключаемые (include) файлы следует также искать в каталоге /usr/include/apache (или в ином соответствующем). Автор использует следующие команды для "сборки" модуля:

gcc -DLINUX=2 -DUSE_HSREGEX -DEAPI -DUSE_EXPAT -I../lib/expat-lite -fpic -O2 -DSHARED_MODULE -I/usr/include/apache -c mod_vitrage.c
gcc -shared -o mod_vitrage.so mod_vitrage.o

В подавляющем большинстве случаев компиляция модуля может быть также выполнена при помощи утилиты apxs, входящей в поставку Apache:

apxs -c mod_vitrage.c

После последовательного запуска двух первых команд или запуска apxs в том же каталоге, где находится mod_vitrage.c, будет создан файл mod_vitrage.so, который и предстоит "подключать" к Apache.

Файл mod_vitrage.so следует скопировать в тот каталог, где находятся все прочие модули (это может быть, например, /usr/lib/apache), после чего предстоит последний этап - изменение httpd.conf (конфигурационного файла веб-сервера). В него должны быть добавлены следующие строки (все упоминаемые ключевые слова - LoadModule, AddModule, AddType, AddHandler - подробно описаны в руководстве пользователя Apache, к которому вы можете обратиться в случае возникновения вопросов или проблем):

LoadModule vitrage_module /usr/lib/apache/mod_vitrage.so
AddModule mod_vitrage.c
AddType text/html .vhtml
AddHandler vitrage-parsed .vhtml

Если вы собираетесь использовать VITRAGE в качестве расширения HTML, вы, скорее всего, будете описывать собственные тэги в специальных конфигурационных файлах VITRAGE. Процедура описания новых тэгов и использования конфигурационных файлов будет затронута в разделе "Ваш собственный язык гипертекстовой разметки" руководства. Сейчас же следует знать, что по умолчанию конфигурационные файлы имеют имя vitrage (строчными латинскими буквами без расширения), и эти файлы следует защитить от скачивания следующими строками в httpd.conf:

<Files vitrage>
Order allow,deny
Deny from all
</Files>

В этом же разделе руководства целесообразно отметить, что страницы, при разметке которых использован расширенный с помощью VITRAGE язык HTML, мы будем называть VHTML-страницами (VHTML-файлами, файлами VHTML), а соответствующие им файлы будут иметь расширение ".vhtml", например, index.vhtml. В связи с этим может оказаться полезной мысль о дополнении значения параметра DirectoryIndex в файле httpd.conf именем "index.vhtml", например:

DirectoryIndex index.htm index.html index.php index.shtml index.php3 index.vhtml index.cgi

Кроме всего этого, на данном этапе можно осуществить настройку параметров модуля для всего веб-сервера в целом (то есть установить параметры по умолчанию), а также для отдельных виртуальных хостов (секции VirtualHost конфигурационного файла) и каталогов (секции Directory). Список ключевых слов, отвечающих за настройку возможностей VITRAGE, комментарии и рекомендации приведены в данном руководстве в разделе "Идеология VITRAGE. Ключевые слова и их использование".

После компиляции и настройки можно запускать (или перезапускать) Apache. VITRAGE готов к плодотворной работе.
 

· О HTML, форматировании, доменах, тэгах, атрибутах и парсинге

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

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

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

Если вы собираетесь использовать VITRAGE для манипуляции виртуальными хостами (доменами), вам следует владеть соответствующей терминологией (домены, поддомены, уровень домена и т.п.).

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

Единственный термин, объяснение которого мы позволим себе привести здесь, - это термин "парсинг". Под парсингом здесь и далее будет пониматься "разбор" модулем VITRAGE VHTML-файлов, анализ используемых в них тэгов, атрибутов, переменных и других допустимых объектов, а также их преобразования и вычисления в соответствии с правилами, встроенными в модуль VITRAGE, и правилами, задаваемыми пользователем модуля.

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

В устной речи допустимы также производные от слова "парсинг" "жаргонные" глаголы - "парсить", "пропарсить", значения которых, с учетом вышесказанного, выглядят очевидными.

Автор не исключает и других трактовок и определений понятия "парсинг". На самом деле, средств разработки, использующих технологию парсинга, "разбора", достаточно много - это и PHP, и Parser, и даже SSI.
 

· Идеология VITRAGE. Ключевые слова и их использование

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

Идеология VITRAGE такова, что значения большинства параметров настройки могут распространяться на любой объект, находящийся под управлением Apache, - на веб-сервер в целом, на отдельный виртуальный хост или на отдельный каталог (включая все его подкаталоги). Таким образом, допустимо использование большинства ключевых слов как для установки значений по умолчанию в httpd.conf, так и для конфигурации более конкретных объектов - в секциях VirtualHost и Directory, а также в файлах .htaccess. Принципы работы с httpd.conf, его секциями, а также файлами .htaccess подробно описаны в руководстве по использованию Apache.

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

  1. Оптимизация HTML управляется ключевыми словами VGStripSpaces и VGStripLines.
  2. Быстрое создание виртуальных доменов возможно с использованием ключевых слов VGMultiSitePath и VGMultiDomainLevel.
  3. VITRAGE сможет преобразовывать структуру каталогов в структуру доменов, если вы будете использовать ключевые слова VGBaseDomain и VGBaseSubLevel.
  4. И, наконец, для расширения HTML вы будете использовать слова VGParse, VGConfigFile (или VGConfigFileOverride), VGParseOldStyle.

Еще два ключевых слова управляют способом "выдачи" HTML-файлов (в том числе и файлов VHTML) пользователю.

VGCache. Этот параметр управляет кэшированием страниц браузером пользователя и может принимать одно из двух значений - "On" или "Off". Если значение VGCache равно "On" (по умолчанию), HTML-страницы будут "выдаваться" пользователю в том виде, в котором они существуют на сервере, то есть модуль VITRAGE не будет оказывать на них никакого влияния. Изменив значение VGCache на "Off", мы инициируем принудительную установку даты изменения "выдаваемой" страницы на текущую, гарантируя тем самым, что браузер пользователя загрузит ее с сервера целиком, а не воспользуется кэшем.

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

VGCache Off
VGCache On

VGMimeAfter. Этим ключевым словом вы можете изменять MIME-тип выдаваемых пользователю файлов. По умолчанию, очевидно, значение этого параметра равно "text/html", и смысл в его изменении практически всегда отсутствует. Примеры применения данного ключевого слова:

VGMimeAfter text/plain
VGMimeAfter text/html
VGMimeAfter text/rtf

Обращаем внимание на то, что VITRAGE использует идеологию "перекрывания" значений ключевых слов для более крупных объектов значениями для объектов более мелких. Например, значение параметра по умолчанию будет заменено значением параметра виртуального хоста (если оно указано!), которое, в свою очередь, будет "перекрыто" значением параметра для конкретного каталога.

При использовании файлов .htaccess и структуры вложенных каталогов значение параметра для каталога верхнего уровня распространяется на все подкаталоги до тех пор, пока в подкаталоге не будет встречен .htaccess, содержащий новое значение для данного параметра.

Единственным исключением из этого "правила перекрывания" является ключевое слово VGConfigFile, об особенностях которого речь пойдет в разделе "Ваш собственный язык гипертекстовой разметки".
 

· Применение 1. Оптимизация HTML

Даже если вы не собираетесь расширять HTML при помощи VITRAGE, "прозрачная" для пользователей оптимизация HTML-страниц "на лету" стоит того, чтобы начать использовать данный модуль.

Обычно хорошая HTML-верстка строго структурирована и выглядит следующим образом:

<html>
 
<head>
<title>Заголовок страницы</title>
</head>
 
<body>
<p>Страница,    созданная   для   примера
<ul>
<li>Пример   1
<li>Пример    2
<li>Пример   3
</ul>
</body>
 
</html>

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

Кроме того, если верстка выполняется в каком-либо редакторе, работающем под Windows, каждая строка исходного текста HTML с большой долей вероятности будет оканчиваться не одним специальным символом, имеющим код 0A, а двумя - 0D и 0A. Это также излишне "утяжелит" страницу.

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

Ну и, разумеется, чаще всего лишней информацией в HTML-файлах являются "пустые строки", то есть строки, состоящие только из спецсимвола с кодом 0A (или двух спецсимволов - 0D и 0A).

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

Для управления оптимизацией используются два ключевых слова: VGStripSpaces и VGStripLines.

Ключевое слово VGStripSpaces отвечает за оптимизацию пробелов и символов табуляции. При этом возможны три значения этого параметра - "Off" (по умолчанию; никакой оптимизации не производится), "On" (оптимизируются только те последовательности пробелов и символов табуляции, которые находятся в начале строк) и "Full" (оптимизируются все последовательности пробелов и символов табуляции).

Ключевое слово VGStripLines обеспечивает оптимизацию завершающих строку символов и удаление пустых строк. Если значение этого параметра равно "Off" (по умолчанию), то оптимизация не производится. Если значение параметра - "On", все последовательности символов с кодами 0D и 0A, завершающих строки, преобразуются в один символ с кодом 0A. И, наконец, если присвоить данному параметру значение "Full", то, кроме замены завершающих строки символов, VITRAGE удалит из передаваемого пользователю HTML-кода все пустые строки.

Примеры использования данных ключевых слов:

VGStripSpaces Off
VGStripSpaces Full
VGStripSpaces On
VGStripLines Full
VGStripLines Off
VGStripLines On

При полностью включенной оптимизации ("VGStripSpaces Full" и "VGStripLines Full") приведенный выше пример будет загружен пользователем в следующем виде (разумеется, и в первоначальном, и в этом виде страница отображается браузером совершенно одинаково):

<html>
<head>
<title>Заголовок страницы</title>
</head>
<body>
<p>Страница, созданная для примера
<ul>
<li>Пример 1
<li>Пример 2
<li>Пример 3
</ul>
</body>
</html>

Заметим дополнительно, что стоит с особой внимательностью относиться к оптимизации тех HTML-страниц, для которых важно "оригинальное" форматирование. Примером таких страниц могут быть страницы, при форматировании которых использован тэг <pre>. Для каталогов, содержащих подобные страницы, оптимизацию (по крайней мере, оптимизацию пробелов и символов табуляции) рекомендуется отключать.

Если ваш веб-сервер Apache "обслуживает" несколько виртуальных серверов, то, возможно, вам покажется удачной идея уставить значения по умолчанию (в httpd.conf) для VGStripSpaces и VGStripLines, равные "Off", а затем включать оптимизацию для каждого виртуального сервера индивидуально по мере необходимости.

Очевидно, что оптимизация страниц (при соответствующих установках ключевых слов) будет выполняться и в том случае, когда вы дополнительно используете VITRAGE в качестве расширителя HTML, то есть VHTML-страницы также будут оптимизироваться.

Отвечая на часто задаваемый вопрос о том, можно ли оптимизировать страницы, сгенерированные иными средствами, например, PHP, Perl или SSI, автор замечает, что "штатный" способ осуществить такое действие ему неизвестен. Более того, в ближайшее время автор не планирует нахождение, обеспечение и описание такой возможности, потому что идеологически VITRAGE должен не дополнять перечисленные выше технологии, а полностью заменять их для определенного рода задач. Если вами, однако, найден способ решения поставленной задачи и вы можете его подробно описать, свяжитесь с автором модуля VITRAGE, возможно, ваше решение будет включено в данное руководство.
 

· Применение 2. Создание виртуальных хостов (доменов) за мгновение

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

Традиционно для создания нового виртуального хоста требуется создание каталога, в котором будет расположено содержимое соответствующего домену сайта, внесение изменений в конфигурационный файл Apache (httpd.conf) и перезапуск веб-сервера Apache для принятия всех изменений.

Модуль VITRAGE позволит решить эту задачу за мгновение, "в один ход", сведя создание нового виртуального хоста к созданию каталога.

Итак, предположим, что в конфигурационном файле Apache (httpd.conf) присутствует следующее описание виртуального хоста:

<VirtualHost 10.1.1.1>
ServerName domain.ru
ServerAdmin webmaster@domain.ru
DocumentRoot /home/web/domain.ru/www
ErrorLog /home/web/domain.ru/log/error.log
CustomLog /home/web/domain.ru/log/access.log common
CustomLog /home/web/domain.ru/log/referer.log referer
CustomLog /home/web/domain.ru/log/agent.log agent
</VirtualHost>

Используя в секции VirtualHost файла httpd.conf ключевые слова VITRAGE VGMultiSitePath и VGMultiDomainLevel, разработчик сможет осуществить следующее: каждый подкаталог вида некое.доменное.имя, созданный в каталоге /home/web/domain.ru/www, будет автоматически поставлен в соответствие домену некое.доменное.имя, после чего адрес http://некое.доменное.имя будет естественным образом указывать на содержимое каталога /home/web/domain.ru/www/некое.доменное.имя.

Обозначенные ключевые слова нельзя указывать в файлах .htaccess в силу логической последовательности восприятия ключевых слов и обработки каталогов веб-сервером Apache.

Прежде всего, рассмотрим действие ключевого слова VGMultiSitePath. Значением этого параметра является путь к тому каталогу, в котором будут создаваться образующие домены подкаталоги. Чаще всего значение VGMultiSitePath совпадает со значением параметра DocumentRoot из соответствующей секции VirtualHost файла httpd.conf (хотя это вовсе не обязательно!):

VGMultiSitePath /home/web/domain.ru/www

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

Допустим, мы хотим создать виртуальные хосты host1.domain.ru, host2.domain.ru и subhost.host2.domain.ru. Для этого, с учетом описанных выше настроек, нам потребуется лишь создать такие каталоги:

/home/web/domain.ru/www/host1.domain.ru/
/home/web/domain.ru/www/host2.domain.ru/
/home/web/domain.ru/www/subhost.host2.domain.ru/

После выполнения этого действия соответствующие адреса (http://host1.domain.ru, http://host2.domain.ru и http://subhost.host2.domain.ru) начнут функционировать незамедлительно.

Если есть необходимость в работе адреса http://domain.ru, следует дополнительно создать каталог

/home/web/domain.ru/www/domain.ru/

- и это важная особенность данного применения модуля VITRAGE.

Если вы хотите, чтобы наряду с адресами http://host1.domain.ru, http://domain.ru функционировали и адреса http://www.host1.domain.ru, http://www.domain.ru, вам потребуется создать соответствующие каталоги (www.host1.domain.ru, www.domain.ru), содержимое которых будет идентично содержимому каталогов host1.domain.ru, domain.ru. В UNIX-подобных операционных системах очень удобно выполнять такую операцию с использованием "символьных ссылок" (symlinks), обычно создающихся командой ln.

Поскольку доменные имена независимы от регистра их написания (т.е. домен HOST.domain.ru равнозначен домену host.domain.ru), следует создавать соответствующие каталоги, используя строчные буквы. Каталоги, созданные с использованием заглавных букв, вероятнее всего, не будут функционировать должным образом.

Ключевое слово VGMultiDomainLevel определяет максимальный уровень для доменов, которые могут быть образованы созданием каталогов. Этот параметр может принимать значение любого неотрицательного целого числа, начиная с "0" (по умолчанию; уровень доменов не ограничен).

Если мы заранее знаем, что максимальный уровень доменов, который мы будем создавать, не превышает 3 (домен третьего уровня - это домен вида host.domain.ru), описание ключевого слова VGMultiDomainLevel должно быть следующим:

VGMultiDomainLevel 3

При этом (внимание!) обращение http://www.host1.domain.ru (и вообще любой адрес вида http://большой.уровень.host1.domain.ru) будет воспринято модулем как обращение, равнозначное http://host1.domain.ru. То есть все запрашиваемые виртуальные хосты, имеющий уровень выше заданного в VGMultiDomainLevel, будут "обрезаться" до максимально допустимого уровня, после чего уже будет произведено обращение к соответствующему каталогу.

Не следует забывать, что данная схема не будет работать без соответствующим образом настроенного DNS. Все создаваемые доменные имена должны быть описаны в DNS, а их IP-адреса должны быть идентичны IP-адресу, указанному в конфигурации Apache для соответствующего виртуального хоста (в нашем примере - 10.1.1.1).

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

ErrorDocument 404 /apache/not-found.html

вам потребуется либо помещать этот файл в каждом каталоге, преобразующемся в домен (чтобы любой адрес вида http://домен/apache/not-found.html был верным), либо изменить данную установку на один из следующих вариантов:

ErrorDocument 404 http://один.из.доменов/apache/not-found.html
ErrorDocument 404 "File not found

В первом случае вам достаточно будет иметь только одну копию файла not-found.html, во втором случае вместо HTML-файла в случае ошибки будет отображаться простое текстовое сообщение.
 

· Применение 3. Преобразование структуры каталогов в структуру доменов

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

Предположим, что разработчик имеет следующее описание домена в файле конфигурации Apache (httpd.conf):

<VirtualHost 10.1.1.1>
ServerName domain.ru
ServerAdmin webmaster@domain.ru
DocumentRoot /home/web/domain.ru/www
ErrorLog /home/web/domain.ru/log/error.log
CustomLog /home/web/domain.ru/log/access.log common
CustomLog /home/web/domain.ru/log/referer.log referer
CustomLog /home/web/domain.ru/log/agent.log agent
</VirtualHost>

Прежде всего, это означает, что в каталоге /home/web/domain.ru/www находится содержимое сайта, вызываемого по адресу domain.ru. Очевидно, что в этом каталоге могут находиться подкаталоги, каждый из которых будет доступен по адресу http://domain.ru/каталог/.

Сущность описываемой задачи заключается в следующем: поставить в соответствие каждому из подкаталогов каталога /home/web/domain.ru/www домен вида каталог.domain.ru. Более того, подкаталогам большей вложенности должны соответствовать поддомены вида подкаталог.каталог.domain.ru.

Если такая задача будет решена, то для следующей структуры каталогов:

/home/web/domain.ru/www/
/home/web/domain.ru/www/catalog1/
/home/web/domain.ru/www/catalog1/subcatalog1/
/home/web/domain.ru/www/catalog2/
/home/web/domain.ru/www/catalog2/subcatalog1/
/home/web/domain.ru/www/catalog2/subcatalog1/anothercatalog/
/home/web/domain.ru/www/catalog2/subcatalog2/

должны соответственно функционировать домены

domain.ru
catalog1.domain.ru
subcatalog1.catalog1.domain.ru
catalog2.domain.ru
subcatalog1.catalog2.domain.ru
anothercatalog.subcatalog1.catalog2.domain.ru
subcatalog2.catalog2.domain.ru

При этом, что вполне логично, к содержимому каталога /home/web/domain.ru/www/catalog2/subcatalog1/anothercatalog/ будут вести следующие адреса:

http://domain.ru/catalog2/subcatalog1/anothercatalog/
http://catalog2.domain.ru/subcatalog1/anothercatalog/
http://subcatalog1.catalog2.domain.ru/anothercatalog/
http://anothercatalog.subcatalog1.catalog2.domain.ru/

Для решения подобной задачи (назовем ее задачей преобразования структуры каталогов в структуру доменов) имеет смысл воспользоваться услугами модуля VITRAGE. Для этого обратим внимание на два ключевых слова, указываемых в секции VirtualHost файла httpd.conf и отвечающих за подобное преобразование: VGBaseDomain и VGBaseSubLevel.

Эти ключевые слова нельзя использовать в файлах .htaccess в силу логической последовательности восприятия ключевых слов и обработки каталогов веб-сервером Apache.

Ключевое слово VGBaseDomain предназначено для указания "базового домена", то есть домена самого верхнего уровня, для которого будут формироваться поддомены. Чаще всего значение VGBaseDomain совпадает со значением параметра ServerName, который описывается в секции VirtualHost (хотя это вовсе не обязательно!). Для нашего примера строка в httpd.conf, задающая значение параметра VGBaseDomain будет выглядеть следующим образом:

VGBaseDomain domain.ru

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

Второе ключевое слово - VGBaseSubLevel - имеет смысл только при описанном параметре VGBaseDomain и позволяет задать максимальный уровень вложенности каталогов, подлежащих преобразованию в домены. Этот параметр может принимать значение любого неотрицательного целого числа, начиная с "0" (по умолчанию; уровень вложенности не ограничен).

Для описанной выше задачи в ее неизменном варианте, вероятнее всего, наиболее подойдет значение параметра VGBaseSubLevel, равное "0" (отсутствие каких-либо ограничений):

VGBaseSubLevel 0

Если мы усложним задачу и потребуем, чтобы преобразованию подвергались все подкаталоги до второго уровня вложенности включительно (то есть не должен преобразовываться каталог anothercatalog), нам потребуется указать следующее описание параметра:

VGBaseSubLevel 2

Если нас интересуют только подкаталоги первого уровня (соответствующие в примере доменам catalog1.domain.ru и catalog2.domain.ru), то строка конфигурации будет выглядеть так:

VGBaseSubLevel 1

И снова не следует забывать, что данная схема не будет работать без соответствующей настройки DNS. Все образуемые доменные имена должны быть соответствующим образом описаны, а их IP-адреса должны совпадать с IP-адресом, указанному в конфигурации Apache для виртуального хоста (в примере - 10.1.1.1). Каждый поддомен может быть описан в конфигурационном файле DNS индивидуально, можно также воспользоваться записью вида

*   A   10.1.1.1

для описания "полного набора" поддоменов.

Обратим внимание и на то, что совет, приведенный в конце предыдущего раздела руководства (о внимательном отношении к настройкам Apache, чувствительным к адресам виртуальных серверов и структуры каталогов), стоит принять во внимание и при использовании VITRAGE для преобразования структуры каталогов в структуру доменов.

Более того, при таком применении модуля вас может ждать еще одна проблема, суть которой проще всего показать на примере.

Допустим, мы имеем следующую структуру каталогов:

/
/img/
/img/main/
/products/
/services/

и следующие настройки модуля VITRAGE в соответствующей секции VirtualHost конфигурационного файла Apache (httpd.conf):

VGBaseDomain my.domain.ru
VGBaseSubLevel 0

Таким образом, доступными окажутся домены my.domain.ru, img.my.domain.ru, main.img.my.domain.ru, products.my.domain.ru и services.domain.ru.

Допустим также, что в каталоге products находится файл index.html, в котором используются ссылки на изображения, хранящиеся в каталогах /img и /img/main/:

<a href="../img/main/image.jpg"><img src="/img/image.jpg" width=30 height=40 alt="" border=0></a>

Очевидно, что данный код будет работоспособным, если запрос к странице будет выглядеть как http://my.domain.ru/products/index.html. Но вот если мы попытаемся получить эту страницу запросом http://products.my.domain.ru/index.html, то изображение отображаться не будет, а также не будет функционировать ссылка. Действительно, для домена products.my.domain.ru файл index.html уже находится в "корневом" каталоге, для которого каталогов /img/ и ../img/main/ не существует.

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

<a href="http://main.img.my.domain.ru/image.jpg"><img src="http://img.my.domain.ru/image.jpg" width=30 height=40 alt="" border=0></a>

или такой:

<a href="http://img.my.domain.ru/main/image.jpg"><img src="http://my.domain.ru/img/image.jpg" width=30 height=40 alt="" border=0></a>

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

· Применение 4. Ваш собственный язык гипертекстовой разметки

Несмотря на то, что оптимизация HTML-файлов, манипуляция виртуальными хостами и каталогами - это весьма важные задачи, именно расширение языка HTML является основным применением модуля VITRAGE и приоритетным направлением, развиваемым его автором.

В рамках этого направления модуль VITRAGE предлагает HTML-верстальщику перейти от стандартного языка гипертекстовой разметки HTML к расширенному VHTML, создавать и описывать элементы которого может, в том числе, и сам верстальщик.

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

Данный раздел руководства детально описывает теорию VHTML, его возможности и их использование.

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

  • Общие концепции, ключевые слова, конфигурационные файлы vitrage, их защита
  • Файлы *.vhtml. Самое простое применение VHTML для перенаправления на другие страницы
  • Описание и использование тэгов, работа с переменными
  • Встроенные тэги и их описание
  • Встроенные переменные, их значение и использование
  • Язык Primitive, его операторы и его использование
  • Дополнительные сведения. "Тонкие" моменты

Перечень всех встроенных тэгов VITRAGE:

  • <%parse%>
  • <%noparse%>
  • <%varse%>
  • <%novarse%>
  • <%oldstyle%>
  • <%newstyle%>
  • <%debug%>
  • <%nodebug%>
  • <%echo%>
  • <%tag%>
  • <%query%>
  • <%vitrage%>
  • <%copy%>
  • <%copyd%>
  • <%var%>
  • <%vard%>
  • <%unset%>
  • <%unsetd%>
  • <%empty%>
  • <%emptyd%>
  • <%true%>
  • <%trued%>
  • <%false%>
  • <%falsed%>
  • <%drop%>
  • <%dropd%>
  • <%setifnot%>
  • <%setifnotd%>
  • <%include%>
  • <%require%>
  • <%file%>
  • <%primitive%>
  • <%integer%>
  • <%integerd%>
  • <%htmlchars%>
  • <%htmlcharsd%>
  • <%rawchars%>
  • <%rawcharsd%>
  • <%htmlrawchars%>
  • <%htmlrawcharsd%>
  • <%unescape%>
  • <%unescaped%>
  • <%inc%>
  • <%incd%>
  • <%dec%>
  • <%decd%>
  • <%join%>
  • <%joind%>
  • <%nothing%>
  • <%everything%>
  • <%interpret%>
  • <%return%>
  • <%exit%>
  • <%break%>
  • <%write%>
  • <%writed%>
  • <%writeln%>
  • <%writelnd%>
  • <%append%>
  • <%appendd%>
  • <%appendln%>
  • <%appendlnd%>
  • <%read%>
  • <%readd%>
  • <%readln%>
  • <%readlnd%>
  • <%stat%>
  • <%statd%>
  • <%%%rem%%%>

Перечень всех встроенных переменных (атрибутов) VITRAGE:

  • %oquery%
  • %query%
  • %self%
  • %uri%
  • %ouri%
  • %dir%
  • %name%
  • %port%
  • %host%
  • %lt%
  • %gt%
  • %quot%
  • %space%
  • %tab%
  • %nl%
  • %s%
  • %percent%
  • %%%none%%%
  • %parse%
  • %noparse%
  • %times%
  • %btimes%
  • %random%
  • %rand%
  • %timestamp%
  • %time%
  • %module%
  • %version%
  • %shuffle%
  • %recurse%
  • %norecurse%
  • %tag%
  • %authuser%
  • %remoteip%
  • %localip%
  • %true%
  • %false%
  • NoPoweredBy

Перечень всех операторов Primitive:

  • . (print)
  • / (div)
  • % (mod)
  • ++ (inc)
  • -- (dec)
  • +
  • *
  • -
  • sign (sgn)
  • join (strcat)
  • lower
  • dup
  • over
  • drop
  • pow (power, ^)
  • swap (swop)
  • gt
  • lt
  • = (==, eq)
  • le
  • ge
  • ne (!=)
  • and (&&)
  • or (||)
  • xor
  • not (!)
  • int
  • negate (neg)
  • abs
  • clear (clstk, empty)
  • depth (stack)
  • in
  • out
  • var
  • instack
  • outstack
  • rnd (rand, random)
  • strlen (length)
  • strcmp
  • issubstr
  • substr
  • copy
  • move
  • del (delete)
  • if
  • true
  • false
  • ver (version)
  • module (powered)

Перечень файловых атрибутов, устанавливаемых тэгом <%stat[d]%>:

  • isfile
  • isdir
  • uid
  • gid
  • mode
  • size
  • blksize
  • blocks
  • atime
  • mtime
  • ctime

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

· VHTML: Общие концепции, ключевые слова, конфигурационные файлы vitrage

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Файлы *.vhtml. Перенаправление на другие страницы

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Описание и использование тэгов, работа с переменными

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Встроенные тэги и их описание

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Встроенные переменные, их значение и использование

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Язык Primitive, его операторы и его использование

В настоящее время этот раздел готовится к публикации.
 

· VHTML: Дополнительные сведения. "Тонкие" моменты

В настоящее время этот раздел готовится к публикации.
 

· Немного о стилях парсинга

Для общей полноты сведений коснемся еще одного момента, связанного с эволюцией развития модуля VITRAGE.

Дело в том, что до версии 0.10 модуль VITRAGE осуществлял парсинг несколько иначе, чем сейчас. Старый стиль парсинга был "построчным", то есть объектами шагов работы VITRAGE были не тэги, а строки VHTML-файлов. Схема работы модуля была при этом такова: VITRAGE получал из VHTML-файла очередную строку (или описание тэга из файла конфигурации), после чего заменял в этой строке (или в описании тэга) все переменные на их значения, а уже затем начинал последовательную работу с тэгами. Эту схему ярко иллюстрирует следующий пример:

<%vitrage% A=1>
<%vitrage% A=2><%echo% str="$A$">

Очевидно, что после работы данного кода модуль должен вывести значение переменной A, то есть "2". Старый же стиль предполагает, что сначала во всей строке произойдет замена переменных на их значения (а значение переменной A на момент начала обработки второй строки примера равно "1"!), а затем уже будут исполнены тэги. Таким образом, в соответствии со старым стилем парсинга, модуль выведет для данного примера число "1".

Совершенно ошибочной в старом стиле парсинга была бы следующая конструкция:

<%vitrage% G="$%gt%$">

поскольку до выполнения тэга (на этапе замены переменных значениями) она была бы преобразована в

<%vitrage% G=">">

а это, согласно правилам парсинга, является нарушением вложенности знаков "<" и ">". Для вывода знаков "<" и ">" с использованием старого стиля парсинга применялись хитрости вида

<%var% 1="%gt%">

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

Для совместимости со старыми версиями, новые версии VITRAGE содержат полную поддержку старого стиля парсинга, а управление стилями осуществляется при помощи ключевого слова VGParseOldStyle, которое может принимать значения "Off" (по умолчанию; используется новый последовательный стиль) и "On" (будет использоваться старый стиль парсинга):

VGParseOldStyle On
VGParseOldStyle Off

"Отголоском" старого стиля парсинга в новом стиле стал встроенный тэг <%require%>, особенности действия которого описаны в разделе "Ваш собственный язык гипертекстовой разметки". Вероятнее всего, теперь это единственный случай, когда вам потребуется представление о старом построчном стиле парсинга.
 

· Практические примеры

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

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

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

 
· Пример 1. "Распорки" для табличной верстки

Очень часто в современной табличной HTML-верстке приходится использовать так называемые "распорки" - прозрачные GIF-файлы разного размера. Обычно для решения подобной задачи создается один файл (назовем его dot.gif) размером в один пиксель, а ширина и высота "распорок" указывается в атрибутах width и height тэга <img>, например:

<img src="/images/dot.gif" alt="" border=0 width=32 height=64>

Если схема верстки достаточно сложная, таких "распорок" будет несколько, причем они будут, вероятно, иметь разные размеры. При помощи модуля VITRAGE мы можем упростить процесс добавления "распорок" введением нового тэга, атрибутами которого будут требуемые высота и ширина. Назовем этот тэг <dot>, а значениями высоты и ширины по умолчанию выберем "1":

<dot width=1 height=1>
<img src="/images/dot.gif" alt="" border=0 width=$width$ height=$height$>
</dot>

После внесения такого описания в файл vitrage мы можем использовать этот тэг при верстке:

<dot width=32 height=64>
<dot width=188>
<dot>
<dot height=52>

 
· Пример 2. Практичная вставка изображений

Правилом хорошего тона в HTML-верстке при вставки изображений посредством тэга <src> является указание значений для атрибутов border и alt. Замечено, что атрибут border чаще всего принимает значение "0", а атрибут alt - значение "" (пустая строка). Пользуясь этим наблюдением, можно задать новый тэг, в котором атрибутам border и alt будут присвоены соответствующие значения по умолчанию:

<image src="" border=0 alt="" width=1 height=1>
<img src="$src$" border=$border$ alt="$alt$" width=$width$ height=$height$>
</image>

Заметим, что в описании можно было и не указывать значений по умолчанию для атрибутов src, width и height, но будем считать это действие правилом хорошего тона в VHTML-верстке (к тому же это очень помогает не забывать, какие атрибуты должен или может иметь данный тэг).

Таким образом, мы избавляемся от необходимости каждый раз повторять конструкцию "alt="" border=0" при вставке изображений, но, однако, можем и изменять эти значения при необходимости:

<image src="/img/dot.gif" width=10 height=15>
<image src="logo.jpg" width=64 height=64 alt="[Логотип]">
<image src="email.gif" width=20 height=16 border=1 alt="[E-mail]">

Кстати, с использованием данного тэга описание тэга <dot> из предыдущего примера может стать таким:

<dot width=1 height=1>
<image src="/images/dot.gif" width=$width$ height=$height$>
</dot>

 
· Пример 3. "Колонтитулы", инициализация и глобальные параметры сайта

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

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

"Шапку" сайта автор обычно описывает тэгом <header>. "Шапка" HTML-страницы включает в себя блок <head>...</head>, который, в свою очередь включает в себя заголовок и ключевые слова. Поскольку заголовок и ключевые слова изменяются от страницы к странице, имеет смысл передавать их тэгу <header> в виде соответствующих атрибутов:

<header title="" keywords="">
<html>
<head>
<meta name="keywords" content="$keywords$">
<title>$title$</title>
</head>
<body>
</header>

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

Дополнительно стоит задуматься о том, что часто самые большие различия наблюдаются между титульной (главной) страницей и остальными страницами сайта. Для этого опишем в тэге <header> атрибут main, который будет иметь значение по умолчанию "" в том случае, если страница не является титульной, и будет принимать любое непустое значение, если это главная страница.

Итак:

<keywords content="">
<meta name="keywords" content="$content$">
</keywords>

<header title="" keywords="" main="">
<html><%vitrage% main="$main$">
<head>
<keywords content="$keywords$" %parse%="$keywords$">
<title>$title$</title>
</head>
<body>
<%echo% str="Добро пожаловать на сайт нашей компании!" %parse%="$main$">
</header>

Глобальную переменную main, очевидно, теперь можно использовать в любом месте VHTML-файлов и описаний тэгов, например:

<%echo% str="Эта надпись появится только на титульной странице" %parse%="$main$">

Если страницы расположены в разных каталогах и содержат относительные ссылки (на страницы или изображения) имеет смысл также передавать тэгу <header> в качестве параметра ссылку на "корневой каталог" сайта. Назовем этот атрибут root.

На этапе описания "шапки" следует подумать и о том, что многие страницы содержат одни и те же данные - адреса, телефоны - которые теоретически могут поменяться в будущем. Для того чтобы избежать необходимости изменять их при необходимости на всех страницах, опишем все подобные данные в качестве глобальных переменных (глобальных параметров сайта), которые и будем использовать при форматировании страниц. Для определенности удобно делать это в отдельном тэге, вызываемом из тэга <header>. Поскольку можно сказать, что описание глобальных параметров сайта - это его иницализация, назовем соответствующий тэг <init>.

Окончательно имеем:

<init>
<%vitrage%
email="elk@elk.ru"
address="г. Иркутск, ул. Лермонтова, 108"
url="http://vitrage.sibweb.ru">
</init>

<keywords content="">
<meta name="keywords" content="$content$">
</keywords>

<header title="" keywords="" main="" root="">
<html><%vitrage% main="$main$" root="$root$">
<head><init>
<keywords content="$keywords$" %parse%="$keywords$">
<title>$title$</title>
</head>
<body>
<%echo% str="Добро пожаловать на сайт нашей компании!" %parse%="$main$">
<image src="$root$img/logotype.gif" alt="Логотип" width=100 height=65>
</header>

Нижняя часть большинства сайтов неизменна: она обычно содержит сведения об авторах, контактные координаты и счетчик посещений. Автор модуля чаще всего описывает нижнюю часть сайтов тэгом <footer>, и выглядеть это может так:

<footer>
<hr width=100%>
<table width=100% border=0 cellpadding=4 cellspacing=0><tr>
<td align=left valign=top><image src="http://count.elk.ru/" alt="Счетчик" width=90 height=29></td>
<td align=right valign=top>Copyright c <a href="mailto:$email$">Siberian Web</a><br>Создано с использованием технологии VITRAGE</td>
</tr></table>
</body>
</html>
</footer>

В том случае, если нижняя часть страниц изменяется в зависимости от каких-либо условий, эти условия можно задавать тем же способом, что и для тэга <header> - передавая их в качестве значений атрибутов.

В конечном итоге, каждая из VHTML-страниц сайта будет выглядеть так:

<header title="Компания: Продукция" root="../">
<p>Эта страница посвящена предлагаемой продукции.
<p>Список продукции вы сможете получить, отправив нам <a href="mailto:$email$">запрос</a>.
<footer>

В описании титульной страницы присвоим атрибуту main тэга <header> какое-либо значение:

<header title="Компания" keywords="компания, продукция" main="1">
<p>Ознакомьтесь со списком предлагаемой нами <a href="products/">продукции</a>.
<footer>

Если же и внутренние части страниц имеют ярко выраженную структуру, можно подумать об описании ее дополнительными тэгами. Вариант такого рода действий приведен далее в примере 7.
 

· Пример 4. Ссылки: нужные и ненужные

Часто встречаются ситуации, когда при разных условиях один и тот же объект на HTML-странице (например, изображение) может выступать в роли гиперссылки, а может и не выступать. Например, если единая "шапка" сайта содержит его логотип, то на титульной странице логотип не должен исполнять роль ссылки, а на внутренних страницах - должен (ссылка будет вести на титульную страницу).

Для решения такой задачи опишем в конфигурационном файле два новых тэга, которые будут дублировать конструкции "<a href="...">" и "</a>".

<href link=""><a href="$link$"></href>
</href></a><//href>

После этого мы можем описать "шапку" сайта (или ее часть) следующим образом ("флагом", сигнализирующим о том, что страница является титульной, вновь будет переменная main):

<logotype>
<href link="/" %noparse%="$main$"><image src="/logo.jpg" width=100 height=80></href %noparse%="$main$">
</logotype>

Таким образом, ссылка появится только в том случае, если страница не является титульной.

Задача имеет и второе очевидное решение - при помощи встроенного тэга <%tag%>:

<logotype>
<%tag% str="a href=$%quot%$/$%quot%$" %noparse%="$main$"><image src="/logo.jpg" width=100 height=80><%tag% str="/a" %noparse%="$main$">
</logotype>

Автору представляется более изящным первое решение.
 

· Пример 5. Многоязычные сайты

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

Прежде всего, необходимо определить, какие части сайта будут одними и теми же в различных версиях. Очевидно, такими частями будут "колонтитулы" и элементы дизайна, не привязанные к языку. Опишем такие элементы в соответствующих тэгах, например, так, как это показано в примерах 3 и 7.

Тэгу <header> (см. пример 3) имеет смысл передавать в качестве атрибута указатель на язык текущей страницы. Значениями такого атрибута могут быть, например, строки "rus" (русский язык), "eng" (английский язык), "ger" (немецкий язык) и т.п. На основе значения этого атрибута, которое в дальнейшем целесообразно присвоить глобальной переменной, мы будем делать выбор между зависящими от языка вариантами:

<init_rus>
<%%%rem%%% Инициализация для русскоязычной версии>
<%vitrage%
email="info@domain.com"
site_name="Наша компания"
welcome="Добро пожаловать на наш сайт!">
</init_rus>

<init_eng>
<%%%rem%%% Инициализация для англоязычной версии>
<%vitrage%
email="england@domain.com"
site_name="Our company"
welcome="Welcome to our site!">
</init_eng>

<header title="" main="" root="" language="">
<html><%vitrage% main="$main$" root="$root$" language="$language$">
<head><init_$language$>
<title>$site_name$: $title$</title>
</head>
<body>
<%echo% str="" %parse%="$main$">
<a href="$root$$language$/about/"><image src="$root$img/logo_$language$.gif" alt="$site_name$" width=100 height=65></a>
</header>

Догадаться, как можно использовать получаемую переменную language, несложно. Она может являться частью названий графических файлов, тэгов, каталогов, переменных и т.д. Теперь все зависит только от того, насколько грамотно будет спланирована структура тэгов, файлов и каталогов для разных версий сайта.

О структуре каталогов следует упомянуть особо. Традиционно для многоязычных сайтов ее верхний уровень выглядит так:

/
/eng/
/rus/
/ger/

В "корневом" каталоге сайта обычно располагается титульная страница (/index.vhtml), которая предлагает пользователю выбор языка. В зависимости от выбора пользователь будет "направлен" в один из "языковых" каталогов. Структуры "языковых" каталогов для удобства рекомендуется делать идентичными: в этом случае мы сможем пользоваться записью вида "$language$раздел/подраздел/".

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

VGConfigFile vitrage

(внимание: не "VGConfigFileOverride"!) в файлах .htaccess каждого из каталогов.

Например, мы можем описать в каждом каталоге зависящий от языка тэг <header>, который будет передавать в общий тэг <header> соответствующее обозначение для языка страницы:

<header title="" root="">
<header title="$title$" root="$root$" language="eng">
</header>

Описав "шапку" таким образом, мы сможем не беспокоиться об указании атрибута language тэга <header> в каждом VHTML-файле англоязычной версии сайта - нужное значение будет передано в "основную шапку" благодаря предусмотрительно описанной "языковой" "шапке".

В итоге одна из страниц англоязычной версии может выглядеть, например, так:

<header title="Products" root="../../">
<p><b><i>$site_name$</i>: Our products</b>
<p><hr width=100%>
<p><a href="mailto:$email$">Contact us</a> to get our price-list.
<footer>

Заметим: ничто не напоминает в данном VHTML-тексте о существовании версий сайта на других языках или о каком-либо особом статусе английского языка. Мы используем обычные переменные - email, site_name. Точно такие же переменные мы сможем использовать и в любых других страницах любых других языковых версий сайта, и в каждом случае они будут иметь аналогичный смысл и правильные значения.

Как видно, VITRAGE может существенно упростить создание многоязычного сайта при хорошем планировании его структуры и структуры его страниц.
 

· Пример 6. Организация меню

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

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

<menuitem text="" link="" image="" active="">
<href link="$link$" %noparse%="$active$"><image src="img/$image$" alt="$text$" width=70 height=20></href link="$link$" %noparse%="$active$">
</menuitem>

Мы можем упростить этот тэг, называя каталоги сайта, на которые ссылаются элементы меню, и изображения одинаково. "Флаг" active же будем не передавать, а вычислять исходя из сведений о названии активного пункта меню. Это наименование будет содержаться в глобальной переменной activeitem, а фактом "активности" того или иного элемента меню будет совпадение названия активного пункта с переменной name.

При этом тэг <menuitem> будет выглядеть таким образом (обратим внимание на то, что нам оказалось чуть проще вычислить не "флаг активности", а "флаг неактивности", что для решения задачи непринципиально):

<menuitem text="" name="">
<%vitrage% notactive="$name$">
<%unsetd% notactive="$activeitem$">
<%setifnot% var=notactive>
<href link="$name$/" %parse%="$notactive$"><image src="img/$name$.gif" alt="$text$" width=70 height=20></href link="$link$" %parse%="$notactive$">
</menuitem>

После описания тэга-элемента меню описывается тэг, формирующий меню целиком. Такой тэг будет принимать атрибут, определяющий название активного элемент меню, и будет содержать несколько последовательных вызовов <menuitem>:

<menu activeitem="">
<%vitrage% activeitem="$activeitem$">
<menuitem text="Продукция" name="products">
<menuitem text="Услуги" name="services">
<menuitem text="Ссылки" name="links">
<menuitem text="О компании" name="about">
</menu>

Вызывая теперь тэг <menu> из VHTML-страниц, мы всегда сможем сформировать меню с выделенным отсутствием ссылки активным элементом:

<menu activeitem="products">
<menu activeitem="about">

 
· Пример 7. "Инфоблоки", "сепараторы" и прочие однотипные элементы

Описание структурных единиц страниц сайта - информационных блоков, различного рода разделителей ("сепараторов"), элементов дизайна и т.п. - это, наряду с описанием "колонтитулов" и меню, самое естественное применение модуля VITRAGE.

Под "инфоблоком" будем понимать совокупность данных (текста, графики), "облаченных" в единообразный внешний вид, например, в импровизированное "окно с заголовком".

Если на страницах сайта предполагается активное использование таких визуальных элементов, имеет смысл описывать их соответствующими тэгами (при этом следует заранее определить, какие атрибуты стоит передавать тэгам; в примере мы передаем заголовок "инфоблока", его цвет, а также цвета рамки и внутренней части "окна"):

<block title="" color=#000000 titlecolor=#ffffff blockcolor=#ffffff>
<table width=100% border=0 cellpadding=2 cellspacing=0 bgcolor=$color$>
<tr><td align=center>
<font color=$titlecolor$>$title$</font>
</td></tr>
<tr><td><table width=100% border=0 cellpadding=4 cellspacing=0 bgcolor=$blockcolor$>
<tr><td><div align=justify>
</block>

</block>
</div></td></tr>
</table></td></tr>
</table>
<//block>

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

<block title="Продукция номер 1" color=#008080 titlecolor=#d0d0d0>
<p>Здесь вы можете прочесть про продукцию номер 1.
<p><image src="product1.jpg" width=260 height=220>
<p>Выше приведена ее фотография.
</block>

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

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

<separator height=1 color=#ff0000>
<table width=100% border=0 cellpadding=0 cellspacing=0 bgcolor=$color$>
<tr><td><dot height=$height$></td></tr>
</table>
</separator>

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

· Пример 8. Практичная организация форм и их обработка

С точки зрения HTML-кода многие формы (формы "обратной связи", формы заказа и т.п.) очень похожи между собой. В данном примере мы покажем, как при помощи VITRAGE значительно упростить создание форм в VHTML-страницах. Кроме этого, мы покажем любопытный прием оповещения пользователя об успешной или неудачной обработке заполненной им формы.

Сначала опишем набор тэгов, необходимый для быстрой и практичной организации форм. Мы последовательно опишем тэги, необходимые для создания таких элементов форм, как hidden, text, textarea, checkbox, а также тэги <eform> и </eform> для начала и окончания описания формы. Тэг <eform> дополнительно будет осуществлять инициализацию необходимых переменных, а тэг </eform> будет содержать код кнопки submit и определение нескольких служебных переменных, которые в виде hidden будут передаваться скрипту, обрабатывающему данные формы. Итак:

<eformcustom name="" add="">
<%vitrage% eformitems=0 %noparse%="$eformitems$">
<%inc% var=eformitems>
<tr>
<td align=right$add$>$name$<%echo% str=":" %parse%="$name$">&nbsp;</td>
<td align=left><input type=hidden name="d$eformitems$" value="$name$">
</eformcustom>

</eformcustom>
</td>
</tr>
<//eformcustom>

<eformhidden name="" value="">
<eformcustom name="$name$">
<input type=hidden name="v$eformitems$" value="$value$">
</eformcustom>
</eformhidden>

<eformtext name="" value="" size=28 maxlength=250>
<eformcustom name="$name$">
<input type=text name="v$eformitems$" size=$size$ maxlength=$maxlength$ value="$value$">
</eformcustom>
</eformtext>

<eformtextarea name="" value="" cols=27 rows=6>
<eformcustom name="$name$" add=" valign=top">
<textarea name="v$eformitems$" cols=$cols$ rows=$rows$></textarea>
</eformcustom>
</eformtextarea>

<eformcheckbox name="" value="" checked="">
<%vitrage% add=" checked" %parse%="$checked$">
<%vitrage% add="" %noparse%="$checked$">
<eformcustom name="$name$">
<input type=checkbox name=v$eformitems$ value="$value$"$add$> $value$
</eformcustom>
</eformcheckbox>

<eform action="" name="" email="" descr="">
<%vitrage% add=" name=$%quot%$$name$$%quot%$" %parse%="$name$">
<%vitrage% add="" %noparse%="$name$">
<%vitrage% eformmail="$email$" eformitems="" eformdescr="$descr$">
<form$add$ action="$action$" method=post>
<table border=0 cellpadding=2 cellspacing=0>
</eform>

</eform submit="Отправить">
<%vitrage% add=" colspan=2" %parse%="$eformitems$">
<%vitrage% add="" %noparse%="$eformitems$">
<tr><td$add$ align=right>
<input type=hidden name="email" value="$eformmail$">
<input type=hidden name="descr" value="$eformdescr$">
<input type=hidden name="host" value="$%host%$">
<input type=hidden name="fb" value="$%uri%$">
<input type=submit value="$submit$">
</td></tr>
</table>
</form>
<//eform>

Позволим себе привести некоторые комментарии. Атрибуты, принимаемые тэгами <eformhidden>, <eformtext>, <eformtextarea>, <eformcheckbox> очевидны - это значения по умолчанию (value), размеры (size, rows, cols, maxlength), краткие текстовые описания (name) и атрибуты состояния (checked). Значения по умолчанию для них следует задавать в зависимости конкретных нужд, определяемых для каждого сайта индивидуально.

Тэг <eform> принимает в качестве атрибутов имя формы (name), ее краткое описание (descr), адрес скрипта-обработчика (action) и адрес электронной почты, на который будут высланы вводимые с помощью формы данные (email).

Тэг </eform> содержит один атрибут, определяющий текстовую надпись на кнопке подтверждения ввода информации (submit).

Данные формы будут передаваться в скрипт парами переменных - d1 и v1, d2 и v2 и т.д. до dN и vN, где N - общее количество элементов формы. Эти переменные содержат краткие текстовые описания элементов и данные, передаваемые с их помощью.

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

Теперь мы можем легко формировать необходимые нам формы в VHTML-страницах:

<eform action="/forms/feedback.php3" name="fbForm" email="elk@elk.ru" descr="Обратная связь">
<eformtext name="Ваше имя" size=36>
<eformtext name="Компания" size=36>
<eformtext name="Адрес" size=36>
<eformtext name="Телефон, факс" size=36>
<eformtext name="E-mail" size=36>
<eformcheckbox name="Наш ответ" value="мы должны вам ответить" checked="1">
<eformtextarea name="Текст сообщения" cols=35 rows=6>
</eform>

Или, например:

<eform action="/forms/order.php3" name="orderForm" email="elk@elk.ru" descr="Заказ продукции">
<eformtext name="Ваше имя" value="(ваше ФИО)">
<eformtext name="Компания" value="(ваша компания)">
<eformtext name="E-mail">
<eformtext name="Телефон, факс">
<eformtext name="Продукция" value="Карбид кальция">
<eformtext name="Спецификации">
<eformtext name="Количество">
<eformtext name="Пункт назначения" value="(порт или ж/д станция)">
<eformtext name="Условия поставки">
<eformtext name="Дата отправки" value="(1-2-6-12 мес.)">
<eformtext name="Упаковка" value="(навалом, мешки, контейнеры и т.п.)">
<eformtext name="Способ оплаты" value="(предоплата, аккредитив и т.п.)">
<eformtextarea name="Дополнительная информация">
</eform submit="Заказать">

После того, как пользователь заполнит сформированную таким образом форму, его данные должны быть обработаны скриптом, написанным на одном из подходящих языков (например, на PHP или Perl). В скрипте необходимо будет поочередно рассматривать пары переменных d1 и v1, d2 и v2 и т.д. до тех пор, пока такие переменные будут существовать. После придания информации нужного вида (например, вида "описание: значение") данные можно переслать по электронной почте на адрес, хранимый в переменной email, сопроводив письмо комментарием descr.

После выполнения этих действий автор предлагает следующую схему действий. Скрипт, обрабатывающий данные формы, должен перенаправить пользователя обратно, на ту страницу, с которой было осуществлено отправление, воспользовавшись для этого переменными host и fb, в которых были переданы адрес хоста и адрес страницы соответственно. Кроме этого следует передать этой странице в качестве параметров сведения о том, что произошла обработка формы и, если это необходимо, сведения об ошибке. Автор рекомендует воспользоваться для этого параметрами fb (fb=1 - форма была обработана) и fe (fb=1&fe=1 - форма была обработана, произошла ошибка). На языке PHP, например, это можно осуществить так:

<?
$location = "http://$host/$fb";
if ($error) Header("Location: $location?fb=1&fe=1");
else Header("Location: $location?fb=1");
exit;
?>

В VHTML-страницу же должен быть включен код, который обработает эти переменные и оповестит пользователя о случившемся. Этот код может быть таким:

1. Описание тэга, который будет выполняться, если существует переменная fb (этот тэг сгенерирует необходимое сообщения в зависимости от значения переменной fe):

<initbodyadd>
<%vitrage% bodyadd=" onLoad=$%quot%$alert('Ваша информация отправлена. Спасибо.');$%quot%$" %noparse%="$fe$">
<%vitrage% bodyadd=" onLoad=$%quot%$alert('Произошла ошибка, ваша информация не отравлена. Извините.');$%quot%$" %parse%="$fe$">
</initbodyadd>

2. Вызов по мере необходимости описанного выше тэга:

<%setifnot% var1=fb var2=fe>
<%vitrage% bodyadd="">
<initbodyadd %parse%="$fb$">

3. Значением переменной bodyadd дополним тэг <body>, например:

<body bgcolor=#ffffff text=#000000 link=#0000ff alink=#ff0000 vlink=#000080$bodyadd$>

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

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

· Пример 9. Случайные операции

При создании одного из сайтов перед автором модуля возникла следующая задача. "Шапка" сайта формировалась из трех изображений, для каждого из которых существовало три варианта. Эти файлы имели имена 1_1.gif, 1_2.gif, 1_3.gif, 2_1.gif, 2_2.gif, 2_3.gif, 3_1.gif, 3_2.gif и 3_3.gif (первое число в названии - номер изображения, второе - номер варианта). Необходимо было сформировать "шапку" таким образом, чтобы в ней присутствовали три разных изображения, соответствующие трем разным вариантам. Например, набор изображений 1_2.gif, 2_3.gif и 3_1.gif будет допустимым, а набор 1_3.gif, 2_2.gif и 3_3.gif - нет (в наборе присутствуют два файла третьего варианта).

Для решения этой задачи используется возможность работы VITRAGE со случайными операциями, декларируемыми атрибутом %random%.

"Зафиксируем" первые числа имен файлов, то есть будем считать заранее, что файлы в наборе называются 1_?.gif, 2_?.gif, 3_?.gif. Очевидно, что для решения задачи теперь следует лишь получить случайную комбинацию из трех чисел - 1, 2 и 3, которые "дополнят" искомые имена файлов. Допустим, что номера вариантов для трех файлов должны содержаться соответственно в переменных var1, var2 и var3.

Прежде всего, случайным образом определим, какому из файлов будет соответствовать вариант 1, предварительно проинициализировав переменные:

<%vitrage% var1="" var2="" var3="">
<%vitrage% var1=1 var2=1 var3=1 %random%=1>

В результате этих операций одна из переменных var1, var2, var3 примет значение "1", другие же переменные будут иметь значения пустых строк.

Вторым шагом присвоим значение "2" одной из оставшихся переменных. Для определения, какая из переменных уже имеет значение "1", воспользуемся атрибутом условия %parse%:

<%copy% temp1=var1 temp2=var2 temp3=var3>
<%vitrage% var1=2 var2=2 %random%=1 %parse%="$temp3$">
<%vitrage% var1=2 var3=2 %random%=1 %parse%="$temp2$">
<%vitrage% var2=2 var3=2 %random%=1 %parse%="$temp1$">

Мы не можем использовать в качестве условий значения самих переменных var1, var2 и var3, потому что, если условие будет истинным, например, в первом тэге <%vitrage%>, изменится значение одной из двух оставшихся переменных, что повлечет за собой неверное исполнение одного из следующих тэгов.

И, наконец, похожим способом присвоим оставшейся переменной значение "3":

<%vitrage% var1=3 %noparse%="$var1$">
<%vitrage% var2=3 %noparse%="$var2$">
<%vitrage% var3=3 %noparse%="$var3$">

Теперь у нас нет необходимости использовать дополнительные переменные, поскольку при любом выполнении тэгов значение "3" будет присвоено только той переменной, которая до сих пор имела значение "" (пустая строка).

Задача можно решить и с использованием датчика случайных чисел (атрибута %rand%), но в данном случае для организации логики придется описывать дополнительные тэги. Идею этого решения рассмотрим на примере двух файлов и двух вариантов (соответственно, необходимо распределить значения "1" и "2" между переменными var1 и var2).

Итак, описываем новые тэги:

<set1><%vitrage% var2=2></set1>
<set2><%vitrage% var2=1></set2>

и используем один из них после определения варианта для первого файла:

<%vitrage% %rand%=2><%vitrage% var1=$%rand%$><set$var1$>

Начиная с версии VITRAGE 1.20, исходную задачу очень легко можно решить при помощи встроенного атрибута %shuffle%:

<%vitrage% var1=1 var2=2 var3=3 %shuffle%=1>

Задача решена "в один ход". Именно это решение является рекомендуемым для тех, кто использует модуль VITRAGE версии 1.20 и выше.

Не исключены и другие решения (например, случайный выбор из полного набора комбинаций или решение с привлечением Primitive). Вообще говоря, многие практические задачи можно решить с помощью VITRAGE несколькими корректными способами.
 

· Пример 10. Циклы

Часто действия по формированию разного рода меню, списков и т.п. целесообразно выполнять с использованием циклов, предварительно пронумеровав каким-либо образом соответствующие объекты. Допустим, нам необходимо выполнить следующую последовательность действий:

  • в "шапке" сайта отобразить пять изображений с именами image1.gif, image3.gif, image5.gif, image7.gif, image9.gif;
  • в нижней части сайта отобразить пять изображений с именами image2.gif, image4.gif, image6.gif, image8.gif, image10.gif;
  • каждому из изображений поставить в соответствие комментарий, задаваемый переменной altN, где N - номер изображения;
  • сформировать список из комментариев, расположенных в обратном порядке (т.е. с 10 по 1).

Прежде чем показать решение задачи, отметим, что переменные alt1, alt2 и т.д. удобно задавать при инициализации сайта, например, в тэге <init>, как это было предложено в примере 3.

Решаться же поставленная задача будет описанием следующих тэгов:

<image>
<%copy% alt="alt$id$">
<img src="image$id$.gif" alt="$alt$" border=0>
</image>

<imageTop>
<%primitive% s="$%times%$ 2 * 1 - %id in">
<image>
</imageTop>

<imageBottom>
<%primitive% s="$%times%$ 2 * %id in">
<image>
</imageBottom>

<altList>
<li><%var% v="alt$%btimes%$">
</altList>

и последовательным их вызовом:

<imageTop %times%=5>
<ul>
<altList %times%=10>
</ul>
<imageBottom %times%=5>

Обратим особое внимание на использование в описании тэга <altList> переменной %btimes% - именно она обеспечивает обратный порядок расположения комментариев в формируемом списке.

Последовательности операторов Primitive, очевидно, вычисляют нужный номер изображения (и описания) на основе переменной цикла %times%, а тэг <image> введен просто для удобства и сокращения записей. Тэг <image> использует значение глобальной переменной id, вычисляемое в тэгах <imageTop> и <imageBottom>, и именно в связи с глобальностью этой переменной ее можно не передавать тэгу <image> с использованием атрибута.

Отметим также примененный прием получения значений переменных, имя которых само содержит переменные: это сделано при помощи тэга <%copy%>.
 

· Пример 11. "Ленты" данных, текущее время и связанные с этим тонкости

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

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

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

Для организации такой схемы в модуле VITRAGE предусмотрены встроенные тэги, выбор среди которых следует осуществлять исходя из цели включения и вида подключаемого файла данных. Самой простой способ - подключение при помощи тэга <%file%>:

<%file% name="include/news.html">

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

Если подключаемый файл содержит VHTML-код и логически является частью формируемой страницы, следует использовать тэг <%require%>:

<%require% name="include/products.vhtml">

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

При использовании тэга <%require%> следует помнить, что указанный файл будет подключен только после окончания обработки текущей строки подключающего VHTML-файла. В связи с этим во избежание трудностей восприятия не рекомендуется использовать <%require%> в описаниях новых тэгов. Логичнее всего, если тэг <%require%> будет последним тэгом в строке подключающего VHTML-файла.

В том случае, если в подключаемом файле необходимо запретить замену глобальных переменных их значениями (такая необходимость может возникнуть, если доступ к файлу имеет редактор, который может случайно или преднамеренно использовать отображение глобальных переменных в незапланированных целях), следует пользоваться парой встроенных тэгов <%novarse%> и <%varse%>:

<%novarse%><%require% name="include/products.vhtml">
<%varse%>

И, наконец, в тех случаях, когда нам необходимо подключать VHTML-файл, но уже обработанный (то есть включать в одну страницу результат обработки другого VHTML-файла), мы можем воспользоваться тэгом <%include%>:

<%include% name="include/products.vhtml">

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

При необходимости возможна передача данных подключаемым с помощью тэга <%include%> файлам через так называемые параметры:

<%include% name="include/news.vhtml?b=1&e=10">

Используя такой метод (он называется "метод GET"), мы можем передать файлу любые данные, которые будут доступны в виде глобальных переменных (в приведенном выше примере в файле news.vhtml мы сможем оперировать переменными b и e). Но следует знать, что формируемый подобным образом URL необходимо кодировать согласно RFC 1738. В данном случае достаточно воспользоваться тэгом <%rawchars%> для передаваемых данных:

<%vitrage% name="Модуль VITRAGE" ver="версия 1.10">
<%rawchars% var1=name var2=ver>
<%include% file="include/file.vhtml?name=$name$&ver=$ver$">

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

<p><b>21.05&nbsp;14:07</b> Новость 12
<p><b>21.05&nbsp;14:05</b> Новость 11
<p><b>21.05&nbsp;13:35</b> Новость 10

Или, если используются описанные в файле vitrage тэги:

<прайс>Продукция 1<описание стандарт="ГОСТ 11066-74" оптовая="договорная" экспортная="10,10"></прайс>
<прайс>Продукция 2<описание стандарт="ТУ 6-02-01-030-91" оптовая="договорная" экспортная="310,25"></прайс>
<прайс>Продукция 3<описание стандарт="ТУ 6-02-709-76" оптовая="договорная" экспортная="120,20"></прайс>
<прайс>Продукция 4<описание стандарт="ГОСТ 26371-84" оптовая="4500,00" экспортная="4512,00"></прайс>

Такое расположение данных позволяет упростить их изменение и дополнение с использованием, в том числе, специально созданных для этого средств. Одним из подобных редакторов однотипных данных, записанных построчно, является VITRAGEd, разработанный автором модуля специально для разнообразных "лент". Этот онлайновый редактор (работа с ним осуществляется непосредственно через веб-интерфейс) вместе с документацией доступен для свободной загрузки на сайте модуля VITRAGE.

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

<!-- Powered by SibWeb's VITRAGE 1.10 -->

Если пользоваться для включения одних VHTML-файлов в другие тэгом <%include%> (то есть тэгом, включающем не сам VHTML-файл, а результат его обработки модулем), такие сведения, очевидно, будут сопровождать каждое включение каждого VHTML-файла. Чтобы избежать этой ситуации, мы можем запретить модулю VITRAGE добавление в конец обработанного им VHTML-файла сведений о своей версии посредством определения глобальной переменной NoPoweredBy:

<%vitrage% NoPoweredBy=1>

Сопутствующей задачей подключения "лент" изменяемых данных является отображение текущей даты и текущего времени. VITRAGE предлагает для этой цели встроенную переменную %time%, которой может быть присвоено значение текущего времени согласно выбранному шаблону. Более подробно принципы формирования шаблонов даты и времени приведены в соответствующем разделе данного руководства, здесь же приведем несколько наиболее распространенных форм. Например, текущее время вида "12:34" можно получить при помощи следующего шаблона:

<%vitrage% %time%="%H:%M">

Текущая дата вида "12.01.2002" формируется следующим образом:

<%vitrage% %time%="%d.%m.%Y">

Если же нам нужна форма "Сегодня 12/01/02, текущее время 12:34", нам следует задать шаблон так:

<%vitrage% %time%="Сегодня %d/%m/%y, текущее время %H:%M">

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

VGCache Off

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

· Пример 12. Подключение внешних скриптов и передача им данных

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

Один подход вполне очевиден: создать большую часть страниц при помощи VITRAGE, а оставшуюся - ту, в которой требуются более сложные действия, - при помощи, например, PHP или Perl. К плюсам такого подхода следует отнести его необычайную простоту, к минусам же - необходимость повторения всех элементов навигации, блоков и т.д. дважды: для VITRAGE и для "стороннего" средства.

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

Второй подход - это включение внешнего по отношению к VHTML-файлу скрипта непосредственно в VHTML-страницу с использованием тэга <%include%>.

Допустим, что на странице нам необходимо отобразить число секунд, оставшихся до заданного момента времени в будущем. Эту задачу легко решает следующий PHP-скрипт:

<?
if (IsSet($ts)) $ts = intval($ts);
else $ts = time();
$y = 2000; $nr = 0;
do {
$y++; $nr++;
$left = mktime(15, 30, 0, 9, 21, $y) - $ts;
} while ($left < 0);
echo "Сейчас " . date("H:i:s d/m/Y", $ts) . "<br>\n";
if ($left > 0) {
echo "До $nr-й годовщины осталось $left сек. Это примерно:<br>\n";
echo "<b>&middot;&nbsp;</b>" . intval($left / 60) . " мин.<br>\n";
echo "<b>&middot;&nbsp;</b>" . intval($left / 3600) . " час.<br>\n";
echo "<b>&middot;&nbsp;</b>" . intval($left / 86400) . " сут.<br>\n";
}
?>

Сам же скрипт (точнее, результат его работы) мы подключим в VHTML-файл следующим образом:

<%include% file="scripts/time.php">

Если мы желаем передать сведения о текущем времени PHP-скрипту из VHTML-файла, мы можем осуществить это с использованием встроенной переменной %timestamp%:

<%include% file="scripts/time.php?ts=$%timestamp%$">

Используя такой метод (он, как мы помним, называется "метод GET"), мы можем передать скрипту любые данные. Но, как и в предыдущем примере, не следует забывать о необходимости кодирования URL согласно RFC 1738 с помощью тэга <%rawchars%>:

<%vitrage% name="Модуль VITRAGE" %time%="%d/%m/%Y">
<%rawchars% var1=name var2=%time%>
<%include% file="scripts/data.php?name=$name$&time=$%time%$">

Из-за того, что, вероятнее всего, страницы, использующие внешние скрипты, являются динамическими (оперируют данными, изменяющимися с течением времени), рекомендуется принудительно отключать кэширование для каталогов, содержащих такие страницы (ключевым словом VGCache в файле .htaccess):

VGCache Off

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

· Пример 13. Несколько приемов работы с файлами

Начиная с версии 1.16, модуль VITRAGE получил возможность работы с файлами. Рассмотрим в рамках данного примера следующие задачи:

  • построчное копирование одного файла в другой;
  • отображение исходного кода VHTML-файла;
  • отображение размера и даты модификации выбранного файла.

Первую задачу успешно решает следующий набор тэгов:

<filecopyline destination="">
<%copy% line="file%$%times%$">
<%append% "$destination$"="$line$">
</filecopyline>

<filecopy source="" destination="">
<%read% file="$source$">
<%write% "$destination$"="" %parse%="$file$">
<filecopyline destination="$destination$" %times%="$file$">
</filecopy>

Теперь, вызывая тэг <filecopy> следующим образом:

<filecopy source="index.vhtml" destination="index.copy">

мы получим точную копию файла index.vhtml в файле index.copy. Обратим внимание на то, что у текущего каталога должны быть установлены права, позволяющие пользователю, от имени которого запускается веб-сервер Apache, создавать файлы.

Команда

<%write% "$destination$"="" %parse%="$file$">

в тэге <filecopy> создаст новый файл, если он еще не существует, или "обнулит" уже существующий файл. Заметим, что этот тэг будет выполнен только в том случае, если исходный файл был успешно прочтен и содержал хотя бы одну строку.

Изменив в тэге <filecopyline> %times% на %btimes%, мы получим копию файла, в котором строки будут расположены в обратном порядке.

Задача отображения исходного кода VHTML-страницы аналогична предыдущей задаче с условием, что строки исходного файла не копируются в другой файл, а выводятся обычным способом. Каждая из строк предварительно должна быть обработана тэгом <%htmlcharsd%>, чтобы все специальные символы ("<", ">", "&", кавычки) заменялись соответствующими последовательностями ("&lt;", "&gt", "&amp;", "&quot;"), делая исходный код доступным для отображения в браузере. Итак:

<filesourceline>
<%htmlcharsd% line="f%$%times%$">
$line$<br>
</filesourceline>

<filesource file="">
<%readln% f="$file$">
<filesourceline %times%="$f$">
</filesource>

Вызывая из VHTML-файла тэг <filesource>:

<filesource file="index.vhtml">

мы получим отображение исходного кода файла index.vhtml.

Обратим внимание на то, что мы осуществляем чтение файла встроенным тэгом <%readln%>, который удаляет из прочтенных строк символы их завершения: это позволит нам сделать вывод строк файла более аккуратным.

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

<fileinfo file="">
<%stat% f="$file$">
<%echo% str="Файл не существует" %noparse%="$f$">
<%vitrage% %timestamp%=$f%mtime$ %parse%="$f$">
<%vitrage% %time%="%Y.%m.%d" %parse%="$f$">
<%primitive% s="%f%size out 1024 / %size in" %parse%="$f$">
<%echo% str="Дата: $%time%$; $size$&nbsp;КБ" %parse%="$f$">
</fileinfo>

Никаких "особых хитростей" в описании данного тэга нет: для определения, существует файл или нет, многократно используется значение переменной f, определенной встроенным тэгом <%stat%>, а пересчет байтов в килобайты выполняет простая последовательность операторов Primitive.
 

· Пример 14. "Бесконечный копирайт"

Многие разработчики помещают в исходный код HTML-страницы в качестве комментария сведения о себе, обычно выглядящие следующим образом:

<!-- Copyright (с) 2001-2002 SibWeb -->

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

<copyright year="2001">
<%vitrage% %time%="%Y">
<%vitrage% current="-$%time%$">
<%emptyd% current="-$year$">
$%lt%$!-- Copyright $year$$current$ (c) SibWeb --$%gt%$
</copyright>

Указывая в качестве значения атрибута year текущий год, мы получим надпись

<!-- Copyright (с) 2002 SibWeb -->

В том случае, если текущий год не совпадает с первым, в надписи будет отображен интервал, например:

<!-- Copyright (с) 2001-2002 SibWeb -->

 
· Заключение

Автор модуля VITRAGE искренне надеется, что созданная им технология будет полезна многим веб-разработчикам и HTML-верстальщикам.

Если вы владеете языком программирования C, вы без особого труда сможете изменять исходные тексты модуля по своему усмотрению. Например, вам будут доступны значения параметров модуля по умолчанию, наименования встроенных тэгов и переменных, установка зависимости данных (имен тэгов и переменных, а также операторов Primitive) от регистра, режим "отладки" и т.п. Если вы вносите в текст модуля значительные принципиальные изменения, не сочтите за труд переслать вашу версию VITRAGE автору (желательно с легкими для чтения и понимания комментариями).

Самая последняя авторская версия модуля в виде исходных текстов на языке C всегда доступна на сайте vitrage.sibweb.ru, а с автором модуля VITRAGE можно связаться по электронной почте: elk@elk.ru. Вопросы, пожелания, предложения и замечания только приветствуются.