hsx

2024-10-12

Hypertext S-expression

Upstream URL

github.com/skyizwhite/hsx

Author

skyizwhite, Bo Yao

Maintainer

skyizwhite <paku@skyizwhite.dev>

License

MIT
README

HSX

HSX (Hypertext S-expression) is a simple yet powerful HTML5 generation library for Common Lisp. It was forked from flute.

Introduction

HSX allows you to generate HTML using S-expressions, providing a more Lisp-friendly way to create web content. By using the hsx macro, you can define HTML elements and their attributes in a concise and readable manner.

Getting Started

Basic Usage

Use the hsx macro to create HTML elements. Attributes are specified using a property list following the element name, and child elements are nested directly within.

(hsx
  (div :id "example" :class "container"
    (h1 "Welcome to HSX")
    (p "This is an example paragraph.")))

This generates:

<div id="example" class="container">
  <h1>Welcome to HSX</h1>
  <p>This is an example paragraph.</p>
</div>

Examples

Dynamic Content

HSX allows embedding Common Lisp code directly within your HTML structure, making it easy to generate dynamic content.

(hsx
  (div
    (p :id (format nil "id-~a" (random 100)))
    (ul
      (loop :for i :from 1 :to 5 :collect (li (format nil "Item ~a" i))))
    (if (> (random 10) 5)
        (p "Condition met!")
        (p "Condition not met!"))))

This might generate:

<div>
  <p id="id-42"></p>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
  <p>Condition not met!</p>
</div>

Using Fragments

To group multiple elements without adding an extra wrapper, use the fragment <>.

(hsx
  (<>
    (h1 "Grouped Elements")
    (p "First paragraph.")
    (p "Second paragraph.")))

This generates:

<h1>Grouped Elements</h1>
<p>First paragraph.</p>
<p>Second paragraph.</p>

Creating Components

You can define reusable components with the defcomp macro. Components are functions that can take keyword arguments and properties.

(defcomp card (&key title children)
  (hsx
    (div :class "card"
      (h1 title)
      children)))

Or using a property list:

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

Usage example:

(hsx
  (card :title "Card Title"
    (p "This is a card component.")))

Generates:

<div class="card">
  <h1>Card Title</h1>
  <p>This is a card component.</p>
</div>

Rendering HTML

To render HSX to an HTML string, use the render-to-string function.

(render-to-string
  (hsx
    (div :class "content"
      (h1 "Rendered to String")
      (p "This HTML is generated as a string."))))

License

This project is licensed under the MIT License.

© 2024 skyizwhite

© 2018 Bo Yao

Feel free to contribute to the project and report any issues or feature requests on the GitHub repository.

Dependencies (5)

  • alexandria
  • cl-str
  • mstrings
  • named-readtables
  • rove

Dependents (0)

    • GitHub
    • Quicklisp