diff options
| author | Asko Nõmm <asko@apesrc.com> | 2026-02-11 01:43:36 +0200 |
|---|---|---|
| committer | Asko Nõmm <asko@apesrc.com> | 2026-02-11 01:43:36 +0200 |
| commit | 91d32658b66c236ae6ba467c4cbdfafd6a2590c8 (patch) | |
| tree | d6771e9838f9c98dc9af06581c07b8cc2173f279 | |
| parent | d541af8bd5ae9d696bc87b6df5071d0f59c6d119 (diff) | |
Allow nesting of `defhtml` (#1)
| -rw-r--r-- | src/dompa/nodes.cljc | 27 | ||||
| -rw-r--r-- | test/dompa/nodes_test.cljc | 62 |
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 |
