diff --git a/CHANGES.md b/CHANGES.md index 5695d7a7c..6057916df 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -58,6 +58,7 @@ - Fix handoff text with opacity [Taiga #2384](https://tree.taiga.io/project/penpot/issue/2384) - Restored rules color [Taiga #2460](https://tree.taiga.io/project/penpot/issue/2460) - Fix thumbnail not taking frame blending mode [Taiga #2301](https://tree.taiga.io/project/penpot/issue/2301) +- Fix import/export with SVG edge cases [Taiga #2389](https://tree.taiga.io/project/penpot/issue/2389) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 48cc1adb0..a702d522d 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -32,7 +32,6 @@ [app.util.strings :as ust] [app.util.timers :as ts] [cuerdas.core :as str] - [debug :refer [debug?]] [rumext.alpha :as mf])) (def ^:const viewbox-decimal-precision 3) diff --git a/frontend/src/app/main/ui/shapes/export.cljs b/frontend/src/app/main/ui/shapes/export.cljs index 9f26a0712..f794f687d 100644 --- a/frontend/src/app/main/ui/shapes/export.cljs +++ b/frontend/src/app/main/ui/shapes/export.cljs @@ -195,6 +195,12 @@ :penpot:suffix suffix :penpot:scale (str scale)}])) +(defn style->str + [style] + (->> style + (map (fn [[key val]] (str (d/name key) ":" val))) + (str/join "; "))) + (mf/defc export-svg-data [shape] [:* (when (contains? shape :svg-attrs) @@ -203,6 +209,10 @@ svg-defs (->> shape :svg-defs keys (mapv d/name) (str/join ","))] [:> "penpot:svg-import" #js {:penpot:svg-attrs (when-not (empty? svg-attrs) svg-attrs) + ;; Style and filter are special properties so we need to save it otherwise will be indistingishible from + ;; standard properties + :penpot:svg-style (when (contains? (:svg-attrs shape) :style) (style->str (get-in shape [:svg-attrs :style]))) + :penpot:svg-filter (when (contains? (:svg-attrs shape) :filter) (get-in shape [:svg-attrs :filter])) :penpot:svg-defs (when-not (empty? svg-defs) svg-defs) :penpot:svg-transform (when svg-transform (str svg-transform)) :penpot:svg-viewbox-x (get-in shape [:svg-viewbox :x]) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 0da6e0fa0..e331f149b 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -33,6 +33,7 @@ [app.main.ui.workspace.viewport.utils :as utils] [app.main.ui.workspace.viewport.widgets :as widgets] [beicon.core :as rx] + [debug :refer [debug?]] [rumext.alpha :as mf])) ;; --- Viewport @@ -192,7 +193,7 @@ [:& use/export-page {:options options}] - [:& (mf/provider use/include-metadata-ctx) {:value false} + [:& (mf/provider use/include-metadata-ctx) {:value (debug? :show-export-metadata)} [:& (mf/provider embed/context) {:value true} ;; Render root shape [:& shapes/root-shape {:key page-id diff --git a/frontend/src/app/util/import/parser.cljs b/frontend/src/app/util/import/parser.cljs index 8a51ff871..f17b7f915 100644 --- a/frontend/src/app/util/import/parser.cljs +++ b/frontend/src/app/util/import/parser.cljs @@ -22,6 +22,9 @@ (def uuid-regex #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}") +(def uuid-regex-prefix + #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-") + (defn valid? [root] (contains? (:attrs root) :xmlns:penpot)) @@ -554,20 +557,31 @@ (defn remove-prefix [s] (cond-> s (string? s) - (str/replace (re-pattern (str uuid-regex "-")) ""))) + (str/replace uuid-regex-prefix ""))) (defn get-svg-attrs - [svg-data svg-attrs] - (let [assoc-key + [svg-import svg-data svg-attrs] + (let [process-attr (fn [acc prop] - (let [key (keyword prop)] - (if-let [v (or (get svg-data key) - (get-in svg-data [:attrs key]))] - (assoc acc key (remove-prefix v)) - acc)))] + (cond + (and (= prop "style") + (contains? (:attrs svg-import) :penpot:svg-style)) + (let [style (get-in svg-import [:attrs :penpot:svg-style])] + (assoc acc :style (parse-style style))) + (and (= prop "filter") + (contains? (:attrs svg-import) :penpot:svg-filter)) + (let [style (get-in svg-import [:attrs :penpot:svg-filter])] + (assoc acc :filter (parse-style style))) + + :else + (let [key (keyword prop)] + (if-let [v (or (get svg-data key) + (get-in svg-data [:attrs key]))] + (assoc acc key (remove-prefix v)) + acc))))] (->> (str/split svg-attrs ",") - (reduce assoc-key {})))) + (reduce process-attr {})))) (defn get-svg-defs [node] @@ -595,7 +609,7 @@ (cond-> props :true - (assoc :svg-attrs (get-svg-attrs svg-data svg-attrs)) + (assoc :svg-attrs (get-svg-attrs svg-import svg-data svg-attrs)) (some? viewbox-x) (assoc :svg-viewbox {:x (d/parse-double viewbox-x) diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index c70bce1ed..d46e0b35c 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -46,6 +46,9 @@ ;; When active the thumbnails will be displayed with a sepia filter :thumbnails + + ;; When active we can check in the browser the export values + :show-export-metadata }) ;; These events are excluded when we activate the :events flag