summaryrefslogtreecommitdiff
path: root/src/dompa/nodes.cljc
diff options
context:
space:
mode:
authorAsko Nõmm <asko@nmm.ee>2025-09-14 14:40:01 +0300
committerAsko Nõmm <asko@nmm.ee>2025-09-14 14:40:01 +0300
commit37b555f71ea6ebaea9ff183f186abc46cf9b1a67 (patch)
treecd2fb542c4654af2bb4446a442fdc3550a813379 /src/dompa/nodes.cljc
parentc9fb6f1c80a83f9e8ea88f7db3caedae57985fd7 (diff)
Restructure and start working on tests
Diffstat (limited to 'src/dompa/nodes.cljc')
-rw-r--r--src/dompa/nodes.cljc59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/dompa/nodes.cljc b/src/dompa/nodes.cljc
new file mode 100644
index 0000000..d035116
--- /dev/null
+++ b/src/dompa/nodes.cljc
@@ -0,0 +1,59 @@
+(ns dompa.nodes)
+
+(def ^:private default-void-nodes
+ #{:!doctype :area :base :br :col :embed :hr :img :input
+ :link :meta :source :track :wbr})
+
+(defn- node->html-reducer-fn
+ [void-nodes nodes->html-fn]
+ (fn [html node]
+ (cond
+ (= (-> node :name) :dompa/text)
+ (str html (-> node :value))
+
+ (contains? void-nodes (-> node :name))
+ (str "<" (-> node :name) ">")
+
+ :else
+ (let [value (nodes->html-fn (-> node :children))]
+ (str "<" (-> node :name) ">" value "</" (-> node :name) ">")))))
+
+(defn traverse
+ "Recursively traverses given tree of `nodes` with a `traverser-fn`
+ that gets a single node passed to it and returns a new updated tree.
+ If the traverses function returns `nil`, the node will be removed.
+ In any other case the node will be replaced. If you wish to keep
+ a node unchanged, just return it as-is."
+ [nodes traverser-fn]
+ (-> (fn [updated-nodes node]
+ (if-let [updated-node (traverser-fn node)]
+ (let [children (traverse (-> updated-node :children) traverser-fn)]
+ (conj updated-nodes (assoc updated-node :children children)))
+ updated-nodes))
+ (reduce [] nodes)))
+
+(defn ->html
+ "Transform a vector of `nodes` into an HTML string.
+
+ Options:
+ - `void-nodes` - A set of node names that are self-closing, defaults to:
+ - `:!doctype`
+ - `:area`
+ - `:base`
+ - `:br`
+ - `:col`
+ - `:embed`
+ - `:hr`
+ - `:img`
+ - `:input`
+ - `:link`
+ - `:meta`
+ - `:source`
+ - `:track`
+ - `:wbr`
+ "
+ ([nodes]
+ (->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