From 011ccd6b2aeba7375e2992dc7e58d26c56e760e2 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Sat, 19 Oct 2024 00:13:33 +0900
Subject: [PATCH 01/10] Update system version

---
 hsx.asd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hsx.asd b/hsx.asd
index aba1850..dffc354 100644
--- a/hsx.asd
+++ b/hsx.asd
@@ -1,5 +1,5 @@
 (defsystem "hsx"
-  :version "0.1.0"
+  :version "0.2.1"
   :description "Hypertext S-expression"
   :author "skyizwhite, Bo Yao"
   :maintainer "skyizwhite <paku@skyizwhite.dev>"

From a170c58530fa82b9f9fc8440a14fbe57f466b8fc Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Thu, 12 Dec 2024 12:57:05 +0900
Subject: [PATCH 02/10] Improve find-builtin-symbols

---
 src/dsl.lisp   | 33 ++++++++++++++---------
 tests/dsl.lisp | 73 +++++++++++++++++++++++++++++---------------------
 2 files changed, 63 insertions(+), 43 deletions(-)

diff --git a/src/dsl.lisp b/src/dsl.lisp
index 680c85a..f196866 100644
--- a/src/dsl.lisp
+++ b/src/dsl.lisp
@@ -16,18 +16,27 @@
   "Detect built-in HSX elements and automatically import them."
   (find-builtin-symbols form))
 
-(defun find-builtin-symbols (node)
-  (if (atom node)
-      (or (and (symbolp node)
-               (not (keywordp node))
-               (find-symbol (string node) :hsx/builtin))
-          node)
-      (cons (find-builtin-symbols (car node))
-            (mapcar (lambda (n)
-                      (if (listp n)
-                          (find-builtin-symbols n)
-                          n))
-                    (cdr node)))))
+(defun get-builtin-symbol (sym)
+  (multiple-value-bind (builtin-sym kind)
+      (find-symbol (string sym) :hsx/builtin)
+    (and (eq kind :external) builtin-sym)))
+
+(defun find-builtin-symbols (form)
+  (check-type form cons)
+  (let* ((head (first form))
+         (tail (rest form))
+         (well-formed-p (listp tail))
+         (builtin-sym (and (symbolp head)
+                           (not (keywordp head))
+                           (get-builtin-symbol head))))
+    (if (and well-formed-p builtin-sym)
+        (cons builtin-sym
+              (mapcar (lambda (sub-form)
+                        (if (consp sub-form)
+                            (find-builtin-symbols sub-form)
+                            sub-form))
+                      tail))
+        form)))
 
 ;;;; defhsx macro
 
