diff --git a/common/src/app/common/files/builder.cljc b/common/src/app/common/files/builder.cljc index 46c1e9131..0fe6b98d3 100644 --- a/common/src/app/common/files/builder.cljc +++ b/common/src/app/common/files/builder.cljc @@ -15,6 +15,7 @@ [app.common.geom.shapes :as gsh] [app.common.pprint :as pp] [app.common.schema :as sm] + [app.common.svg :as csvg] [app.common.types.components-list :as ctkl] [app.common.types.container :as ctn] [app.common.types.file :as ctf] @@ -300,9 +301,13 @@ (-> file (update :parent-stack pop)))) -(defn create-shape [file type data] - (let [obj (-> (cts/setup-shape (assoc data :type type)) +(defn create-shape + [file type data] + (let [obj (-> (assoc data :type type) + (update :svg-attrs csvg/attrs->props) + (cts/setup-shape) (check-name file :type))] + (-> file (commit-shape obj) (assoc :last-id (:id obj)) diff --git a/common/src/app/common/svg.cljc b/common/src/app/common/svg.cljc index 878d56109..7974eaa28 100644 --- a/common/src/app/common/svg.cljc +++ b/common/src/app/common/svg.cljc @@ -608,12 +608,18 @@ (contains? svg-attr-list k) (contains? svg-present-list k)) (cond + (nil? v) + res + (= k :class) (assoc res :className v) (= k :style) - (let [v (if (string? v) (parse-style v) v)] - (assoc res k (attrs->props v false))) + (let [v (if (string? v) (parse-style v) v) + v (not-empty (attrs->props v false))] + (if v + (assoc res k v) + res)) :else (let [k (if (contains? non-react-props k) @@ -624,68 +630,6 @@ {} attrs))) -(defn clean-attrs - "Transforms attributes to their react equivalent - - DEPRECATED: replaced by attrs->props" - ([attrs] - (clean-attrs attrs true)) - - ([attrs whitelist?] - (letfn [(known-property? [[key _]] - (or (not whitelist?) - (contains? svg-attr-list key) - (contains? svg-present-list key))) - - (camelize [s] - (when (string? s) - #?(:cljs (js* "~{}.replace(\":\", \"-\").replace(/-./g, x=>x[1].toUpperCase())", s) - :clj (str/camel s)))) - - (transform-key [key] - (if (contains? non-react-props key) - key - (-> (d/name key) - (camelize) - (keyword)))) - - (format-styles [style-str] - (->> (str/split style-str ";") - (map str/trim) - (map #(str/split % ":")) - (group-by first) - (map (fn [[key val]] - [(transform-key key) - (second (first val))])) - (into {}))) - - (clean-key [[key val]] - (let [key (keyword key)] - (cond - (= key :class) - [:className val] - - (and (= key :style) - (string? val)) - [key (format-styles val)] - - (and (= key :style) - (map? val)) - [key (clean-attrs val false)] - - :else - [(transform-key key) val])))] - - ;; Removed this warning because slows a lot rendering with big svgs - #_(let [filtered-props (->> attrs (remove known-property?) (map first))] - (when (seq filtered-props) - (.warn js/console "Unknown properties: " (str/join ", " filtered-props)))) - - (into {} - (comp (filter known-property?) - (map clean-key)) - attrs)))) - (defn update-attr-ids "Replaces the ids inside a property" [attrs replace-fn] @@ -723,7 +667,8 @@ (reduce visit-node result (:content node))))] (visit-node {} content))) -(defn extract-defs [{:keys [attrs] :as node}] +(defn extract-defs + [{:keys [attrs] :as node}] (if-not (map? node) [{} node] @@ -741,19 +686,22 @@ [node-defs node]))) -(defn find-attr-references [attrs] +(defn find-attr-references + [attrs] (->> attrs (mapcat (fn [[_ attr-value]] (if (string? attr-value) (extract-ids attr-value) (find-attr-references attr-value)))))) -(defn find-node-references [node] +(defn find-node-references + [node] (let [current (->> (find-attr-references (:attrs node)) (into #{})) children (->> (:content node) (map find-node-references) (flatten) (into #{}))] (vec (into current children)))) -(defn find-def-references [defs references] +(defn find-def-references + [defs references] (loop [result (into #{} references) checked? #{} to-check (first references) @@ -778,7 +726,8 @@ (first pending) (rest pending)))))) -(defn svg-transform-matrix [shape] +(defn svg-transform-matrix + [shape] (if (:svg-viewbox shape) (let [{svg-x :x svg-y :y @@ -810,34 +759,39 @@ ;; Transforms spec: ;; https://www.w3.org/TR/SVG11/single-page.html#coords-TransformAttribute - -(defn format-translate-params [params] +(defn format-translate-params + [params] (assert (or (= (count params) 1) (= (count params) 2))) (if (= (count params) 1) [(gpt/point (nth params 0) 0)] [(gpt/point (nth params 0) (nth params 1))])) -(defn format-scale-params [params] +(defn format-scale-params + [params] (assert (or (= (count params) 1) (= (count params) 2))) (if (= (count params) 1) [(gpt/point (nth params 0))] [(gpt/point (nth params 0) (nth params 1))])) -(defn format-rotate-params [params] +(defn format-rotate-params + [params] (assert (or (= (count params) 1) (= (count params) 3)) (str "??" (count params))) (if (= (count params) 1) [(nth params 0) (gpt/point 0 0)] [(nth params 0) (gpt/point (nth params 1) (nth params 2))])) -(defn format-skew-x-params [params] +(defn format-skew-x-params + [params] (assert (= (count params) 1)) [(nth params 0) 0]) -(defn format-skew-y-params [params] +(defn format-skew-y-params + [params] (assert (= (count params) 1)) [0 (nth params 0)]) -(defn to-matrix [{:keys [type params]}] +(defn to-matrix + [{:keys [type params]}] (assert (#{"matrix" "translate" "scale" "rotate" "skewX" "skewY"} type)) (case type "matrix" (apply gmt/matrix params) @@ -847,7 +801,8 @@ "skewX" (apply gmt/skew-matrix (format-skew-x-params params)) "skewY" (apply gmt/skew-matrix (format-skew-y-params params)))) -(defn parse-transform [transform-attr] +(defn parse-transform + [transform-attr] (if transform-attr (let [process-matrix (fn [[_ type params]] @@ -865,7 +820,8 @@ (defn format-move [[x y]] (str "M" x " " y)) (defn format-line [[x y]] (str "L" x " " y)) -(defn points->path [points-str] +(defn points->path + [points-str] (let [points (->> points-str (re-seq number-regex) (filter (comp not empty? first)) diff --git a/common/test/common_tests/svg_test.cljc b/common/test/common_tests/svg_test.cljc index f5731999f..364286e5f 100644 --- a/common/test/common_tests/svg_test.cljc +++ b/common/test/common_tests/svg_test.cljc @@ -12,21 +12,21 @@ (t/deftest clean-attrs-1 (let [attrs {:class "foobar"} - result (svg/clean-attrs attrs)] + result (svg/attrs->props attrs)] (t/is (= result {:className "foobar"})))) (t/deftest clean-attrs-2 (let [attrs {:overline-position "top" :style {:fill "none" :stroke-dashoffset 1}} - result (svg/clean-attrs attrs true)] + result (svg/attrs->props attrs true)] (t/is (= result {:overlinePosition "top", :style {:fill "none", :strokeDashoffset 1}})))) (t/deftest clean-attrs-3 (let [attrs {:overline-position "top" :style (str "fill:#00801b;fill-opacity:1;stroke:none;stroke-width:2749.72;" "stroke-linecap:round;stroke-dasharray:none;stop-color:#000000")} - result (svg/clean-attrs attrs true)] + result (svg/attrs->props attrs true)] (t/is (= result {:overlinePosition "top", :style {:fill "#00801b", :fillOpacity "1", diff --git a/frontend/src/app/main/ui/shapes/export.cljs b/frontend/src/app/main/ui/shapes/export.cljs index 959be058f..5c03bf78f 100644 --- a/frontend/src/app/main/ui/shapes/export.cljs +++ b/frontend/src/app/main/ui/shapes/export.cljs @@ -29,7 +29,7 @@ (cond (map? node) - [:> (d/name tag) (clj->js (csvg/clean-attrs attrs)) + [:> (d/name tag) (obj/map->obj (csvg/attrs->props attrs)) (for [child content] [:& render-xml {:xml child :key (swap! internal-counter inc)}])] diff --git a/frontend/src/app/main/ui/shapes/svg_defs.cljs b/frontend/src/app/main/ui/shapes/svg_defs.cljs index 50092747c..c2f0fa2be 100644 --- a/frontend/src/app/main/ui/shapes/svg_defs.cljs +++ b/frontend/src/app/main/ui/shapes/svg_defs.cljs @@ -13,6 +13,7 @@ [app.common.geom.shapes :as gsh] [app.common.geom.shapes.bounds :as gsb] [app.common.svg :as csvg] + [app.util.object :as obj] [rumext.v2 :as mf])) (defn add-matrix [attrs transform-key transform-matrix] @@ -23,7 +24,9 @@ (str transform-matrix " " val) (str transform-matrix))))) -(mf/defc svg-node [{:keys [type node prefix-id transform bounds]}] +(mf/defc svg-node + {::mf/wrap-props false} + [{:keys [type node prefix-id transform bounds]}] (cond (string? node) node @@ -48,7 +51,7 @@ attrs (-> attrs (csvg/update-attr-ids prefix-id) - (csvg/clean-attrs) + (csvg/attrs->props) ;; This clasname will be used to change the transform on the viewport ;; only necessary for groups because shapes have their own transform (cond-> (and (or transform-gradient? @@ -80,7 +83,7 @@ :transform (str transform)}] [mf/Fragment #js {}])] - [:> (name tag) (clj->js attrs) + [:> (name tag) (obj/map->obj attrs) [:> wrapper wrapper-props (for [[index node] (d/enumerate content)] [:& svg-node {:key (dm/str "node-" index) diff --git a/frontend/src/app/main/ui/shapes/svg_raw.cljs b/frontend/src/app/main/ui/shapes/svg_raw.cljs index 21f8c1951..c1b2f5d1b 100644 --- a/frontend/src/app/main/ui/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/shapes/svg_raw.cljs @@ -10,7 +10,7 @@ [app.common.geom.shapes :as gsh] [app.common.svg :as csvg] [app.main.ui.context :as muc] - [app.main.ui.shapes.attrs :as usa] + [app.main.ui.shapes.attrs :as attrs] [app.util.object :as obj] [cuerdas.core :as str] [rumext.v2 :as mf])) @@ -41,7 +41,7 @@ props (mf/with-memo [shape render-id] (-> #js {} - (usa/add-fill-props! shape render-id) + (attrs/add-fill-props! shape render-id) (obj/unset! "transform") (obj/set! "x" x) (obj/set! "y" y) @@ -79,8 +79,7 @@ props (mf/with-memo [shape render-id] (let [element-id (dm/get-in shape [:svg-attrs :id]) - props (-> #js {} - (usa/add-fill-props! shape render-id))] + props (attrs/add-fill-props! #js {} shape render-id)] (when (and (some? element-id) (contains? ids-mapping element-id)) diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index 3946075c8..2e3875e18 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -199,7 +199,8 @@ (rx/tap #(progress! context :upload-media name)) (rx/merge-map #(rp/cmd! :upload-file-media-object %)))) -(defn resolve-text-content [node context] +(defn resolve-text-content + [node context] (let [resolve (:resolve context)] (->> node (ct/transform-nodes