Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions src/huff2/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -262,25 +262,49 @@

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Public api

(defn- emit-parsed!
[append! {:keys [allow-raw *explainer *parser]
:or {allow-raw false, *explainer explainer, *parser parser}} h]
(let [parsed (*parser h)]
(if (= parsed :malli.core/invalid)
(let [{:keys [value]} (*explainer h)]
(throw (ex-info "Invalid huff form passed to html. See [[hiccup-schema]] for more info"
{:value value})))
(emit append! parsed {:allow-raw allow-raw :parser *parser}))))

(defn html
"Generates html from hiccupy data-structures.

What's hiccupy data look like? see: [[hiccup-schema]].

Can I extend this by adding new types of nodes? Yes: see: [[huff2.extension]]!"
([h] (html {} h))
([{:keys [allow-raw *explainer *parser] :or {allow-raw false
*explainer explainer
*parser parser} :as _opts} h]
(let [parsed (*parser h)]
(if (= parsed :malli.core/invalid)
(let [{:keys [value]} (*explainer h)]
(throw (ex-info "Invalid huff form passed to html. See [[hiccup-schema]] for more info" {:value value})))
(let [sb (StringBuilder.)
append! (fn append! [& strings] (doseq [s strings :when s] (.append ^StringBuilder sb s)))]
(emit append! parsed {:allow-raw allow-raw :parser *parser})
(raw-string (str sb)))))))
([opts h]
(let [sb (StringBuilder.)
append! (fn append! [& strings]
(doseq [s strings :when s] (.append ^StringBuilder sb s)))]
(emit-parsed! append! opts h)
(raw-string (str sb)))))

(defn page
([h] (page {} h))
([opts h] (str "<!doctype html>" (html opts h))))

(defn html-write
"Writes html from hiccup data to a java.io.Writer. Returns nil.
Does not flush the writer."
([^java.io.Writer writer h] (html-write writer {} h))
([^java.io.Writer writer opts h]
(let [append! (fn append! [& strings]
(doseq [s strings :when s]
(.write ^java.io.Writer writer (str s))))]
(emit-parsed! append! opts h)
nil)))

(defn page-write
"Writes a full HTML page (with doctype) to a java.io.Writer. Returns nil.
Does not flush the writer."
([^java.io.Writer writer h] (page-write writer {} h))
([^java.io.Writer writer opts h]
(.write ^java.io.Writer writer "<!doctype html>")
(html-write writer opts h)))
26 changes: 25 additions & 1 deletion test/huff/core2_test.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns huff.core2-test
(:require [huff2.core :as h]
[clojure.string :as str]
[clojure.test :refer [deftest is]]))
[clojure.test :refer [deftest is testing]]))

(deftest class-list-equality-test
(is (= (h/html [:div]) (h/html [:div])))
Expand Down Expand Up @@ -180,3 +180,27 @@
(str (h/html [:div {:style {:width (-> 10 h/vmin)}}]))))
(is (= "<div style=\"width:10vmax;\"></div>"
(str (h/html [:div {:style {:width (-> 10 h/vmax)}}])))))

(deftest html-write-test
(let [sw (java.io.StringWriter.)]
(h/html-write sw [:div.hello#world "!"])
(is (= "<div id=\"world\" class=\"hello\">!</div>" (str sw))))
(testing "matches html output"
(let [sw (java.io.StringWriter.)
hiccup [:ul (for [n (range 3)] [:li n])]]
(h/html-write sw hiccup)
(is (= (str (h/html hiccup)) (str sw)))))
(testing "with opts"
(let [sw (java.io.StringWriter.)]
(h/html-write sw {:allow-raw true} [:hiccup/raw-html "<b>bold</b>"])
(is (= "<b>bold</b>" (str sw)))))
(testing "components"
(let [sw (java.io.StringWriter.)
greet (fn [name] [:span "Hello, " name])]
(h/html-write sw [:div [greet "World"]])
(is (= "<div><span>Hello, World</span></div>" (str sw))))))

(deftest page-write-test
(let [sw (java.io.StringWriter.)]
(h/page-write sw {:allow-raw true} [:h1 "hi"])
(is (= "<!doctype html><h1>hi</h1>" (str sw)))))