0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

Adds flip,proportion and rotation

This commit is contained in:
alonso.torres 2021-06-14 16:00:16 +02:00
parent a106c728ba
commit d6e009ce78
7 changed files with 189 additions and 40 deletions

View file

@ -87,15 +87,15 @@
:changes []})))
(defn add-page
[file name]
(let [page-id (uuid/next)]
[file data]
(let [page-id (uuid/next)
page (-> init/empty-page-data
(assoc :id page-id)
(d/deep-merge data))]
(-> file
(commit-change
{:type :add-page
:id page-id
:name name
:page (-> init/empty-page-data
(assoc :name name))})
:page page})
;; Current page being edited
(assoc :current-page-id page-id)

View file

@ -7,14 +7,65 @@
(ns app.libs.file-builder
(:require
[app.common.data :as d]
[app.common.file-builder :as fb]))
[app.common.file-builder :as fb]
[cuerdas.core :as str]))
(defn parse-data [data]
(as-> data $
(js->clj $ :keywordize-keys true)
;; Transforms camelCase to kebab-case
(d/deep-mapm
(fn [[k v]]
[(-> k d/name str/kebab keyword) v]) $)))
(deftype File [^:mutable file]
Object
(addPage [self name]
(set! file (fb/add-page file name))
(str (:current-page-id file))))
(addPage
([self name]
(addPage self name nil))
([self name options]
(set! file (fb/add-page file {:name name :options options}))
(str (:current-page-id file))))
(closePage [self]
(set! file (fb/close-page file)))
(addArtboard [self data]
(set! file (fb/add-artboard file (parse-data data)))
(str (:last-id file)))
(closeArtboard [self data]
(set! file (fb/close-artboard file)))
(addGroup [self data]
(set! file (fb/add-group file (parse-data data)))
(str (:last-id file)))
(closeGroup [self]
(set! file (fb/close-group file)))
(createRect [self data]
(set! file (fb/create-rect file (parse-data data))))
(createCircle [self data]
(set! file (fb/create-circle file (parse-data data))))
(createPath [self data]
(set! file (fb/create-path file (parse-data data))))
(createText [self data]
(set! file (fb/create-text file (parse-data data))))
(createImage [self data]
(set! file (fb/create-image file (parse-data data))))
(createSVG [self data]
(set! file (fb/create-svg-raw file (parse-data data))))
(closeSVG [self]
(set! file (fb/close-svg-raw file))))
(defn create-file-export [^string name]
(File. (fb/create-file name)))

View file

@ -16,6 +16,7 @@
[app.common.uuid :as uuid]
[app.main.ui.shapes.circle :as circle]
[app.main.ui.shapes.embed :as embed]
[app.main.ui.shapes.export :as use]
[app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.frame :as frame]
[app.main.ui.shapes.group :as group]
@ -158,6 +159,9 @@
:style {:width "100%"
:height "100%"
:background background-color}}
[:& use/export-page {:options (:options data)}]
(for [item shapes]
(let [frame? (= (:type item) :frame)]
(cond

View file

@ -83,6 +83,37 @@
(cond-> mask?
(obj/set! "penpot:masked-group" "true"))))))
(defn prefix-keys [m]
(letfn [(prefix-entry [[k v]]
[(str "penpot:" (d/name k)) v])]
(into {} (map prefix-entry) m)))
(mf/defc export-grid-data
[{:keys [grids]}]
[:> "penpot:grids" #js {}
(for [{:keys [type display params]} grids]
(let [props (->> (d/without-keys params [:color])
(prefix-keys)
(clj->js))]
[:> "penpot:grid"
(-> props
(obj/set! "penpot:color" (get-in params [:color :color]))
(obj/set! "penpot:opacity" (get-in params [:color :opacity]))
(obj/set! "penpot:type" (d/name type))
(cond-> (some? display)
(obj/set! "penpot:display" (str display))))]))])
(mf/defc export-page
[{:keys [options]}]
[:> "penpot:page" #js {}
(let [saved-grids (get options :saved-grids)]
(when-not (empty? saved-grids)
(let [parse-grid
(fn [[type params]]
{:type type :params params})
grids (->> saved-grids (mapv parse-grid))]
[:& export-grid-data {:grids grids}])))])
(mf/defc export-data
[{:keys [shape]}]
(let [props (-> (obj/new)
@ -135,5 +166,10 @@
(clj->js))))]
[:> "penpot:svg-content" props
(for [leaf (->> shape :content :content (filter string?))]
[:> "penpot:svg-child" {} leaf])]))]))
[:> "penpot:svg-child" {} leaf])]))
(when (and (= (:type shape) :frame)
(not (empty? (:grids shape))))
[:& export-grid-data {:grids (:grids shape)}])]))

View file