diff --git a/tests/dsl.lisp b/tests/dsl.lisp
index d8bce5d..8bd6408 100644
--- a/tests/dsl.lisp
+++ b/tests/dsl.lisp
@@ -1,67 +1,78 @@
 (defpackage #:hsx-test/dsl
   (:use #:cl
         #:rove
-        #:hsx/dsl
-        #:hsx/builtin)
+        #:hsx/dsl)
+  (:import-from #:hsx/builtin)
   (:import-from #:hsx/element
                 #:element-props
                 #:element-children))
 (in-package #:hsx-test/dsl)
 
+(deftest find-builtin-symbols-test
+  (testing "normal-cases"
+    (ok (expands '(hsx (div div div))
+                 '(hsx/builtin:div div div)))
+    (ok (expands '(hsx (div (div div (div))))
+                 '(hsx/builtin:div
+                   (hsx/builtin:div
+                     div
+                     (hsx/builtin:div)))))
+    (ok (expands '(hsx (div
+                         (labels ((div () "div"))
+                           (hsx (div)))))
+                 '(hsx/builtin:div
+                   (labels ((div () "div"))
+                     (hsx (div)))))))
+
+  (testing "ignore-cases"
+    (ok (expands '(hsx (div . div))
+                 '(div . div)))
+    (ok (expands '(hsx ((div)))
+                 '((div))))
+    (ok (expands '(hsx (div
+                         (labels ((div () "div"))
+                           (div))))
+                 '(hsx/builtin:div
+                   (labels ((div () "div"))
+                     (div)))))))
+
 (deftest dsl-test
-  (testing "find-symbols"
-    (ok (expands
-         '(hsx (div '(:div "div")
-                 div
-                 (div
-                   'div
-                   (div)
-                   :div)
-                 "div"))
-         '(hsx/builtin:div '(:div "div")
-           div
-           (hsx/builtin:div
-             'div
-             (hsx/builtin:div)
-             :div)
-           "div"))))
-  
   (testing "empty-hsx"
-    (let ((elm (div)))
+    (let ((elm (hsx (div))))
       (ok (null (element-props elm)))
       (ok (null (element-children elm)))))
  
   (testing "hsx-with-static-props"
-    (let ((elm (div :prop1 "value1" :prop2 "value2")))
+    (let ((elm (hsx (div :prop1 "value1" :prop2 "value2"))))
       (ok (equal '(:prop1 "value1" :prop2 "value2")
                  (element-props elm)))
       (ok (null (element-children elm)))))
   
   (testing "hsx-with-dynamic-props"
     (let* ((props '(:prop1 "value1" :prop2 "value2"))
-           (elm (div props)))
+           (elm (hsx (div props))))
       (ok (equal props (element-props elm)))
       (ok (null (element-children elm)))))
   
   (testing "hsx-with-children"
-    (let ((elm (div
-                 "child1"
-                 "child2")))
+    (let ((elm (hsx (div
+                      "child1"
+                      "child2"))))
       (ok (null (element-props elm)))
       (ok (equal (list "child1" "child2") (element-children elm)))))
   
   (testing "hsx-with-static-props-and-children"
-    (let ((elm (div :prop1 "value1" :prop2 "value2"
-                 "child1"
-                 "child2")))
+    (let ((elm (hsx (div :prop1 "value1" :prop2 "value2"
+                      "child1"
+                      "child2"))))
       (ok (equal '(:prop1 "value1" :prop2 "value2")
                  (element-props elm)))
       (ok (equal (list "child1" "child2") (element-children elm)))))
   
   (testing "hsx-with-dynamic-props-and-children"
     (let* ((props '(:prop1 "value1" :prop2 "value2"))
-           (elm (div props
-                  "child1"
-                  "child2")))
+           (elm (hsx (div props
+                       "child1"
+                       "child2"))))
       (ok (equal props (element-props elm)))
       (ok (equal (list "child1" "child2") (element-children elm))))))

From 6abb647246b0fe900f7c7f18ee0427282586c8ff Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Thu, 12 Dec 2024 13:09:51 +0900
Subject: [PATCH 03/10] Update README

---
 README.md | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 4055a2a..730e943 100644
--- a/README.md
+++ b/README.md
@@ -39,10 +39,12 @@ HSX allows embedding Common Lisp code directly within your HTML structure, makin
   (div
     (p :id (format nil "id-~a" (random 100)))
     (ul
-      (loop :for i :from 1 :to 5 :collect (li (format nil "Item ~a" i))))
+      (loop
+        :for i :from 1 :to 5 :collect
+        (hsx (li (format nil "Item ~a" i)))))
     (if (> (random 10) 5)
-        (p "Condition met!")
-        (p "Condition not met!"))))
+        (hsx (p "Condition met!"))
+        (hsx (p "Condition not met!")))))
 ```
 
 This might generate:

From 33dd8e82051305840dc3f5bfc480a5f3dd1ec951 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Thu, 12 Dec 2024 13:10:14 +0900
Subject: [PATCH 04/10] Update system version to v0.3.0

---
 hsx.asd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hsx.asd b/hsx.asd
index dffc354..fccc84d 100644
--- a/hsx.asd
+++ b/hsx.asd
@@ -1,5 +1,5 @@
 (defsystem "hsx"
-  :version "0.2.1"
+  :version "0.3.0"
   :description "Hypertext S-expression"
   :author "skyizwhite, Bo Yao"
   :maintainer "skyizwhite <paku@skyizwhite.dev>"

From 3193054e04052ace1108b34d80116ff85b03d98b Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Thu, 12 Dec 2024 14:00:42 +0900
Subject: [PATCH 05/10] Update README

---
 README.md | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 730e943..4c63e73 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,14 @@
 # HSX
 
-HSX (Hypertext S-expression) is a simple yet powerful HTML5 generation library for Common Lisp. It was forked from [flute](https://github.com/ailisp/flute/).
+HSX (Hypertext S-expression) is a simple yet powerful HTML5 generation library for Common Lisp.
+
+This project is a fork of [ailisp/flute](https://github.com/ailisp/flute/).
+
+## Warning
+
+This software is still ALPHA quality. The APIs likely change.
+
+Please check the [release notes](https://github.com/skyizwhite/hsx/releases).
 
 ## Introduction
 

From dfc074ec71a931156e83c86a650447ae783462ab Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Fri, 13 Dec 2024 01:33:01 +0900
Subject: [PATCH 06/10] Fix defcomp to detect components in HSX

---
 src/dsl.lisp   | 38 ++++++++++++++++++++++++--------------
 tests/dsl.lisp | 35 ++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/src/dsl.lisp b/src/dsl.lisp
index f196866..577ce58 100644
--- a/src/dsl.lisp
+++ b/src/dsl.lisp
@@ -13,27 +13,34 @@
 ;;;; hsx macro
 
 (defmacro hsx (form)
-  "Detect built-in HSX elements and automatically import them."
-  (find-builtin-symbols form))
+  "Detect HSX elements and automatically import them."
+  (detect-elements form))
 
 (defun get-builtin-symbol (sym)
   (multiple-value-bind (builtin-sym kind)
       (find-symbol (string sym) :hsx/builtin)
     (and (eq kind :external) builtin-sym)))
 
-(defun find-builtin-symbols (form)
+(defun start-with-tilde-p (sym)
+  (string= "~" (subseq (string sym) 0 1)))
+
+(defun get-component-symbol (sym)
+  (and (start-with-tilde-p sym) sym))
+
+(defun detect-elements (form)
   (check-type form cons)
   (let* ((head (first form))
          (tail (rest form))
          (well-formed-p (listp tail))
-         (builtin-sym (and (symbolp head)
-                           (not (keywordp head))
-                           (get-builtin-symbol head))))
-    (if (and well-formed-p builtin-sym)
-        (cons builtin-sym
+         (detected-sym (and (symbolp head)
+                            (not (keywordp head))
+                            (or (get-builtin-symbol head)
+                                (get-component-symbol head)))))
+    (if (and well-formed-p detected-sym)
+        (cons detected-sym
               (mapcar (lambda (sub-form)
                         (if (consp sub-form)
-                            (find-builtin-symbols sub-form)
+                            (detect-elements sub-form)
                             sub-form))
                       tail))
         form)))
@@ -67,16 +74,19 @@
   `(eval-when (:compile-toplevel :load-toplevel :execute)
      (defhsx ,name ,(make-keyword name))))
 
