Simple and powerful HTML generation library
Find a file
2024-06-06 13:35:40 +09:00
.github/workflows Rename CI to test 2024-06-01 20:16:53 +09:00
src Export readers of element slots 2024-06-06 13:35:40 +09:00
tests Add error for invalid props declaration. 2024-06-03 09:03:58 +09:00
.gitignore Add qlfile 2024-02-03 14:55:44 +09:00
hsx-test.asd Improve test 2024-06-02 14:23:13 +09:00
hsx.asd Define hsx package 2024-05-27 16:54:46 +09:00
LICENSE Update license 2024-02-09 20:21:04 +09:00
qlfile Add fiveam-asdf 2024-06-01 07:02:47 +09:00
qlfile.lock Add fiveam-asdf 2024-06-01 07:02:47 +09:00
README.md Rename render to render-to-string 2024-06-01 22:54:43 +09:00

HSX

⚠️ This project is a work in progress. Roadmap

HSX (Hypertext S-expression) is a straightforward HTML5 generation library for Common Lisp.

This project is a fork of flute, originally created by Bo Yao.

Usage

With the hsx macro, you can construct HTML using S-expressions.

The property list (inline form is also available) following the element name is interpreted as attributes, while the remaining elements are interpreted as child elements.

When a property is given a boolean value:

  • t results in the key being displayed without a value.
  • nil results in the property not being displayed at all.
  • Any other type of value results in the key-value pair being displayed.
(hsx
  (div :id "greeting" :class "flex"
    (h1 "Hello World")
    (p
      "This is"
      (strong '(:class "red")
        "an example!"))))

This code generates the following HTML:

<div id="greeting" class="flex">
  <h1>Hello World</h1>
  <p>
    This is
    <strong class="red">an example!</strong>
  </p>
</div>

HSX elements are essentially functions, allowing you to compose them freely and embed Common Lisp code within them.

(hsx
  (div
    (p :id (+ 1 1))
    (ul
      (loop
        :for i :from 1 :to 3
        :collect (li (format nil "item~a" i))))
    (if t
        (p "true")
        (p "false"))))

This generates:

<div>
  <p id="2"></p>
  <ul>
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
  </ul>
  <p>true</p>
</div>

The fragment <> allows you to group multiple elements without introducing additional wrappers.

(hsx
  (<>
    (h1 "Title")
    (p "This is a paragraph.")
    (p "This is another paragraph.")))

This generates:

<h1>Title</h1>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

You can create HSX components using the defcomp macro. Components are essentially functions that accept keyword arguments, a property list, or both.

The children property accepts the children of a component.

(defcomp card (&key title children)
  (hsx
    (div
      (h1 title)
      children)))

or

(defcomp card (&rest props)
  (hsx
    (div
      (h1 (getf props :title))
      (getf props :children))))

This can then be used as follows:

(hsx
  (card :title "card1"
    (p "Lorem ipsum...")))

Which generates:

<div>
  <h1>card1</h1>
  <p>Lorem ipsum...</p>
</div>

To output HSX as an HTML string, use the render-to-string method.

(render-to-string (hsx ...))

License

This project is licensed under the terms of the MIT license.

© 2024 skyizwhite

© 2018 Bo Yao