151 lines
2.7 KiB
Markdown
151 lines
2.7 KiB
Markdown
# HSX
|
|
|
|
HSX (Hypertext S-expression) is a simple and powerful HTML (Living Standard)
|
|
generation library for Common Lisp.
|
|
|
|
This project is a fork of [ailisp/flute](https://github.com/ailisp/flute/).
|
|
|
|
## Warning
|
|
|
|
This software is still in ALPHA quality. The APIs are likely to change.
|
|
|
|
Please check the [release notes](https://code.skyizwhite.dev/paku/hsx/releases)
|
|
for updates.
|
|
|
|
## Getting Started
|
|
|
|
### Basic Usage
|
|
|
|
Use the `hsx` macro to create HTML elements. Attributes are specified using a
|
|
property list after the element name, and child elements are nested directly
|
|
inside.
|
|
|
|
```lisp
|
|
(hsx
|
|
(div :id "example" :class "container"
|
|
(h1 "Welcome to HSX")
|
|
(p "This is an example paragraph.")))
|
|
```
|
|
|
|
This generates:
|
|
|
|
```html
|
|
<div id="example" class="container">
|
|
<h1>Welcome to HSX</h1>
|
|
<p>This is an example paragraph.</p>
|
|
</div>
|
|
```
|
|
|
|
To convert an HSX object into an HTML string, use the `render-to-string`
|
|
function:
|
|
|
|
```lisp
|
|
(render-to-string
|
|
(hsx ...))
|
|
```
|
|
|
|
### Embedding Content
|
|
|
|
HSX allows you to embed Common Lisp forms directly within your HTML structure.
|
|
|
|
When working with HSX elements inside embedded Lisp forms, you should use the
|
|
`hsx` macro again.
|
|
|
|
```lisp
|
|
(hsx
|
|
(div
|
|
(p :id (format nil "id-~a" (random 100)))
|
|
(ul
|
|
(loop
|
|
:for i :from 1 :to 5 :collect
|
|
(hsx (li (format nil "Item ~a" i)))))
|
|
(if (> (random 10) 5)
|
|
(hsx (p "Condition met!"))
|
|
(hsx (p "Condition not met!")))))
|
|
```
|
|
|
|
This might generate:
|
|
|
|
```html
|
|
<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
|
|
`<>`.
|
|
|
|
```lisp
|
|
(hsx
|
|
(<>
|
|
(h1 "Grouped Elements")
|
|
(p "First paragraph.")
|
|
(p "Second paragraph.")))
|
|
```
|
|
|
|
This generates:
|
|
|
|
```html
|
|
<h1>Grouped Elements</h1>
|
|
<p>First paragraph.</p>
|
|
<p>Second paragraph.</p>
|
|
```
|
|
|
|
### Creating Components
|
|
|
|
You can define reusable components using the `defcomp` macro. Component names
|
|
must begin with a tilde (`~`). Properties should be declared using `&key`,
|
|
`&rest`, or both. The body must return an HSX element.
|
|
|
|
```lisp
|
|
(defcomp ~card (&key title children)
|
|
(hsx
|
|
(div :class "card"
|
|
(h1 title)
|
|
children)))
|
|
```
|
|
|
|
Alternatively, you can use a property list:
|
|
|
|
```lisp
|
|
(defcomp ~card (&rest props)
|
|
(hsx
|
|
(div :class "card"
|
|
(h1 (getf props :title))
|
|
(getf props :children))))
|
|
```
|
|
|
|
Usage example:
|
|
|
|
```lisp
|
|
(hsx
|
|
(~card :title "Card Title"
|
|
(p "This is a card component.")))
|
|
```
|
|
|
|
Generates:
|
|
|
|
```html
|
|
<div class="card">
|
|
<h1>Card Title</h1>
|
|
<p>This is a card component.</p>
|
|
</div>
|
|
```
|
|
|
|
## License
|
|
|
|
This project is licensed under the MIT License.
|
|
|
|
© 2024 skyizwhite
|
|
|
|
© 2018 Bo Yao
|