From bd136d64af74edc30ebae5a6928612a85d8cb240 Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Fri, 28 Mar 2025 15:20:57 +0900 Subject: [PATCH 1/6] Update README.md # Conflicts: # README.md --- README.md | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d546227..8ad47b8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 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 lightweight and expressive HTML generation library for Common Lisp, inspired by JSX. It allows you to write HTML using native Lisp syntax. > π§ **ALPHA NOTICE:** > This library is still in early development. APIs may change. @@ -35,19 +35,13 @@ Is internally transformed (by macro expansion) into: 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 ```lisp (hsx (div :id "main" :class "container" (h1 "Hello, HSX!") - (p "This is a simple paragraph.") - (ul - (loop for i from 1 to 3 collect - (hsx (li (format nil "Item ~a" i))))))) + (p "This is a simple paragraph."))) ``` Generates: @@ -56,11 +50,6 @@ Generates: <div id="main" class="container"> <h1>Hello, HSX!</h1> <p>This is a simple paragraph.</p> - <ul> - <li>Item 1</li> - <li>Item 2</li> - <li>Item 3</li> - </ul> </div> ``` @@ -73,7 +62,7 @@ Use `render-to-string` to convert an HSX structure to a string of HTML: (hsx ...)) ``` -## π Escaping Behavior +## π Escaping text All elements automatically escape special characters in content to prevent XSS and HTML injection: @@ -176,10 +165,6 @@ Or loop: (hsx (li item)))))) ``` -## π·οΈ Built-in Tags - -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. - ## π License MIT License From bd5f4d749d843cf5493c39acc96fc8dab39f2e98 Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Fri, 28 Mar 2025 16:23:15 +0900 Subject: [PATCH 2/6] Amend --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ad47b8..927bb49 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,8 @@ Or loop: ## π 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) From 91206c9ed0fd9fd314f898967b3e4d27f9074d2f Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Sun, 30 Mar 2025 20:20:17 +0900 Subject: [PATCH 3/6] Amend --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 927bb49..b98fe8a 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,17 @@ For example: Is internally transformed (by macro expansion) into: ```lisp -(create-element :article '(:class "container") - (list - (create-element :h1 nil (list "Title")) - (create-element :p nil (list "Paragraph")) - (create-element #'~share-button '(:service :x) (list)))) +(create-element :article + (list :class "container") + (list (create-element :h1 + (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. From 79640a16fa01ca35969d6e8bb56d745d8a047738 Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Tue, 1 Apr 2025 01:36:49 +0900 Subject: [PATCH 4/6] Amend --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b98fe8a..72f9252 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # 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. +**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:** +> π§ **BETA NOTICE:** > This library is still in early development. APIs may change. > See [release notes](https://github.com/skyizwhite/hsx/releases) for details. @@ -39,8 +39,6 @@ Is internally transformed (by macro expansion) into: (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. - ## π Quick Example ```lisp From 314f7cb2733c5270feed533603ec04e8a2e51cf7 Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Sun, 18 May 2025 19:00:35 +0900 Subject: [PATCH 5/6] Add link to usage example --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 72f9252..a90fd1c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ **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. +[Practical usage example](https://github.com/skyizwhite/website) + > π§ **BETA NOTICE:** > This library is still in early development. APIs may change. > See [release notes](https://github.com/skyizwhite/hsx/releases) for details. From 22001ef3e229ce9cfb52d3ea30a3b70460dbff04 Mon Sep 17 00:00:00 2001 From: Akira Tempaku <paku@skyizwhite.dev> Date: Mon, 19 May 2025 23:33:22 +0900 Subject: [PATCH 6/6] Add clsx utility --- README.md | 4 ++++ hsx.asd | 2 +- src/main.lisp | 6 ++++-- src/utils.lisp | 6 +++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a90fd1c..4023a32 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,10 @@ Or loop: (hsx (li item)))))) ``` +## Utils + +- `(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 MIT License diff --git a/hsx.asd b/hsx.asd index 10f33bb..e3fa1f0 100644 --- a/hsx.asd +++ b/hsx.asd @@ -1,5 +1,5 @@ (defsystem "hsx" - :version "0.5.0" + :version "0.6.0" :description "Simple and powerful HTML generation library." :author "Akira Tempaku, Bo Yao" :maintainer "Akira Tempaku <paku@skyizwhite.dev>" diff --git a/src/main.lisp b/src/main.lisp index 80f1fab..440bf6d 100644 --- a/src/main.lisp +++ b/src/main.lisp @@ -2,9 +2,11 @@ (:nicknames #:hsx/main) (:use #:cl #:hsx/element - #:hsx/dsl) + #:hsx/dsl + #:hsx/utils) (:import-from #:hsx/builtin) (:export #:hsx #:defcomp - #:render-to-string)) + #:render-to-string + #:clsx)) (in-package :hsx) diff --git a/src/utils.lisp b/src/utils.lisp index 2a1f397..94a3b25 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -5,7 +5,8 @@ #:make-keyword #:symbolicate) (:export #:escape-html-attribute - #:escape-html-text-content)) + #:escape-html-text-content + #:clsx)) (in-package #:hsx/utils) (defparameter *text-content-escape-map* @@ -40,3 +41,6 @@ (defun escape-html-attribute (str) (escape-string str *attribute-escape-map*)) + +(defun clsx (&rest strs) + (format nil "~{~a~^ ~}" (remove nil strs)))