Генерация встроенного 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>
Другие вопросы по тегам