mirror of
https://github.com/penpot/penpot.git
synced 2025-03-30 16:41:20 -05:00
✨ Adjustments to svgclean
This commit is contained in:
parent
d3345c0fa6
commit
7482122964
11 changed files with 301 additions and 76 deletions
File diff suppressed because one or more lines are too long
|
@ -132,8 +132,9 @@
|
|||
"Return a map without the keys provided
|
||||
in the `keys` parameter."
|
||||
[data keys]
|
||||
(persistent!
|
||||
(reduce #(dissoc! %1 %2) (transient data) keys)))
|
||||
(when data
|
||||
(persistent!
|
||||
(reduce #(dissoc! %1 %2) (transient data) keys))))
|
||||
|
||||
(defn remove-at-index
|
||||
[v index]
|
||||
|
|
|
@ -285,6 +285,24 @@
|
|||
(dissoc :modifiers)))
|
||||
shape)))
|
||||
|
||||
(defn update-group-viewbox
|
||||
"Updates the viewbox for groups imported from SVG's"
|
||||
[{:keys [selrect svg-viewbox] :as group} new-selrect]
|
||||
(let [;; Gets deltas for the selrect to update the svg-viewbox (for svg-imports)
|
||||
deltas {:x (- (:x new-selrect) (:x selrect))
|
||||
:y (- (:y new-selrect) (:y selrect))
|
||||
:width (- (:width new-selrect) (:width selrect))
|
||||
:height (- (:height new-selrect) (:height selrect))}]
|
||||
|
||||
(cond-> group
|
||||
svg-viewbox
|
||||
(update :svg-viewbox
|
||||
#(-> %
|
||||
(update :x + (:x deltas))
|
||||
(update :y + (:y deltas))
|
||||
(update :width + (:width deltas))
|
||||
(update :height + (:height deltas)))))))
|
||||
|
||||
(defn update-group-selrect [group children]
|
||||
(let [shape-center (gco/center-shape group)
|
||||
transform (:transform group (gmt/matrix))
|
||||
|
@ -306,6 +324,7 @@
|
|||
|
||||
;; Updates the shape and the applytransform-rect will update the other properties
|
||||
(-> group
|
||||
(update-group-viewbox new-selrect)
|
||||
(assoc :selrect new-selrect)
|
||||
(assoc :points new-points)
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -35,7 +35,8 @@
|
|||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
[potok.core :as ptk]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(declare persist-changes)
|
||||
(declare persist-sychronous-changes)
|
||||
|
@ -392,7 +393,7 @@
|
|||
(or (contains? props :data)
|
||||
(contains? props :uris)))))
|
||||
|
||||
(defn parse-svg [text]
|
||||
(defn parse-svg [[name text]]
|
||||
(->> (http/send! {:method :post
|
||||
:uri "/api/svg"
|
||||
:headers {"content-type" "image/svg+xml"}
|
||||
|
@ -400,13 +401,9 @@
|
|||
(rx/map (fn [{:keys [status body]}]
|
||||
(let [result (t/decode body)]
|
||||
(if (= status 200)
|
||||
result
|
||||
(assoc result :name name)
|
||||
(throw result)))))))
|
||||
|
||||
(defn fetch-svg [uri]
|
||||
(->> (http/send! {:method :get :uri uri})
|
||||
(rx/map :body)))
|
||||
|
||||
(defn url-name [url]
|
||||
(let [query-idx (str/last-index-of url "?")
|
||||
url (if (> query-idx 0) (subs url 0 query-idx) url)
|
||||
|
@ -414,6 +411,12 @@
|
|||
ext-idx (str/last-index-of filename ".")]
|
||||
(if (> ext-idx 0) (subs filename 0 ext-idx) filename)))
|
||||
|
||||
(defn fetch-svg [name uri]
|
||||
(->> (http/send! {:method :get :uri uri})
|
||||
(rx/map #(vector
|
||||
(or name (url-name uri))
|
||||
(:body %)))))
|
||||
|
||||
(defn- handle-upload-error [on-error stream]
|
||||
(->> stream
|
||||
(rx/catch
|
||||
|
@ -467,10 +470,8 @@
|
|||
|
||||
(->> (rx/from uris)
|
||||
(rx/filter svg-url?)
|
||||
(rx/merge-map fetch-svg)
|
||||
(rx/merge-map (partial fetch-svg name))
|
||||
(rx/merge-map parse-svg)
|
||||
(rx/with-latest vector uris)
|
||||
(rx/map #(assoc (first %) :name (or name (url-name (second %)))))
|
||||
(rx/do on-svg)))))
|
||||
|
||||
(defn- upload-data [file-id local? name data force-media on-image on-svg]
|
||||
|
@ -485,6 +486,12 @@
|
|||
:is-local local?
|
||||
:content blob}))
|
||||
|
||||
extract-content
|
||||
(fn [blob]
|
||||
(let [name (or name (.-name blob))]
|
||||
(-> (.text blob)
|
||||
(p/then #(vector name %)))))
|
||||
|
||||
file-stream (->> (rx/from data)
|
||||
(rx/map di/validate-file))]
|
||||
(rx/merge
|
||||
|
@ -496,10 +503,8 @@
|
|||
|
||||
(->> file-stream
|
||||
(rx/filter svg-blob?)
|
||||
(rx/merge-map #(.text %))
|
||||
(rx/merge-map extract-content)
|
||||
(rx/merge-map parse-svg)
|
||||
(rx/with-latest vector file-stream)
|
||||
(rx/map #(assoc (first %) :name (.-name (second %))))
|
||||
(rx/do on-svg)))))
|
||||
|
||||
(defn- upload-media-objects
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
shape)))
|
||||
|
||||
(defn create-raw-svg [name frame-id svg-data {:keys [attrs] :as data}]
|
||||
(let [{:keys [x y width height]} svg-data]
|
||||
(let [{:keys [x y width height offset-x offset-y]} svg-data]
|
||||
(-> {:id (uuid/next)
|
||||
:type :svg-raw
|
||||
:name name
|
||||
|
@ -101,7 +101,8 @@
|
|||
:content (cond-> data
|
||||
(map? data) (update :attrs usvg/clean-attrs))}
|
||||
(assoc :svg-attrs attrs)
|
||||
(assoc :svg-viewbox (select-keys svg-data [0 0 :width :height]))
|
||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||
(assoc :x offset-x :y offset-y)))
|
||||
(gsh/setup-selrect))))
|
||||
|
||||
(defn create-svg-root [frame-id svg-data]
|
||||
|
@ -119,7 +120,8 @@
|
|||
(dissoc :viewBox :xmlns))))))
|
||||
|
||||
(defn create-group [name frame-id svg-data {:keys [attrs]}]
|
||||
(let [{:keys [x y width height offset-x offset-y]} svg-data]
|
||||
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
||||
{:keys [x y width height offset-x offset-y]} svg-data]
|
||||
(-> {:id (uuid/next)
|
||||
:type :group
|
||||
:name name
|
||||
|
@ -128,8 +130,10 @@
|
|||
:y (+ y offset-y)
|
||||
:width width
|
||||
:height height}
|
||||
(assoc :svg-attrs (dissoc attrs :transform))
|
||||
(assoc :svg-viewbox (select-keys svg-data [:x :y :width :height]))
|
||||
(assoc :svg-transform svg-transform)
|
||||
(assoc :svg-attrs (d/without-keys attrs usvg/inheritable-props))
|
||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||
(assoc :x offset-x :y offset-y)))
|
||||
(gsh/setup-selrect))))
|
||||
|
||||
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||
|
@ -220,7 +224,7 @@
|
|||
(contains? attrs :ry) (assoc :ry (d/parse-double (:ry attrs))))
|
||||
|
||||
(merge metadata)
|
||||
(assoc :svg-transform transform)
|
||||
#_(assoc :svg-transform transform)
|
||||
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
|
||||
(assoc :svg-attrs (dissoc attrs :x :y :width :height :rx :ry :transform)))))
|
||||
|
||||
|
@ -257,20 +261,10 @@
|
|||
:frame-id frame-id}
|
||||
|
||||
(merge metadata)
|
||||
(assoc :svg-transform transform)
|
||||
#_(assoc :svg-transform transform)
|
||||
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
|
||||
(assoc :svg-attrs (dissoc attrs :cx :cy :r :rx :ry :transform)))))
|
||||
|
||||
(defn add-transform [transform node]
|
||||
(letfn [(append-transform [old-transform]
|
||||
(if (or (nil? old-transform) (empty? old-transform))
|
||||
transform
|
||||
(str old-transform " " transform)))]
|
||||
|
||||
(cond-> node
|
||||
transform
|
||||
(update-in [:attrs :transform] append-transform))))
|
||||
|
||||
(defn parse-svg-element [frame-id svg-data element-data unames]
|
||||
(let [{:keys [tag attrs]} element-data
|
||||
attrs (usvg/format-styles attrs)
|
||||
|
@ -286,14 +280,17 @@
|
|||
use-tag? (and (= :use tag) (contains? defs href-id))]
|
||||
|
||||
(if use-tag?
|
||||
;; TODO: If the child is a symbol we've to take the width/height into account
|
||||
(let [use-data (get defs href-id)
|
||||
translate (gpt/point (:x attrs 0) (:y attrs 0))
|
||||
attrs' (dissoc attrs :x :y :width :height :href :xlink:href)
|
||||
;; TODO: If the child is a symbol we've to take the width/height into account
|
||||
use-data (update use-data :attrs #(let [attrs (usvg/format-styles %)]
|
||||
(d/deep-merge attrs' attrs)))
|
||||
[shape children] (parse-svg-element frame-id svg-data use-data unames)]
|
||||
[(-> shape (gsh/move translate)) children])
|
||||
|
||||
displacement (gpt/point (d/parse-double (:x attrs "0")) (d/parse-double (:y attrs "0")))
|
||||
disp-matrix (str (gmt/translate-matrix displacement))
|
||||
element-data (-> element-data
|
||||
(assoc :tag :g)
|
||||
(update :attrs dissoc :x :y :width :height :href :xlink:href)
|
||||
(update :attrs usvg/add-transform disp-matrix)
|
||||
(assoc :content [use-data]))]
|
||||
(parse-svg-element frame-id svg-data element-data unames))
|
||||
|
||||
;; SVG graphic elements
|
||||
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
|
||||
|
@ -304,7 +301,8 @@
|
|||
:ellipse) (create-circle-shape name frame-id svg-data element-data)
|
||||
:path (create-path-shape name frame-id svg-data element-data)
|
||||
:polyline (create-path-shape name frame-id svg-data (-> element-data usvg/polyline->path))
|
||||
:polygon (create-path-shape name frame-id svg-data (-> element-data usvg/polygon->path))
|
||||
:polygo (create-path-shape name frame-id svg-data (-> element-data usvg/polygon->path))
|
||||
:line (create-path-shape name frame-id svg-data (-> element-data usvg/line->path))
|
||||
#_other (create-raw-svg name frame-id svg-data element-data))
|
||||
|
||||
(assoc :svg-defs (select-keys (:defs svg-data) references))
|
||||
|
@ -313,7 +311,7 @@
|
|||
|
||||
children (cond->> (:content element-data)
|
||||
(= tag :g)
|
||||
(mapv #(add-transform (:transform attrs) %)))]
|
||||
(mapv #(usvg/inherit-attributes attrs %)))]
|
||||
[shape children]))))
|
||||
|
||||
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames [rchs uchs]] [index data]]
|
||||
|
@ -365,20 +363,24 @@
|
|||
:height vb-height
|
||||
:name svg-name))
|
||||
|
||||
[def-nodes svg-data] (usvg/extract-defs svg-data)
|
||||
[def-nodes svg-data] (-> svg-data
|
||||
(usvg/fix-default-values)
|
||||
(usvg/fix-percents)
|
||||
(usvg/extract-defs))
|
||||
|
||||
svg-data (assoc svg-data :defs def-nodes)
|
||||
|
||||
root-shape (create-svg-root frame-id svg-data)
|
||||
root-id (:id root-shape)
|
||||
|
||||
changes (dwc/add-shape-changes page-id objects selected root-shape)
|
||||
changes (dwc/add-shape-changes page-id objects selected root-shape false)
|
||||
|
||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
||||
[_ [rchanges uchanges]] (reduce reducer-fn [unames changes] (d/enumerate (:content svg-data)))
|
||||
|
||||
reg-objects-action {:type :reg-objects
|
||||
:page-id page-id
|
||||
:shapes (->> rchanges (map :id) (remove nil?) (into #{root-id}) vec)}
|
||||
:shapes (->> rchanges (filter #(= :add-obj (:type %))) (map :id) reverse vec)}
|
||||
|
||||
rchanges (conj rchanges reg-objects-action)]
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@
|
|||
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
(obj/merge!
|
||||
#js {:className "group"
|
||||
:pointerEvents pointer-events
|
||||
#js {:pointerEvents pointer-events
|
||||
:mask (when (and mask (not expand-mask)) (mask-str mask))}))]
|
||||
|
||||
[:> :g props
|
||||
|
|
|
@ -48,23 +48,17 @@
|
|||
:else
|
||||
(let [{:keys [tag attrs content]} node
|
||||
|
||||
transform-gradient? (and (#{:linearGradient :radialGradient} tag)
|
||||
(= "userSpaceOnUse" (get attrs :gradientUnits "userSpaceOnUse")))
|
||||
transform-gradient? (and (contains? usvg/gradient-tags tag)
|
||||
(= "userSpaceOnUse" (get attrs :gradientUnits "objectBoundingBox")))
|
||||
|
||||
transform-pattern? (and (= :pattern tag)
|
||||
(every? d/num-string? [(:x attrs "0") (:y attrs "0") (:width attrs "0") (:height attrs "0")])
|
||||
(= "userSpaceOnUse" (get attrs :patternUnits "userSpaceOnUse")))
|
||||
|
||||
transform-clippath? (and (= :clipPath tag)
|
||||
(= "userSpaceOnUse" (get attrs :clipPathUnits "userSpaceOnUse")))
|
||||
|
||||
transform-filter? (and (= #{:filter
|
||||
;; Filter primitives. We need to remap subregions
|
||||
:feBlend :feColorMatrix :feComponentTransfer :feComposite :feConvolveMatrix
|
||||
:feDiffuseLighting :feDisplacementMap :feFlood :feGaussianBlur
|
||||
:feImage :feMerge :feMorphology :feOffset
|
||||
:feSpecularLighting :feTile :feTurbulence} tag)
|
||||
(= "userSpaceOnUse" (get attrs :filterUnits "userSpaceOnUse")))
|
||||
transform-filter? (and (contains? usvg/filter-tags tag)
|
||||
(= "userSpaceOnUse" (get attrs :filterUnits "objectBoundingBox")))
|
||||
|
||||
attrs (-> attrs
|
||||
(usvg/update-attr-ids prefix-id)
|
||||
|
@ -88,8 +82,6 @@
|
|||
|
||||
(mf/defc svg-defs [{:keys [shape render-id]}]
|
||||
(let [svg-defs (:svg-defs shape)
|
||||
;;_ (when (:svg-transform shape)
|
||||
;; (.log js/console (:name shape) (:old-transform shape) (str (:svg-transform shape))))
|
||||
|
||||
transform (mf/use-memo
|
||||
(mf/deps shape)
|
||||
|
@ -98,7 +90,7 @@
|
|||
(usvg/svg-transform-matrix shape)))
|
||||
|
||||
;; Paths doesn't have transform so we have to transform its gradients
|
||||
transform (if (and (= :path (:type shape)) (contains? shape :svg-transform))
|
||||
transform (if (contains? shape :svg-transform)
|
||||
(gmt/multiply transform (or (:svg-transform shape) (gmt/matrix)))
|
||||
transform)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defonce replace-regex #"#([^\W]+)")
|
||||
|
@ -99,7 +100,8 @@
|
|||
:else
|
||||
(let [replace-id
|
||||
(fn [result it]
|
||||
(str/replace result it (replace-fn it)))]
|
||||
(let [to-replace (replace-fn it)]
|
||||
(str/replace result (str "#" it) (str "#" to-replace))))]
|
||||
(reduce replace-id val (extract-ids val)))))]
|
||||
(d/mapm update-ids attrs)))
|
||||
|
||||
|
@ -119,11 +121,13 @@
|
|||
(reduce visit-node result (:content node))))]
|
||||
(visit-node {} content)))
|
||||
|
||||
(def remove-tags #{:defs :linearGradient})
|
||||
|
||||
(defn extract-defs [{:keys [tag attrs content] :as node}]
|
||||
(if-not (map? node)
|
||||
[{} node]
|
||||
|
||||
(let [remove-node? (fn [{:keys [tag]}] (= tag :defs))
|
||||
(let [remove-node? (fn [{:keys [tag]}] (contains? remove-tags tag))
|
||||
|
||||
rec-result (->> (:content node) (map extract-defs))
|
||||
node (assoc node :content (->> rec-result (map second) (filterv (comp not remove-node?))))
|
||||
|
@ -218,13 +222,13 @@
|
|||
(defn format-scale-params [params]
|
||||
(assert (or (= (count params) 1) (= (count params) 2)))
|
||||
(if (= (count params) 1)
|
||||
[(gpt/point (nth params 0))]
|
||||
[(gpt/point (mth/abs (nth params 0)))]
|
||||
[(gpt/point (nth params 0) (nth params 1))]))
|
||||
|
||||
(defn format-rotate-params [params]
|
||||
(assert (or (= (count params) 1) (= (count params) 3)) (str "??" (count params)))
|
||||
(if (= (count params) 1)
|
||||
[(nth params 0)]
|
||||
[(nth params 0) (gpt/point 0 0)]
|
||||
[(nth params 0) (gpt/point (nth params 1) (nth params 2))]))
|
||||
|
||||
(defn format-skew-x-params [params]
|
||||
|
@ -291,3 +295,207 @@
|
|||
(dissoc :points)
|
||||
(assoc :d (str (points->path (:points attrs)) "Z")))]
|
||||
(assoc node :attrs attrs :tag tag)))
|
||||
|
||||
(defn line->path [{:keys [attrs tag] :as node}]
|
||||
(let [tag :path
|
||||
{:keys [x1 y1 x2 y2]} attrs
|
||||
attrs (-> attrs
|
||||
(dissoc :x1 :x2 :y1 :y2)
|
||||
(assoc :d (str "M" x1 "," y1 " L" x2 "," y2)))]
|
||||
|
||||
(assoc node :attrs attrs :tag tag)))
|
||||
|
||||
(defn add-transform [attrs transform]
|
||||
(letfn [(append-transform [old-transform]
|
||||
(if (or (nil? old-transform) (empty? old-transform))
|
||||
transform
|
||||
(str transform " " old-transform)))]
|
||||
|
||||
(cond-> attrs
|
||||
transform
|
||||
(update :transform append-transform))))
|
||||
|
||||
(defonce inheritable-props
|
||||
[:clip-rule
|
||||
:color
|
||||
:color-interpolation
|
||||
:color-interpolation-filters
|
||||
:color-profile
|
||||
:color-rendering
|
||||
:cursor
|
||||
:direction
|
||||
:dominant-baseline
|
||||
:fill
|
||||
:fill-opacity
|
||||
:fill-rule
|
||||
:font
|
||||
:font-family
|
||||
:font-size
|
||||
:font-size-adjust
|
||||
:font-stretch
|
||||
:font-style
|
||||
:font-variant
|
||||
:font-weight
|
||||
:glyph-orientation-horizontal
|
||||
:glyph-orientation-vertical
|
||||
:image-rendering
|
||||
:letter-spacing
|
||||
:marker
|
||||
:marker-end
|
||||
:marker-mid
|
||||
:marker-start
|
||||
:paint-order
|
||||
:pointer-events
|
||||
:shape-rendering
|
||||
:stroke
|
||||
:stroke-dasharray
|
||||
:stroke-dashoffset
|
||||
:stroke-linecap
|
||||
:stroke-linejoin
|
||||
:stroke-miterlimit
|
||||
:stroke-opacity
|
||||
:stroke-width
|
||||
:text-anchor
|
||||
:text-rendering
|
||||
:transform
|
||||
:visibility
|
||||
:word-spacing
|
||||
:writing-mode])
|
||||
|
||||
(defonce gradient-tags
|
||||
#{:linearGradient
|
||||
:radialGradient})
|
||||
|
||||
(defonce filter-tags
|
||||
#{:filter
|
||||
:feBlend
|
||||
:feColorMatrix
|
||||
:feComponentTransfer
|
||||
:feComposite
|
||||
:feConvolveMatrix
|
||||
:feDiffuseLighting
|
||||
:feDisplacementMap
|
||||
:feFlood
|
||||
:feGaussianBlur
|
||||
:feImage
|
||||
:feMerge
|
||||
:feMorphology
|
||||
:feOffset
|
||||
:feSpecularLighting
|
||||
:feTile
|
||||
:feTurbulence})
|
||||
|
||||
(defn inherit-attributes [group-attrs {:keys [attrs] :as node}]
|
||||
(if (map? node)
|
||||
(let [attrs (-> (format-styles attrs)
|
||||
(add-transform (:transform group-attrs)))
|
||||
attrs (d/deep-merge (select-keys group-attrs inheritable-props) attrs)]
|
||||
(assoc node :attrs attrs))
|
||||
node))
|
||||
|
||||
(defn map-nodes [mapfn node]
|
||||
(let [update-content
|
||||
(fn [content] (cond->> content
|
||||
(vector? content)
|
||||
(mapv (partial map-nodes mapfn))))]
|
||||
|
||||
(cond-> node
|
||||
(map? node)
|
||||
(-> (mapfn)
|
||||
(d/update-when :content update-content)))))
|
||||
|
||||
;; Defaults for some tags per spec https://www.w3.org/TR/SVG11/single-page.html
|
||||
;; they are basicaly the defaults that can be percents and we need to replace because
|
||||
;; otherwise won't work as expected in the workspace
|
||||
(defonce svg-tag-defaults
|
||||
(let [filter-default {:units :filterUnits
|
||||
:default "objectBoundingBox"
|
||||
"objectBoundingBox" {}
|
||||
"userSpaceOnUse" {:x "-10%" :y "-10%" :width "120%" :height "120%"}}
|
||||
filter-values (->> filter-tags
|
||||
(reduce #(merge %1 (hash-map %2 filter-default)) {}))]
|
||||
|
||||
(merge {:linearGradient {:units :gradientUnits
|
||||
:default "objectBoundingBox"
|
||||
"objectBoundingBox" {}
|
||||
"userSpaceOnUse" {:x1 "0%" :y1 "0%" :x2 "100%" :y2 "0%"}}
|
||||
:radialGradient {:units :gradientUnits
|
||||
:default "objectBoundingBox"
|
||||
"objectBoundingBox" {}
|
||||
"userSpaceOnUse" {:cx "50%" :cy "50%" :r "50%"}}
|
||||
:mask {:units :maskUnits
|
||||
:default "userSpaceOnUse"
|
||||
"objectBoundingBox" {}
|
||||
"userSpaceOnUse" {:x "-10%" :y "-10%" :width "120%" :height "120%"}}}
|
||||
filter-values)))
|
||||
|
||||
(defn fix-default-values
|
||||
"Gives values to some SVG elements which defaults won't work when imported into the platform"
|
||||
[svg-data]
|
||||
(let [add-defaults
|
||||
(fn [{:keys [tag attrs] :as node}]
|
||||
(let [prop (get-in svg-tag-defaults [tag :units])
|
||||
default-units (get-in svg-tag-defaults [tag :default])
|
||||
units (get attrs prop default-units)
|
||||
tag-default (get-in svg-tag-defaults [tag units])]
|
||||
(d/update-when node :attrs #(merge tag-default %))))
|
||||
|
||||
fix-node-defaults
|
||||
(fn [node]
|
||||
(cond-> node
|
||||
(contains? svg-tag-defaults (:tag node))
|
||||
(add-defaults)))]
|
||||
|
||||
(->> svg-data (map-nodes fix-node-defaults))))
|
||||
|
||||
(defn calculate-ratio
|
||||
;; sqrt((actual-width)**2 + (actual-height)**2)/sqrt(2).
|
||||
[width height]
|
||||
(/ (mth/sqrt (+ (mth/pow width 2)
|
||||
(mth/pow height 2)))
|
||||
(mth/sqrt 2)))
|
||||
|
||||
(defn fix-percents
|
||||
"Changes percents to a value according to the size of the svg imported"
|
||||
[svg-data]
|
||||
;; https://www.w3.org/TR/SVG11/single-page.html#coords-Units
|
||||
(let [viewbox {:x (:offset-x svg-data)
|
||||
:y (:offset-y svg-data)
|
||||
:width (:width svg-data)
|
||||
:height (:height svg-data)
|
||||
:ratio (calculate-ratio (:width svg-data) (:height svg-data))}]
|
||||
(letfn [(fix-length [prop-length val]
|
||||
(* (get viewbox prop-length) (/ val 100.)))
|
||||
|
||||
(fix-coord [prop-coord prop-length val]
|
||||
(+ (get viewbox prop-coord)
|
||||
(fix-length prop-length val)))
|
||||
|
||||
(fix-percent-attr [attr-key attr-val]
|
||||
(let [is-percent? (str/ends-with? attr-val "%")
|
||||
is-x? #{:x :x1 :x2 :cx}
|
||||
is-y? #{:y :y1 :y2 :cy}
|
||||
is-width? #{:width}
|
||||
is-height? #{:height}
|
||||
is-other? #{:r :stroke-width}]
|
||||
|
||||
(if is-percent?
|
||||
;; JS parseFloat removes the % symbol
|
||||
(let [attr-num (d/parse-double attr-val)]
|
||||
(str (cond
|
||||
(is-x? attr-key) (fix-coord :x :width attr-num)
|
||||
(is-y? attr-key) (fix-coord :y :height attr-num)
|
||||
(is-width? attr-key) (fix-length :width attr-num)
|
||||
(is-height? attr-key) (fix-length :height attr-num)
|
||||
(is-other? attr-key) (fix-length :ratio attr-num)
|
||||
:else (do (.warn js/console "Percent property not converted!" (str attr-key) (str attr-val))
|
||||
attr-val))))
|
||||
attr-val)))
|
||||
|
||||
(fix-percent-attrs [attrs]
|
||||
(d/mapm fix-percent-attr attrs))
|
||||
|
||||
(fix-percent-values [node]
|
||||
(update node :attrs fix-percent-attrs))]
|
||||
|
||||
(->> svg-data (map-nodes fix-percent-values)))))
|
||||
|
|
4
vendor/svgclean/main.js
vendored
4
vendor/svgclean/main.js
vendored
|
@ -15,6 +15,7 @@ const plugins = [
|
|||
{ "convertShapeToPath" : false },
|
||||
{ "convertEllipseToCircle" : false },
|
||||
{ "moveElemsAttrsToGroup" : false },
|
||||
{ "moveGroupAttrsToElems" : false },
|
||||
{ "collapseGroups" : false },
|
||||
{
|
||||
"convertPathData" : {
|
||||
|
@ -28,9 +29,10 @@ const plugins = [
|
|||
{ "mergePaths" : false },
|
||||
{ "sortDefsChildren" : false },
|
||||
{ "removeDimensions" : true },
|
||||
{ "removeStyleElement" : true },
|
||||
{ "removeStyleElement" : false },
|
||||
{ "removeScriptElement" : true },
|
||||
{ "removeOffCanvasPaths" : false },
|
||||
{ "cleanupNumericValues": true}
|
||||
];
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ exports.description = 'rounds numeric values to the fixed precision, removes def
|
|||
|
||||
exports.params = {
|
||||
floatPrecision: 3,
|
||||
leadingZero: true,
|
||||
leadingZero: false,
|
||||
defaultPx: true,
|
||||
convertToPx: true
|
||||
};
|
||||
|
@ -20,7 +20,8 @@ var regNumericValues = /^([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)(px|pt|pc|mm|cm|m|in|f
|
|||
mm: 96/25.4,
|
||||
in: 96,
|
||||
pt: 4/3,
|
||||
pc: 16
|
||||
pc: 16,
|
||||
em: 16
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,12 +62,8 @@ exports.fn = function(item, params) {
|
|||
|
||||
// convert absolute values to pixels
|
||||
if (params.convertToPx && units && (units in absoluteLengths)) {
|
||||
var pxNum = +(absoluteLengths[units] * match[1]).toFixed(floatPrecision);
|
||||
|
||||
if (String(pxNum).length < match[0].length) {
|
||||
num = pxNum;
|
||||
units = 'px';
|
||||
}
|
||||
num = +(absoluteLengths[units] * match[1]).toFixed(floatPrecision);
|
||||
units = 'px';
|
||||
}
|
||||
|
||||
// and remove leading zero
|
||||
|
|
Loading…
Add table
Reference in a new issue