Hunchentoot/сл-кто Page СоставHunchentoot/сл-кто композиция страницы
Я пытаюсь соединить несколько страниц в 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 "[email protected][~A - ~]Test Site" title))) (:body ,@body))))
Теперь, когда у меня есть чистый текст страницы, или один заполненный HTML литералов как
(define-easy-handler (test-page :uri "/")() (page-template (:title "Splash Page") (:p "Testing testing")))
все это-нормально. Страница выводится правильно, и я могу мгновенно увидеть мои действия. Однако, когда у меня есть страница, состоящая из избыточных элементов, это не так просто. Например, скажем, у меня есть страница, по которой по какой-то причине я хочу отображать три RSS-ленты новостей. Это достаточно сложный компонент, который я хочу, чтобы абстрагировать, так что к моему minnd, я должен быть в состоянии сделать что-то вроде
(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")))))))))))))
Примечание удаление mapcar
для dolist
(я Schemer, не дают мне слишком много трудное время о душе лямбды , но они были неправильным выбором здесь) и использование htm
для блокирования блоков html s-exps (h-exps?), которые иначе не были бы в контексте для with-html-output
. Наконец, мне пришлось обернуть текст, но НЕ :href
свойств в (str)
, чтобы они динамически расширялись.