Ina*_*thi 5 common-lisp hunchentoot
Hunchentoot/cl-who Page Composition
我正试图在hunchentoot中拼几页作为实验,我遇到了意想不到的墙.作为一个例子,我有以下模板宏.
(defmacro page-template ((&key title) &body body)
`(with-html-output-to-string
(*standard-output* nil :prologue t :indent t)
(:html :xmlns "http://www.w3.org/1999/xhtml" :xml\:lang "en" :lang "en"
(:head (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8")
(:title ,(format nil "~@[~A - ~]Test Site" title)))
(:body ,@body))))
现在,当我有一个纯文本页面,或一个填充html文字像
(define-easy-handler (test-page :uri "/") () (page-template (:title "Splash Page") (:p "Testing testing")))
一切都很好.页面输出正确,我可以立即看到我的代码的努力.但是,当我有一个由冗余元素组成的页面时,它并不那么简单.例如,假设我有一个页面,无论出于什么原因我想要显示三个RSS新闻源.这是一个足够复杂的组件,我想将它抽象出来,所以对我来说,我应该能够做类似的事情
(define-easy-handler (test-feed :uri "/feeds") ()
(page-template (:title "Splash Page")
(publish-newsfeed "http://nf-one.html")
(publish-newsfeed "http://nf-two.html")
(publish-newsfeed "http://nf-three.html")))
(defmacro publish-newsfeed (url &optional (item-limit 5))
(flet ((get-text (s-tree node-path) (car (last (xmls-tools:find-subtree s-tree node-path)))))
(let ((rss-feed (xmls:parse (drakma:http-request url))))
`(:div :class "rss-feed"
(:a :href ,(get-text rss-feed '("channel" "link")) :target "_top" (:h1 ,(get-text rss-feed '("channel" "title"))))
(:ul ,@(mapcar #'(lambda (item)
`(:li (:a :href ,(get-text item '("link")) :target "_top" (:h2 ,(get-text item '("title"))))
(:p :class "date" ,(get-text item '("pubDate")))
(:p ,(get-text item '("description")))))
(let ((items (xmls-tools:find-all-children (xmls-tools:find-subtree rss-feed '("channel")) "item")))
(if (> (length items) item-limit) (subseq items 0 item-limit) items))))))))
但上面的结果是"服务器错误"页面.我不确定为什么; page-template是一个宏,所以调用publish-newsfeed不应该扩展,直到它们在上下文中with-html-output-to-string.谁能告诉我我做错了什么?
此外,仔细检查各种Hunchentoot/cl-who教程,他们似乎都没有做这种页面组合.任何有Hunchentoot经验的人都可以告诉我将页面分解为组件的正确/规范方法是什么?
编辑:
下面是Ramarren的正确回应; 在with-html-output宏下不同的评价规则的工作.实际上在这种情况下实际工作的发布新闻源的版本
(defun publish-newsfeed (url &optional (item-limit 5))
(flet ((get-text (s-tree node-path) (car (last (xmls-tools:find-subtree s-tree node-path)))))
(let* ((rss-feed (xmls:parse (drakma:http-request url)))
(items (xmls-tools:find-all-children (xmls-tools:find-subtree rss-feed '("channel")) "item"))
(ltd-items (if (> (length items) item-limit) (subseq items 0 item-limit) items)))
(with-html-output
(*standard-output* nil :indent t)
(:div :class "rss-feed"
(:a :href (get-text rss-feed '("channel" "link")) :target "_top" (:h1 (str (get-text rss-feed '("channel" "title")))))
(:ul (dolist (item ltd-items)
(htm (:li (:h2 (:a :href (get-text item '("link")) :target "_top" (str (get-text item '("title")))))
(:p :class "date" (str (get-text item '("pubDate"))))
(:p (str (get-text item '("description")))))))))))))
请注意删除mapcarfor dolist(我是一个Schemer,不要给我太多关于喜欢lambdas的困难时间,但它们不是这里的正确选择),以及使用htm转义html s-exps的块(h-exps?)否则不会出现在上下文中with-html-output.最后,我必须包装文本但不包含:href属性(str )以使它们动态扩展.