diff --git a/README.md b/README.md index 4023a32..d546227 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # HSX β Hypertext S-expression -**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. +**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. -[Practical usage example](https://github.com/skyizwhite/website) - -> π§ **BETA NOTICE:** +> π§ **ALPHA NOTICE:** > This library is still in early development. APIs may change. > See [release notes](https://github.com/skyizwhite/hsx/releases) for details. @@ -28,26 +26,28 @@ For example: Is internally transformed (by macro expansion) into: ```lisp -(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)))) +(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)))) ``` +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."))) + (p "This is a simple paragraph.") + (ul + (loop for i from 1 to 3 collect + (hsx (li (format nil "Item ~a" i))))))) ``` Generates: @@ -56,6 +56,11 @@ 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> ``` @@ -68,7 +73,7 @@ Use `render-to-string` to convert an HSX structure to a string of HTML: (hsx ...)) ``` -## π Escaping text +## π Escaping Behavior All elements automatically escape special characters in content to prevent XSS and HTML injection: @@ -171,15 +176,13 @@ Or loop: (hsx (li item)))))) ``` -## Utils +## π·οΈ Built-in Tags -- `(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. +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 - -Β© 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) diff --git a/hsx.asd b/hsx.asd index e3fa1f0..10f33bb 100644 --- a/hsx.asd +++ b/hsx.asd @@ -1,5 +1,5 @@ (defsystem "hsx" - :version "0.6.0" + :version "0.5.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 440bf6d..80f1fab 100644 --- a/src/main.lisp +++ b/src/main.lisp @@ -2,11 +2,9 @@ (:nicknames #:hsx/main) (:use #:cl #:hsx/element - #:hsx/dsl - #:hsx/utils) + #:hsx/dsl) (:import-from #:hsx/builtin) (:export #:hsx #:defcomp - #:render-to-string - #:clsx)) + #:render-to-string)) (in-package :hsx) diff --git a/src/utils.lisp b/src/utils.lisp index 94a3b25..2a1f397 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -5,8 +5,7 @@ #:make-keyword #:symbolicate) (:export #:escape-html-attribute - #:escape-html-text-content - #:clsx)) + #:escape-html-text-content)) (in-package #:hsx/utils) (defparameter *text-content-escape-map* @@ -41,6 +40,3 @@ (defun escape-html-attribute (str) (escape-string str *attribute-escape-map*)) - -(defun clsx (&rest strs) - (format nil "~{~a~^ ~}" (remove nil strs)))