From a2e703f10554f3aa99487b53de4e5e6a5d6ebddd Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Sun, 26 Oct 2025 11:21:58 +0200 Subject: Add alias for test repl --- deps.edn | 1 + 1 file changed, 1 insertion(+) diff --git a/deps.edn b/deps.edn index ed48cd9..31d2d77 100644 --- a/deps.edn +++ b/deps.edn @@ -2,6 +2,7 @@ :paths ["src" "resources"] :aliases {:dev {:extra-paths ["resources/clj-kondo"] :extra-deps {clj-kondo/clj-kondo {:mvn/version "2025.09.22"}}} + :test {:extra-paths ["test"]} :test-clj {:extra-paths ["test"] :extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd6"}} -- cgit v1.2.3 From bb8a17fa2517324ac6cd0ce498dcc189a2d8fb2c Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Sun, 26 Oct 2025 11:22:46 +0200 Subject: #9: Implement zipper support --- src/dompa/nodes.cljc | 15 ++++++++++++++- test/dompa/nodes_test.cljc | 29 ++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/dompa/nodes.cljc b/src/dompa/nodes.cljc index 9dbecd0..e99b364 100644 --- a/src/dompa/nodes.cljc +++ b/src/dompa/nodes.cljc @@ -1,4 +1,5 @@ -(ns dompa.nodes) +(ns dompa.nodes + (:require [clojure.zip :as zip])) (def ^:private default-void-nodes #{:!doctype :!DOCTYPE :area :base :br :col :embed :hr :img :input @@ -50,6 +51,18 @@ updated-nodes)) (reduce [] nodes))) +(defn zip + "Creates a zipper for given a given `node`." + [node] + (zip/zipper + (fn branch? [node] + (boolean (seq (:node/children node)))) + (fn children [node] + (:node/children node)) + (fn make-node [node children] + (assoc node :node/children children)) + node)) + (defn ->html "Transform a vector of `nodes` into an HTML string. diff --git a/test/dompa/nodes_test.cljc b/test/dompa/nodes_test.cljc index 2606be6..ca8d483 100644 --- a/test/dompa/nodes_test.cljc +++ b/test/dompa/nodes_test.cljc @@ -1,9 +1,12 @@ (ns dompa.nodes-test - #?(:clj (:require [clojure.test :refer [deftest is testing]] - [dompa.nodes :refer [$ defhtml traverse ->html]] - [dompa.html :as html])) + #?(:clj (:require + [clojure.test :refer [deftest is testing]] + [clojure.zip :as zip] + [dompa.html :as html] + [dompa.nodes :as nodes :refer [$ defhtml]])) #?(:cljs (:require [cljs.test :refer-macros [deftest testing is]] - [dompa.nodes :refer [$ traverse ->html] :refer-macros [defhtml]] + [clojure.zip :as zip] + [dompa.nodes :as nodes :refer [$] :refer-macros [defhtml]] [dompa.html :as html]))) (defhtml hello [who] @@ -18,7 +21,7 @@ ($ :ul (->> items (map (fn [item] - ($ :li ($ item)))) + ($ :li ($ item)))) (into [])))) (deftest list-items-test @@ -53,5 +56,17 @@ node))] (is (= "
world hello
" (-> (html/->nodes "
hello world
") - (traverse traverser-fn) - ->html))))) + (nodes/traverse traverser-fn) + nodes/->html))))) + +(deftest zip-test + (let [nodes (html/->nodes "

hello

world

") + zipper (nodes/zip (first nodes))] + (is (= :div + (:node/name (zip/node zipper)))) + (is (= "hello" + (-> zipper + zip/down + zip/down + zip/node + :node/value))))) \ No newline at end of file -- cgit v1.2.3 From a0a150d89d30af3ca4d586fc7874d70778b51e73 Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Sun, 26 Oct 2025 11:34:51 +0200 Subject: Update README --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 003cd07..d106d1b 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,23 @@ The function you provide to `traverse` dictates the outcome for each node: * To **remove a node**, return `nil`. * To **replace a node with many nodes on the same level**, return a [fragment node](#fragment-nodes), which will be replaced by its children during HTML transformation. +#### Zipping + +You can also use the `dompa.nodes/zip` function to create a [zipper](https://clojuredocs.org/clojure.zip/zipper) of a node, i.e: + +```clojure +(ns my.app + (:require [dompa.nodes :as nodes] + [clojure.zip :as zip]) + +(->> (nodes/zip {..node}) + zip/down + zip/node) +``` + +And of course you can use this in combination with the `traverse` method as well, since the `traverse` method always operates on a single node at a time, +and the zipper always starts with a root node, the two complement each other well. + ----- ### 🛠️ Building Nodes with the `$` Helper -- cgit v1.2.3