@ -14,6 +14,7 @@
[app.main.ui.context :as muc]
[app.main.ui.measurements :as msr]
[app.main.ui.shapes.embed :as embed]
[app.main.ui.shapes.export :as use]
[app.main.ui.workspace.shapes :as shapes]
[app.main.ui.workspace.shapes.text.editor :as editor]
[app.main.ui.workspace.viewport.actions :as actions]
@ -188,6 +189,8 @@
:style {:background-color (get options :background "#E8E9EA")
:pointer-events "none"}}
[:& use/export-page {:options options}]
[:& (mf/provider embed/context) {:value true}
;; Render root shape
[:& shapes/root-shape {:key page-id

View file

@ -32,7 +32,8 @@
(defn get-data
([node]
(->> node :content (d/seek #(= :penpot:shape (:tag %)))))
(->> node :content (d/seek #(or (= :penpot:shape (:tag %))
(= :penpot:page (:tag %))))))
([node tag]
(->> (get-data node)
:content
@ -98,6 +99,41 @@
m
attrs))
(defn without-penpot-prefix
[m]
(let [no-penpot-prefix?
(fn [[k v]]
(not (str/starts-with? (d/name k) "penpot:")))]
(into {} (filter no-penpot-prefix?) m)))
(defn remove-penpot-prefix
[m]
(into {}
(map (fn [[k v]]
(if (str/starts-with? (d/name k) "penpot:")
[(-> k d/name (str/replace "penpot:" "") keyword) v]
[k v])))
m))
(defn camelize [[k v]]
[(-> k d/name str/camel keyword) v])
(defn camelize-keys
[m]
(assert (map? m) (str m))
(into {} (map camelize) m))
(defn fix-style-attr
[m]
(let [fix-style
(fn [[k v]]
(if (= k :style)
[k (-> v parse-style camelize-keys)]
[k v]))]
(d/deep-mapm (comp camelize fix-style) m)))
(def search-data-node? #{:rect :image :path :text :circle})
(defn get-svg-data
@ -372,6 +408,26 @@
:suffix (get-meta node :suffix)
:scale (get-meta node :scale d/parse-double)})
(defn parse-grid-node [node]
(let [attrs (-> node :attrs remove-penpot-prefix)
color {:color (:color attrs)
:opacity (-> attrs :opacity d/parse-double)}
params (-> (d/without-keys attrs [:color :opacity :display :type])
(d/update-when :size d/parse-double)
(d/update-when :item-length d/parse-double)
(d/update-when :gutter d/parse-double)
(d/update-when :margin d/parse-double)
(assoc :color color))]
{:type (-> attrs :type keyword)
:display (-> attrs :display str->bool)
:params params}))
(defn parse-grids [node]
(let [grid-node (get-data node :penpot:grids)]
(->> grid-node :content (mapv parse-grid-node))))
(defn extract-from-data
([node tag]
(extract-from-data node tag identity))
@ -477,32 +533,6 @@
props)))
(defn without-penpot-prefix
[m]
(let [no-penpot-prefix?
(fn [[k v]]
(not (str/starts-with? (d/name k) "penpot:")))]
(into {} (filter no-penpot-prefix?) m)))
(defn camelize [[k v]]
[(-> k d/name str/camel keyword) v])
(defn camelize-keys
[m]
(assert (map? m) (str m))
(into {} (map camelize) m))
(defn fix-style-attr
[m]
(let [fix-style
(fn [[k v]]
(if (= k :style)
[k (-> v parse-style camelize-keys)]
[k v]))]
(d/deep-mapm (comp camelize fix-style) m)))
(defn add-svg-content
[props node]
(let [svg-content (get-data node :penpot:svg-content)
@ -522,6 +552,12 @@
:tag tag
:content node-content})))
(defn add-frame-data [props node]
(let [grids (parse-grids node)]
(cond-> props
(not (empty? grids))
(assoc :grids grids))))
(defn get-image-name
[node]
(get-in node [:attrs :penpot:name]))
@ -550,6 +586,9 @@
(cond-> (= :svg-raw type)
(add-svg-content node))
(cond-> (= :frame type)
(add-frame-data node))
(cond-> (= :group type)
(add-group-data node))
@ -561,3 +600,17 @@
(cond-> (= :text type)
(add-text-data node))))))
(defn parse-page-data
[node]
(let [style (parse-style (get-in node [:attrs :style]))
background (:background style)
grids (->> (parse-grids node)
(group-by :type)
(d/mapm (fn [k v] (-> v first :params))))]
(cond-> {}
(some? background)
(assoc-in [:options :background] background)
(not (empty? grids))
(assoc-in [:options :saved-grids] grids))))

View file

@ -137,11 +137,13 @@
[file [page-name content]]
(if (cip/valid? content)
(let [nodes (->> content cip/node-seq)
file-id (:id file)]
file-id (:id file)
page-data (-> (cip/parse-page-data content)
(assoc :name page-name))]
(->> (rx/from nodes)
(rx/filter cip/shape?)
(rx/mapcat (partial resolve-images file-id))
(rx/reduce add-shape-file (fb/add-page file page-name))
(rx/reduce add-shape-file (fb/add-page file page-data))
(rx/map fb/close-page)))
(rx/empty)))