четверг, 1 января 2009 г.

Создание html на языке tcl

Небольшая библиотечка для создания html-документов. Использую в AOL web server. Простейшая страничка выглядит так:

<%
html ! {
head ! {
title - {Главная страница}
}
body ! {
menu
path mainpage
h3 - {Минимальная страница}
copyright
}
}
%>



############# Тэги #############
# шаблон для генерации стандартного html-тэга
proc mbg_tag {name args} {
array set opts $args
ns_adp_puts -nonewline "<$name"
foreach {argname argvalue} [array get opts] {
if {$argname ne "!" && $argname ne "-"} {ns_adp_puts -nonewline " [string range $argname 1 end]='$argvalue'"}
}
ns_adp_puts -nonewline ">"
if [info exists opts(!)] {uplevel 1 $opts(!)}
if [info exists opts(-)] {ns_adp_puts -nonewline $opts(-) }
ns_adp_puts -nonewline "</$name>"
}
# создаем нужные нам тэги
foreach name {meta title body form fieldset table thead tfoot tbody tr td th acronym textarea center pre a font button div span ul li select b i u s p h1 h2 h3 h4 h5 h6 br hr img} {
proc $name args {
set name [lindex [info level 0] 0]
uplevel 1 mbg_tag $name $args
}
}

# тэги, которые не могут быть созданы по стандартному шаблону, определяются в секции виджеты
############# Виджеты #############
proc html {args} {
ns_adp_puts {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xml:lang="ru-RU" lang="ru-RU" xmlns="http://www.w3.org/1999/xhtml">}
array set opts $args
ns_adp_puts -nonewline <html>
if [info exists opts(!)] {uplevel 1 $opts(!)}
if [info exists opts(-)] {ns_adp_puts -nonewline $opts(-) }
ns_adp_puts -nonewline </html>
}
# нестандартный тэг
proc option {args} {
set name [lindex [info level 0] 0]
array set opts $args

# равно по значению ключа
if {[info exists opts(=)] && [info exists opts(-value)] && $opts(=) eq $opts(-value)} {
set opts(-selected) {selected}
}
# равно по отображаемому значению
if {[info exists opts(~)] && [info exists opts(-)] && $opts(~) eq $opts(-)} {
set opts(-selected) {selected}
}

ns_adp_puts -nonewline "<$name"
foreach {argname argvalue} [array get opts] {
if {$argname ne "~" && $argname ne "=" && $argname ne "!" && $argname ne "-"} {ns_adp_puts -nonewline " [string range $argname 1 end]='$argvalue'"}
}
ns_adp_puts -nonewline ">"
if [info exists opts(!)] {uplevel 1 $opts(!)}
if [info exists opts(-)] {ns_adp_puts -nonewline $opts(-) }
ns_adp_puts -nonewline "</$name>"
}


proc script {args} {
set name [lindex [info level 0] 0]
array set opts $args

if {![info exists opts(-type)]} {set opts(-type) {text/javascript}}

ns_adp_puts -nonewline "<$name"
foreach {argname argvalue} [array get opts] {
if {$argname ne "!" && $argname ne "-"} {ns_adp_puts -nonewline " [string range $argname 1 end]='$argvalue'"}
}
ns_adp_puts -nonewline ">"
if [info exists opts(!)] {uplevel 1 $opts(!)}
if [info exists opts(-)] {ns_adp_puts -nonewline $opts(-) }
ns_adp_puts -nonewline "</$name>"
}

# нестандартный тэг
proc input {args} {
set name [lindex [info level 0] 0]
array set opts $args
if {[info exists opts(=)] && [info exists opts(-value)] && $opts(=) eq $opts(-value)} {
set opts(-checked) 1
}
ns_adp_puts -nonewline "<$name"
foreach {argname argvalue} [array get opts] {
ns_adp_puts -nonewline " [string range $argname 1 end]='$argvalue'"
}
ns_adp_puts -nonewline "/>"
}


Элементы menu, path и другие определяются по усмотрению разработчика.

Upd.

В настоящее время в AOL Server использую следующую реализацию для стандартных тэгов.


############################################
# Copyright 2009, Mobile Business Group
############################################

# создаем ансамбль для каждого нового потока (единожды)
ns_ictl trace create {
namespace eval ::ns_html:: {
namespace ensemble create
}
}

namespace eval ::ns_html:: {
namespace export *
# для этой функции можно прозрачно реализовать кэширование
proc puts {args} {
global _ns_html_buffer
if {[info exists _ns_html_buffer] == 1} {
append _ns_html_buffer {*}$args
} else {
ns_adp_append {*}$args
}
#ns_adp_puts {*}$args
}
}

# шаблон для генерации стандартного html-тэга
proc ::ns_html::tag {name args} {
set name [string range $name [string last : $name]+1 end]

array set opts $args
# чтобы не указывать каждый раз и name и id.
if { [info exists opts(-id)] && ![info exists opts(-name)] } {
set opts(-name) $opts(-id)
}
if { [info exists opts(-name)] && ![info exists opts(-id)] } {
set opts(-id) $opts(-name)
}
ns_html::puts "<$name"
foreach {argname argvalue} [array get opts] {
if {$argname ne "!" && $argname ne "-"} {
ns_html::puts " [string range $argname 1 end]='$argvalue'"
}
}
ns_html::puts ">"
if [info exists opts(!)] {
uplevel 1 $opts(!)
}
if [info exists opts(-)] {
ns_html::puts $opts(-)
}
ns_html::puts "" \n
}

# стандартные тэги без проверки атрибутов
# включены тэги предварительной спецификации HTML5, тэги center, font, strike are deprecated!
# некоторые из этих тэгов могут быть переопределены
foreach name {html meta title body head style link
script form fieldset select textarea input option
table thead tfoot tbody tr td th
center a font button div span p img label
ol ul li
b i u s
h1 h2 h3 h4 h5 h6
br hr
var code kbd tt samp pre acronym
section header footer nav article canvas
aside figure dialog dd dt
m mark time meter progress
video audio
details datagrid menu command} {
proc ::ns_html::$name args {
set name [lindex [info level 0] 0]
uplevel 1 ns_html::tag $name $args
}
}

Комментариев нет:


(C) Alexey Pechnikov aka MBG, mobigroup.ru