Skip to content

Commit

Permalink
Don't rename props for custom elements
Browse files Browse the repository at this point in the history
Custom element names must always contain hyphen so we can use that to
keep track of which elements are native vs. custom when parsing tag
name.

Fixes #322
  • Loading branch information
Deraen committed Nov 8, 2017
1 parent f0650a6 commit 77fea48
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
74 changes: 55 additions & 19 deletions src/reagent/impl/template.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,56 @@
(apply x args))
:else (clj->js x)))

;; Previous few functions copied for custom elements,
;; without mapping from class to className etc.

(def custom-prop-name-cache #js{})

(defn cached-custom-prop-name [k]
(if (named? k)
(if-some [k' (cache-get custom-prop-name-cache (name k))]
k'
(aset prop-name-cache (name k)
(util/dash-to-camel k)))
k))

(defn custom-kv-conv [o k v]
(doto o
(aset (cached-custom-prop-name k)
(convert-prop-value v))))

(defn convert-custom-prop-value [x]
(cond (js-val? x) x
(named? x) (name x)
(map? x) (reduce-kv custom-kv-conv #js{} x)
(coll? x) (clj->js x)
(ifn? x) (fn [& args]
(apply x args))
:else (clj->js x)))

(defn oset [o k v]
(doto (if (nil? o) #js{} o)
(aset k v)))

(defn oget [o k]
(if (nil? o) nil (aget o k)))

(defn set-id-class [p id-class]
(defn set-id-class
"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."
[props id-class]
(let [id ($ id-class :id)
p (if (and (some? id)
(nil? (oget p "id")))
(oset p "id" id)
p)]
(if-some [class ($ id-class :className)]
(let [old (oget p "className")]
(oset p "className" (if (nil? old)
class
(str class " " old))))
p)))
class ($ id-class :class)]
(cond-> props
;; Only use ID from tag keyword if no :id in props already
(and (some? id)
(nil? (:id props)))
(assoc :id id)

;; Merge classes
class
(assoc :class (let [old-class (:class props)]
(if (nil? old-class) class (str class " " old-class)))))))

(defn stringify-class [{:keys [class] :as props}]
(if (coll? class)
Expand All @@ -100,10 +131,12 @@
props))

(defn convert-props [props id-class]
(-> props
stringify-class
convert-prop-value
(set-id-class id-class)))
(let [props (-> props
stringify-class
(set-id-class id-class))]
(if ($ id-class :custom)
(convert-custom-prop-value props)
(convert-prop-value props))))

;;; Specialization for input components

Expand Down Expand Up @@ -134,7 +167,7 @@
($! node :value rendered-value)
(when (fn? on-write)
(on-write rendered-value)))

;; Setting "value" (below) moves the cursor position to the
;; end which gives the user a jarring experience.
;;
Expand Down Expand Up @@ -280,9 +313,12 @@
(string/replace class #"\." " "))]
(assert tag (str "Invalid tag: '" hiccup-tag "'"
(comp/comp-name)))
#js{:name tag
:id id
:className class}))
#js {:name tag
:id id
:class class
;; Custom element names must contain hyphen
;; https://www.w3.org/TR/custom-elements/#custom-elements-core-concepts
:custom (not= -1 (.indexOf tag "-"))}))

(defn try-get-key [x]
;; try catch to avoid clojurescript peculiarity with
Expand Down
9 changes: 9 additions & 0 deletions test/reagenttest/testreagent.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,3 +1064,12 @@
(is (re-find #"<div style=\"text-align:center(;?)\">foo</div>"
(server/render-to-static-markup
[:div {:style {:text-align "center"}} "foo"]))))

(deftest custom-element-class-prop
(is (re-find #"<custom-element class=\"foobar\">foo</custom-element>"
(server/render-to-static-markup
[:custom-element {:class "foobar"} "foo"])))

(is (re-find #"<custom-element class=\"foobar\">foo</custom-element>"
(server/render-to-static-markup
[:custom-element.foobar "foo"]))) )

0 comments on commit 77fea48

Please sign in to comment.