Skip to content
Embeddable HTML templating engine for Common Lisp with JSX-like syntax
Common Lisp
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
tests
.travis.yml
README.md
cl-syntax-lsx.asd
file.lisp
html.lisp
lsx.asd
main.lisp
reader.lisp
syntax.lisp
tag.lisp
template.lisp

README.md

LSX

Quicklisp dist Build Status Coverage Status

Embeddable HTML templating engine with JSX-like syntax.

Usage

(ql:quickload '(:lsx :local-time))

(lsx:enable-lsx-syntax)

<br/>
;=> #<LSX/HTML:ELEMENT br {1003F98BF3}>

(lsx:render-object <br/> t)
;-> <br>
;=> NIL

(lsx:render-object <a href="/hello">Say Hello</a> t)
;-> <a href="/hello">Say Hello</a>
;=> NIL


;;
;; Embed Lisp code in {}

(lsx:render-object <a href="/hello">Say Hello at {(local-time:now)}</a> t)
;-> <a href="/hello">Say Hello at 2018-09-14T05:04:55.009102+09:00</a>
;=> NIL

Defining custom tags

(lsx:deftag welcome (&key name)
  <h1>{name}</h1>)

<welcome name="fukamachi"></welcome>
;=> #<WELCOME {10028D74D3}>

(lsx:render-object <welcome name="fukamachi" /> t)
;-> <h1>fukamachi</h1>
;=> NIL

Defining templates

(lsx:deftemplate default-layout ()
  (title body)
  (:render
    <html>
      <head>
        <title>{title}</title>
      </head>
      <body>
        {body}
      </body>
    </html>))

(lsx:deftemplate index-page (default-layout)
  ()
  (:default-initargs
   :title "Index"
   :body <h1>Welcome</h1>))

(lsx:render 'index-page)
;=> "<!DOCTYPE html>
;    <html>
;          <head>
;            <title>Index</title>
;          </head>
;          <body>
;            <h1>Welcome</h1>
;          </body>
;        </html>
;    "

Loading from file

;; example.lsx
(lambda (&key (name "Guest"))
<html>
  <head>
    <title>Welcome {name}</title>
  </head>
  <body>
    <div id="main"><h1>Hello</h1><p><a href="/entries">Show Entries</a></p></div>
  </body>
</html>)
(lsx:read-lsx-file #P"example.lsx")
;=> #<FUNCTION (LAMBDA (&KEY :NAME) :IN "~/Programs/lib/lsx/example.lsx") {1005E72B5B}>

(lsx:render-object (funcall * :name "fukamachi") t)
;-> <!DOCTYPE html>
;   <html>
;     <head>
;       <title>Welcome fukamachi</title>
;     </head>
;     <body>
;       <div id="main"><h1>Hello</h1><p><a href="/entries">Show Entries</a></p></div>
;     </body>
;   </html>
;=> NIL

How it works

LSX syntax is implemented as reader macro. It's able to see how it's expanded with quoting.

'<br/>
;=> (LSX/TAG:H 'BR (LIST))

'<a href="/hello">Say Hello</a>
;=> (LSX/TAG:H 'A (LIST (CONS "href" "/hello")) (LIST "Say Hello"))

'<a href="/hello">Say Hello at {(local-time:now)}</a>
;=> (LSX/TAG:H 'A (LIST (CONS "href" "/hello")) (LIST "Say Hello at " (LAMBDA () (LOCAL-TIME:NOW))))

h is a function to make an element. It takes a single required argument, a tag-name as a string, and 2 optional arguments, attributes as an association list and children as a list of elements.

;; Same as <br/>
(lsx:h "br")
;=> #<LSX/HTML:ELEMENT br {10033183D3}>

(lsx:h "a" '(("href" . "/hello")) '("Say Hello"))
;=> #<LSX/HTML:ELEMENT a {100331D823}>

(lsx:h "a" '(("href" . "/hello")) (list "Say Hello at " (lambda () (local-time:now))))

See Also

Author

Copyright

Copyright (c) 2018 Eitaro Fukamachi

License

Licensed under the BSD 2-Clause License.

You can’t perform that action at this time.