ruricolist/spinneret

Allow composition of HTML with macros

K1D77A opened this issue · 1 comments

(defun %html-block-title (title)
  (spinneret:with-html (:h2 title)))

(defmacro %html-left-bordered ((name) &body body)
  `(spinneret:with-html
     (:div :id ,(format nil "~(~A~)-bordered" name)
           :class "left-bordered"
           ,@body)))

(defmacro %html-new-block ((name title &key (pre-body nil)
                                         (post-body nil))
                           &body body)
  `(spinneret:with-html
     (:div :id ,(format nil "~(~A~)-div" name)
           :class "functionality-block"
           (%html-block-title ,title)
           (:div :class "pre-body"
           (%html-left-bordered (,name)
             ,@body)
           (:div :class "post-body"
                 ,post-body))))
                 

macroexpansion

  (spinneret:with-html
  (:div :id "oof-div" :class "functionality-block" (%html-block-title "bog")
   (:div :class "pre-body" nil)
   (%html-left-bordered ("oof")
     (:p "boof"))
   (:div :class "post-body" nil)))

executing

  LUNA-SITE> (%html-new-block ("oof" "bog") (:p "boof"))
  Execution of a form compiled with errors.
Form:
  (SPINNERET::CATCH-OUTPUT
 (%HTML-LEFT-BORDERED (SPINNERET::FORMAT-TEXT (FORMATTER "oof"))
   (SPINNERET::WITH-TAG (:P)
     "boof")))
Compile-time error:
  during macroexpansion of
(SPINNERET::CATCH-OUTPUT
 (%HTML-LEFT-BORDERED #
   #)).
Use *BREAK-ON-SIGNALS* to intercept.

 Error while parsing arguments to DEFMACRO %HTML-LEFT-BORDERED:
   too many elements in
     (SPINNERET::FORMAT-TEXT (FORMATTER "oof"))
   to satisfy lambda list
     (NAME):
   exactly 1 expected, but got 2
   [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]

Restarts:
 0: [RETRY] Retry SLY mREPL evaluation request.
 1: [*ABORT] Return to SLY's top level.
 2: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {100E7C8333}>)

Is it possible to modify with-html so that its possible to compose forms with defmacro?

Thanks.

The problem here is that Spinneret interprets strings in places that look like function calls as if they were calls to format. So when it sees

(%html-left-bordered ("oof")

It expands ("oof") into (format "oof").

Note that if you substitute a symbol for the string it works:

(with-html-string
  (%html-new-block (#:|oof| "bog") (:p "boof")))
=>
"<div class=functionality-block id=oof-div>
 <h2>bog</h2>
 <div class=pre-body>
  <div class=left-bordered id=oof-bordered>
   <p>boof
  </div>
  <div class=post-body>
  </div>
 </div>
</div>"