mirror of
https://github.com/penpot/penpot.git
synced 2025-05-17 20:46:09 +02:00
✨ Export library data (images, typographies, colors)
This commit is contained in:
parent
4d0dcc5876
commit
fbf1c10077
3 changed files with 113 additions and 24 deletions
|
@ -556,3 +556,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
m)))
|
m)))
|
||||||
|
|
||||||
|
(defn not-empty?
|
||||||
|
[coll]
|
||||||
|
(boolean (seq coll)))
|
||||||
|
|
|
@ -6,17 +6,21 @@
|
||||||
|
|
||||||
(ns app.worker.export
|
(ns app.worker.export
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.config :as cfg]
|
||||||
[app.main.render :as r]
|
[app.main.render :as r]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.zip :as uz]
|
[app.util.http :as http]
|
||||||
[app.util.json :as json]
|
[app.util.json :as json]
|
||||||
|
[app.util.zip :as uz]
|
||||||
[app.worker.impl :as impl]
|
[app.worker.impl :as impl]
|
||||||
[beicon.core :as rx]))
|
[beicon.core :as rx]
|
||||||
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
(defn create-manifest
|
(defn create-manifest
|
||||||
"Creates a manifest entry for the given files"
|
"Creates a manifest entry for the given files"
|
||||||
[team-id files]
|
[team-id file-id files]
|
||||||
(letfn [(format-page [manifest page]
|
(letfn [(format-page [manifest page]
|
||||||
(-> manifest
|
(-> manifest
|
||||||
(assoc (str (:id page))
|
(assoc (str (:id page))
|
||||||
|
@ -24,18 +28,35 @@
|
||||||
|
|
||||||
(format-file [manifest file]
|
(format-file [manifest file]
|
||||||
(let [name (:name file)
|
(let [name (:name file)
|
||||||
pages (->> (get-in file [:data :pages]) (mapv str))
|
is-shared (:is-shared file)
|
||||||
index (->> (get-in file [:data :pages-index]) (vals)
|
pages (->> (get-in file [:data :pages])
|
||||||
|
(mapv str))
|
||||||
|
index (->> (get-in file [:data :pages-index])
|
||||||
|
(vals)
|
||||||
(reduce format-page {}))]
|
(reduce format-page {}))]
|
||||||
(-> manifest
|
(-> manifest
|
||||||
(assoc (str (:id file))
|
(assoc (str (:id file))
|
||||||
{:name name
|
{:name name
|
||||||
|
:shared is-shared
|
||||||
:pages pages
|
:pages pages
|
||||||
:pagesIndex index}))))]
|
:pagesIndex index
|
||||||
|
:hasComponents (d/not-empty? (get-in file [:data :components]))
|
||||||
|
:hasImages (d/not-empty? (get-in file [:data :media]))
|
||||||
|
:hasColors (d/not-empty? (get-in file [:data :colors]))
|
||||||
|
:hasTypographies (d/not-empty? (get-in file [:data :typographies]))}))))]
|
||||||
(let [manifest {:teamId (str team-id)
|
(let [manifest {:teamId (str team-id)
|
||||||
|
:fileId (str file-id)
|
||||||
:files (->> (vals files) (reduce format-file {}))}]
|
:files (->> (vals files) (reduce format-file {}))}]
|
||||||
(json/encode manifest))))
|
(json/encode manifest))))
|
||||||
|
|
||||||
|
(defn process-pages [file]
|
||||||
|
(let [pages (get-in file [:data :pages])
|
||||||
|
pages-index (get-in file [:data :pages-index])]
|
||||||
|
(->> pages
|
||||||
|
(map #(hash-map
|
||||||
|
:file-id (:id file)
|
||||||
|
:data (get pages-index %))))))
|
||||||
|
|
||||||
(defn get-page-data
|
(defn get-page-data
|
||||||
[{file-id :file-id {:keys [id name] :as data} :data}]
|
[{file-id :file-id {:keys [id name] :as data} :data}]
|
||||||
(->> (r/render-page data)
|
(->> (r/render-page data)
|
||||||
|
@ -45,30 +66,45 @@
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:markup markup}))))
|
:markup markup}))))
|
||||||
|
|
||||||
(defn process-pages [file]
|
|
||||||
(let [pages (get-in file [:data :pages])
|
|
||||||
pages-index (get-in file [:data :pages-index])]
|
|
||||||
(->> pages
|
|
||||||
(map #(hash-map
|
|
||||||
:file-id (:id file)
|
|
||||||
:data (get pages-index %))))))
|
|
||||||
|
|
||||||
(defn collect-page
|
(defn collect-page
|
||||||
[{:keys [id file-id markup] :as page}]
|
[{:keys [id file-id markup] :as page}]
|
||||||
[(str file-id "/" id ".svg") markup])
|
[(str file-id "/" id ".svg") markup])
|
||||||
|
|
||||||
|
(defn collect-color
|
||||||
|
[result color]
|
||||||
|
(-> result
|
||||||
|
(assoc (str (:id color))
|
||||||
|
(->> (select-keys color [:name :color :opacity :gradient])
|
||||||
|
(d/deep-mapm
|
||||||
|
(fn [[k v]]
|
||||||
|
[(-> k str/camel) v]))))))
|
||||||
|
|
||||||
|
(def ^:const typography-keys [:name :font-family :font-id :font-size
|
||||||
|
:font-style :font-variant-id :font-weight
|
||||||
|
:letter-spacing :line-height :text-transform])
|
||||||
|
(defn collect-typography
|
||||||
|
[result typography]
|
||||||
|
(-> result
|
||||||
|
(assoc (str (:id typography))
|
||||||
|
(->> (select-keys typography typography-keys)
|
||||||
|
(d/deep-mapm
|
||||||
|
(fn [[k v]]
|
||||||
|
[(-> k str/camel) v]))))))
|
||||||
|
|
||||||
(defn export-file
|
(defn export-file
|
||||||
[team-id file-id]
|
[team-id file-id]
|
||||||
|
|
||||||
(let [files-stream
|
(let [files-stream
|
||||||
(->> (rp/query :file {:id file-id})
|
(->> (rx/merge (rp/query :file {:id file-id})
|
||||||
|
(->> (rp/query :file-libraries {:file-id file-id})
|
||||||
|
(rx/flat-map identity)
|
||||||
|
(rx/map #(assoc % :is-shared true))))
|
||||||
(rx/reduce #(assoc %1 (:id %2) %2) {})
|
(rx/reduce #(assoc %1 (:id %2) %2) {})
|
||||||
(rx/share))
|
(rx/share))
|
||||||
|
|
||||||
manifest-stream
|
manifest-stream
|
||||||
(->> files-stream
|
(->> files-stream
|
||||||
(rx/map #(create-manifest team-id %))
|
(rx/map #(create-manifest team-id file-id %))
|
||||||
(rx/map #(vector "manifest.json" %)))
|
(rx/map #(vector "manifest.json" %)))
|
||||||
|
|
||||||
render-stream
|
render-stream
|
||||||
|
@ -79,6 +115,48 @@
|
||||||
(rx/flat-map get-page-data)
|
(rx/flat-map get-page-data)
|
||||||
(rx/share))
|
(rx/share))
|
||||||
|
|
||||||
|
colors-stream
|
||||||
|
(->> files-stream
|
||||||
|
(rx/flat-map vals)
|
||||||
|
(rx/map #(vector (:id %) (get-in % [:data :colors])))
|
||||||
|
(rx/filter #(d/not-empty? (second %)))
|
||||||
|
(rx/map (fn [[file-id colors]]
|
||||||
|
(let [markup
|
||||||
|
(->> (vals colors)
|
||||||
|
(reduce collect-color {})
|
||||||
|
(json/encode))]
|
||||||
|
[(str file-id "/colors.json") markup]))))
|
||||||
|
|
||||||
|
typographies-stream
|
||||||
|
(->> files-stream
|
||||||
|
(rx/flat-map vals)
|
||||||
|
(rx/map #(vector (:id %) (get-in % [:data :typographies])))
|
||||||
|
(rx/filter #(d/not-empty? (second %)))
|
||||||
|
(rx/map (fn [[file-id typographies]]
|
||||||
|
(let [markup
|
||||||
|
(->> (vals typographies)
|
||||||
|
(reduce collect-typography {})
|
||||||
|
(json/encode))]
|
||||||
|
[(str file-id "/typographies.json") markup]))))
|
||||||
|
|
||||||
|
media-stream
|
||||||
|
(->> files-stream
|
||||||
|
(rx/flat-map vals)
|
||||||
|
(rx/map #(vector (:id %) (get-in % [:data :media])))
|
||||||
|
(rx/filter #(d/not-empty? (second %)))
|
||||||
|
(rx/flat-map
|
||||||
|
(fn [[file-id media]]
|
||||||
|
(->> media vals (mapv #(assoc % :file-id file-id)))))
|
||||||
|
|
||||||
|
(rx/flat-map
|
||||||
|
(fn [media]
|
||||||
|
(->> (http/send!
|
||||||
|
{:uri (cfg/resolve-file-media media)
|
||||||
|
:response-type :blob
|
||||||
|
:method :get})
|
||||||
|
(rx/map :body)
|
||||||
|
(rx/map #(vector (str file-id "/images/" (:id media)) %))))))
|
||||||
|
|
||||||
pages-stream
|
pages-stream
|
||||||
(->> render-stream
|
(->> render-stream
|
||||||
(rx/map collect-page))]
|
(rx/map collect-page))]
|
||||||
|
@ -90,7 +168,13 @@
|
||||||
:file file-id
|
:file file-id
|
||||||
:data (str "Render " (:file-name %) " - " (:name %)))))
|
:data (str "Render " (:file-name %) " - " (:name %)))))
|
||||||
|
|
||||||
(->> (rx/merge manifest-stream pages-stream)
|
(->> (rx/merge
|
||||||
|
manifest-stream
|
||||||
|
pages-stream
|
||||||
|
#_components-stream
|
||||||
|
media-stream
|
||||||
|
colors-stream
|
||||||
|
typographies-stream)
|
||||||
(rx/reduce conj [])
|
(rx/reduce conj [])
|
||||||
(rx/with-latest-from files-stream)
|
(rx/with-latest-from files-stream)
|
||||||
(rx/flat-map (fn [[data files]]
|
(rx/flat-map (fn [[data files]]
|
||||||
|
|
|
@ -25,12 +25,13 @@
|
||||||
|
|
||||||
(defn create-file
|
(defn create-file
|
||||||
"Create a new file on the back-end"
|
"Create a new file on the back-end"
|
||||||
[project-id name]
|
[project-id file-desc]
|
||||||
(let [file-id (uuid/next)]
|
(let [file-id (uuid/next)]
|
||||||
(rp/mutation
|
(rp/mutation
|
||||||
:create-temp-file
|
:create-temp-file
|
||||||
{:id file-id
|
{:id file-id
|
||||||
:name name
|
:name (:name file-desc)
|
||||||
|
:is-shared (:shared file-desc)
|
||||||
:project-id project-id
|
:project-id project-id
|
||||||
:data (-> cp/empty-file-data (assoc :id file-id))})))
|
:data (-> cp/empty-file-data (assoc :id file-id))})))
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@
|
||||||
(rx/flat-map (comp :files json/decode :content))
|
(rx/flat-map (comp :files json/decode :content))
|
||||||
(rx/flat-map
|
(rx/flat-map
|
||||||
(fn [[file-id file-desc]]
|
(fn [[file-id file-desc]]
|
||||||
(->> (create-file project-id (:name file-desc))
|
(->> (create-file project-id file-desc)
|
||||||
(rx/flat-map #(process-file % file-id file-desc zip-file)))))))
|
(rx/flat-map #(process-file % file-id file-desc zip-file)))))))
|
||||||
|
|
||||||
(defmethod impl/handler :import-file
|
(defmethod impl/handler :import-file
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue