Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
22001ef3e2 | |||
314f7cb273 | |||
79640a16fa | |||
91206c9ed0 | |||
bd5f4d749d | |||
bd136d64af |
4 changed files with 33 additions and 30 deletions
49
README.md
49
README.md
|
@ -1,8 +1,10 @@
|
||||||
# HSX – Hypertext S-expression
|
# HSX – Hypertext S-expression
|
||||||
|
|
||||||
**HSX** is a lightweight and expressive HTML generation library for Common Lisp, inspired by JSX. It allows you to write HTML using native Lisp syntax via S-expressions.
|
**HSX** is a simple and powerful HTML generation library for Common Lisp, inspired by JSX. It allows you to write HTML using native Lisp syntax.
|
||||||
|
|
||||||
> 🚧 **ALPHA NOTICE:**
|
[Practical usage example](https://github.com/skyizwhite/website)
|
||||||
|
|
||||||
|
> 🚧 **BETA NOTICE:**
|
||||||
> This library is still in early development. APIs may change.
|
> This library is still in early development. APIs may change.
|
||||||
> See [release notes](https://github.com/skyizwhite/hsx/releases) for details.
|
> See [release notes](https://github.com/skyizwhite/hsx/releases) for details.
|
||||||
|
|
||||||
|
@ -26,28 +28,26 @@ For example:
|
||||||
Is internally transformed (by macro expansion) into:
|
Is internally transformed (by macro expansion) into:
|
||||||
|
|
||||||
```lisp
|
```lisp
|
||||||
(create-element :article '(:class "container")
|
(create-element :article
|
||||||
(list
|
(list :class "container")
|
||||||
(create-element :h1 nil (list "Title"))
|
(list (create-element :h1
|
||||||
(create-element :p nil (list "Paragraph"))
|
(list)
|
||||||
(create-element #'~share-button '(:service :x) (list))))
|
(list "Title"))
|
||||||
|
(create-element :p
|
||||||
|
(list)
|
||||||
|
(list "Paragraph"))
|
||||||
|
(create-element #'~share-button
|
||||||
|
(list :service :x)
|
||||||
|
(list))))
|
||||||
```
|
```
|
||||||
|
|
||||||
This is made possible via the hsx macro, which detects HTML tags and components, then rewrites them using create-element. Tags are converted to keywords (e.g., div → :div), and custom components (starting with ~) are passed as functions.
|
|
||||||
|
|
||||||
This uniform representation allows rendering, manipulation, and analysis of the HTML structure in a Lisp-friendly way.
|
|
||||||
|
|
||||||
|
|
||||||
## 🚀 Quick Example
|
## 🚀 Quick Example
|
||||||
|
|
||||||
```lisp
|
```lisp
|
||||||
(hsx
|
(hsx
|
||||||
(div :id "main" :class "container"
|
(div :id "main" :class "container"
|
||||||
(h1 "Hello, HSX!")
|
(h1 "Hello, HSX!")
|
||||||
(p "This is a simple paragraph.")
|
(p "This is a simple paragraph.")))
|
||||||
(ul
|
|
||||||
(loop for i from 1 to 3 collect
|
|
||||||
(hsx (li (format nil "Item ~a" i)))))))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Generates:
|
Generates:
|
||||||
|
@ -56,11 +56,6 @@ Generates:
|
||||||
<div id="main" class="container">
|
<div id="main" class="container">
|
||||||
<h1>Hello, HSX!</h1>
|
<h1>Hello, HSX!</h1>
|
||||||
<p>This is a simple paragraph.</p>
|
<p>This is a simple paragraph.</p>
|
||||||
<ul>
|
|
||||||
<li>Item 1</li>
|
|
||||||
<li>Item 2</li>
|
|
||||||
<li>Item 3</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -73,7 +68,7 @@ Use `render-to-string` to convert an HSX structure to a string of HTML:
|
||||||
(hsx ...))
|
(hsx ...))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔐 Escaping Behavior
|
## 🔐 Escaping text
|
||||||
|
|
||||||
All elements automatically escape special characters in content to prevent XSS and HTML injection:
|
All elements automatically escape special characters in content to prevent XSS and HTML injection:
|
||||||
|
|
||||||
|
@ -176,13 +171,15 @@ Or loop:
|
||||||
(hsx (li item))))))
|
(hsx (li item))))))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🏷️ Built-in Tags
|
## Utils
|
||||||
|
|
||||||
All standard HTML5 tags (and a few extras like `<>`, `raw!`) are automatically defined and exported from the hsx package. You don’t need to declare them manually.
|
- `(clsx &rest strs)`: A utility function for constructing class strings conditionally. It removes `nil` from the string list, then joins the remaining strings with spaces.
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
• © 2024 Akira Tempaku
|
|
||||||
• © 2018 Bo Yao (original [flute](https://github.com/ailisp/flute) project)
|
© 2024 Akira Tempaku
|
||||||
|
|
||||||
|
© 2018 Bo Yao (original [flute](https://github.com/ailisp/flute) project)
|
||||||
|
|
||||||
|
|
2
hsx.asd
2
hsx.asd
|
@ -1,5 +1,5 @@
|
||||||
(defsystem "hsx"
|
(defsystem "hsx"
|
||||||
:version "0.5.0"
|
:version "0.6.0"
|
||||||
:description "Simple and powerful HTML generation library."
|
:description "Simple and powerful HTML generation library."
|
||||||
:author "Akira Tempaku, Bo Yao"
|
:author "Akira Tempaku, Bo Yao"
|
||||||
:maintainer "Akira Tempaku <paku@skyizwhite.dev>"
|
:maintainer "Akira Tempaku <paku@skyizwhite.dev>"
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
(:nicknames #:hsx/main)
|
(:nicknames #:hsx/main)
|
||||||
(:use #:cl
|
(:use #:cl
|
||||||
#:hsx/element
|
#:hsx/element
|
||||||
#:hsx/dsl)
|
#:hsx/dsl
|
||||||
|
#:hsx/utils)
|
||||||
(:import-from #:hsx/builtin)
|
(:import-from #:hsx/builtin)
|
||||||
(:export #:hsx
|
(:export #:hsx
|
||||||
#:defcomp
|
#:defcomp
|
||||||
#:render-to-string))
|
#:render-to-string
|
||||||
|
#:clsx))
|
||||||
(in-package :hsx)
|
(in-package :hsx)
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#:make-keyword
|
#:make-keyword
|
||||||
#:symbolicate)
|
#:symbolicate)
|
||||||
(:export #:escape-html-attribute
|
(:export #:escape-html-attribute
|
||||||
#:escape-html-text-content))
|
#:escape-html-text-content
|
||||||
|
#:clsx))
|
||||||
(in-package #:hsx/utils)
|
(in-package #:hsx/utils)
|
||||||
|
|
||||||
(defparameter *text-content-escape-map*
|
(defparameter *text-content-escape-map*
|
||||||
|
@ -40,3 +41,6 @@
|
||||||
|
|
||||||
(defun escape-html-attribute (str)
|
(defun escape-html-attribute (str)
|
||||||
(escape-string str *attribute-escape-map*))
|
(escape-string str *attribute-escape-map*))
|
||||||
|
|
||||||
|
(defun clsx (&rest strs)
|
||||||
|
(format nil "~{~a~^ ~}" (remove nil strs)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue