Механика FBI.
Основные принципы
В общих чертах всё работает следующим образом. В системе висит alterator с модулями ensign (управляет бакендами) и fbi (управляет фронтендами). Доступ к alterator осуществляется через локальный UNIX-Socket. Рядом настроен http сервер и cgi в нём. При поступлении http-запроса, в cgi происходит декодирование, разбор нужных переменных среды, после чего работа передаётся alterator. Alterator выясняет по адресу к какому backend обращались, выясняет у его напарника (template-*) желаемый frontend и передаёт ему запрос. Frontend делает всё что ему требуется, в том числе запрашивает у backend нужные подробности, берёт html-шаблон, модифицирует его и отправляет ответ наверх. CGI принимает запрос, преобразует в настоящий html, подправляет по ходу урлы и отдаёт результат пользователю.
Замечание: путь / приравнивается к /index.
Каждый frontend регистрирует две функции, на обработку get и на обработку post запросов.
Данная инструкция должна быть последней в тексте frontend (по аналогии с object для бакенда).
Каждая функция принимает следующие параметры:
- url – URL по которому было произведено обращение
- url-args – параметры запроса. В случае запроса POST url-args также включают в себя данные формы. В случае наличия одинаковых параметров в строке запроса и в форме предпочтение отдаётся вторым. Их формат – список пар (параметр . значение). Парметр – строка.
- template-args – параметры переданные помощником бакенда специально для шаблона, чтобы задать специфическое повееие. Формат – список пар (параметр . значение). Параметр – символ.
Генерируем HTML
Как было сказано, результат каждой процедуры обработчика – генерация строк. В случае работы с HTML – соответственно надо сгенерировать содержимое Web-страницы.
Замечание: Все дальнейшие процедуры работают с XHTML, соответственно крайне рекомендуется проверять страницу с помощью xmllint прежде чем работать с ней дальше, fbi пока даёт не слишком вразумительный ответ в случае неправильного XML.
Замечание: cgi квотирует все строки переданные ему со стороны frontend, поэтому не пытайтесь создавать теги вручную
1. Использование функций html: и @:
Поскольку каждый раз рисовать открыающие и закрывающие теги очень не удобно, можно воспользоваться функцией html:. В качестве первого параметра передаётся имя тега, а далее передаются параметры и содержимое создаваемого контейнера. Параметры создаются с помощью фунеции @. Первый параметр этой функции – имя (символ), второй – значение (строка).
2. Использование семейства функций html:* :
Создавать html уже стало легче, но в лучших традициях Scheme для самых распространённых элементов существуют заранее подготовленные функции:
- html:input – создание строки ввода, принимает два параметра – имя и значение. Возможна передача дополнительных параметров.
- html:textarea – создание текстового поля, принимает два параметра – имя и значение. Возможна передача дополнительных параметров.
- html:select – создание поля выбора, принимает три параметра – имя, текущее значение и список возможных вариантов.
- html:a – создание гипер-ссылки, первый параметр – текст внутри ссылки, все остальные параметры склеиваются в URL, к URL автоматически добавляется в начале путь к скрипту, поэтому для создания гиперссылок лучше всего именно этой функцией, а ручное создание оставить на исключительные ситуации.
- html:tr – создание «строки» в таблицы. Каждый из принятых параметров автоматически огружается тегами td. Например (html:tr “a” “b”) равносильно строке "<tr><td>a</td><td>b</td></tr>".
Замечание: На этом количестве функций можно не останавливаться. Если будут какие пожелания – заказывайте.
3. Использование html-шаблонов.
Даже при наличии большого количества функций высокого уровня рисовать html не так удобно. Остаётся ещё масса тегов которые приходится таскать с собой «в нагрузку». Кроме того, давайте дадим поработать дизайнеру (или программе nvu). Загрузка готовго html-шаблона происходит командой template.
Если файл менять не надо, то на этом можно и остановиться, но так бывает крайне редко. Зачастую требуется заполнить форму реальными данными или вообще пересоздать её в зависимости от требований пользователя. Говоря языком разработчика – требуется «наложить заплатку» (patch) на html-файл. Для указания тега с которым надо провести дополнительную работу используется команда *tag:*, первый обязательный параметр команды – имя тега.
В примере выше будет произведена замена содержимого внутри всех тегов p. Если требуется уточнить теги с какими параметрами должны подлежать обработке, то эти параметры указываются в привычном уже синтаксисе:
В этом примере будет произведена содержимого внутри тегов div с атрибутом ' class="a" ' на слово “class a”, а содержимое тегов div с атрибутом ' class="b” subclass="c” ' станет «class b/c”.
Возможно не только замена содержимого тегов, особые виды операций указываются в виде параметра 'template-operation. Возможны варианты: replace-content (по-умолчанию), append-content (добавить новое содержимое), replace-tag (заменить весь блок отмеченный данным тегом на что-то новое).
В этом примере теги div с классом “will-be-replaced” будут заменены на теги p с содержимым new-content, а в таблицу будет добавлена новая строчка. Но на этом возможности по изменению не заканчиваются. В качестве нового содержимого можно указать процедуру принимающую два параметра options и content, тогда в случае нахождения требуемого тега, процедура исполнится с options, равным полному набору атрибутов найденого тега и content, содержащим внутреннее содержимое тега в виде s-выражения. Таким образом можно например делать custom теги управляемые параметрами.
В этом примере все теги custom будут заменены параграфом содержащим перечисление их атрибутов. При желании процедуры можно свободно перемешивать с обычным содержимым.
Интернационализация
Браузеры могут сообщать свой предпочитаемый язык. Можно этим воспользоваться и сделать многоязычные интерфейсы. Делается это следующим образом.
1. Отмечаем интересующие фрагменты текста тегами span с параметром translate “_". Значение параметра translated – просто некоторое ключевое слово. Задавая разные ключевые слова можно забирать переводы фраз из разных словарей.
2. Поскольку xgettext не умеет вытаскивать переводы, то пользуемся утилиткой alterator-xgettext в комбинации с обычными xgettext.
3. В месте использования template добавляем инструкции для перевода translate-tag:, первый параметр – ключевое слово, второй параметр – имя словаря.
Замечание: если захочется ещё чего-то странного – пишите, заказывайте.