Content Rendering
Page Rendering
These functions can be used during rendering to retrieve an information about the page:
reblocks/page:rendergeneric-functionreblocks/page:render-bodygeneric-functionreblocks/page:render-dependenciesgeneric-function
Render protocol first renders the widget tree and
only after that renders page HTML headers.
Thus you might use setf on these functions during
widget rendering to change the title, description
or keywords:
If you want to change these variables globally for the whole application, then define a before method like this:
(defmethod reblocks/page:render :before ((app disk-analyzer) inner-html &rest rest)
(declare (ignore rest))
(setf (reblocks/page:get-title)
"Cloud Analyzer - Saves space and money!")
(setf (reblocks/page:get-description)
"Helps to save money when storing data in the Cloud.")
(setf (reblocks/page:get-keywords)
(list "cloud"
"storage"
"analyzer")))
HTML Rendering
Out of the box, Reblocks provides a few facilities for HTML generation.
They are based on Spinneret templating engine. Old version of Weblocks used
CL-WHO instead. But Spinneret is more flexible and what is more important,
it escapes content by default, preventing HTML injection vulnerability.
Most of the time, you only will need a reblocks/html:with-html macro, which is
similary to Spinneret's one, but binds a few special variables to a stream
to write output to and how to write it:
(reblocks/html:with-html ()
(:ul
(:li "One")
(:li "Two")
(:li "Three")))
;.. <ul>
;.. <li>One
;.. <li>Two
;.. <li>Three
;.. </ul>
;=> NILSometimes you might want to get a HTML string instead. In this case you might use
reblocks/html:with-html-string:
cl-transcript
(reblocks/html:with-html-string ()
(:ul
(:li "One")
(:li "Two")
(:li "Three")))
;..
;=> "<ul>
;-> <li>One
;-> <li>Two
;-> <li>Three
;-> </ul>"
You can use any other templating engine, just ensure
it writes output to the reblocks/html:*stream* variable.
For more advanced UI, look at the REBLOCKS-UI documentation.
Widget Rendering
For rendering a widget content you have to define a method for reblocks/widget:render generic-function.
Use reblocks/html:with-html macro to write HTML using lisp expression. Under the hood, this macro
uses a great Spinneret library:
(defwidget foo ()
())
(defmethod reblocks/widget:render ((obj foo))
(reblocks/html:with-html ()
(:p "Hello world!")))
Also, any string or object, returned from the render method, will be used to render widget's content. For example, you might do:
(defmethod reblocks/widget:render ((obj foo))
"<b>Hello</b> world!")But in this case, symbols < and > will be escaped and you will not see "Hello" in bold font.
If you don't want to use Spinneret for rendering but want to get HTML non-escaped, you need to write
HTML string into the reblocks/html:*stream* stream like this:
Note, in this case we should explicitly say that our method does not return anything useful:
(defmethod reblocks/widget:render ((obj foo))
(write-string "<b>Hello</b> world!"
reblocks/html:*stream*
)
(values))This will render "Hello" in bold as desired.
You can use this method for rendering some widgets using template engines other than Spinneret, such as:
https://github.com/mmontone/djula
https://github.com/kanru/cl-mustache
https://github.com/moderninterpreters/markup
Just use engine you like and write it's output to reblocks/html:*stream*!
Sub-widget Rendering
Reblocks pages are represented by a root widget which can have sub-widgets. Thus we have a widgets trivial-mimes:find-mime.types
To render subwidgets, you have to call reblocks/widget:render generic-function
on each subwidget insite the widget's reblocks/widget:render generic-function method:
(defmethod reblocks/widget:render ((obj some-widget))
(reblocks/widget:render (header-widget obj))
(reblocks/widget:render (table-widget obj)))If you are using reblocks/html:with-html macro and wrap subwidgets with a custom HTML
tag, then you can use implicit rendering and just pass subwidgets to Spinneret's HTML tag:
(defmethod reblocks/widget:render ((obj some-widget))
(reblocks/html:with-html ()
(:div :class "flex flex-col"
(header-widget obj)
(table-widget obj))))This works because Reloblocks defines a method for spinneret:html generic-function.