Skip to content

Instantly share code, notes, and snippets.

@apeckham
Created November 25, 2022 20:24
Show Gist options
  • Save apeckham/cd800e745370820e0064193fcd962bb1 to your computer and use it in GitHub Desktop.
Save apeckham/cd800e745370820e0064193fcd962bb1 to your computer and use it in GitHub Desktop.
custom tags in hiccup/clojure
(ns www.custom-tags
(:require
[clojure.walk :refer [postwalk]]))
(defn walk
[input fns]
(postwalk (fn [node]
(if (vector? node)
(if-let [f (fns (first node))]
(apply f (rest node))
node)
node))
input))
(ns www.custom-tags-test
(:require
[clojure.test :refer [deftest is testing]]
[hiccup.core :refer [html]]
[www.custom-tags :as custom-tags])
(:import
(clojure.lang ArityException)))
(deftest html-test (is (= "<b>asdf</b>" (html [:b "asdf"]))))
(def bold+italic
{:arity (fn [child] [:blink child])
:bold #(into [] (concat [:b] %&))
:italic #(into [] (concat [:i] %&))
:link (fn [{:keys [href]} & children] (into [] (concat [:a {:href href}] children)))
:string (constantly "asdf")})
(deftest walk-test
(let [w #(custom-tags/walk % bold+italic)]
(testing "vector" (is (vector? (w [:bold "asdf"]))))
(testing "one param" (is (= [:b "asdf"] (w [:bold "asdf"]))))
(testing "no params" (is (= [:b] (w [:bold]))))
(testing "two params" (is (= [:b "asdf" "zxcv"] (w [:bold "asdf" "zxcv"]))))
(testing "ignores unrecognized tags" (is (= [:zzzz] (w [:zzzz]))))
(testing "bold and bold" (is (= [:b [:b "asdf"]] (w [:bold [:bold "asdf"]]))))
(testing "bold and italic" (is (= [:b [:i "asdf"]] (w [:bold [:italic "asdf"]]))))
(testing "link"
(is (= [:a {:href "example.com"} [:b "hey"]] (w [:link {:href "example.com"} [:bold "hey"]]))))
(testing "arity"
(testing "exactly one arg" (is (= [:blink "zxcv"] (w [:arity "zxcv"]))))
(testing "too few args"
(is (thrown-with-msg? ArityException #"Wrong number of args \(0\)" (w [:arity]))))
(testing "too many args"
(is
(thrown-with-msg? ArityException #"Wrong number of args \(2\)" (w [:arity "a" "b"])))))
(testing "string" (is (= "asdf" (w [:string]))))))
(deftest walk+html-test
(is (= "<b><i><b>zzzz</b></i></b>" (html (custom-tags/walk [:bold [:italic [:bold "zzzz"]]] bold+italic)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment