Refactor template a bit

This commit is contained in:
Dan Holmsand 2014-01-06 18:35:05 +01:00
parent 11a1c62024
commit 4099c00838

View File

@ -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)