Common Lisp的人有CL-WHO,这使得HTML模板与“主”语言集成在一起,从而使任务更容易。对于那些不了解CL-WHO的人,它看起来像这样(例如来自CL-WHO的网页):
(with-html-output (*http-stream*)
(:table :border 0 :cellpadding 4
(loop for i below 25 by 5
do (htm
(:tr :align "right"
(loop for j from i below (+ i 5)
do (htm
(:td :bgcolor (if (oddp j)
"pink"
"green")
(fmt "~@R" (1+ j))))))))))
你知道其他语言的这样的图书馆吗?我所知道的(模仿CL-WHO)对于Python来说是Brevé。我对Perl风格特别感兴趣,但有趣的是其他语言如何处理将HTML集成到它们的语法中。
答案 0 :(得分:12)
对于CPAN产品,请查看以下内容(按字母顺序排列)......
使用提供的CL-WHO示例的表格部分(减去罗马数字和s / background-color / color /将代码压缩到屏幕宽度!)....
use Builder;
my $builder = Builder->new;
my $h = $builder->block( 'Builder::XML' );
$h->table( { border => 0, cellpadding => 4 }, sub {
for ( my $i = 1; $i < 25; $i += 5 ) {
$h->tr( { align => 'right' }, sub {
for my $j (0..4) {
$h->td( { color => $j % 2 ? 'pink' : 'green' }, $i + $j );
}
});
}
});
say $builder->render;
use HTML::AsSubs;
my $td = sub {
my $i = shift;
return map {
td( { color => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
} 0..4;
};
say table( { border => 0, cellpadding => 4 },
map {
&tr( { align => 'right' }, $td->( $_ ) )
} loop( below => 25, by => 5 )
)->as_HTML;
use HTML::Tiny;
my $h = HTML::Tiny->new;
my $td = sub {
my $i = shift;
return map {
$h->td( { 'color' => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
} 0..4;
};
say $h->table(
{ border => 0, cellpadding => 4 },
[
map {
$h->tr( { align => 'right' }, [ $td->( $_ ) ] )
} loop( below => 25, by => 5 )
]
);
use Markapl;
template 'MyTable' => sub {
table ( border => 0, cellpadding => 4 ) {
for ( my $i = 1; $i < 25; $i += 5 ) {
row ( align => 'right' ) {
for my $j ( 0.. 4 ) {
td ( color => $j % 2 ? 'pink' : 'green' ) { $i + $j }
}
}
}
}
};
print main->render( 'MyTable' );
package MyTemplates;
use Template::Declare::Tags;
use base 'Template::Declare';
template 'MyTable' => sub {
table {
attr { border => 0, cellpadding => 4 };
for ( my $i = 1; $i < 25; $i += 5 ) {
row {
attr { align => 'right' };
for my $j ( 0..4 ) {
cell {
attr { color => $j % 2 ? 'pink' : 'green' }
outs $i + $j;
}
}
}
}
}
};
package main;
use Template::Declare;
Template::Declare->init( roots => ['MyTemplates'] );
print Template::Declare->show( 'MyTable' );
use XML::Generator;
my $x = XML::Generator->new( pretty => 2 );
my $td = sub {
my $i = shift;
return map {
$x->td( { 'color' => $_ % 2 ? 'pink' : 'green' }, $i + $_ )
} 0..4;
};
say $x->table(
{ border => 0, cellpadding => 4 },
map {
$x->tr( { align => 'right' }, $td->( $_ ) )
} loop( below => 25, by => 5 )
);
以下内容可用于在HTML :: AsSubs / HTML :: Tiny / XML :: Generator示例中生成“循环”....
sub loop {
my ( %p ) = @_;
my @list;
for ( my $i = $p{start} || 1; $i < $p{below}; $i += $p{by} ) {
push @list, $i;
}
return @list;
}
答案 1 :(得分:6)
The Perl Foundation当前授权赞助项目中的一个(lightweight web framework for Perl 6)具有provides a similar interface的工作Perl6代码:
use Tags;
say show {
html {
head { title { 'Tags Demo' } }
body {
outs "hi";
ul :id<numberlist> {
outs "A list from one to ten:";
for 1..10 {
li :class<number>, { $_ }
}
}
}
}
}
浏览或克隆github上的当前代码。
答案 2 :(得分:5)
Perl的CGI模块支持这样的东西。
use CGI ':standard';
use Lisp::Fmt
print header();
print table( { -border => 1, -cellpading => 4},
loop({ below => 25, by=> 5}, sub {
my $i = shift;
tr( {-align => 'right'} ,
loop({ from => $i, below $i + 5}, sub {
my $j = shift;
td({-bgcolor => ($oddp eq $j ? 'pink' : 'green')}
fmt("~@R", 1+$j);
})
)
});
我试图保持lispy,所以你必须自己实现一个lispy loop
函数。我没有真正编写Common List,所以我希望我能正确理解你的代码。
答案 3 :(得分:4)
有stan:一种类似s表达式的语法,用于在{python 中表达xml,来自Divmod's Nevow。我认为这是你想要的。链接教程中的一个例子:
t = T.table[
T.tr[
T.td[ "Name:" ],
T.td[ original.name ]
],
T.tr[
T.td[ "Email:" ],
T.td[T.a(href='mailto:%s' % original.email)[ original.email ] ]
],
T.tr[
T.td[ "Password:" ],
T.td[ "******" ]
],
]
答案 4 :(得分:3)
Perl的标准CGI模块可以做类似的事情:
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw/:standard/;
print
start_html("An example"),
h1(
{
-align => "left",
-class => "headerinfo",
},
'this is an example'
),
"The CGI module has functions that add HTML:",
ul( map li($_),
("start_html",
"h1, h2, h3, etc.",
"ol, ul, li",
"ol, ul, li",
"table, tr, th, td")
),
"and many more.",
end_html();
产生:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>An example</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h1 class="headerinfo" align="left">this is an example</h1>The CGI module has functions that add HTML:<ul><li>start_html</li> <li>h1, h2, h3, etc.</li> <li>ol, ul, li</li> <li>ol, ul, li</li> <li>table, tr, th, td</li></ul>and many more.
</body>
</html>
li部分可以像这样重写
print ol(map li($_), @list);
如果您有列表或数组。
答案 5 :(得分:3)
Clojure中有许多受CL-WHO启发的HTML生成库(正如人们所预料的那样,Clojure是一个Lisp)。以下是使用Compojure和cl-format附带的HTML库执行此操作的方法:
(use 'compojure.html
'com.infolace.format)
(html
[:table {:border 0 :cellpadding 4}
(map (fn [tds] [:tr {:align "right"} tds])
(partition 5 (map (fn [num color]
[:td {:bgcolor color}
(cl-format nil "~@R" (inc num))])
(range 25)
(cycle ["green" "pink"]))))])
Compojure的HTML库充分利用了Clojure的文字哈希映射作为属性/值对,并且使用文字向量代替标签而不是列表,这有助于标签突出一点,避免了对宏魔法的一些需求。 / p>
partition
将一个集合分成若干个元素组。 cycle
生成一个无限重复的集合元素列表。这些加号range
和map
可帮助您避免显式循环和计数器变量。
答案 6 :(得分:1)
Here对于JavaScript来说是这样的。它看起来如下:
T.div({ className: "content"},
T.p("Some ", T.u("paragraph")),
T.p("Another paragraph"))
答案 7 :(得分:1)
Haskell有一个HTML组合库,与CL-WHO没有什么不同。然而,懒惰的函数编程方法确实导致了与Common Lisp中的循环工具不同的惯用迭代结构:
import Data.Char
import Data.List
import Text.Html
-- from http://fawcett.blogspot.com/2007/08/roman-numerals-in-haskell.html
import RomanNumerals
-- Simple roman numeral conversion; returns "" if it cannot convert.
rom :: Int -> String
rom r = let m = toRoman r
in (map toUpper . maybe "" id) m
-- Group a list N elements at a time.
-- groupN 2 [1,2,3,4,5] == [[1,2],[3,4],[5]]
groupN n [] = []
groupN n xs = let (a, b) = splitAt n xs in a : (groupN n b)
pink = "pink" -- for convenience below; green is already covered by Text.Html
rom_table = table ! [border 0, cellpadding 4] << trs
where
-- a list of <tr> entries
trs = map (rom_tr . map rom_td) rom_array
-- generates a <tr> from a list of <td>s
rom_tr tds = tr ! [align "right"] << tds
-- generates a <td> given a numeral and a color
rom_td (r, c) = td ! [bgcolor c] << r
-- our 5 x 5 array (list x list) of numerals and colors
rom_array = (groupN 5 . take 25) rom_colors
-- a theoretically infinite list of pairs of roman numerals and colors
-- (practically, though, the roman numeral library has limits!)
rom_colors = zip (map rom [1..]) colors
-- an infinite list of alternating green and pink colors
colors = cycle [green, pink]
main = let s = prettyHtml rom_table
in putStrLn s
我应该注意Text.Html中还有一个小组合库,用于使用“上方”和“旁边”运算符组合表来计算行/列跨越,但在应用属性复制此示例方面有点过于简单了确切地说,我们不需要花哨分割行和列。
答案 8 :(得分:1)
html-tags,Chicken Scheme扩展名。 html-tags生成[X] HTML或SXML。
这是一个例子(使用循环扩展并考虑字符串输出):
(<table> border: 0 cellpadding: 4
(string-intersperse
(loop for i below 25 by 5
collect
(<tr> align: "right"
(string-intersperse
(loop for j from i below (+ i 5)
collect
(<td> bgcolor: (if (odd? j)
"pink"
"green")
(+ 1 j))))))))
我添加了循环和html-utils扩展的链接(它建立在html标签之上),但stackoverflow正在考虑我是垃圾邮件发送者并且只允许我发布最多两个链接。 / p>
答案 9 :(得分:0)
Racket 的内置 XML library 具有此功能。它能够从“X 表达式”生成 XML/HTML。例如:
#lang racket
(require xml)
(define my-name "XYZ")
(define my-list '("One" "Two" "Three"))
(define my-html
`(html
(head (title "Hello!")
(meta ((charset "utf-8"))))
(body (h1 "Hello!")
(p "This is a paragraph.")
;; HTML attributes.
(p ((id "some-id")
(class "some-class"))
"This is another paragraph.")
(p "This is a link: " (a ((href "https://example.com")) "Example"))
;; Unquoting.
(p "My name is: " ,my-name ".")
(p ,(string-append "My name is: " my-name ".")) ; Same thing.
(ul (li "One")
(li "Two")
(li "Three"))
;; Programatically generate the same list as above.
(ul ,@(map (lambda (x)
`(li ,x))
my-list))
,(comment "This is a HTML comment."))))
(displayln (string-append "<!DOCTYPE html>"
(xexpr->string my-html)))