diff --git a/src/huff2/core.clj b/src/huff2/core.clj index 4e3727e..f78a839 100644 --- a/src/huff2/core.clj +++ b/src/huff2/core.clj @@ -262,6 +262,16 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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. @@ -269,18 +279,32 @@ 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 "" (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 "") + (html-write writer opts h))) diff --git a/test/huff/core2_test.clj b/test/huff/core2_test.clj index b6a1cc1..7ef2ae0 100644 --- a/test/huff/core2_test.clj +++ b/test/huff/core2_test.clj @@ -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]))) @@ -180,3 +180,27 @@ (str (h/html [:div {:style {:width (-> 10 h/vmin)}}])))) (is (= "
" (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 (= "
!
" (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 "bold"]) + (is (= "bold" (str sw))))) + (testing "components" + (let [sw (java.io.StringWriter.) + greet (fn [name] [:span "Hello, " name])] + (h/html-write sw [:div [greet "World"]]) + (is (= "
Hello, World
" (str sw)))))) + +(deftest page-write-test + (let [sw (java.io.StringWriter.)] + (h/page-write sw {:allow-raw true} [:h1 "hi"]) + (is (= "

hi

" (str sw)))))