Генерация встроенного JavaScript с помощью cl-who, parenscript и hunchentoot
Я пытаюсь сгенерировать встроенный JavaScript, но я должен поместить код Parenscript внутри (:script)
а также (str)
теги с использованием cl-кто. ps
, ps*
, ps-inline
а также ps-inline*
кажется, не имеет большого значения для сгенерированного JS.
Это обычный способ написать макрос, чтобы избежать дублирования кода, или есть лучший способ?
Вот моя программа:
(in-package #:ps-test)
(defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html
:lang "en"
(:head
(:meta :http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title ,title)
(:link :type "text/css"
:rel "stylesheet"
:href "/style.css"))
(:body
,@body))))
(defun main ()
(with-html-output (*standard-output* nil :indent t :prologue nil)
(standard-page (:title "Parenscript test")
(:div (str "Hello worldzors"))
(:script :type "text/javascript"
(str (ps (alert "Hello world as well")))))))
(define-easy-handler (docroot :uri "/") ()
(main))
(defun start-ps-test ()
(setf (html-mode) :html5)
(setf *js-string-delimiter* #\")
(start (make-instance 'hunchentoot:easy-acceptor :port 8080)))
(defun stop-ps-test ()
(stop *server*))
(defvar *server* (start-ps-test))
1 ответ
Макросы в этом случае хороши. Хитрость в том, что макросы развертываются в определенном порядке. Скажем, вы определяете js
макрос: когда встречается расширениеwith-html-output
, внутренний вызов ваших макросов (js (alert "Ho Ho Ho"))
выглядит как вызов функции и остается в сгенерированном коде как есть. Если твой js
макрос затем расширяется в (:script ...)
то система будет жаловаться что :script
является неизвестной функцией (при условии, что вы на самом деле не называли такую функцию). Вы должны испустить вложение (who:htm ...)
выражение для интерпретации кода, используя кодер CL-WHO.
(defmacro js (code)
`(who:htm
(:script :type "text/javascript" (who:str (ps:ps ,code)))))
Это работает только в контексте вложения with-html-output
,
Для встроенного Javascript вы не хотите иметь <script>
пометить его, и вы можете просто использовать ps-inline
:
(who:with-html-output (*standard-output*)
(:a :href (ps:ps-inline (void 0))
"A link where the usual HREF behavior is canceled."))
;; prints:
;;
;; <a href='javascript:void(0)'>A link where the usual HREF behavior is canceled.</a>
Но не стесняйтесь использовать макрос, если вы часто делаете одно и то же:
(defmacro link (&body body)
`(who:htm (:a :href #.(ps:ps-inline (void 0)) ,@body)))
(who:with-html-output (*standard-output*) (link "Link"))
;; prints:
;;
;; <a href='javascript:void(0)'>Link</a>