This commit is contained in:
roman01la
2020-07-08 12:55:48 +03:00
parent 05102eaf22
commit 329fafbbea
7 changed files with 287 additions and 289 deletions

View File

@ -1,13 +1,13 @@
(ns rum.core
(:refer-clojure :exclude [ref deref])
(:require
[rum.cursor :as cursor]
[rum.server-render :as render]
[rum.util :refer [collect collect* call-all]]
[rum.derived-atom :as derived-atom]
[daiquiri.compiler :as compiler]
[rum.specs]
[clojure.set :as set])
[rum.cursor :as cursor]
[rum.server-render :as render]
[rum.util :refer [collect collect* call-all]]
[rum.derived-atom :as derived-atom]
[daiquiri.compiler :as compiler]
[rum.specs]
[clojure.set :as set])
(:import
[rum.cursor Cursor]
(rum.server_render JSComponent)))
@ -68,7 +68,6 @@
`(rum.core/lazy-build ~builder (fn ~@render-bodies) ~mixins ~display-name)
`(~builder (fn ~@render-bodies) ~mixins ~display-name)))))
(defmacro defc
"```
(defc name doc-string? (< mixins+)? [ params* ] render-body+)

View File

@ -13,8 +13,8 @@
(defmacro with-compiler-env [[env-sym] & body]
`(binding [ana/*cljs-static-fns* true]
(env/with-compiler-env (env/default-compiler-env)
(let [~env-sym (assoc-in (ana/empty-env) [:ns :name] 'cljs.user)]
~@body))))
(let [~env-sym (assoc-in (ana/empty-env) [:ns :name] 'cljs.user)]
~@body))))
(defn analyze
([env form]
@ -29,11 +29,11 @@
(defn replace-gensyms [forms]
(prewalk
(fn [form]
(if (and (symbol? form)
(re-matches #"attrs\d+" (str form)))
'attrs form))
forms))
(fn [form]
(if (and (symbol? form)
(re-matches #"attrs\d+" (str form)))
'attrs form))
forms))
(defn ===
"Same as clojure.core/=, but strips of numbers from gensyms before comparison."
@ -77,127 +77,127 @@
(defmacro are-html [& body]
`(are [form# expected#]
(=== (macroexpand-1 `(html ~form#)) expected#)
(=== (macroexpand-1 `(html ~form#)) expected#)
~@body))
(deftest test-compile-html
(testing "basic tags"
(are-html
'[:div] '(daiquiri.core/create-element "div" nil nil)
'["div"] '(daiquiri.core/create-element "div" nil nil)
'['div] '(daiquiri.core/create-element "div" nil nil)))
'[:div] '(daiquiri.core/create-element "div" nil nil)
'["div"] '(daiquiri.core/create-element "div" nil nil)
'['div] '(daiquiri.core/create-element "div" nil nil)))
(testing "tag syntax sugar"
(are-html
'[:#foo] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "foo") nil)
'[:div#foo] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "foo") nil)
'[:div.foo] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "foo") nil)
'[:.foo] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "foo") nil)
'[:div.a.b] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a b") nil)
'[:div#foo.bar] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "foo" "bar") nil)
'[:div.foo (str "bar" "baz")] '(clojure.core/let [attrs (str "bar" "baz")]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs)
(daiquiri.interpreter/attributes (daiquiri.normalize/merge-with-class {:class ["foo"]} attrs))
(js* "{'className':~{}}" "foo"))
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
'[:#foo] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "foo") nil)
'[:div#foo] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "foo") nil)
'[:div.foo] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "foo") nil)
'[:.foo] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "foo") nil)
'[:div.a.b] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a b") nil)
'[:div#foo.bar] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "foo" "bar") nil)
'[:div.foo (str "bar" "baz")] '(clojure.core/let [attrs (str "bar" "baz")]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs)
(daiquiri.interpreter/attributes (daiquiri.normalize/merge-with-class {:class ["foo"]} attrs))
(js* "{'className':~{}}" "foo"))
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
(testing "tags containing text"
(are-html
'[:text "Lorem Ipsum"] '(daiquiri.core/create-element "text" nil (cljs.core/array "Lorem Ipsum"))))
'[:text "Lorem Ipsum"] '(daiquiri.core/create-element "text" nil (cljs.core/array "Lorem Ipsum"))))
(testing "contents are concatenated"
(are-html
'[:div "foo" "bar"] '(daiquiri.core/create-element "div" nil (cljs.core/array "foo" "bar"))
'[:div [:p] [:br]] '(daiquiri.core/create-element "div" nil
(cljs.core/array
(daiquiri.core/create-element "p" nil nil)
(daiquiri.core/create-element "br" nil nil)))))
'[:div "foo" "bar"] '(daiquiri.core/create-element "div" nil (cljs.core/array "foo" "bar"))
'[:div [:p] [:br]] '(daiquiri.core/create-element "div" nil
(cljs.core/array
(daiquiri.core/create-element "p" nil nil)
(daiquiri.core/create-element "br" nil nil)))))
(testing "seqs are expanded"
(are-html
'[:div (list "foo" "bar")] '(clojure.core/let [attrs (list "foo" "bar")]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
'(list [:p "a"] [:p "b"])
'(daiquiri.compiler/interpret-maybe (list [:p "a"] [:p "b"]))))
'[:div (list "foo" "bar")] '(clojure.core/let [attrs (list "foo" "bar")]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
'(list [:p "a"] [:p "b"])
'(daiquiri.compiler/interpret-maybe (list [:p "a"] [:p "b"]))))
(testing "tags can contain tags"
(are-html
'[:div [:p]] '(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:p [:span [:a "foo"]]] '(daiquiri.core/create-element "p" nil
(cljs.core/array
(daiquiri.core/create-element "span" nil
(cljs.core/array (daiquiri.core/create-element "a" nil (cljs.core/array "foo")))))))))
'[:div [:p]] '(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:p [:span [:a "foo"]]] '(daiquiri.core/create-element "p" nil
(cljs.core/array
(daiquiri.core/create-element "span" nil
(cljs.core/array (daiquiri.core/create-element "a" nil (cljs.core/array "foo")))))))))
(deftest test-attributes
(testing "tag with empty attribute map"
(are-html
'[:div {}] '(daiquiri.core/create-element "div" nil nil)))
'[:div {}] '(daiquiri.core/create-element "div" nil nil)))
(testing "tag with populated attribute map"
(are-html
'[:div {:min "1", :max "2"}] '(daiquiri.core/create-element "div" (js* "{'min':~{},'max':~{}}" "1" "2") nil)
'[:img {"id" "foo"}] '(daiquiri.core/create-element "img" (js* "{'id':~{}}" "foo") nil)
'[:img {:id "foo"}] '(daiquiri.core/create-element "img" (js* "{'id':~{}}" "foo") nil)))
'[:div {:min "1", :max "2"}] '(daiquiri.core/create-element "div" (js* "{'min':~{},'max':~{}}" "1" "2") nil)
'[:img {"id" "foo"}] '(daiquiri.core/create-element "img" (js* "{'id':~{}}" "foo") nil)
'[:img {:id "foo"}] '(daiquiri.core/create-element "img" (js* "{'id':~{}}" "foo") nil)))
(testing "attribute values are escaped"
(are-html
'[:div {:id "\""}] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "\"") nil)))
'[:div {:id "\""}] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "\"") nil)))
(testing "attributes are converted to their ReactDOM equivalents"
(are-html
'[:div {:class "classy"}] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "classy") nil)
'[:div {:data-foo-bar "baz"}] '(daiquiri.core/create-element "div" (js* "{'data-foo-bar':~{}}" "baz") nil)
'[:label {:for "foo"}] '(daiquiri.core/create-element "label" (js* "{'htmlFor':~{}}" "foo") nil)))
'[:div {:class "classy"}] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "classy") nil)
'[:div {:data-foo-bar "baz"}] '(daiquiri.core/create-element "div" (js* "{'data-foo-bar':~{}}" "baz") nil)
'[:label {:for "foo"}] '(daiquiri.core/create-element "label" (js* "{'htmlFor':~{}}" "foo") nil)))
(testing "boolean attributes"
(are-html
'[:input {:type "checkbox" :checked true}] '(daiquiri.core/create-element "input" (js* "{'type':~{},'checked':~{}}" "checkbox" true) nil)
'[:input {:type "checkbox" :checked false}] '(daiquiri.core/create-element "input" (js* "{'type':~{},'checked':~{}}" "checkbox" false) nil)))
'[:input {:type "checkbox" :checked true}] '(daiquiri.core/create-element "input" (js* "{'type':~{},'checked':~{}}" "checkbox" true) nil)
'[:input {:type "checkbox" :checked false}] '(daiquiri.core/create-element "input" (js* "{'type':~{},'checked':~{}}" "checkbox" false) nil)))
(testing "nil attributes"
(are-html
'[:span {:class nil} "foo"] '(daiquiri.core/create-element "span" (js* "{'className':~{}}" nil) (cljs.core/array "foo"))))
'[:span {:class nil} "foo"] '(daiquiri.core/create-element "span" (js* "{'className':~{}}" nil) (cljs.core/array "foo"))))
(testing "empty attributes"
(are-html
'[:span {} "foo"] '(daiquiri.core/create-element "span" nil (cljs.core/array "foo"))))
'[:span {} "foo"] '(daiquiri.core/create-element "span" nil (cljs.core/array "foo"))))
(testing "tag with aria attributes"
(are-html
'[:div {:aria-disabled true}] '(daiquiri.core/create-element "div" (js* "{'aria-disabled':~{}}" true) nil)))
'[:div {:aria-disabled true}] '(daiquiri.core/create-element "div" (js* "{'aria-disabled':~{}}" true) nil)))
(testing "tag with data attributes"
(are-html
'[:div {:data-toggle "modal" :data-target "#modal"}] '(daiquiri.core/create-element "div" (js* "{'data-toggle':~{},'data-target':~{}}" "modal" "#modal") nil)))
'[:div {:data-toggle "modal" :data-target "#modal"}] '(daiquiri.core/create-element "div" (js* "{'data-toggle':~{},'data-target':~{}}" "modal" "#modal") nil)))
(testing "tag with custom attributes"
(are-html
'[:div {"ng-hello" "hello"}] '(daiquiri.core/create-element "div" (js* "{'ng-hello':~{}}" "hello") nil))))
'[:div {"ng-hello" "hello"}] '(daiquiri.core/create-element "div" (js* "{'ng-hello':~{}}" "hello") nil))))
(deftest compiled-tags
(testing "tag content can be vars, and vars can be type-hinted with some metadata"
(let [x "foo"
y {:id "id"}]
(are-html
'[:span x] '(clojure.core/let [attrs x]
(daiquiri.core/create-element "span"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
'[:span ^:attrs y] '(clojure.core/let [attrs y]
(daiquiri.core/create-element "span" (daiquiri.interpreter/attributes attrs) nil)))))
'[:span x] '(clojure.core/let [attrs x]
(daiquiri.core/create-element "span"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
'[:span ^:attrs y] '(clojure.core/let [attrs y]
(daiquiri.core/create-element "span" (daiquiri.interpreter/attributes attrs) nil)))))
(testing "tag content can be forms, and forms can be type-hinted with some metadata"
(are-html
'[:span (str (+ 1 1))] '(clojure.core/let [attrs (str (+ 1 1))]
(daiquiri.core/create-element "span"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
[:span ({:foo "bar"} :foo)] '(daiquiri.core/create-element "span" nil (cljs.core/array "bar"))
'[:span ^:attrs (merge {:type "button"} attrs)] '(clojure.core/let [attrs (merge {:type "button"} attrs)]
(daiquiri.core/create-element "span" (daiquiri.interpreter/attributes attrs) nil))))
'[:span (str (+ 1 1))] '(clojure.core/let [attrs (str (+ 1 1))]
(daiquiri.core/create-element "span"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))
[:span ({:foo "bar"} :foo)] '(daiquiri.core/create-element "span" nil (cljs.core/array "bar"))
'[:span ^:attrs (merge {:type "button"} attrs)] '(clojure.core/let [attrs (merge {:type "button"} attrs)]
(daiquiri.core/create-element "span" (daiquiri.interpreter/attributes attrs) nil))))
(testing "attributes can contain vars"
(let [id "id"]
(are-html
'[:div {:id id}] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" id) (cljs.core/array))
'[:div {:id id} "bar"] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" id) (cljs.core/array "bar")))))
'[:div {:id id}] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" id) (cljs.core/array))
'[:div {:id id} "bar"] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" id) (cljs.core/array "bar")))))
(testing "attributes are evaluated"
(are-html
'[:img {:src (str "/foo" "/bar")}] '(daiquiri.core/create-element "img" (js* "{'src':~{}}" (str "/foo" "/bar")) (cljs.core/array))
'[:div {:id (str "a" "b")} (str "foo")] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" (str "a" "b"))
(cljs.core/array (daiquiri.compiler/interpret-maybe (str "foo"))))))
'[:img {:src (str "/foo" "/bar")}] '(daiquiri.core/create-element "img" (js* "{'src':~{}}" (str "/foo" "/bar")) (cljs.core/array))
'[:div {:id (str "a" "b")} (str "foo")] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" (str "a" "b"))
(cljs.core/array (daiquiri.compiler/interpret-maybe (str "foo"))))))
(testing "type hints"
;; TODO. Use cljs type inference
(let [string "x"]
(are-html
'[:span ^String string] '(daiquiri.core/create-element "span" nil (cljs.core/array string)))))
'[:span ^String string] '(daiquiri.core/create-element "span" nil (cljs.core/array string)))))
(testing "values are evaluated only once"
(let [times-called (atom 0)
foo #(swap! times-called inc)]
@ -207,114 +207,113 @@
(deftest fragments
(testing "React 16 fragment syntactic support"
(are-html
'[:*] '(daiquiri.core/create-element daiquiri.core/fragment nil nil)
'[:<>] '(daiquiri.core/create-element daiquiri.core/fragment nil nil)
'[:*] '(daiquiri.core/create-element daiquiri.core/fragment nil nil)
'[:<>] '(daiquiri.core/create-element daiquiri.core/fragment nil nil)
'[:* [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:<> [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:* [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:<> [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil (cljs.core/array (daiquiri.core/create-element "p" nil nil)))
'[:* [:p] [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil
(cljs.core/array (daiquiri.core/create-element "p" nil nil) (daiquiri.core/create-element "p" nil nil)))
'[:<> [:p] [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil
(cljs.core/array (daiquiri.core/create-element "p" nil nil) (daiquiri.core/create-element "p" nil nil)))
'[:* [:p] [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil
(cljs.core/array (daiquiri.core/create-element "p" nil nil) (daiquiri.core/create-element "p" nil nil)))
'[:<> [:p] [:p]] '(daiquiri.core/create-element daiquiri.core/fragment nil
(cljs.core/array (daiquiri.core/create-element "p" nil nil) (daiquiri.core/create-element "p" nil nil)))
'[:dl (for [n (range 2)]
[:* {:key n}
[:dt {} (str "term " n)]
[:dd {} (str "definition " n)]])]
'(daiquiri.core/create-element
"dl"
nil
(cljs.core/array
(into-array
(clojure.core/for
[n (range 2)]
(daiquiri.core/create-element
daiquiri.core/fragment
(js* "{'key':~{}}" n)
(cljs.core/array
(daiquiri.core/create-element "dt" nil (cljs.core/array (daiquiri.compiler/interpret-maybe (str "term " n))))
(daiquiri.core/create-element "dd" nil (cljs.core/array (daiquiri.compiler/interpret-maybe (str "definition " n)))))))))))))
'[:dl (for [n (range 2)]
[:* {:key n}
[:dt {} (str "term " n)]
[:dd {} (str "definition " n)]])]
'(daiquiri.core/create-element
"dl"
nil
(cljs.core/array
(into-array
(clojure.core/for
[n (range 2)]
(daiquiri.core/create-element
daiquiri.core/fragment
(js* "{'key':~{}}" n)
(cljs.core/array
(daiquiri.core/create-element "dt" nil (cljs.core/array (daiquiri.compiler/interpret-maybe (str "term " n))))
(daiquiri.core/create-element "dd" nil (cljs.core/array (daiquiri.compiler/interpret-maybe (str "definition " n)))))))))))))
(deftest test-issue-2-merge-class
(are-html
'[:div.a {:class (if (true? true) "true" "false")}] '(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (if (true? true) "true" "false")]))
(cljs.core/array))
'[:div.a.b {:class (if (true? true) ["true"] "false")}] '(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" "b" (if (true? true) ["true"] "false")]))
(cljs.core/array))))
'[:div.a {:class (if (true? true) "true" "false")}] '(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (if (true? true) "true" "false")]))
(cljs.core/array))
'[:div.a.b {:class (if (true? true) ["true"] "false")}] '(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" "b" (if (true? true) ["true"] "false")]))
(cljs.core/array))))
(deftest test-issue-3-recursive-js-literal
(are-html
'[:div.interaction-row {:style {:position "relative"}}] '(daiquiri.core/create-element "div"
(js* "{'style':~{},'className':~{}}" (js* "{'position':~{}}" "relative") "interaction-row")
nil))
'[:div.interaction-row {:style {:position "relative"}}] '(daiquiri.core/create-element "div"
(js* "{'style':~{},'className':~{}}" (js* "{'position':~{}}" "relative") "interaction-row")
nil))
(let [username "foo"
hidden #(if %1 {:display "none"} {:display "block"})]
(are-html
'[:ul.nav.navbar-nav.navbar-right.pull-right
[:li.dropdown {:style (hidden (nil? username))}
[:a.dropdown-toggle {:role "button" :href "#"} (str "Welcome, " username)
[:span.caret]]
[:ul.dropdown-menu {:role "menu" :style {:left 0}}]]]
'(daiquiri.core/create-element
"ul"
(js* "{'className':~{}}" "nav navbar-nav navbar-right pull-right")
'[:ul.nav.navbar-nav.navbar-right.pull-right
[:li.dropdown {:style (hidden (nil? username))}
[:a.dropdown-toggle {:role "button" :href "#"} (str "Welcome, " username)
[:span.caret]]
[:ul.dropdown-menu {:role "menu" :style {:left 0}}]]]
'(daiquiri.core/create-element
"ul"
(js* "{'className':~{}}" "nav navbar-nav navbar-right pull-right")
(cljs.core/array
(daiquiri.core/create-element
"li"
(js* "{'style':~{},'className':~{}}" (daiquiri.interpreter/attributes (hidden (nil? username))) "dropdown")
(cljs.core/array
(daiquiri.core/create-element
"li"
(js* "{'style':~{},'className':~{}}" (daiquiri.interpreter/attributes (hidden (nil? username))) "dropdown")
(cljs.core/array
(daiquiri.core/create-element
"a"
(js* "{'role':~{},'href':~{},'className':~{}}" "button" "#" "dropdown-toggle")
(cljs.core/array
(daiquiri.compiler/interpret-maybe (str "Welcome, " username))
(daiquiri.core/create-element "span" (js* "{'className':~{}}" "caret") nil)))
(daiquiri.core/create-element
"ul"
(js* "{'role':~{},'style':~{},'className':~{}}" "menu" (js* "{'left':~{}}" 0) "dropdown-menu")
nil))))))))
(daiquiri.core/create-element
"a"
(js* "{'role':~{},'href':~{},'className':~{}}" "button" "#" "dropdown-toggle")
(cljs.core/array
(daiquiri.compiler/interpret-maybe (str "Welcome, " username))
(daiquiri.core/create-element "span" (js* "{'className':~{}}" "caret") nil)))
(daiquiri.core/create-element
"ul"
(js* "{'role':~{},'style':~{},'className':~{}}" "menu" (js* "{'left':~{}}" 0) "dropdown-menu")
nil))))))))
(deftest test-issue-22-id-after-class
(are-html
[:div.well#setup] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "setup" "well") nil)))
[:div.well#setup] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "setup" "well") nil)))
(deftest test-issue-25-comma-separated-class
(are-html
'[:div.c1.c2 "text"] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "c1 c2") (cljs.core/array "text"))
'[:div.aa (merge {:class "bb"})] '(clojure.core/let [attrs (merge {:class "bb"})]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs)
(daiquiri.interpreter/attributes (daiquiri.normalize/merge-with-class {:class ["aa"]} attrs))
(js* "{'className':~{}}" "aa"))
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
'[:div.c1.c2 "text"] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "c1 c2") (cljs.core/array "text"))
'[:div.aa (merge {:class "bb"})] '(clojure.core/let [attrs (merge {:class "bb"})]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs)
(daiquiri.interpreter/attributes (daiquiri.normalize/merge-with-class {:class ["aa"]} attrs))
(js* "{'className':~{}}" "aa"))
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
(deftest test-issue-33-number-warning
(are-html
'[:div (count [1 2 3])] '(clojure.core/let [attrs (count [1 2 3])]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
'[:div (count [1 2 3])] '(clojure.core/let [attrs (count [1 2 3])]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))
(deftest test-issue-37-camel-case-style-attrs
(are-html
'[:div {:style {:z-index 1000}}] '(daiquiri.core/create-element "div" (js* "{'style':~{}}" (js* "{'zIndex':~{}}" 1000)) nil)))
'[:div {:style {:z-index 1000}}] '(daiquiri.core/create-element "div" (js* "{'style':~{}}" (js* "{'zIndex':~{}}" 1000)) nil)))
(deftest shorthand-div-forms
(are-html
[:#test] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "test") nil)
'[:.klass] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "klass") nil)
'[:#test.klass] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass") nil)
'[:#test.klass1.klass2] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass1 klass2") nil)
'[:.klass1.klass2#test] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass1 klass2") nil)))
[:#test] '(daiquiri.core/create-element "div" (js* "{'id':~{}}" "test") nil)
'[:.klass] '(daiquiri.core/create-element "div" (js* "{'className':~{}}" "klass") nil)
'[:#test.klass] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass") nil)
'[:#test.klass1.klass2] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass1 klass2") nil)
'[:.klass1.klass2#test] '(daiquiri.core/create-element "div" (js* "{'id':~{},'className':~{}}" "test" "klass1 klass2") nil)))
(deftest test-namespaced-fn-call
(are-html
'(some-ns/comp "arg") '(daiquiri.compiler/interpret-maybe (some-ns/comp "arg"))
'(some.ns/comp "arg") '(daiquiri.compiler/interpret-maybe (some.ns/comp "arg"))))
'(some-ns/comp "arg") '(daiquiri.compiler/interpret-maybe (some-ns/comp "arg"))
'(some.ns/comp "arg") '(daiquiri.compiler/interpret-maybe (some.ns/comp "arg"))))
(defmacro expand-html [form]
`(macroexpand-1 '(html ~form)))
@ -323,8 +322,8 @@
(is (=== (expand-html [:div (map identity ["A" "B"])])
'(clojure.core/let [attrs (map identity ["A" "B"])]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs))))))))
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs))))))))
(deftest test-compile-div-with-nested-list
(is (= (expand-html [:div '("A" "B")])
@ -336,8 +335,8 @@
(is (=== (expand-html [:div (vector "A" "B")])
'(clojure.core/let [attrs (vector "A" "B")]
(daiquiri.core/create-element "div"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs))))))))
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs))))))))
(deftest test-class-as-set
(is (= (expand-html [:div.a {:class #{"a" "b" "c"}}])
@ -346,22 +345,22 @@
(deftest test-class-as-list
(is (= (expand-html [:div.a {:class (list "a" "b" "c")}])
'(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (list "a" "b" "c")]))
(cljs.core/array)))))
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (list "a" "b" "c")]))
(cljs.core/array)))))
(deftest test-class-as-vector
(is (= (expand-html [:div.a {:class (vector "a" "b" "c")}])
'(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (vector "a" "b" "c")]))
(cljs.core/array)))))
(js* "{'className':~{}}" (daiquiri.util/join-classes ["a" (vector "a" "b" "c")]))
(cljs.core/array)))))
(deftest test-class-merge-symbol
(let [class #{"b"}]
(are-html
[:div.a {:class class}]
'(daiquiri.core/create-element "div"
(js* "{'className':~{}}" "a b")
nil))))
[:div.a {:class class}]
'(daiquiri.core/create-element "div"
(js* "{'className':~{}}" "a b")
nil))))
(deftest test-issue-90
(is (= (expand-html [:div nil (case :a :a "a")])
@ -369,10 +368,10 @@
(deftest test-compile-attr-class
(are [form expected]
(= expected (compiler/compile-attr :class form))
(= expected (compiler/compile-attr :class form))
nil nil
"foo" "foo"
'("foo" "bar" ) "foo bar"
'("foo" "bar") "foo bar"
["foo" "bar"] "foo bar"
#{"foo" "bar"} "foo bar"
'(set "foo" "bar") '(daiquiri.util/join-classes (set "foo" "bar"))
@ -386,24 +385,24 @@
(deftest test-optimize-for-loop
(is (=== (expand-html [:ul (for [n (range 3)] [:li n])])
'(daiquiri.core/create-element "ul" nil
(cljs.core/array
(into-array
(clojure.core/for
[n (range 3)]
(clojure.core/let
[attrs n]
(daiquiri.core/create-element
"li"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))))))
(cljs.core/array
(into-array
(clojure.core/for
[n (range 3)]
(clojure.core/let
[attrs n]
(daiquiri.core/create-element
"li"
(if (clojure.core/map? attrs) (daiquiri.interpreter/attributes attrs) nil)
(if (clojure.core/map? attrs) nil (cljs.core/array (daiquiri.compiler/interpret-maybe attrs)))))))))))
(is (=== (expand-html [:ul (for [n (range 3)] [:li ^:attrs n])])
'(daiquiri.core/create-element "ul" nil
(cljs.core/array
(into-array
(clojure.core/for
[n (range 3)]
(clojure.core/let [attrs n]
(daiquiri.core/create-element "li" (daiquiri.interpreter/attributes attrs) nil)))))))))
(cljs.core/array
(into-array
(clojure.core/for
[n (range 3)]
(clojure.core/let [attrs n]
(daiquiri.core/create-element "li" (daiquiri.interpreter/attributes attrs) nil)))))))))
(deftest test-compile-case
(is (= (expand-html [:div {:class "a"}
@ -412,11 +411,11 @@
"b" [:div "b"]
[:div "else"])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/case "a"
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
(daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(cljs.core/array
(clojure.core/case "a"
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
(daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(deftest test-compile-cond
(is (= (expand-html [:div {:class "a"}
@ -425,11 +424,11 @@
"b" [:div "b"]
:else [:div "else"])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/cond
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
:else (daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(cljs.core/array
(clojure.core/cond
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
:else (daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(deftest test-compile-condp
(is (= (expand-html [:div {:class "a"}
@ -438,11 +437,11 @@
"b" [:div "b"]
[:div "else"])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/condp = "a"
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
(daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(cljs.core/array
(clojure.core/condp = "a"
"a" (daiquiri.core/create-element "div" nil (cljs.core/array "a"))
"b" (daiquiri.core/create-element "div" nil (cljs.core/array "b"))
(daiquiri.core/create-element "div" nil (cljs.core/array "else"))))))))
(deftest test-optimize-if
(is (= (expand-html (if true [:span "foo"] [:span "bar"]))
@ -453,16 +452,16 @@
(deftest test-compile-if-not
(is (= (expand-html [:div {:class "a"} (if-not false [:div [:div]])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/if-not false
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(cljs.core/array
(clojure.core/if-not false
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(deftest test-compile-if-some
(is (= (expand-html [:div {:class "a"} (if-some [x true] [:div [:div]])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/if-some [x true]
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(cljs.core/array
(clojure.core/if-some [x true]
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(deftest test-issue-115
(is (= (expand-html [:a {:id :XY}])
@ -472,8 +471,8 @@
(let [css {:table-cell "bg-blue"}]
(is (= (expand-html [:div {:class (:table-cell css)} [:span "abc"]])
'(daiquiri.core/create-element "div"
(js* "{'className':~{}}" (daiquiri.util/join-classes [(:table-cell css)]))
(cljs.core/array (daiquiri.core/create-element "span" nil (cljs.core/array "abc"))))))))
(js* "{'className':~{}}" (daiquiri.util/join-classes [(:table-cell css)]))
(cljs.core/array (daiquiri.core/create-element "span" nil (cljs.core/array "abc"))))))))
(deftest test-issue-141-inline
(testing "with attributes"
@ -486,36 +485,36 @@
(deftest test-compile-attributes-non-literal-key
(is (= (expand-html [:input {(case :checkbox :checkbox :checked :value) "x"}])
'(daiquiri.core/create-element "input"
(daiquiri.interpreter/attributes {(case :checkbox :checkbox :checked :value) "x"})
(cljs.core/array)))))
(daiquiri.interpreter/attributes {(case :checkbox :checkbox :checked :value) "x"})
(cljs.core/array)))))
(deftest test-issue-158
(is (= (expand-html [:div {:style (merge {:margin-left "2rem"}
(when focused? {:color "red"}))}])
'(daiquiri.core/create-element "div"
(js* "{'style':~{}}" (daiquiri.interpreter/attributes (merge {:margin-left "2rem"} (when focused? {:color "red"}))))
(cljs.core/array)))))
(js* "{'style':~{}}" (daiquiri.interpreter/attributes (merge {:margin-left "2rem"} (when focused? {:color "red"}))))
(cljs.core/array)))))
(deftest test-compile-when
(is (= (expand-html [:div {:class "a"} (when true [:div [:div]])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/when true
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(cljs.core/array
(clojure.core/when true
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(deftest test-compile-when-not
(is (= (expand-html [:div {:class "a"} (when-not false [:div [:div]])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/when-not false
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(cljs.core/array
(clojure.core/when-not false
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(deftest test-compile-when-some
(is (= (expand-html [:div {:class "a"} (when-some [x true] [:div [:div]])])
'(daiquiri.core/create-element "div" (js* "{'className':~{}}" "a")
(cljs.core/array
(clojure.core/when-some [x true]
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
(cljs.core/array
(clojure.core/when-some [x true]
(daiquiri.core/create-element "div" nil (cljs.core/array (daiquiri.core/create-element "div" nil nil)))))))))
;; type inference
(deftest test-infer-tag-any

View File

@ -12,9 +12,9 @@
(deftest test-static-children-as-arguments
(let [el (interpret
[:div
[:div {:class "1" :key 1}]
[:div {:class "2" :key 2}]])
[:div
[:div {:class "1" :key 1}]
[:div {:class "2" :key 2}]])
c1 (aget (.. el -props -children) 0)
c2 (aget (.. el -props -children) 1)]
(is (= "div" (.. el -type)))
@ -34,21 +34,21 @@
(deftest test-issue-80
(let [el (interpret
[:div
[:div {:class (list "foo" "bar")}]
[:div {:class (vector "foo" "bar")}]
(let []
[:div {:class (list "foo" "bar")}])
(let []
[:div {:class (vector "foo" "bar")}])
(when true
[:div {:class (list "foo" "bar")}])
(when true
[:div {:class (vector "foo" "bar")}])
(do
[:div {:class (list "foo" "bar")}])
(do
[:div {:class (vector "foo" "bar")}])])]
[:div
[:div {:class (list "foo" "bar")}]
[:div {:class (vector "foo" "bar")}]
(let []
[:div {:class (list "foo" "bar")}])
(let []
[:div {:class (vector "foo" "bar")}])
(when true
[:div {:class (list "foo" "bar")}])
(when true
[:div {:class (vector "foo" "bar")}])
(do
[:div {:class (list "foo" "bar")}])
(do
[:div {:class (vector "foo" "bar")}])])]
(is (= "div" (.. el -type)))
(is (= 8 (count (.. el -props -children))))
(doseq [c (.. el -props -children)]
@ -63,10 +63,10 @@
(deftest test-issue-57
(let [payload {:username "john" :likes 2}
el (interpret
(let [{:keys [username likes]} payload]
[:div
[:div (str username " (" likes ")")]
[:div "!Pixel Scout"]]))
(let [{:keys [username likes]} payload]
[:div
[:div (str username " (" likes ")")]
[:div "!Pixel Scout"]]))
c1 (aget (.. el -props -children) 0)
c2 (aget (.. el -props -children) 1)]

View File

@ -7,7 +7,7 @@
(deftest test-merge-with-class
(are [maps expected]
(= expected (apply normalize/merge-with-class maps))
(= expected (apply normalize/merge-with-class maps))
[]
nil
[{:a 1} {:b 2}]
@ -24,7 +24,7 @@
(deftest test-strip-css
(are [x expected]
(= expected (normalize/strip-css x))
(= expected (normalize/strip-css x))
nil nil
"" ""
"foo" "foo"
@ -33,7 +33,7 @@
(deftest test-match-tag
(are [tag expected]
(= expected (normalize/match-tag tag))
(= expected (normalize/match-tag tag))
:div ["div" nil []]
:div#foo ["div" "foo" []]
:div#foo.bar ["div" "foo" ["bar"]]
@ -49,7 +49,7 @@
(deftest test-normalize-class
(are [class expected]
(= expected (normalize/normalize-class class))
(= expected (normalize/normalize-class class))
nil nil
:x ["x"]
"x" ["x"]
@ -61,7 +61,7 @@
(deftest test-attributes
(are [attrs expected]
(= expected (normalize/attributes attrs))
(= expected (normalize/attributes attrs))
nil nil
{} {}
{:class nil} {:class nil}
@ -71,7 +71,7 @@
(deftest test-children
(are [children expected]
(= expected (normalize/children children))
(= expected (normalize/children children))
[] []
1 [1]
"x" ["x"]
@ -84,7 +84,7 @@
(deftest test-element
(are [element expected]
(= expected (normalize/element element))
(= expected (normalize/element element))
[:div] ["div" {} '()]
[:div {:class nil}] ["div" {:class nil} '()]
[:div#foo] ["div" {:id "foo"} '()]
@ -97,9 +97,9 @@
(deftest test-element-meta
(are [element expected]
(= (->> (nth (normalize/element element) 2)
(map (comp true? :inline meta)))
expected)
(= (->> (nth (normalize/element element) 2)
(map (comp true? :inline meta)))
expected)
'[:span (constantly 1)] [false]
'[:span ^:inline (constantly 1)] [true]
'[:span ^:inline (constantly 1) nil ^:inline (constantly 2)] [true true]))

View File

@ -7,7 +7,7 @@
(deftest test-camel-case
(are [attr expected]
(= expected (u/camel-case attr))
(= expected (u/camel-case attr))
nil nil
"" ""
:data :data
@ -18,7 +18,7 @@
(deftest test-camel-case-keys
(are [attrs expected]
(= expected (u/camel-case-keys attrs))
(= expected (u/camel-case-keys attrs))
{:id "x"}
{:id "x"}
{:class "x"}
@ -36,7 +36,7 @@
(deftest test-html-to-dom-attrs
(are [attrs expected]
(= expected (u/html-to-dom-attrs attrs))
(= expected (u/html-to-dom-attrs attrs))
{:id "x"}
{:id "x"}
{:class "x"}
@ -61,7 +61,7 @@
(deftest test-join-classes
(are [classes expected]
(= expected (u/join-classes classes))
(= expected (u/join-classes classes))
["a"] "a"
#{"a"} "a"
["a" "b"] "a b"

View File

@ -6,12 +6,12 @@
(defn replace-gensyms [sym forms]
(prewalk
(fn [form]
(if (and (symbol? form)
(re-matches (re-pattern (str sym "\\d+")) (str form)))
sym
form))
forms))
(fn [form]
(if (and (symbol? form)
(re-matches (re-pattern (str sym "\\d+")) (str form)))
sym
form))
forms))
(defmacro eval-in-temp-ns [& forms]
`(binding [*ns* *ns*]
@ -49,28 +49,28 @@
(deftest defc-conditions
(testing "no conditions supplied"
(is (= (replace-gensyms 'pre-post-test
(#'rum.core/-defc 'rum.core/build-defc
{:ns {:name 'core}} ; cljs?
'(pre-post-test ([y] {:x 1})
([y z] (+ y z 1)))))
(#'rum.core/-defc 'rum.core/build-defc
{:ns {:name 'core}} ; cljs?
'(pre-post-test ([y] {:x 1})
([y z] (+ y z 1)))))
'(def pre-post-test
(rum.core/lazy-build rum.core/build-defc
(clojure.core/fn
([y] (do {:x 1}))
([y z] (do (daiquiri.compiler/interpret-maybe (+ y z 1)))))
nil
"core/pre-post-test")))))
(clojure.core/fn
([y] (do {:x 1}))
([y z] (do (daiquiri.compiler/interpret-maybe (+ y z 1)))))
nil
"core/pre-post-test")))))
(testing "some conditions supplied"
(is (= (replace-gensyms 'pre-post-test
(#'rum.core/-defc 'rum.core/build-defc
{:ns {:name 'core}} ; cljs?
'(pre-post-test ([y] {:pre [(pos? y)]} {:x 1})
([y z] (+ y z 1)))))
(#'rum.core/-defc 'rum.core/build-defc
{:ns {:name 'core}} ; cljs?
'(pre-post-test ([y] {:pre [(pos? y)]} {:x 1})
([y z] (+ y z 1)))))
'(def pre-post-test
(rum.core/lazy-build rum.core/build-defc
(clojure.core/fn
([y] {:pre [(pos? y)]} (do {:x 1}))
([y z] (do (daiquiri.compiler/interpret-maybe (+ y z 1)))))
nil
"core/pre-post-test"))))))
(clojure.core/fn
([y] {:pre [(pos? y)]} (do {:x 1}))
([y z] (do (daiquiri.compiler/interpret-maybe (+ y z 1)))))
nil
"core/pre-post-test"))))))

View File

@ -18,7 +18,7 @@
(println " actual:" (formatter-fn (:actual m))))))
(cljs.test/run-tests
(cljs.test/empty-env)
'daiquiri.interpreter-test
'daiquiri.normalize-test
'daiquiri.util-test)
(cljs.test/empty-env)
'daiquiri.interpreter-test
'daiquiri.normalize-test
'daiquiri.util-test)