diff --git a/src/cloact/impl/template.cljs b/src/cloact/impl/template.cljs index 130a3c4..7ad50da 100644 --- a/src/cloact/impl/template.cljs +++ b/src/cloact/impl/template.cljs @@ -2,26 +2,26 @@ (ns cloact.impl.template (:require-macros [cloact.debug :refer [dbg prn println]]) (:require [clojure.string :as string] - [cloact.impl.reactimport :as reacts] + [cloact.impl.reactimport :as reactimport] [cloact.impl.util :as util])) -(def React reacts/React) +(def React reactimport/React) (def isClient (not (nil? (try (.-document js/window) (catch js/Object e nil))))) (defn dash-to-camel [dashed] - (let [words (string/split (name dashed) #"-") - camels (map string/capitalize (rest words))] - (apply str (first words) camels))) + (let [words (-> dashed name (string/split #"-"))] + (apply str (first words) + (->> words rest (map string/capitalize))))) -(def attr-aliases {"class" "className" - "for" "htmlFor" - "charset" "charSet"}) +(def attr-aliases {:class "className" + :for "htmlFor" + :charset "charSet"}) (defn undash-prop-name [n] - (let [undashed (dash-to-camel n)] - (get attr-aliases undashed undashed))) + (or (attr-aliases n) + (dash-to-camel n))) (def cached-prop-name (memoize undash-prop-name)) (def cached-style-name (memoize dash-to-camel)) @@ -34,47 +34,44 @@ (ifn? val) (fn [& args] (apply val args)) :else (clj->js val))) -(defn set-tag-extra [props [id class]] - (set! (.-id props) id) +(defn set-id-class [props [id class]] + (aset props "id" id) (when class - (set! (.-className props) - (if-let [old (.-className props)] - (str class " " old) - class)))) + (aset props "className" (if-let [old (aget props "className")] + (str class " " old) + class)))) -(defn convert-props [props extra] +(defn convert-props [props id-class] (let [is-empty (empty? props)] (cond - (and is-empty (nil? extra)) nil + (and is-empty (nil? id-class)) nil (identical? (type props) js/Object) props :else (let [objprops (js-obj)] (when-not is-empty (doseq [[k v] props] (aset objprops (cached-prop-name k) (convert-prop-value v)))) - (when-not (nil? extra) - (set-tag-extra objprops extra)) + (when-not (nil? id-class) + (set-id-class objprops id-class)) objprops)))) (defn map-into-array [f coll] - (let [a (into-array coll) - len (alength a)] - (dotimes [i len] + (let [a (into-array coll)] + (dotimes [i (alength a)] (aset a i (f (aget a i)))) a)) (declare as-component) -(defn wrapped-render [this comp extra] +(defn wrapped-render [this comp id-class] (let [inprops (aget this "props") args (.-cljsArgs inprops) - [_ scnd] args - hasprops (or (nil? scnd) (map? scnd)) - jsprops (convert-props (if hasprops scnd) extra) - jsargs (->> args - (drop (if hasprops 2 1)) + props (nth args 1 nil) + hasprops (or (nil? props) (map? props)) + jsargs (->> (if hasprops (drop 1 args) args) (map-into-array as-component))] - (.apply comp nil (.concat (array jsprops) jsargs)))) + (aset jsargs 0 (convert-props (if hasprops props) id-class)) + (.apply comp nil jsargs))) (defn wrapped-should-update [C nextprops nextstate] (let [a1 (-> C (aget "props") .-cljsArgs) @@ -82,16 +79,14 @@ (not (util/equal-args a1 a2)))) (defn wrap-component [comp extras] - (let [spec #js {:render #(this-as C (wrapped-render C comp extras)) - :shouldComponentUpdate - #(this-as C (wrapped-should-update C %1 %2))}] - (.createClass React spec))) + (.createClass React (js-obj "render" + #(this-as C (wrapped-render C comp extras)) + "shouldComponentUpdate" + #(this-as C (wrapped-should-update C %1 %2))))) ;; From Weavejester's Hiccup, via pump: -;; https://github.com/weavejester/hiccup/blob/master/src/hiccup/compiler.clj#L32 (def ^{:doc "Regular expression that parses a CSS-style id and class - from a tag name." - :private true} + from a tag name."} re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?") (def DOM (aget React "DOM")) @@ -101,17 +96,17 @@ comp (aget DOM tag) class' (when class (string/replace class #"\." " "))] + (assert comp (str "Unknown tag: " tag)) [comp (when (or id class') [id class'])])) (defn get-wrapper [tag] - (let [[comp extra] (parse-tag tag)] - (wrap-component comp extra))) + (let [[comp id-class] (parse-tag tag)] + (wrap-component comp id-class))) (def cached-wrapper (memoize get-wrapper)) (defn fn-to-class [f] - (assert (fn? f)) (let [spec (meta f) withrender (merge spec {:render f}) res (cloact.core/create-class withrender) @@ -119,26 +114,29 @@ (set! (.-cljsReactClass f) wrapf) wrapf)) -(defn as-class [x] - (cond - (keyword? x) (cached-wrapper x) - (not (nil? (.-cljsReactClass x))) (.-cljsReactClass x) - :else (do (assert (fn? x)) - (if (.isValidClass React x) - (set! (.-cljsReactClass x) (wrap-component x nil)) - (fn-to-class x))))) +(defn as-class [tag] + (if (keyword? tag) + (cached-wrapper tag) + (do + (assert (fn? tag)) + (let [cached-class (.-cljsReactClass tag)] + (if-not (nil? cached-class) + cached-class + (if (.isValidClass React tag) + (set! (.-cljsReactClass tag) (wrap-component tag nil)) + (fn-to-class tag))))))) (defn vec-to-comp [v] (assert (pos? (count v))) (let [[tag props] v c (as-class tag) - obj (js-obj)] - (set! (.-cljsArgs obj) v) + jsprops (js-obj)] + (set! (.-cljsArgs jsprops) v) (when (map? props) (let [key (:key props)] (when-not (nil? key) - (set! (.-key obj) key)))) - (c obj))) + (aset jsprops "key" key)))) + (c jsprops))) (defn as-component [x] (cond (vector? x) (vec-to-comp x)