Compare commits

...

6 commits

Author SHA1 Message Date
22001ef3e2
Add clsx utility 2025-05-19 23:33:22 +09:00
314f7cb273
Add link to usage example 2025-05-18 19:00:35 +09:00
79640a16fa
Amend 2025-04-01 01:36:49 +09:00
91206c9ed0
Amend 2025-03-30 20:25:03 +09:00
bd5f4d749d
Amend 2025-03-30 20:25:03 +09:00
bd136d64af
Update README.md
# Conflicts:
#	README.md
2025-03-30 20:25:02 +09:00
4 changed files with 33 additions and 30 deletions

View file

@ -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 dont 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)

View file

@ -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>"

View file

@ -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)

View file

@ -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)))