summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsko Nõmm <asko@apesrc.com>2026-02-11 01:43:36 +0200
committerAsko Nõmm <asko@apesrc.com>2026-02-11 01:43:36 +0200
commit91d32658b66c236ae6ba467c4cbdfafd6a2590c8 (patch)
treed6771e9838f9c98dc9af06581c07b8cc2173f279
parentd541af8bd5ae9d696bc87b6df5071d0f59c6d119 (diff)
Allow nesting of `defhtml` (#1)
-rw-r--r--src/dompa/nodes.cljc27
-rw-r--r--test/dompa/nodes_test.cljc62
2 files changed, 65 insertions, 24 deletions
diff --git a/src/dompa/nodes.cljc b/src/dompa/nodes.cljc
index e717690..58ff045 100644
--- a/src/dompa/nodes.cljc
+++ b/src/dompa/nodes.cljc
@@ -110,28 +110,6 @@
`(defn ~name ~args
(->html (vector ~@elements)))))
-(defn $$
- "Creates a new node
-
- Usage:
-
- ```clojure
- ($ :div
- ($ \"hello world\" ))
- ```"
- [name & opts]
- (if (string? name)
- {:node/name :dompa/text
- :node/value (apply str name opts)}
- (let [first-opt (first opts)
- attrs? (and (map? first-opt)
- (not (contains? first-opt :node/name)))
- attrs (if attrs? first-opt {})
- children (if attrs? (rest opts) opts)]
- (cond-> {:node/name name}
- attrs? (assoc :node/attrs attrs)
- (seq children) (assoc :node/children (flatten children))))))
-
(defn- list-of-one?
[coll]
(and (sequential? coll)
@@ -160,10 +138,11 @@
(list-of-many? opt)
{:node/name :<>
- :node/children (remove nil? opt)}
+ :node/children (->> (map nodes-from-opt opt)
+ (remove nil?))}
(list-of-one? opt)
- (first opt)
+ (nodes-from-opt (first opt))
:else
{:node/name :dompa/text
diff --git a/test/dompa/nodes_test.cljc b/test/dompa/nodes_test.cljc
index da9b7db..0340abb 100644
--- a/test/dompa/nodes_test.cljc
+++ b/test/dompa/nodes_test.cljc
@@ -45,6 +45,68 @@
(is (= "<ul><li>one</li><li>two</li></ul>"
(empty-list-items ["one" "two"])))))
+(defhtml greeting [who]
+ ($ :span who))
+
+(defhtml page [who]
+ ($ :div
+ (greeting who)))
+
+(defhtml badge [text]
+ ($ :span {:class "badge"} text))
+
+(defhtml card [title]
+ ($ :div {:class "card"}
+ (badge title)))
+
+(defhtml list-item [text]
+ ($ :li text))
+
+(defhtml my-list [items]
+ ($ :ul
+ (->> items
+ (map list-item)
+ (into []))))
+
+(defhtml header [title]
+ ($ :h1 title))
+
+(defhtml nav [items]
+ ($ :nav
+ ($ :ul
+ (->> items
+ (map list-item)
+ (into [])))))
+
+(defhtml layout [title nav-items body]
+ ($ :div
+ (header title)
+ (nav nav-items)
+ ($ :main body)))
+
+(deftest nested-defhtml-test
+ (testing "simple nesting of defhtml"
+ (is (= "<div><span>world</span></div>"
+ (page "world"))))
+
+ (testing "nested defhtml with attributes"
+ (is (= "<div class=\"card\"><span class=\"badge\">Hello</span></div>"
+ (card "Hello"))))
+
+ (testing "nested defhtml via map/collection"
+ (is (= "<ul><li>a</li><li>b</li><li>c</li></ul>"
+ (my-list ["a" "b" "c"]))))
+
+ (testing "deeply nested defhtml (three levels)"
+ (is (= "<div><h1>Title</h1><nav><ul><li>a</li><li>b</li></ul></nav><main>content</main></div>"
+ (layout "Title" ["a" "b"] "content"))))
+
+ (testing "mixing defhtml and $ in the same parent"
+ (is (= "<div><span>hi</span><p>bye</p></div>"
+ (nodes/->html [($ :div
+ (greeting "hi")
+ ($ :p "bye"))])))))
+
(deftest $-test
(testing "a simple node"
(is (= {:node/name :div