-(defmacro defcomp (name props &body body)
-  "Define a function component for use in HSX.
-The props must be declared with either &key or &rest (or both).
+(defmacro defcomp (~name props &body body)
+  "Define a function component for HSX.
+The component name must start with a tilde (~).
+Properties must be declared using &key, &rest, or both.
 The body must return an HSX element."
+  (unless (start-with-tilde-p ~name)
+    (error "The component name must start with a tilde (~~)."))
   (unless (or (null props)
               (member '&key props)
               (member '&rest props))
     (error "Component properties must be declared with either &key, &rest, or both."))
-  (let ((%name (symbolicate '% name)))
+  (let ((%name (symbolicate '% ~name)))
     `(eval-when (:compile-toplevel :load-toplevel :execute)
        (defun ,%name ,props
          ,@body)
-       (defhsx ,name (fdefinition ',%name)))))
+       (defhsx ,~name (fdefinition ',%name)))))
diff --git a/tests/dsl.lisp b/tests/dsl.lisp
index 8bd6408..31abea8 100644
--- a/tests/dsl.lisp
+++ b/tests/dsl.lisp
@@ -8,33 +8,34 @@
                 #:element-children))
 (in-package #:hsx-test/dsl)
 
-(deftest find-builtin-symbols-test
-  (testing "normal-cases"
+(defcomp ~comp1 (&key children)
+  (hsx (div children)))
+
+(deftest detect-elements-test
+  (testing "detect-tags"
     (ok (expands '(hsx (div div div))
                  '(hsx/builtin:div div div)))
     (ok (expands '(hsx (div (div div (div))))
                  '(hsx/builtin:div
                    (hsx/builtin:div
                      div
-                     (hsx/builtin:div)))))
-    (ok (expands '(hsx (div
-                         (labels ((div () "div"))
-                           (hsx (div)))))
-                 '(hsx/builtin:div
-                   (labels ((div () "div"))
-                     (hsx (div)))))))
+                     (hsx/builtin:div))))))
 
-  (testing "ignore-cases"
+  (testing "detect-components"
+    (ok (expands '(hsx (~comp1 (div)))
+                 '(~comp1 (hsx/builtin:div)))))
+
+  (testing "ignore-malformed-form"
     (ok (expands '(hsx (div . div))
                  '(div . div)))
     (ok (expands '(hsx ((div)))
-                 '((div))))
-    (ok (expands '(hsx (div
-                         (labels ((div () "div"))
-                           (div))))
-                 '(hsx/builtin:div
-                   (labels ((div () "div"))
-                     (div)))))))
+                 '((div)))))
+
+  (testing "ignore-cl-form"
+    (ok (expands '(hsx (labels ((div () "div"))
+                         (div)))
+                 '(labels ((div () "div"))
+                   (div))))))
 
 (deftest dsl-test
   (testing "empty-hsx"

From 4490c741976dc1cfc06e83b9a7a9922a11f6e461 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Fri, 13 Dec 2024 01:35:31 +0900
Subject: [PATCH 07/10] Update README

---
 README.md | 47 +++++++++++++++++++----------------------------
 1 file changed, 19 insertions(+), 28 deletions(-)

diff --git a/README.md b/README.md
index 4c63e73..4bd5733 100644
--- a/README.md
+++ b/README.md
@@ -6,19 +6,15 @@ This project is a fork of [ailisp/flute](https://github.com/ailisp/flute/).
 
 ## Warning
 
-This software is still ALPHA quality. The APIs likely change.
+This software is still in ALPHA quality. The APIs are likely to change.
 
-Please check the [release notes](https://github.com/skyizwhite/hsx/releases).
-
-## Introduction
-
-HSX allows you to generate HTML using S-expressions, providing a more Lisp-friendly way to create web content. By using the `hsx` macro, you can define HTML elements and their attributes in a concise and readable manner.
+Please check the [release notes](https://github.com/skyizwhite/hsx/releases) for updates.
 
 ## Getting Started
 
 ### Basic Usage
 
-Use the `hsx` macro to create HTML elements. Attributes are specified using a property list following the element name, and child elements are nested directly within.
+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
@@ -36,11 +32,18 @@ This generates:
 </div>
 ```
 
-## Examples
+To convert an HSX object into an HTML string, use the `render-to-string` function:
 
-### Dynamic Content
+```lisp
+(render-to-string
+  (hsx ...))
+```
 
-HSX allows embedding Common Lisp code directly within your HTML structure, making it easy to generate dynamic content.
+### 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
@@ -91,22 +94,22 @@ This generates:
 <p>Second paragraph.</p>
 ```
 
-## Creating Components
+### Creating Components
 
-You can define reusable components with the `defcomp` macro. Components are functions that can take keyword arguments and properties.
+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)
+(defcomp ~card (&key title children)
   (hsx
     (div :class "card"
       (h1 title)
       children)))
 ```
 
-Or using a property list:
+Alternatively, you can use a property list:
 
 ```lisp
-(defcomp card (&rest props)
+(defcomp ~card (&rest props)
   (hsx
     (div :class "card"
       (h1 (getf props :title))
@@ -117,7 +120,7 @@ Usage example:
 
 ```lisp
 (hsx
-  (card :title "Card Title"
+  (~card :title "Card Title"
     (p "This is a card component.")))
 ```
 
@@ -130,18 +133,6 @@ Generates:
 </div>
 ```
 
-## Rendering HTML
-
-To render HSX to an HTML string, use the `render-to-string` function.
-
-```lisp
-(render-to-string
-  (hsx
-    (div :class "content"
-      (h1 "Rendered to String")
-      (p "This HTML is generated as a string."))))
-```
-
 ## License
 
 This project is licensed under the MIT License.

From f60259ec4a101de87c5364c3f1b571706448d3a0 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Fri, 13 Dec 2024 01:37:10 +0900
Subject: [PATCH 08/10] Update system version to v0.4.0

---
 hsx.asd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hsx.asd b/hsx.asd
index fccc84d..b1151ae 100644
--- a/hsx.asd
+++ b/hsx.asd
@@ -1,5 +1,5 @@
 (defsystem "hsx"
-  :version "0.3.0"
+  :version "0.4.0"
   :description "Hypertext S-expression"
   :author "skyizwhite, Bo Yao"
   :maintainer "skyizwhite <paku@skyizwhite.dev>"

From fa7fc1605e14aaca8d449fe21c2ee2d0f23a5ec4 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Tue, 17 Dec 2024 16:14:46 +0900
Subject: [PATCH 09/10] Modify the wording

---
 src/dsl.lisp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/dsl.lisp b/src/dsl.lisp
index 577ce58..27d785a 100644
--- a/src/dsl.lisp
+++ b/src/dsl.lisp
@@ -16,7 +16,7 @@
   "Detect HSX elements and automatically import them."
   (detect-elements form))
 
-(defun get-builtin-symbol (sym)
+(defun detect-builtin-symbol (sym)
   (multiple-value-bind (builtin-sym kind)
       (find-symbol (string sym) :hsx/builtin)
     (and (eq kind :external) builtin-sym)))
@@ -24,7 +24,7 @@
 (defun start-with-tilde-p (sym)
   (string= "~" (subseq (string sym) 0 1)))
 
-(defun get-component-symbol (sym)
+(defun detect-component-symbol (sym)
   (and (start-with-tilde-p sym) sym))
 
 (defun detect-elements (form)
@@ -34,8 +34,8 @@
          (well-formed-p (listp tail))
          (detected-sym (and (symbolp head)
                             (not (keywordp head))
-                            (or (get-builtin-symbol head)
-                                (get-component-symbol head)))))
+                            (or (detect-builtin-symbol head)
+                                (detect-component-symbol head)))))
     (if (and well-formed-p detected-sym)
         (cons detected-sym
               (mapcar (lambda (sub-form)
@@ -75,16 +75,16 @@
      (defhsx ,name ,(make-keyword name))))
 
 (defmacro defcomp (~name props &body body)
-  "Define a function component for HSX.
+  "Define an HSX function component.
 The component name must start with a tilde (~).
-Properties must be declared using &key, &rest, or both.
-The body must return an HSX element."
+Component properties must be declared using &key, &rest, or both.
+The body of the component must produce a valid HSX element."
   (unless (start-with-tilde-p ~name)
     (error "The component name must start with a tilde (~~)."))
   (unless (or (null props)
               (member '&key props)
               (member '&rest props))
-    (error "Component properties must be declared with either &key, &rest, or both."))
+    (error "Component properties must be declared using &key, &rest, or both."))
   (let ((%name (symbolicate '% ~name)))
     `(eval-when (:compile-toplevel :load-toplevel :execute)
        (defun ,%name ,props

From a73af8d936260585e92035827c161ba0bc3075b8 Mon Sep 17 00:00:00 2001
From: paku <paku@skyizwhite.dev>
Date: Fri, 20 Dec 2024 23:38:19 +0900
Subject: [PATCH 10/10] Update description

---
 README.md | 2 +-
 hsx.asd   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 4bd5733..b036ba3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # HSX
 
-HSX (Hypertext S-expression) is a simple yet powerful HTML5 generation library for Common Lisp.
+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/).
 
diff --git a/hsx.asd b/hsx.asd
index b1151ae..c5ab13d 100644
--- a/hsx.asd
+++ b/hsx.asd
@@ -1,6 +1,6 @@
 (defsystem "hsx"
   :version "0.4.0"
-  :description "Hypertext S-expression"
+  :description "Simple and powerful HTML generation library."
   :author "skyizwhite, Bo Yao"
   :maintainer "skyizwhite <paku@skyizwhite.dev>"
   :license "MIT"