diff --git a/src/cljss/builder.clj b/src/cljss/builder.clj index c7dc2f2..c08348b 100644 --- a/src/cljss/builder.clj +++ b/src/cljss/builder.clj @@ -8,30 +8,33 @@ (map? value))) (defn build-styles [cls styles] - (c/reset-env! {:cls cls}) - (let [pseudo (filterv utils/pseudo? styles) - nested (->> styles - (filterv (comp not utils/pseudo?)) - (filterv utils/nested?)) - [mstatic mvals] (some-> styles :cljss.core/media build-media) - styles (dissoc styles :cljss.core/media) - styles (filterv #(and (not (utils/pseudo? %)) (not (utils/nested? %))) styles) - [static vals] (c/collect-styles cls styles) - pstyles (->> pseudo - (reduce - (fn [coll [rule styles]] - (conj coll (c/collect-styles (str cls (subs (name rule) 1)) styles))) - [])) - nstyles (->> nested - (reduce - (fn [coll [rule styles]] - (conj coll (c/collect-styles (str cls " " rule) styles))) - [])) - vals (->> pstyles - (mapcat second) - (into vals) - (concat mvals) - (into [])) + (let [rule-index 0 + pseudo (filterv utils/pseudo? styles) + nested (->> styles + (filterv (comp not utils/pseudo?)) + (filterv utils/nested?)) + [mstatic mvals mrule-index] (some-> styles :cljss.core/media ((partial build-media cls rule-index))) + rule-index (or mrule-index rule-index) + styles (dissoc styles :cljss.core/media) + styles (filterv #(and (not (utils/pseudo? %)) (not (utils/nested? %))) styles) + + [static vals rule-index] (c/collect-styles cls styles rule-index) + [pstyles rule-index] (c/collect-dynamic-styles + rule-index + pseudo + cls + (fn [rule] (subs (name rule) 1))) + [nstyles rule-index] (c/collect-dynamic-styles + rule-index + nested + cls + (fn [rule] (str " " rule))) + + vals (->> pstyles + (mapcat second) + (into vals) + (concat mvals) + (into [])) vals (->> nstyles (mapcat second) (into vals)) diff --git a/src/cljss/collect.clj b/src/cljss/collect.clj index 64ecfba..224176e 100644 --- a/src/cljss/collect.clj +++ b/src/cljss/collect.clj @@ -1,12 +1,6 @@ (ns cljss.collect (:require [cljss.utils :refer [build-css]])) -(def env* (atom {:id 0 - :cls nil})) - -(defn reset-env! [v] - (reset! env* (merge {:id 0 :cls nil} v))) - (defn dynamic? [[_ value]] (not (or (string? value) (number? value)))) @@ -14,21 +8,33 @@ (defn varid [cls idx [rule]] [rule (str "--var-" cls "-" idx)]) -(defn collect-styles [cls styles] - (let [id (:cls @env*) - dynamic (filterv dynamic? styles) - static (filterv (comp not dynamic?) styles) - vars - (reduce - (fn [vars ds] - (let [ret (conj vars (varid id (:id @env*) ds))] - (swap! env* update :id inc) - ret)) - [] - dynamic) - vals (mapv (fn [[_ var] [_ exp]] [var exp]) vars dynamic) - static (->> vars - (map (fn [[rule var]] [rule (str "var(" var ")")])) - (concat static) - (build-css cls))] - [static vals])) +(defn collect-styles + ([cls styles rule-index] (collect-styles cls styles rule-index nil)) + ([cls styles rule-index tail-class] + (let [dynamic (filterv dynamic? styles) + static (filterv (comp not dynamic?) styles) + [vars rule-index] (reduce + (fn [[vars idx] ds] + (let [ret (conj vars (varid cls idx ds))] + [ret (inc idx)])) + [[] rule-index] + dynamic) + vals (mapv (fn [[_ var] [_ exp]] [var exp]) vars dynamic) + static (->> vars + (map (fn [[rule var]] [rule (str "var(" var ")")])) + (concat static) + (build-css (str cls tail-class)))] + [static vals rule-index]))) + +(defn collect-dynamic-styles [rule-index rules cls tail-class-g] + (loop + [idx rule-index + acc [] + coll rules] + (if (not (seq coll)) + [acc idx] + (let [[rule styles] (first coll) + [static vals nxt-idx] (collect-styles cls styles idx (tail-class-g rule))] + (recur nxt-idx + (conj acc [static vals]) + (rest coll)))))) diff --git a/src/cljss/media.clj b/src/cljss/media.clj index af14377..9eb9f9d 100644 --- a/src/cljss/media.clj +++ b/src/cljss/media.clj @@ -234,44 +234,41 @@ (clojure.string/join " ") (str "@media ")))) -(defn compile-media-dispatch [styles] +(defn compile-media-dispatch [styles _ _] (cond (contains? styles :media) :media (contains? styles :styles) :styles)) (defmulti compile-media #'compile-media-dispatch) -(defmethod compile-media :media [{media :media}] +(defmethod compile-media :media [{media :media} cls rule-index] (->> (seq media) (reduce - (fn [[sstyles svalues] [query styles]] - (let [[static values] (compile-media {:styles styles}) + (fn [[sstyles svalues nxt-idx] [query styles]] + (let [[static values nxt-idx] (compile-media {:styles styles} cls nxt-idx) query (-compile-media-query query)] - [(str sstyles query static) (concat svalues values)])) - ["" []]))) + [(str sstyles query static) (concat svalues values) nxt-idx])) + ["" [] rule-index]))) -(defmethod compile-media :styles [{styles :styles}] +(defmethod compile-media :styles [{styles :styles} cls rule-index] (let [pseudo (filterv utils/pseudo? styles) - pstyles (->> pseudo - (reduce - (fn [coll [rule styles]] - (conj coll (c/collect-styles (str (:cls @c/env*) (subs (name rule) 1)) styles))) - [])) + [pstyles rule-index] (c/collect-dynamic-styles rule-index pseudo cls (fn [rule] (subs (name rule) 1))) + styles (filterv (comp not utils/pseudo?) styles) - [static values] (c/collect-styles (:cls @c/env*) styles) + [static values rule-index] (c/collect-styles cls styles rule-index) values (->> pstyles (mapcat second) (into values))] [(str "{" (apply str static (map first pstyles)) "}") - values])) + values + rule-index])) -(defn build-media [styles] - (compile-media {:media styles})) +(defn build-media [cls rule-index styles] + (compile-media {:media styles} cls rule-index)) (comment - (c/reset-env! {:cls "class"}) - (build-media + "class" {[[:only :screen :and [:min-width "300px"]] [:print :and [:color]]] {:font-size 'p diff --git a/src/cljss/sheet.cljs b/src/cljss/sheet.cljs index 318309a..e709f31 100644 --- a/src/cljss/sheet.cljs +++ b/src/cljss/sheet.cljs @@ -26,15 +26,8 @@ (throw (js/Error. (str "A stylesheet can only have " limit " rules")))) (when-not (@cache cls-name) (swap! cache conj cls-name) - (let [rule (if (ifn? rule) (rule) rule) - rules-count (gobj/get (gobj/get sheet "cssRules") "length")] - (if dev? - (dom/appendChild tag (dom/createTextNode rule)) - (try - (.insertRule sheet rule rules-count) - (catch :default e - (when dev? - (js/console.warn "Illegal CSS rule" rule)))))))) + (let [rule (if (ifn? rule) (rule) rule)] + (dom/appendChild tag (dom/createTextNode rule))))) (flush! [this] (-> tag .-parentNode