Refactor template code

- Use two types to store native and hiccup data
- Rename comp to component so cljs.core/comp is not shadowd
- Use className instead of class property
- Rename name property to tag
- Use static properties for React key

Use of static properties in this and other commits shrinks test-suite
output size by 2-3kB.
This commit is contained in:
Juho Teperi 2018-04-19 19:45:13 +03:00
parent 7482b2821e
commit 9c9825c289
2 changed files with 62 additions and 70 deletions

View File

@ -207,7 +207,7 @@
nil)) nil))
(defn get-wrapper [key f name] (defn get-wrapper [key f]
(let [wrap (custom-wrapper key f)] (let [wrap (custom-wrapper key f)]
(when (and wrap f) (when (and wrap f)
(assert-callable f)) (assert-callable f))
@ -239,33 +239,33 @@
legacy-render (nil? render-fun) legacy-render (nil? render-fun)
render-fun (or render-fun render-fun (or render-fun
(:render fmap)) (:render fmap))
name (str (or (:displayName fmap) display-name (str (or (:displayName fmap)
(util/fun-name render-fun))) (util/fun-name render-fun)))
name (case name display-name (case display-name
"" (str (gensym "reagent")) "" (str (gensym "reagent"))
name) display-name)
fmap (reduce-kv (fn [m k v] obj #js {}]
(assoc m k (get-wrapper k v name))) ;; React lifecycle properties are added to object using
{} fmap)] ;; gobj/set so the names are never mangled. This will
(assoc fmap ;; probably require externs with npm to work.
:displayName name (reduce-kv (fn [obj k v]
:autobind false (doto obj
:cljsLegacyRender legacy-render (gobj/set (name k) (get-wrapper k v))))
:reagentRender render-fun obj
:render (:render static-fns)))) (dissoc fmap :render :reagentRender :displayName :componentFunction))
;; These can be manged, if property is not mentioned in the extern.
(defn map-to-js [m] (set! (.-displayName obj) display-name)
(reduce-kv (fn [o k v] (set! (.-autobind obj) false)
(doto o (set! (.-cljsLegacyRender obj) legacy-render)
(gobj/set (name k) v))) (set! (.-reagentRender obj) render-fun)
#js{} m)) (set! (.-render obj) (:render static-fns))
obj))
(defn cljsify [body] (defn cljsify [body]
(-> body (-> body
camelify-map-keys camelify-map-keys
add-obligatory add-obligatory
wrap-funs wrap-funs))
map-to-js))
(defn create-class [body] (defn create-class [body]
{:pre [(map? body)]} {:pre [(map? body)]}

View File

@ -17,7 +17,7 @@
from a tag name."} from a tag name."}
re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?") re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?")
(deftype NativeWrapper []) (deftype NativeWrapper [tag id className])
;;; Common utilities ;;; Common utilities
@ -100,13 +100,6 @@
(apply x args)) (apply x args))
:else (clj->js x))) :else (clj->js x)))
(defn oset [o k v]
(doto (if (nil? o) #js {} o)
(gobj/set k v)))
(defn oget [o k]
(if (nil? o) nil (gobj/get o k)))
(defn set-id-class (defn set-id-class
"Takes the id and class from tag keyword, and adds them to the "Takes the id and class from tag keyword, and adds them to the
other props. Parsed tag is JS object with :id and :class properties." other props. Parsed tag is JS object with :id and :class properties."
@ -263,10 +256,10 @@
:component-did-update input-component-set-value :component-did-update input-component-set-value
:component-will-unmount input-unmount :component-will-unmount input-unmount
:reagent-render :reagent-render
(fn [argv comp jsprops first-child] (fn [argv component jsprops first-child]
(let [this comp/*current-component*] (let [this comp/*current-component*]
(input-render-setup this jsprops) (input-render-setup this jsprops)
(make-element argv comp jsprops first-child)))}) (make-element argv component jsprops first-child)))})
(defn reagent-input (defn reagent-input
[] []
@ -277,18 +270,19 @@
;;; Conversion from Hiccup forms ;;; Conversion from Hiccup forms
(deftype HiccupTag [tag id className custom])
(defn parse-tag [hiccup-tag] (defn parse-tag [hiccup-tag]
(let [[tag id class] (->> hiccup-tag name (re-matches re-tag) next) (let [[tag id className] (->> hiccup-tag name (re-matches re-tag) next)
class (when-not (nil? class) className (when-not (nil? className)
(string/replace class #"\." " "))] (string/replace className #"\." " "))]
(assert tag (str "Invalid tag: '" hiccup-tag "'" (assert tag (str "Invalid tag: '" hiccup-tag "'" (comp/comp-name)))
(comp/comp-name))) (->HiccupTag tag
#js {:name tag id
:id id className
:class class
;; Custom element names must contain hyphen ;; Custom element names must contain hyphen
;; https://www.w3.org/TR/custom-elements/#custom-elements-core-concepts ;; https://www.w3.org/TR/custom-elements/#custom-elements-core-concepts
:custom (not= -1 (.indexOf tag "-"))})) (not= -1 (.indexOf tag "-")))))
(defn try-get-key [x] (defn try-get-key [x]
;; try catch to avoid clojurescript peculiarity with ;; try catch to avoid clojurescript peculiarity with
@ -307,7 +301,8 @@
(defn reag-element [tag v] (defn reag-element [tag v]
(let [c (comp/as-class tag) (let [c (comp/as-class tag)
jsprops #js {:argv v}] jsprops #js {}]
(set! (.-argv jsprops) v)
(when-some [key (key-from-vec v)] (when-some [key (key-from-vec v)]
(set! (.-key jsprops) key)) (set! (.-key jsprops) key))
(react/createElement c jsprops))) (react/createElement c jsprops)))
@ -315,19 +310,16 @@
(defn fragment-element [argv] (defn fragment-element [argv]
(let [props (nth argv 1 nil) (let [props (nth argv 1 nil)
hasprops (or (nil? props) (map? props)) hasprops (or (nil? props) (map? props))
jsprops (convert-prop-value (if hasprops props)) jsprops (or (convert-prop-value (if hasprops props))
#js {})
first-child (+ 1 (if hasprops 1 0))] first-child (+ 1 (if hasprops 1 0))]
(when-some [key (key-from-vec argv)] (when-some [key (key-from-vec argv)]
(oset jsprops "key" key)) (set! (.-key jsprops) key))
(make-element argv react/Fragment jsprops first-child))) (make-element argv react/Fragment jsprops first-child)))
(defn adapt-react-class (defn adapt-react-class
[c] [c]
(let [x (->NativeWrapper)] (->NativeWrapper c nil nil))
(set! (.-name x) c)
(set! (.-id x) nil)
(set! (.-class x) nil)
x))
(def tag-name-cache #js{}) (def tag-name-cache #js{})
@ -339,20 +331,20 @@
v))) v)))
(defn native-element [parsed argv first] (defn native-element [parsed argv first]
(let [comp (.-name parsed) (let [component (.-tag parsed)
props (nth argv first nil) props (nth argv first nil)
hasprops (or (nil? props) (map? props)) hasprops (or (nil? props) (map? props))
jsprops (convert-props (if hasprops props) parsed) jsprops (or (convert-props (if hasprops props) parsed)
#js {})
first-child (+ first (if hasprops 1 0))] first-child (+ first (if hasprops 1 0))]
(if (input-component? comp) (if (input-component? component)
(-> [(reagent-input) argv comp jsprops first-child] (-> [(reagent-input) argv component jsprops first-child]
(with-meta (meta argv)) (with-meta (meta argv))
as-element) as-element)
(let [key (-> (meta argv) get-key) (do
p (if (nil? key) (when-some [key (-> (meta argv) get-key)]
jsprops (set! (.-key jsprops) key))
(oset jsprops "key" key))] (make-element argv component jsprops first-child)))))
(make-element argv comp p first-child)))))
(defn str-coll [coll] (defn str-coll [coll]
(if (dev?) (if (dev?)
@ -379,12 +371,12 @@
pos (.indexOf n ">")] pos (.indexOf n ">")]
(case pos (case pos
-1 (native-element (cached-parse n) v 1) -1 (native-element (cached-parse n) v 1)
0 (let [comp (nth v 1 nil)] 0 (let [component (nth v 1 nil)]
;; Support [:> comp ...] ;; Support [:> component ...]
(assert (= ">" n) (hiccup-err v "Invalid Hiccup tag")) (assert (= ">" n) (hiccup-err v "Invalid Hiccup tag"))
(assert (or (string? comp) (fn? comp)) (assert (or (string? component) (fn? component))
(hiccup-err v "Expected React component in")) (hiccup-err v "Expected React component in"))
(native-element #js{:name comp} v 2)) (native-element (->HiccupTag component nil nil nil) v 2))
;; Support extended hiccup syntax, i.e :div.bar>a.foo ;; Support extended hiccup syntax, i.e :div.bar>a.foo
;; Apply metadata (e.g. :key) to the outermost element. ;; Apply metadata (e.g. :key) to the outermost element.
;; Metadata is probably used only with sequeneces, and in that case ;; Metadata is probably used only with sequeneces, and in that case
@ -461,12 +453,12 @@
;; ;; "_store" (js-obj) ;; ;; "_store" (js-obj)
;; ))) ;; )))
(defn make-element [argv comp jsprops first-child] (defn make-element [argv component jsprops first-child]
(case (- (count argv) first-child) (case (- (count argv) first-child)
;; Optimize cases of zero or one child ;; Optimize cases of zero or one child
0 (react/createElement comp jsprops) 0 (react/createElement component jsprops)
1 (react/createElement comp jsprops 1 (react/createElement component jsprops
(as-element (nth argv first-child nil))) (as-element (nth argv first-child nil)))
(.apply react/createElement nil (.apply react/createElement nil
@ -474,4 +466,4 @@
(when (>= k first-child) (when (>= k first-child)
(.push a (as-element v))) (.push a (as-element v)))
a) a)
#js[comp jsprops] argv)))) #js[component jsprops] argv))))