mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 10:21:39 +02:00
✨ SVG import enhancements
This commit is contained in:
parent
92e07c3b54
commit
c380400578
4 changed files with 584 additions and 181 deletions
|
@ -164,27 +164,28 @@
|
||||||
(gsh/setup-selrect))))
|
(gsh/setup-selrect))))
|
||||||
|
|
||||||
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||||
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
(when (and (contains? attrs :d) (not (empty? (:d attrs)) ))
|
||||||
path-content (ugp/path->content (:d attrs))
|
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
||||||
content (cond-> path-content
|
path-content (ugp/path->content (:d attrs))
|
||||||
svg-transform
|
content (cond-> path-content
|
||||||
(gsh/transform-content svg-transform))
|
svg-transform
|
||||||
|
(gsh/transform-content svg-transform))
|
||||||
|
|
||||||
selrect (gsh/content->selrect content)
|
selrect (gsh/content->selrect content)
|
||||||
points (gsh/rect->points selrect)
|
points (gsh/rect->points selrect)
|
||||||
|
|
||||||
origin (gpt/negate (gpt/point svg-data))]
|
origin (gpt/negate (gpt/point svg-data))]
|
||||||
(-> {:id (uuid/next)
|
(-> {:id (uuid/next)
|
||||||
:type :path
|
:type :path
|
||||||
:name name
|
:name name
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:content content
|
:content content
|
||||||
:selrect selrect
|
:selrect selrect
|
||||||
:points points}
|
:points points}
|
||||||
(assoc :svg-viewbox (select-keys selrect [:x :y :width :height]))
|
(assoc :svg-viewbox (select-keys selrect [:x :y :width :height]))
|
||||||
(assoc :svg-attrs (dissoc attrs :d :transform))
|
(assoc :svg-attrs (dissoc attrs :d :transform))
|
||||||
(assoc :svg-transform svg-transform)
|
(assoc :svg-transform svg-transform)
|
||||||
(gsh/translate-to-frame origin))))
|
(gsh/translate-to-frame origin)))))
|
||||||
|
|
||||||
(defn calculate-rect-metadata [rect-data transform]
|
(defn calculate-rect-metadata [rect-data transform]
|
||||||
(let [points (-> (gsh/rect->points rect-data)
|
(let [points (-> (gsh/rect->points rect-data)
|
||||||
|
@ -333,7 +334,7 @@
|
||||||
;; SVG graphic elements
|
;; SVG graphic elements
|
||||||
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
|
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
|
||||||
(let [shape (-> (case tag
|
(let [shape (-> (case tag
|
||||||
(:g :a) (create-group name frame-id svg-data element-data)
|
(:g :a :svg) (create-group name frame-id svg-data element-data)
|
||||||
:rect (create-rect-shape name frame-id svg-data element-data)
|
:rect (create-rect-shape name frame-id svg-data element-data)
|
||||||
(:circle
|
(:circle
|
||||||
:ellipse) (create-circle-shape name frame-id svg-data element-data)
|
:ellipse) (create-circle-shape name frame-id svg-data element-data)
|
||||||
|
@ -344,34 +345,42 @@
|
||||||
:image (create-image-shape name frame-id svg-data element-data)
|
:image (create-image-shape name frame-id svg-data element-data)
|
||||||
#_other (create-raw-svg name frame-id svg-data element-data))
|
#_other (create-raw-svg name frame-id svg-data element-data))
|
||||||
|
|
||||||
(assoc :svg-defs (select-keys (:defs svg-data) references))
|
)
|
||||||
(setup-fill)
|
shape (when (some? shape)
|
||||||
(setup-stroke))
|
(-> shape
|
||||||
|
(assoc :svg-defs (select-keys (:defs svg-data) references))
|
||||||
|
(setup-fill)
|
||||||
|
(setup-stroke)))
|
||||||
|
|
||||||
children (cond->> (:content element-data)
|
children (cond->> (:content element-data)
|
||||||
(= tag :g)
|
(= tag :g)
|
||||||
(mapv #(usvg/inherit-attributes attrs %)))]
|
(mapv #(usvg/inherit-attributes attrs %)))]
|
||||||
[shape children]))))
|
[shape children]))))
|
||||||
|
|
||||||
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames [rchs uchs]] [index data]]
|
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames [rchs uchs]] [index data]]
|
||||||
(let [[shape children] (parse-svg-element frame-id svg-data data unames)
|
(let [[shape children] (parse-svg-element frame-id svg-data data unames)]
|
||||||
shape-id (:id shape)
|
(if (some? shape)
|
||||||
|
(let [shape-id (:id shape)
|
||||||
|
|
||||||
[rch1 uch1] (dwc/add-shape-changes page-id objects selected shape false)
|
[rch1 uch1] (dwc/add-shape-changes page-id objects selected shape false)
|
||||||
|
|
||||||
;; Mov-objects won't have undo because we "delete" the object in the undo of the
|
;; Mov-objects won't have undo because we "delete" the object in the undo of the
|
||||||
;; previous operation
|
;; previous operation
|
||||||
rch2 [{:type :mov-objects
|
rch2 [{:type :mov-objects
|
||||||
:parent-id parent-id
|
:parent-id parent-id
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:index index
|
:index index
|
||||||
:shapes [shape-id]}]
|
:shapes [shape-id]}]
|
||||||
|
|
||||||
;; Careful! the undo changes are concatenated reversed (we undo in reverse order
|
;; Careful! the undo changes are concatenated reversed (we undo in reverse order
|
||||||
changes [(d/concat rchs rch1 rch2) (d/concat uch1 uchs)]
|
changes [(d/concat rchs rch1 rch2) (d/concat uch1 uchs)]
|
||||||
unames (conj unames (:name shape))
|
unames (conj unames (:name shape))
|
||||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
||||||
(reduce reducer-fn [unames changes] (d/enumerate children))))
|
(reduce reducer-fn [unames changes] (d/enumerate children)))
|
||||||
|
|
||||||
|
;; Cannot create the data from curren tags
|
||||||
|
[unames [rchs uchs]])))
|
||||||
|
|
||||||
(declare create-svg-shapes)
|
(declare create-svg-shapes)
|
||||||
|
|
||||||
|
|
|
@ -32,20 +32,24 @@
|
||||||
mask (when show-mask? (first childs))
|
mask (when show-mask? (first childs))
|
||||||
childs (if show-mask? (rest childs) childs)
|
childs (if show-mask? (rest childs) childs)
|
||||||
|
|
||||||
props (-> (attrs/extract-style-attrs shape)
|
mask-props (when (and mask (not expand-mask))
|
||||||
(obj/merge!
|
#js {:clipPath (clip-str mask)
|
||||||
#js {:pointerEvents pointer-events
|
:mask (mask-str mask)})
|
||||||
:clipPath (when (and mask (not expand-mask)) (clip-str mask))
|
mask-wrapper (if (and mask (not expand-mask))
|
||||||
:mask (when (and mask (not expand-mask)) (mask-str mask))}))]
|
"g"
|
||||||
|
mf/Fragment)
|
||||||
|
|
||||||
[:> :g props
|
props (-> (attrs/extract-style-attrs shape))]
|
||||||
(when mask
|
|
||||||
[:> render-mask #js {:frame frame :mask mask}])
|
|
||||||
|
|
||||||
(for [item childs]
|
[:> mask-wrapper mask-props
|
||||||
[:& shape-wrapper {:frame frame
|
[:> :g (attrs/extract-style-attrs shape)
|
||||||
:shape item
|
(when mask
|
||||||
:key (:id item)}])]))))
|
[:> render-mask #js {:frame frame :mask mask}])
|
||||||
|
|
||||||
|
(for [item childs]
|
||||||
|
[:& shape-wrapper {:frame frame
|
||||||
|
:shape item
|
||||||
|
:key (:id item)}])]]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,15 +60,19 @@
|
||||||
transform-filter? (and (contains? usvg/filter-tags tag)
|
transform-filter? (and (contains? usvg/filter-tags tag)
|
||||||
(= "userSpaceOnUse" (get attrs :filterUnits "objectBoundingBox")))
|
(= "userSpaceOnUse" (get attrs :filterUnits "objectBoundingBox")))
|
||||||
|
|
||||||
|
transform-mask? (and (= :mask tag)
|
||||||
|
(= "userSpaceOnUse" (get attrs :maskUnits "objectBoundingBox")))
|
||||||
|
|
||||||
attrs (-> attrs
|
attrs (-> attrs
|
||||||
(usvg/update-attr-ids prefix-id)
|
(usvg/update-attr-ids prefix-id)
|
||||||
(usvg/clean-attrs)
|
(usvg/clean-attrs)
|
||||||
|
|
||||||
(cond->
|
(cond->
|
||||||
transform-gradient? (add-matrix :gradientTransform transform)
|
transform-gradient? (add-matrix :gradientTransform transform)
|
||||||
transform-pattern? (add-matrix :patternTransform transform)
|
transform-pattern? (add-matrix :patternTransform transform)
|
||||||
transform-clippath? (add-matrix :transform transform)
|
transform-clippath? (add-matrix :transform transform)
|
||||||
transform-filter? (transform-region transform)))
|
(or transform-filter?
|
||||||
|
transform-mask?) (transform-region transform)))
|
||||||
|
|
||||||
[wrapper wrapper-props] (if (= tag :mask)
|
[wrapper wrapper-props] (if (= tag :mask)
|
||||||
["g" #js {:transform (str transform)}]
|
["g" #js {:transform (str transform)}]
|
||||||
|
|
|
@ -24,6 +24,472 @@
|
||||||
(defonce matrices-regex #"(matrix|translate|scale|rotate|skewX|skewY)\(([^\)]*)\)")
|
(defonce matrices-regex #"(matrix|translate|scale|rotate|skewX|skewY)\(([^\)]*)\)")
|
||||||
(defonce number-regex #"[+-]?\d*(\.\d+)?(e[+-]?\d+)?")
|
(defonce number-regex #"[+-]?\d*(\.\d+)?(e[+-]?\d+)?")
|
||||||
|
|
||||||
|
(defonce tags-to-remove #{:defs :linearGradient :radialGradient :metadata :mask :clipPath :filter :title})
|
||||||
|
|
||||||
|
;; https://www.w3.org/TR/SVG11/eltindex.html
|
||||||
|
(defonce svg-tags-list
|
||||||
|
#{:a
|
||||||
|
:altGlyph
|
||||||
|
:altGlyphDef
|
||||||
|
:altGlyphItem
|
||||||
|
:animate
|
||||||
|
:animateColor
|
||||||
|
:animateMotion
|
||||||
|
:animateTransform
|
||||||
|
:circle
|
||||||
|
:clipPath
|
||||||
|
:color-profile
|
||||||
|
:cursor
|
||||||
|
:defs
|
||||||
|
:desc
|
||||||
|
:ellipse
|
||||||
|
:feBlend
|
||||||
|
:feColorMatrix
|
||||||
|
:feComponentTransfer
|
||||||
|
:feComposite
|
||||||
|
:feConvolveMatrix
|
||||||
|
:feDiffuseLighting
|
||||||
|
:feDisplacementMap
|
||||||
|
:feDistantLight
|
||||||
|
:feFlood
|
||||||
|
:feFuncA
|
||||||
|
:feFuncB
|
||||||
|
:feFuncG
|
||||||
|
:feFuncR
|
||||||
|
:feGaussianBlur
|
||||||
|
:feImage
|
||||||
|
:feMerge
|
||||||
|
:feMergeNode
|
||||||
|
:feMorphology
|
||||||
|
:feOffset
|
||||||
|
:fePointLight
|
||||||
|
:feSpecularLighting
|
||||||
|
:feSpotLight
|
||||||
|
:feTile
|
||||||
|
:feTurbulence
|
||||||
|
:filter
|
||||||
|
:font
|
||||||
|
:font-face
|
||||||
|
:font-face-format
|
||||||
|
:font-face-name
|
||||||
|
:font-face-src
|
||||||
|
:font-face-uri
|
||||||
|
:foreignObject
|
||||||
|
:g
|
||||||
|
:glyph
|
||||||
|
:glyphRef
|
||||||
|
:hkern
|
||||||
|
:image
|
||||||
|
:line
|
||||||
|
:linearGradient
|
||||||
|
:marker
|
||||||
|
:mask
|
||||||
|
:metadata
|
||||||
|
:missing-glyph
|
||||||
|
:mpath
|
||||||
|
:path
|
||||||
|
:pattern
|
||||||
|
:polygon
|
||||||
|
:polyline
|
||||||
|
:radialGradient
|
||||||
|
:rect
|
||||||
|
:script
|
||||||
|
:set
|
||||||
|
:stop
|
||||||
|
:style
|
||||||
|
:svg
|
||||||
|
:switch
|
||||||
|
:symbol
|
||||||
|
:text
|
||||||
|
:textPath
|
||||||
|
:title
|
||||||
|
:tref
|
||||||
|
:tspan
|
||||||
|
:use
|
||||||
|
:view
|
||||||
|
:vkern
|
||||||
|
})
|
||||||
|
|
||||||
|
;; https://www.w3.org/TR/SVG11/attindex.html
|
||||||
|
(defonce svg-attr-list
|
||||||
|
#{:accent-height
|
||||||
|
:accumulate
|
||||||
|
:additive
|
||||||
|
:alphabetic
|
||||||
|
:amplitude
|
||||||
|
:arabic-form
|
||||||
|
:ascent
|
||||||
|
:attributeName
|
||||||
|
:attributeType
|
||||||
|
:azimuth
|
||||||
|
:baseFrequency
|
||||||
|
:baseProfile
|
||||||
|
:bbox
|
||||||
|
:begin
|
||||||
|
:bias
|
||||||
|
:by
|
||||||
|
:calcMode
|
||||||
|
:cap-height
|
||||||
|
:class
|
||||||
|
:clipPathUnits
|
||||||
|
:contentScriptType
|
||||||
|
:contentStyleType
|
||||||
|
:cx
|
||||||
|
:cy
|
||||||
|
:d
|
||||||
|
:descent
|
||||||
|
:diffuseConstant
|
||||||
|
:divisor
|
||||||
|
:dur
|
||||||
|
:dx
|
||||||
|
:dy
|
||||||
|
:edgeMode
|
||||||
|
:elevation
|
||||||
|
:end
|
||||||
|
:exponent
|
||||||
|
:externalResourcesRequired
|
||||||
|
:fill
|
||||||
|
:filterRes
|
||||||
|
:filterUnits
|
||||||
|
:font-family
|
||||||
|
:font-size
|
||||||
|
:font-stretch
|
||||||
|
:font-style
|
||||||
|
:font-variant
|
||||||
|
:font-weight
|
||||||
|
:format
|
||||||
|
:from
|
||||||
|
:fx
|
||||||
|
:fy
|
||||||
|
:g1
|
||||||
|
:g2
|
||||||
|
:glyph-name
|
||||||
|
:glyphRef
|
||||||
|
:gradientTransform
|
||||||
|
:gradientUnits
|
||||||
|
:hanging
|
||||||
|
:height
|
||||||
|
:horiz-adv-x
|
||||||
|
:horiz-origin-x
|
||||||
|
:horiz-origin-y
|
||||||
|
:id
|
||||||
|
:ideographic
|
||||||
|
:in
|
||||||
|
:in2
|
||||||
|
:intercept
|
||||||
|
:k
|
||||||
|
:k1
|
||||||
|
:k2
|
||||||
|
:k3
|
||||||
|
:k4
|
||||||
|
:kernelMatrix
|
||||||
|
:kernelUnitLength
|
||||||
|
:keyPoints
|
||||||
|
:keySplines
|
||||||
|
:keyTimes
|
||||||
|
:lang
|
||||||
|
:lengthAdjust
|
||||||
|
:limitingConeAngle
|
||||||
|
:local
|
||||||
|
:markerHeight
|
||||||
|
:markerUnits
|
||||||
|
:markerWidth
|
||||||
|
:maskContentUnits
|
||||||
|
:maskUnits
|
||||||
|
:mathematical
|
||||||
|
:max
|
||||||
|
:media
|
||||||
|
:method
|
||||||
|
:min
|
||||||
|
:mode
|
||||||
|
:name
|
||||||
|
:numOctaves
|
||||||
|
:offset
|
||||||
|
;; We don't support events
|
||||||
|
;;:onabort
|
||||||
|
;;:onactivate
|
||||||
|
;;:onbegin
|
||||||
|
;;:onclick
|
||||||
|
;;:onend
|
||||||
|
;;:onerror
|
||||||
|
;;:onfocusin
|
||||||
|
;;:onfocusout
|
||||||
|
;;:onload
|
||||||
|
;;:onmousedown
|
||||||
|
;;:onmousemove
|
||||||
|
;;:onmouseout
|
||||||
|
;;:onmouseover
|
||||||
|
;;:onmouseup
|
||||||
|
;;:onrepeat
|
||||||
|
;;:onresize
|
||||||
|
;;:onscroll
|
||||||
|
;;:onunload
|
||||||
|
;;:onzoom
|
||||||
|
:operator
|
||||||
|
:order
|
||||||
|
:orient
|
||||||
|
:orientation
|
||||||
|
:origin
|
||||||
|
:overline-position
|
||||||
|
:overline-thickness
|
||||||
|
:panose-1
|
||||||
|
:path
|
||||||
|
:pathLength
|
||||||
|
:patternContentUnits
|
||||||
|
:patternTransform
|
||||||
|
:patternUnits
|
||||||
|
:points
|
||||||
|
:pointsAtX
|
||||||
|
:pointsAtY
|
||||||
|
:pointsAtZ
|
||||||
|
:preserveAlpha
|
||||||
|
:preserveAspectRatio
|
||||||
|
:primitiveUnits
|
||||||
|
:r
|
||||||
|
:radius
|
||||||
|
:refX
|
||||||
|
:refY
|
||||||
|
:rendering-intent
|
||||||
|
:repeatCount
|
||||||
|
:repeatDur
|
||||||
|
:requiredExtensions
|
||||||
|
:requiredFeatures
|
||||||
|
:restart
|
||||||
|
:result
|
||||||
|
:rotate
|
||||||
|
:rx
|
||||||
|
:ry
|
||||||
|
:scale
|
||||||
|
:seed
|
||||||
|
:slope
|
||||||
|
:spacing
|
||||||
|
:specularConstant
|
||||||
|
:specularExponent
|
||||||
|
:spreadMethod
|
||||||
|
:startOffset
|
||||||
|
:stdDeviation
|
||||||
|
:stemh
|
||||||
|
:stemv
|
||||||
|
:stitchTiles
|
||||||
|
:strikethrough-position
|
||||||
|
:strikethrough-thickness
|
||||||
|
:string
|
||||||
|
:style
|
||||||
|
:surfaceScale
|
||||||
|
:systemLanguage
|
||||||
|
:tableValues
|
||||||
|
:target
|
||||||
|
:targetX
|
||||||
|
:targetY
|
||||||
|
:textLength
|
||||||
|
:title
|
||||||
|
:to
|
||||||
|
:transform
|
||||||
|
:type
|
||||||
|
:u1
|
||||||
|
:u2
|
||||||
|
:underline-position
|
||||||
|
:underline-thickness
|
||||||
|
:unicode
|
||||||
|
:unicode-range
|
||||||
|
:units-per-em
|
||||||
|
:v-alphabetic
|
||||||
|
:v-hanging
|
||||||
|
:v-ideographic
|
||||||
|
:v-mathematical
|
||||||
|
:values
|
||||||
|
:version
|
||||||
|
:vert-adv-y
|
||||||
|
:vert-origin-x
|
||||||
|
:vert-origin-y
|
||||||
|
:viewBox
|
||||||
|
:viewTarget
|
||||||
|
:width
|
||||||
|
:widths
|
||||||
|
:x
|
||||||
|
:x-height
|
||||||
|
:x1
|
||||||
|
:x2
|
||||||
|
:xChannelSelector
|
||||||
|
:xmlns:xlink
|
||||||
|
:xlink:actuate
|
||||||
|
:xlink:arcrole
|
||||||
|
:xlink:href
|
||||||
|
:xlink:role
|
||||||
|
:xlink:show
|
||||||
|
:xlink:title
|
||||||
|
:xlink:type
|
||||||
|
:xml:base
|
||||||
|
:xml:lang
|
||||||
|
:xml:space
|
||||||
|
:y
|
||||||
|
:y1
|
||||||
|
:y2
|
||||||
|
:yChannelSelector
|
||||||
|
:z
|
||||||
|
:zoomAndPan})
|
||||||
|
|
||||||
|
(defonce svg-present-list
|
||||||
|
#{:alignment-baseline
|
||||||
|
:baseline-shift
|
||||||
|
:clip-path
|
||||||
|
:clip-rule
|
||||||
|
:clip
|
||||||
|
:color-interpolation-filters
|
||||||
|
:color-interpolation
|
||||||
|
:color-profile
|
||||||
|
:color-rendering
|
||||||
|
:color
|
||||||
|
:cursor
|
||||||
|
:direction
|
||||||
|
:display
|
||||||
|
:dominant-baseline
|
||||||
|
:enable-background
|
||||||
|
:fill-opacity
|
||||||
|
:fill-rule
|
||||||
|
:fill
|
||||||
|
:filter
|
||||||
|
:flood-color
|
||||||
|
:flood-opacity
|
||||||
|
:font-family
|
||||||
|
:font-size-adjust
|
||||||
|
:font-size
|
||||||
|
:font-stretch
|
||||||
|
:font-style
|
||||||
|
:font-variant
|
||||||
|
:font-weight
|
||||||
|
:glyph-orientation-horizontal
|
||||||
|
:glyph-orientation-vertical
|
||||||
|
:image-rendering
|
||||||
|
:kerning
|
||||||
|
:letter-spacing
|
||||||
|
:lighting-color
|
||||||
|
:marker-end
|
||||||
|
:marker-mid
|
||||||
|
:marker-start
|
||||||
|
:mask
|
||||||
|
:opacity
|
||||||
|
:overflow
|
||||||
|
:pointer-events
|
||||||
|
:shape-rendering
|
||||||
|
:stop-color
|
||||||
|
:stop-opacity
|
||||||
|
:stroke-dasharray
|
||||||
|
:stroke-dashoffset
|
||||||
|
:stroke-linecap
|
||||||
|
:stroke-linejoin
|
||||||
|
:stroke-miterlimit
|
||||||
|
:stroke-opacity
|
||||||
|
:stroke-width
|
||||||
|
:stroke
|
||||||
|
:text-anchor
|
||||||
|
:text-decoration
|
||||||
|
:text-rendering
|
||||||
|
:unicode-bidi
|
||||||
|
:visibility
|
||||||
|
:word-spacing
|
||||||
|
:writing-mode
|
||||||
|
:mask-type})
|
||||||
|
|
||||||
|
(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})
|
||||||
|
|
||||||
|
;; Props not supported by react we need to keep them lowercase
|
||||||
|
(defonce non-react-props
|
||||||
|
#{:mask-type})
|
||||||
|
|
||||||
|
;; 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 extract-ids [val]
|
(defn extract-ids [val]
|
||||||
(->> (re-seq xml-id-regex val)
|
(->> (re-seq xml-id-regex val)
|
||||||
(mapv second)))
|
(mapv second)))
|
||||||
|
@ -61,35 +527,52 @@
|
||||||
|
|
||||||
(defn clean-attrs
|
(defn clean-attrs
|
||||||
"Transforms attributes to their react equivalent"
|
"Transforms attributes to their react equivalent"
|
||||||
[attrs]
|
([attrs] (clean-attrs attrs true))
|
||||||
(letfn [(transform-key [key]
|
([attrs whitelist?]
|
||||||
(-> (d/name key)
|
(letfn [(known-property? [[key _]]
|
||||||
(str/replace ":" "-")
|
(or (not whitelist?)
|
||||||
(str/camel)
|
(contains? svg-attr-list key )
|
||||||
(keyword)))
|
(contains? svg-present-list key )))
|
||||||
|
|
||||||
(format-styles [style-str]
|
(transform-key [key]
|
||||||
(->> (str/split style-str ";")
|
(if (contains? non-react-props key)
|
||||||
(map str/trim)
|
key
|
||||||
(map #(str/split % ":"))
|
(-> (d/name key)
|
||||||
(group-by first)
|
(str/replace ":" "-")
|
||||||
(map (fn [[key val]]
|
(str/camel)
|
||||||
(vector
|
(keyword))))
|
||||||
(transform-key key)
|
|
||||||
(second (first val)))))
|
|
||||||
(into {})))
|
|
||||||
|
|
||||||
(map-fn [[key val]]
|
(lowercase-key [key]
|
||||||
(let [key (keyword key)]
|
(-> (d/name key)
|
||||||
(cond
|
(str/lower)
|
||||||
(= key :class) [:className val]
|
(keyword)))
|
||||||
(and (= key :style) (string? val)) [key (format-styles val)]
|
|
||||||
(and (= key :style) (map? val)) [key (clean-attrs val)]
|
|
||||||
:else (vector (transform-key key) val))))]
|
|
||||||
|
|
||||||
(->> attrs
|
(format-styles [style-str]
|
||||||
(map map-fn)
|
(->> (str/split style-str ";")
|
||||||
(into {}))))
|
(map str/trim)
|
||||||
|
(map #(str/split % ":"))
|
||||||
|
(group-by first)
|
||||||
|
(map (fn [[key val]]
|
||||||
|
(vector
|
||||||
|
(transform-key key)
|
||||||
|
(second (first val)))))
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(map-fn [[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 (vector (transform-key key) val))))
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
(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 map-fn)) attrs))))
|
||||||
|
|
||||||
(defn update-attr-ids
|
(defn update-attr-ids
|
||||||
"Replaces the ids inside a property"
|
"Replaces the ids inside a property"
|
||||||
|
@ -126,18 +609,16 @@
|
||||||
(reduce visit-node result (:content node))))]
|
(reduce visit-node result (:content node))))]
|
||||||
(visit-node {} content)))
|
(visit-node {} content)))
|
||||||
|
|
||||||
(def remove-tags #{:defs :linearGradient})
|
|
||||||
|
|
||||||
(defn extract-defs [{:keys [tag attrs content] :as node}]
|
(defn extract-defs [{:keys [tag attrs content] :as node}]
|
||||||
(if-not (map? node)
|
(if-not (map? node)
|
||||||
[{} node]
|
[{} node]
|
||||||
|
|
||||||
(let [remove-node? (fn [{:keys [tag]}] (contains? remove-tags tag))
|
(let [remove-node? (fn [{:keys [tag]}] (and (some? tag)
|
||||||
|
(or (contains? tags-to-remove tag)
|
||||||
|
(not (contains? svg-tags-list tag)))))
|
||||||
rec-result (->> (:content node) (map extract-defs))
|
rec-result (->> (:content node) (map extract-defs))
|
||||||
node (assoc node :content (->> rec-result (map second) (filterv (comp not remove-node?))))
|
node (assoc node :content (->> rec-result (map second) (filterv (comp not remove-node?))))
|
||||||
|
|
||||||
|
|
||||||
current-node-defs (if (contains? attrs :id)
|
current-node-defs (if (contains? attrs :id)
|
||||||
(hash-map (:id attrs) node)
|
(hash-map (:id attrs) node)
|
||||||
(hash-map))
|
(hash-map))
|
||||||
|
@ -319,76 +800,6 @@
|
||||||
transform
|
transform
|
||||||
(update :transform append-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}]
|
(defn inherit-attributes [group-attrs {:keys [attrs] :as node}]
|
||||||
(if (map? node)
|
(if (map? node)
|
||||||
(let [attrs (-> (format-styles attrs)
|
(let [attrs (-> (format-styles attrs)
|
||||||
|
@ -425,31 +836,6 @@
|
||||||
(reduce-content (:content node)))
|
(reduce-content (:content node)))
|
||||||
value)))
|
value)))
|
||||||
|
|
||||||
;; 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
|
(defn fix-default-values
|
||||||
"Gives values to some SVG elements which defaults won't work when imported into the platform"
|
"Gives values to some SVG elements which defaults won't work when imported into the platform"
|
||||||
[svg-data]
|
[svg-data]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue