English 中文(简体)
CL-WHO类似的HTML模板化用于其他语言?[已关闭]
原标题:
  • 时间:2009-03-22 20:31:07
  •  标签:

我们不允许寻求有关书籍、工具、软件库等推荐的问题。您可以编辑问题,使其可以用事实和引用回答。

Closed 1 year ago.

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整合到它们的语法中也很有趣。

最佳回答

对于CPAN的提供,请按照以下顺序查看(按字母顺序)...

使用CL-WHO示例中的表格部分(去除罗马数字和s/background-color/color/以将代码挤入屏幕宽度!)...

将其翻译成中文:

Builder

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;

将其翻译成中文:

HTML::AsSubs

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;

将其翻译成中文:

HTML::Tiny

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 )    
    ]
);

将其翻译成中文:

Markapl

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  );

将其翻译成中文:

Template::Declare

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  );

将其翻译成中文:

XML::Generator

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 )    
);

将其翻译成中文: And the following can be used to produce the "loop" in HTML::AsSubs / HTML::Tiny / XML::Generator examples....

sub loop {
    my ( %p ) = @_;
    my @list;

    for ( my $i = $p{start} || 1; $i < $p{below}; $i += $p{by} ) {
        push @list, $i;
    }

    return @list;
}
问题回答

Perl 基金会 现在赞助的项目之一(一个 Perl6 轻量级 Web 框架),其拥有可以工作的 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上浏览或克隆当前的代码。

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的编程,因此希望我正确理解了您的代码。

这里有一个名为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[ "******" ]
           ],
       ]

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);

如果您有一个列表或数组。

Clojure

在Clojure中有许多受CL-WHO启发的HTML生成库可用(正如人们所期望的,Clojure是一种Lisp语言)。这是您可以使用Compojurecl-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的字面哈希映射作为属性/值对,并使用字面矢量代替所有内容的列表来标记有助于突出显示标记,并避免了一些宏魔法的需要。

partition将一个集合分成一些固定数量元素的组。cycle生成一个无限重复集合元素的列表。这些加上rangemap可以帮助你避免使用显式循环和计数器变量。

这里是JavaScript的一个类似东西。它看起来像是这样的:(链接)

T.div({ className: "content"},
      T.p("Some ", T.u("paragraph")),
      T.p("Another paragraph"))

Haskell

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中还有一个小的组合库,用于使用“above”和“beside”运算符合成表格以计算行/列跨度,但在应用属性以准确复制此示例方面,它有些过于简单了,而且我们不需要将行和列进行复杂的拆分。

这里有一个名为 html-tagsChicken Scheme 扩展,它可以生成 [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-tags之上的),但是stackoverflow认为我是垃圾邮件发送者,只允许我发布最多两个链接。

Racket的内置XML库具备此功能。它能够从“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)))

domonic 是一个使用魔法方法和dunders来尝试支持这种东西的Python库...

from domonic.html import *
mydom = html(body(h1( Hello, World! )))
print(f"{mydom}")

docs... https://domonic.readthedocs.io/packages/html.html

pip install domonic




相关问题
热门标签