# Dompa [![Tests](https://github.com/askonomm/dompa/actions/workflows/tests.yml/badge.svg)](https://github.com/askonomm/dompa/actions/workflows/tests.yml) [![CodeScene Average Code Health](https://codescene.io/projects/72504/status-badges/average-code-health)](https://codescene.io/projects/72504) A zero-dependency, runtime-agnostic HTML parser (and builder). Dompa is continuesly tested to run in the following Clojure runtimes: - Clojure - ClojureScript - Babashka ## Installation You can fetch it straight from GitHub by adding this to your `deps.edn`: ```clojure {:deps {askonomm/dompa {:git/url "https://github.com/askonomm/dompa" :git/tag "v1.0.1" :git/sha "35de9bc8aaaa165ec3f2efb04691bdca3dd5e446"}}} ``` ## Usage ### Parsing HTML You can use Dompa to parse an HTML string into a vector of nodes like this: ```clojure (ns my.app (:require [dompa.html :as html]) (html/->nodes "
hello world
") ``` Which would result in a data structure such as: ```clojure [{:node/name :div :node/attrs {} :node/children [{:node/name :dompa/text :node/value "hello "} {:node/name :strong :node/attrs {} :node/children [{:node/name :dompa/text :node/value "world"}]}]}] ``` ### Creating HTML You can turn a vector of nodes, such as those above, back into a HTML string as well: ```clojure (ns my.app (:require [dompa.nodes :as nodes]) (nodes/->html [...]) ``` Which would then result in a HTML string. ### Traversing and modifying nodes There's a convenience function `dompa.nodes/traverse` which helps you traverse and modify a node tree, like this: ```clojure (ns my.app (:require [dompa.nodes :refer [traverse]]) (defn update-text-value [node] (if (= :dompa/text (:node/name node)) (assoc node :node/value "updated text") node)) (traverse [...] update-text-value) ``` The above would update all text nodes to have the value of "updated text". If you wish to keep a node unchanged, just return the node as-is, and if you wish to remove a node, return `nil`. ### Create nodes with the `$` helper function If you want a more convenient way of creating nodes, without having to create the full map manually, you can use the `dompa.nodes/$` helper function. Creating a node is as simple as: ```clojure (ns my.app (:require [dompa.nodes :refer [$]]) ($ :button) ``` You can also add attributes to it: ```clojure (ns my.app (:require [dompa.nodes :refer [$]]) ($ :button {:class "some-btn"}) ``` And text nodes can be created by simply omitting the first node name keyword, like so: ```clojure (ns my.app (:require [dompa.nodes :refer [$]]) ($ "hello world") ``` Which now when you put both together can look like this: ```clojure (ns my.app (:require [dompa.nodes :refer [$]]) ($ :button {:class "some-btn"} ($ "hello world")) ``` It's important to note that when creating a text node, it cannot have any children nodes, only literal values and/or vars, whereas non-text nodes can have children as either their second argument, if they lack a attribute map, or as their third argument if they have an argument map. ### Create HTML with the `defhtml` helper macro If you want a more convenient way of creating functions that convert nodes into HTML on their own during compile-time, you can use the `defhtml` macro: ```clojure (ns my.app (:require [dompa.nodes :refer [defhtml $]]) (defhtml hello-page [who] ($ :div ($ "hello " who))) (hello-page "world") ``` And of course making lists and such works the same as you'd imagine: ```clojure (ns my.app (:require [dompa.nodes :refer [defhtml $]]) (def names ["john" "mike" "jenna" "bob"]) (defhtml hello-page [] ($ :div (map #($ (str "hello " %)) names))) (hello-page) ``` Do note that when using the `defhtml` macro in ClojureScript, you have to use `:refer-macros` instead of `:refer`, due to the differences in how ClojureScript deals with macros. ### Other While the above covers the most common use cases of Dompa, such as turning HTML into a tree of nodes and vice versa, you can actually make use of the underlying lower-level stuff that makes it all work separately as well: - `dompa.coordinates/compose` - create coordinates (range positions) of HTML nodes from a HTML string - `dompa.coordinates/unify` - unify coordinates (merges the same block nodes together) - `dompa.coordinates/->nodes` - transform coordinates into a tree of nodes - `dompa.html/->coordinates` - transform HTML into coordinates