summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsko Nõmm <asko@nmm.ee>2025-09-26 19:22:23 +0300
committerAsko Nõmm <asko@nmm.ee>2025-09-26 19:22:23 +0300
commitaf83d8c7cdf85b675016eeeecaa85bb547141f4b (patch)
treeed3b2746f44bda0619a005beab3c4b22fe6914e7
parent537a14bd9e9146cd9f963520aea75778a32ebc42 (diff)
On second thought it's really not related to templating, just nodes, so moving to nodes ns.
-rw-r--r--resources/clj-kondo/config.edn10
-rw-r--r--src/dompa/nodes.cljc52
-rw-r--r--src/dompa/templates.cljc37
-rw-r--r--test/dompa/nodes_test.cljc24
-rw-r--r--test/dompa/templates_test.cljc24
5 files changed, 79 insertions, 68 deletions
diff --git a/resources/clj-kondo/config.edn b/resources/clj-kondo/config.edn
index 1a76557..1fc2855 100644
--- a/resources/clj-kondo/config.edn
+++ b/resources/clj-kondo/config.edn
@@ -1,5 +1,5 @@
-{:hooks {:analyze-call {dompa.templates/$ hooks.dompa/$
- dompa.templates/defhtml hooks.dompa/defhtml}}
- :linters {:dompa.templates/$-arg-validation {:level :warning}
- :dompa.templates/defhtml-arg-validation {:level :warning}}
- :lint-as {dompa.templates/defhtml clojure.core/defn}} \ No newline at end of file
+{:hooks {:analyze-call {dompa.nodes/$ hooks.dompa/$
+ dompa.nodes/defhtml hooks.dompa/defhtml}}
+ :linters {:dompa.nodes/$-arg-validation {:level :warning}
+ :dompa.nodes/defhtml-arg-validation {:level :warning}}
+ :lint-as {dompa.nodes/defhtml clojure.core/defn}} \ No newline at end of file
diff --git a/src/dompa/nodes.cljc b/src/dompa/nodes.cljc
index d72aa75..24d446e 100644
--- a/src/dompa/nodes.cljc
+++ b/src/dompa/nodes.cljc
@@ -73,4 +73,54 @@
(->html nodes {:void-nodes default-void-nodes}))
([nodes {:keys [void-nodes]}]
(-> (node->html-reducer-fn void-nodes ->html)
- (reduce "" nodes)))) \ No newline at end of file
+ (reduce "" nodes))))
+
+(defmacro defhtml
+ "Creates a new function with `name` that outputs HTML.
+
+ Example usage:
+
+ ```clojure
+ (defhtml about-page [who]
+ ($ :div
+ ($ \"hello \" who)))
+
+ (about-page \"world\")
+ ```
+ "
+ [name & args-and-elements]
+ (let [[args & elements] args-and-elements]
+ `(defn ~name ~args
+ (->html (vector ~@elements)))))
+
+(defn $->flat-xf []
+ (fn [rf]
+ (letfn [(step [result input]
+ (if (sequential? input)
+ (reduce step result input)
+ (rf result input)))]
+ (fn
+ ([] (rf))
+ ([result] (rf result))
+ ([result input] (step result input))))))
+
+(defn $->flat [children]
+ (into [] ($->flat-xf) children))
+
+(defmacro $
+ "A helper that simplifies node creation. Particularly useful
+ where you need compile-time composition over run-time, like when
+ combined with the `defhtml` macro."
+ [name & opts]
+ `(if (string? ~name)
+ {:node/name :dompa/text
+ :node/value (str ~name ~@opts)}
+ (let [opts# (list ~@opts)
+ 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 ($->flat children#))))))
diff --git a/src/dompa/templates.cljc b/src/dompa/templates.cljc
deleted file mode 100644
index 2f79fd2..0000000
--- a/src/dompa/templates.cljc
+++ /dev/null
@@ -1,37 +0,0 @@
-(ns dompa.templates
- (:require [dompa.nodes :as nodes]))
-
-(defmacro defhtml
- [name & args-and-elements]
- (let [[args & elements] args-and-elements]
- `(defn ~name ~args
- (nodes/->html (vector ~@elements)))))
-
-(defn ->flat-xf []
- (fn [rf]
- (letfn [(step [result input]
- (if (sequential? input)
- (reduce step result input)
- (rf result input)))]
- (fn
- ([] (rf))
- ([result] (rf result))
- ([result input] (step result input))))))
-
-(defn ->flat [children]
- (into [] (->flat-xf) children))
-
-(defmacro $
- [name & opts]
- `(if (string? ~name)
- {:node/name :dompa/text
- :node/value (str ~name ~@opts)}
- (let [opts# (list ~@opts)
- 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 (->flat children#))))))
diff --git a/test/dompa/nodes_test.cljc b/test/dompa/nodes_test.cljc
index 55f9394..0e2b63f 100644
--- a/test/dompa/nodes_test.cljc
+++ b/test/dompa/nodes_test.cljc
@@ -1,2 +1,24 @@
(ns dompa.nodes-test
- (:require [clojure.test :refer [deftest is testing]]))
+ (:require [clojure.test :refer [deftest is testing]]
+ [dompa.nodes :refer [$]]))
+
+(deftest node-composition-test
+ (testing "a simple node"
+ (is (= {:node/name :div
+ :node/children [{:node/name :dompa/text
+ :node/value "hello world"}]}
+ ($ :div ($ "hello world")))))
+
+ (testing "a fragment node"
+ (is (= {:node/name :<>
+ :node/children [{:node/name :span
+ :node/children [{:node/name :dompa/text
+ :node/value "hello"}]}
+ {:node/name :span
+ :node/children [{:node/name :dompa/text
+ :node/value "world"}]}]}
+ ($ :<>
+ ($ :span
+ ($ "hello"))
+ ($ :span
+ ($ "world")))))))
diff --git a/test/dompa/templates_test.cljc b/test/dompa/templates_test.cljc
deleted file mode 100644
index 6bbaf2c..0000000
--- a/test/dompa/templates_test.cljc
+++ /dev/null
@@ -1,24 +0,0 @@
-(ns dompa.templates-test
- (:require [clojure.test :refer [deftest is testing]]
- [dompa.templates :refer [defhtml $]]))
-
-(deftest node-composition-test
- (testing "a simple node"
- (is (= {:node/name :div
- :node/children [{:node/name :dompa/text
- :node/value "hello world"}]}
- ($ :div ($ "hello world")))))
-
- (testing "a fragment node"
- (is (= {:node/name :<>
- :node/children [{:node/name :span
- :node/children [{:node/name :dompa/text
- :node/value "hello"}]}
- {:node/name :span
- :node/children [{:node/name :dompa/text
- :node/value "world"}]}]}
- ($ :<>
- ($ :span
- ($ "hello"))
- ($ :span
- ($ "world")))))))