0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-10 14:51:37 -05:00

🐛 Fix incorrect svg-attrs handlng on .zip import process

This commit is contained in:
Andrey Antukh 2024-01-08 16:13:04 +01:00
parent 77472aabea
commit b6c257bfc5
7 changed files with 56 additions and 92 deletions

View file

@ -15,6 +15,7 @@
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pprint :as pp] [app.common.pprint :as pp]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.svg :as csvg]
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.container :as ctn] [app.common.types.container :as ctn]
[app.common.types.file :as ctf] [app.common.types.file :as ctf]
@ -300,9 +301,13 @@
(-> file (-> file
(update :parent-stack pop)))) (update :parent-stack pop))))
(defn create-shape [file type data] (defn create-shape
(let [obj (-> (cts/setup-shape (assoc data :type type)) [file type data]
(let [obj (-> (assoc data :type type)
(update :svg-attrs csvg/attrs->props)
(cts/setup-shape)
(check-name file :type))] (check-name file :type))]
(-> file (-> file
(commit-shape obj) (commit-shape obj)
(assoc :last-id (:id obj)) (assoc :last-id (:id obj))

View file

@ -608,12 +608,18 @@
(contains? svg-attr-list k) (contains? svg-attr-list k)
(contains? svg-present-list k)) (contains? svg-present-list k))
(cond (cond
(nil? v)
res
(= k :class) (= k :class)
(assoc res :className v) (assoc res :className v)
(= k :style) (= k :style)
(let [v (if (string? v) (parse-style v) v)] (let [v (if (string? v) (parse-style v) v)
(assoc res k (attrs->props v false))) v (not-empty (attrs->props v false))]
(if v
(assoc res k v)
res))
:else :else
(let [k (if (contains? non-react-props k) (let [k (if (contains? non-react-props k)
@ -624,68 +630,6 @@
{} {}
attrs))) 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 (defn update-attr-ids
"Replaces the ids inside a property" "Replaces the ids inside a property"
[attrs replace-fn] [attrs replace-fn]
@ -723,7 +667,8 @@
(reduce visit-node result (:content node))))] (reduce visit-node result (:content node))))]
(visit-node {} content))) (visit-node {} content)))
(defn extract-defs [{:keys [attrs] :as node}] (defn extract-defs
[{:keys [attrs] :as node}]
(if-not (map? node) (if-not (map? node)
[{} node] [{} node]
@ -741,19 +686,22 @@
[node-defs node]))) [node-defs node])))
(defn find-attr-references [attrs] (defn find-attr-references
[attrs]
(->> attrs (->> attrs
(mapcat (fn [[_ attr-value]] (mapcat (fn [[_ attr-value]]
(if (string? attr-value) (if (string? attr-value)
(extract-ids attr-value) (extract-ids attr-value)
(find-attr-references 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 #{})) (let [current (->> (find-attr-references (:attrs node)) (into #{}))
children (->> (:content node) (map find-node-references) (flatten) (into #{}))] children (->> (:content node) (map find-node-references) (flatten) (into #{}))]
(vec (into current children)))) (vec (into current children))))
(defn find-def-references [defs references] (defn find-def-references
[defs references]
(loop [result (into #{} references) (loop [result (into #{} references)
checked? #{} checked? #{}
to-check (first references) to-check (first references)
@ -778,7 +726,8 @@
(first pending) (first pending)
(rest pending)))))) (rest pending))))))
(defn svg-transform-matrix [shape] (defn svg-transform-matrix
[shape]
(if (:svg-viewbox shape) (if (:svg-viewbox shape)
(let [{svg-x :x (let [{svg-x :x
svg-y :y svg-y :y
@ -810,34 +759,39 @@
;; Transforms spec: ;; Transforms spec:
;; https://www.w3.org/TR/SVG11/single-page.html#coords-TransformAttribute ;; https://www.w3.org/TR/SVG11/single-page.html#coords-TransformAttribute
(defn format-translate-params
(defn format-translate-params [params] [params]
(assert (or (= (count params) 1) (= (count params) 2))) (assert (or (= (count params) 1) (= (count params) 2)))
(if (= (count params) 1) (if (= (count params) 1)
[(gpt/point (nth params 0) 0)] [(gpt/point (nth params 0) 0)]
[(gpt/point (nth params 0) (nth params 1))])) [(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))) (assert (or (= (count params) 1) (= (count params) 2)))
(if (= (count params) 1) (if (= (count params) 1)
[(gpt/point (nth params 0))] [(gpt/point (nth params 0))]
[(gpt/point (nth params 0) (nth params 1))])) [(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))) (assert (or (= (count params) 1) (= (count params) 3)) (str "??" (count params)))
(if (= (count params) 1) (if (= (count params) 1)
[(nth params 0) (gpt/point 0 0)] [(nth params 0) (gpt/point 0 0)]
[(nth params 0) (gpt/point (nth params 1) (nth params 2))])) [(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)) (assert (= (count params) 1))
[(nth params 0) 0]) [(nth params 0) 0])
(defn format-skew-y-params [params] (defn format-skew-y-params
[params]
(assert (= (count params) 1)) (assert (= (count params) 1))
[0 (nth params 0)]) [0 (nth params 0)])
(defn to-matrix [{:keys [type params]}] (defn to-matrix
[{:keys [type params]}]
(assert (#{"matrix" "translate" "scale" "rotate" "skewX" "skewY"} type)) (assert (#{"matrix" "translate" "scale" "rotate" "skewX" "skewY"} type))
(case type (case type
"matrix" (apply gmt/matrix params) "matrix" (apply gmt/matrix params)
@ -847,7 +801,8 @@
"skewX" (apply gmt/skew-matrix (format-skew-x-params params)) "skewX" (apply gmt/skew-matrix (format-skew-x-params params))
"skewY" (apply gmt/skew-matrix (format-skew-y-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 (if transform-attr
(let [process-matrix (let [process-matrix
(fn [[_ type params]] (fn [[_ type params]]
@ -865,7 +820,8 @@
(defn format-move [[x y]] (str "M" x " " y)) (defn format-move [[x y]] (str "M" x " " y))
(defn format-line [[x y]] (str "L" 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 (let [points (->> points-str
(re-seq number-regex) (re-seq number-regex)
(filter (comp not empty? first)) (filter (comp not empty? first))

View file

@ -12,21 +12,21 @@
(t/deftest clean-attrs-1 (t/deftest clean-attrs-1
(let [attrs {:class "foobar"} (let [attrs {:class "foobar"}
result (svg/clean-attrs attrs)] result (svg/attrs->props attrs)]
(t/is (= result {:className "foobar"})))) (t/is (= result {:className "foobar"}))))
(t/deftest clean-attrs-2 (t/deftest clean-attrs-2
(let [attrs {:overline-position "top" (let [attrs {:overline-position "top"
:style {:fill "none" :style {:fill "none"
:stroke-dashoffset 1}} :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/is (= result {:overlinePosition "top", :style {:fill "none", :strokeDashoffset 1}}))))
(t/deftest clean-attrs-3 (t/deftest clean-attrs-3
(let [attrs {:overline-position "top" (let [attrs {:overline-position "top"
:style (str "fill:#00801b;fill-opacity:1;stroke:none;stroke-width:2749.72;" :style (str "fill:#00801b;fill-opacity:1;stroke:none;stroke-width:2749.72;"
"stroke-linecap:round;stroke-dasharray:none;stop-color:#000000")} "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", (t/is (= result {:overlinePosition "top",
:style {:fill "#00801b", :style {:fill "#00801b",
:fillOpacity "1", :fillOpacity "1",

View file

@ -29,7 +29,7 @@
(cond (cond
(map? node) (map? node)
[:> (d/name tag) (clj->js (csvg/clean-attrs attrs)) [:> (d/name tag) (obj/map->obj (csvg/attrs->props attrs))
(for [child content] (for [child content]
[:& render-xml {:xml child :key (swap! internal-counter inc)}])] [:& render-xml {:xml child :key (swap! internal-counter inc)}])]

View file

@ -13,6 +13,7 @@
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.geom.shapes.bounds :as gsb] [app.common.geom.shapes.bounds :as gsb]
[app.common.svg :as csvg] [app.common.svg :as csvg]
[app.util.object :as obj]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn add-matrix [attrs transform-key transform-matrix] (defn add-matrix [attrs transform-key transform-matrix]
@ -23,7 +24,9 @@
(str transform-matrix " " val) (str transform-matrix " " val)
(str transform-matrix))))) (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 (cond
(string? node) node (string? node) node
@ -48,7 +51,7 @@
attrs attrs
(-> attrs (-> attrs
(csvg/update-attr-ids prefix-id) (csvg/update-attr-ids prefix-id)
(csvg/clean-attrs) (csvg/attrs->props)
;; This clasname will be used to change the transform on the viewport ;; This clasname will be used to change the transform on the viewport
;; only necessary for groups because shapes have their own transform ;; only necessary for groups because shapes have their own transform
(cond-> (and (or transform-gradient? (cond-> (and (or transform-gradient?
@ -80,7 +83,7 @@
:transform (str transform)}] :transform (str transform)}]
[mf/Fragment #js {}])] [mf/Fragment #js {}])]
[:> (name tag) (clj->js attrs) [:> (name tag) (obj/map->obj attrs)
[:> wrapper wrapper-props [:> wrapper wrapper-props
(for [[index node] (d/enumerate content)] (for [[index node] (d/enumerate content)]
[:& svg-node {:key (dm/str "node-" index) [:& svg-node {:key (dm/str "node-" index)

View file

@ -10,7 +10,7 @@
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.svg :as csvg] [app.common.svg :as csvg]
[app.main.ui.context :as muc] [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] [app.util.object :as obj]
[cuerdas.core :as str] [cuerdas.core :as str]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -41,7 +41,7 @@
props (mf/with-memo [shape render-id] props (mf/with-memo [shape render-id]
(-> #js {} (-> #js {}
(usa/add-fill-props! shape render-id) (attrs/add-fill-props! shape render-id)
(obj/unset! "transform") (obj/unset! "transform")
(obj/set! "x" x) (obj/set! "x" x)
(obj/set! "y" y) (obj/set! "y" y)
@ -79,8 +79,7 @@
props props
(mf/with-memo [shape render-id] (mf/with-memo [shape render-id]
(let [element-id (dm/get-in shape [:svg-attrs :id]) (let [element-id (dm/get-in shape [:svg-attrs :id])
props (-> #js {} props (attrs/add-fill-props! #js {} shape render-id)]
(usa/add-fill-props! shape render-id))]
(when (and (some? element-id) (when (and (some? element-id)
(contains? ids-mapping element-id)) (contains? ids-mapping element-id))

View file

@ -199,7 +199,8 @@
(rx/tap #(progress! context :upload-media name)) (rx/tap #(progress! context :upload-media name))
(rx/merge-map #(rp/cmd! :upload-file-media-object %)))) (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)] (let [resolve (:resolve context)]
(->> node (->> node
(ct/transform-nodes (ct/transform-nodes