mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 00:01:51 -05:00
✨ Import library media,color,typographies
This commit is contained in:
parent
aa14d9626f
commit
7d14122746
5 changed files with 143 additions and 54 deletions
|
@ -13,6 +13,7 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[cljs.analyzer.api :as aapi]
|
[cljs.analyzer.api :as aapi]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
|
[cuerdas.core :as str]
|
||||||
#?(:cljs [cljs.reader :as r]
|
#?(:cljs [cljs.reader :as r]
|
||||||
:clj [clojure.edn :as r])
|
:clj [clojure.edn :as r])
|
||||||
#?(:cljs [cljs.core :as core]
|
#?(:cljs [cljs.core :as core]
|
||||||
|
@ -541,12 +542,13 @@
|
||||||
when it's a vector or a map"
|
when it's a vector or a map"
|
||||||
[mfn m]
|
[mfn m]
|
||||||
(let [do-map
|
(let [do-map
|
||||||
(fn [[k v]]
|
(fn [entry]
|
||||||
(cond
|
(let [[k v] (mfn entry)]
|
||||||
(or (vector? v) (map? v))
|
(cond
|
||||||
[k (deep-mapm mfn v)]
|
(or (vector? v) (map? v))
|
||||||
:else
|
[k (deep-mapm mfn v)]
|
||||||
(mfn [k v])))]
|
:else
|
||||||
|
(mfn [k v]))))]
|
||||||
(cond
|
(cond
|
||||||
(map? m)
|
(map? m)
|
||||||
(into {} (map do-map) m)
|
(into {} (map do-map) m)
|
||||||
|
@ -560,3 +562,9 @@
|
||||||
(defn not-empty?
|
(defn not-empty?
|
||||||
[coll]
|
[coll]
|
||||||
(boolean (seq coll)))
|
(boolean (seq coll)))
|
||||||
|
|
||||||
|
(defn kebab-keys [m]
|
||||||
|
(->> m
|
||||||
|
(deep-mapm
|
||||||
|
(fn [[k v]]
|
||||||
|
[(keyword (str/kebab (name k))) v]))))
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
(let [container-id (or (:current-component-id file)
|
(let [container-id (or (:current-component-id file)
|
||||||
(:current-page-id file))
|
(:current-page-id file))
|
||||||
unames (get-in file [:unames container-id])]
|
unames (get-in file [:unames container-id])]
|
||||||
(d/unique-name (or unames #{}) name)))
|
(d/unique-name name (or unames #{}))))
|
||||||
|
|
||||||
(defn clear-names [file]
|
(defn clear-names [file]
|
||||||
(dissoc file :unames))
|
(dissoc file :unames))
|
||||||
|
@ -355,36 +355,32 @@
|
||||||
(defn add-library-color
|
(defn add-library-color
|
||||||
[file color]
|
[file color]
|
||||||
|
|
||||||
(let [id (uuid/next)]
|
(let [id (or (:id color) (uuid/next))]
|
||||||
(commit-change
|
(-> file
|
||||||
file
|
(commit-change
|
||||||
{:type :add-color
|
{:type :add-color
|
||||||
:id id
|
:id id
|
||||||
:color color})
|
:color (assoc color :id id)})
|
||||||
|
(assoc :last-id id))))
|
||||||
id))
|
|
||||||
|
|
||||||
(defn add-library-typography
|
(defn add-library-typography
|
||||||
[file typography]
|
[file typography]
|
||||||
(let [id (uuid/next)]
|
(let [id (or (:id typography) (uuid/next))]
|
||||||
(commit-change
|
(-> file
|
||||||
file
|
(commit-change
|
||||||
{:type :add-typography
|
{:type :add-typography
|
||||||
:id id
|
:id id
|
||||||
:typography typography})
|
:typography (assoc typography :id id)})
|
||||||
|
(assoc :last-id id))))
|
||||||
id))
|
|
||||||
|
|
||||||
(defn add-library-media
|
(defn add-library-media
|
||||||
[file media]
|
[file media]
|
||||||
(let [id (uuid/next)]
|
(let [id (or (:id media) (uuid/next))]
|
||||||
(commit-change
|
(-> file
|
||||||
file
|
(commit-change
|
||||||
{:type :add-media
|
{:type :add-media
|
||||||
:id id
|
:object (assoc media :id id)})
|
||||||
:media media})
|
(assoc :last-id id))))
|
||||||
|
|
||||||
id))
|
|
||||||
|
|
||||||
(defn start-component
|
(defn start-component
|
||||||
[file data]
|
[file data]
|
||||||
|
|
|
@ -31,24 +31,28 @@
|
||||||
(rx/map :body)
|
(rx/map :body)
|
||||||
(rx/flat-map zip/loadAsync)))
|
(rx/flat-map zip/loadAsync)))
|
||||||
|
|
||||||
(defn- process-file [entry path]
|
(defn- process-file
|
||||||
|
[entry path type]
|
||||||
(cond
|
(cond
|
||||||
(nil? entry)
|
(nil? entry)
|
||||||
(p/rejected "No file found")
|
(p/rejected (str "File not found: " path))
|
||||||
|
|
||||||
(.-dir entry)
|
(.-dir entry)
|
||||||
(p/resolved {:dir path})
|
(p/resolved {:dir path})
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(-> (.async entry "text")
|
(-> (.async entry type)
|
||||||
(p/then #(hash-map :path path :content %)))))
|
(p/then #(hash-map :path path :content %)))))
|
||||||
|
|
||||||
(defn get-file
|
(defn get-file
|
||||||
"Gets a single file from the zip archive"
|
"Gets a single file from the zip archive"
|
||||||
[zip path]
|
([zip path]
|
||||||
(-> (.file zip path)
|
(get-file zip path "text"))
|
||||||
(process-file path)
|
|
||||||
(rx/from)))
|
([zip path type]
|
||||||
|
(-> (.file zip path)
|
||||||
|
(process-file path type)
|
||||||
|
(rx/from))))
|
||||||
|
|
||||||
(defn extract-files
|
(defn extract-files
|
||||||
"Creates a stream that will emit values for every file in the zip"
|
"Creates a stream that will emit values for every file in the zip"
|
||||||
|
@ -56,7 +60,7 @@
|
||||||
(let [promises (atom [])
|
(let [promises (atom [])
|
||||||
get-file
|
get-file
|
||||||
(fn [path entry]
|
(fn [path entry]
|
||||||
(let [current (process-file entry path)]
|
(let [current (process-file entry path "text")]
|
||||||
(swap! promises conj current)))]
|
(swap! promises conj current)))]
|
||||||
(.forEach zip get-file)
|
(.forEach zip get-file)
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
:pages pages
|
:pages pages
|
||||||
:pagesIndex index
|
:pagesIndex index
|
||||||
:hasComponents (d/not-empty? (get-in file [:data :components]))
|
:hasComponents (d/not-empty? (get-in file [:data :components]))
|
||||||
:hasImages (d/not-empty? (get-in file [:data :media]))
|
:hasMedia (d/not-empty? (get-in file [:data :media]))
|
||||||
:hasColors (d/not-empty? (get-in file [:data :colors]))
|
:hasColors (d/not-empty? (get-in file [:data :colors]))
|
||||||
:hasTypographies (d/not-empty? (get-in file [:data :typographies]))}))))]
|
:hasTypographies (d/not-empty? (get-in file [:data :typographies]))}))))]
|
||||||
(let [manifest {:teamId (str team-id)
|
(let [manifest {:teamId (str team-id)
|
||||||
|
@ -123,13 +123,13 @@
|
||||||
(->> (vals media)
|
(->> (vals media)
|
||||||
(reduce collect-media {})
|
(reduce collect-media {})
|
||||||
(json/encode))]
|
(json/encode))]
|
||||||
(rx/of (vector (str file-id "/images.json") markup)))
|
(rx/of (vector (str file-id "/media.json") markup)))
|
||||||
|
|
||||||
(->> (rx/from (vals media))
|
(->> (rx/from (vals media))
|
||||||
(rx/map #(assoc % :file-id file-id))
|
(rx/map #(assoc % :file-id file-id))
|
||||||
(rx/flat-map
|
(rx/flat-map
|
||||||
(fn [media]
|
(fn [media]
|
||||||
(let [file-path (str file-id "/images/" (:id media) "." (dom/mtype->extension (:mtype media)))]
|
(let [file-path (str file-id "/media/" (:id media) "." (dom/mtype->extension (:mtype media)))]
|
||||||
(->> (http/send!
|
(->> (http/send!
|
||||||
{:uri (cfg/resolve-file-media media)
|
{:uri (cfg/resolve-file-media media)
|
||||||
:response-type :blob
|
:response-type :blob
|
||||||
|
|
|
@ -11,12 +11,14 @@
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.util.dom :as dom]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.import.parser :as cip]
|
[app.util.import.parser :as cip]
|
||||||
[app.util.json :as json]
|
[app.util.json :as json]
|
||||||
[app.util.zip :as uz]
|
[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]
|
||||||
[tubax.core :as tubax]))
|
[tubax.core :as tubax]))
|
||||||
|
|
||||||
;; Upload changes batches size
|
;; Upload changes batches size
|
||||||
|
@ -144,7 +146,7 @@
|
||||||
(rx/merge-scan f seed ob))
|
(rx/merge-scan f seed ob))
|
||||||
(rx/last)))
|
(rx/last)))
|
||||||
|
|
||||||
(defn resolve-images
|
(defn resolve-media
|
||||||
[file-id node]
|
[file-id node]
|
||||||
(if (and (not (cip/close? node))
|
(if (and (not (cip/close? node))
|
||||||
(cip/has-image? node))
|
(cip/has-image? node))
|
||||||
|
@ -172,7 +174,7 @@
|
||||||
(assoc :name page-name))]
|
(assoc :name page-name))]
|
||||||
(->> (rx/from nodes)
|
(->> (rx/from nodes)
|
||||||
(rx/filter cip/shape?)
|
(rx/filter cip/shape?)
|
||||||
(rx/mapcat (partial resolve-images file-id))
|
(rx/mapcat (partial resolve-media file-id))
|
||||||
(rx/reduce add-shape-file (fb/add-page file page-data))
|
(rx/reduce add-shape-file (fb/add-page file page-data))
|
||||||
(rx/map post-process-file)
|
(rx/map post-process-file)
|
||||||
(rx/map fb/close-page)))
|
(rx/map fb/close-page)))
|
||||||
|
@ -182,20 +184,98 @@
|
||||||
(str dir-id "/" id ".svg"))
|
(str dir-id "/" id ".svg"))
|
||||||
|
|
||||||
(defn process-page [file-id zip [page-id page-name]]
|
(defn process-page [file-id zip [page-id page-name]]
|
||||||
(->> (uz/get-file zip (get-page-path (d/name file-id) page-id))
|
(let [path (get-page-path (d/name file-id) page-id)]
|
||||||
(rx/map (comp tubax/xml->clj :content))
|
(->> (uz/get-file zip path)
|
||||||
(rx/map #(vector page-name %))))
|
(rx/map (comp tubax/xml->clj :content))
|
||||||
|
(rx/map #(vector page-name %)))))
|
||||||
|
|
||||||
(defn process-file
|
(defn process-file-pages
|
||||||
[file file-id file-desc zip]
|
[file file-id file-desc zip]
|
||||||
(let [index (:pagesIndex file-desc)
|
(let [index (:pages-index file-desc)
|
||||||
pages (->> (:pages file-desc)
|
pages (->> (:pages file-desc)
|
||||||
(mapv #(vector % (get-in index [(keyword %) :name]))))]
|
(mapv #(vector % (get-in index [(keyword %) :name]))))]
|
||||||
(->> (rx/from pages)
|
(->> (rx/from pages)
|
||||||
(rx/mapcat #(process-page file-id zip %))
|
(rx/mapcat #(process-page file-id zip %))
|
||||||
(merge-reduce import-page file)
|
(merge-reduce import-page file))))
|
||||||
(rx/flat-map send-changes)
|
|
||||||
(rx/ignore))))
|
(defn process-library-colors
|
||||||
|
[file file-id file-desc zip]
|
||||||
|
(if (:has-colors file-desc)
|
||||||
|
(let [add-color
|
||||||
|
(fn [file [id color]]
|
||||||
|
(let [color (-> (d/kebab-keys color)
|
||||||
|
(d/update-in-when [:gradient :type] keyword))
|
||||||
|
file (fb/add-library-color file color)]
|
||||||
|
(assoc file [:library-mapping id] (:last-id file))))
|
||||||
|
|
||||||
|
path (str (d/name file-id) "/colors.json")]
|
||||||
|
(->> (uz/get-file zip path)
|
||||||
|
(rx/mapcat (comp json/decode :content))
|
||||||
|
(rx/reduce add-color file)))
|
||||||
|
|
||||||
|
(rx/of file)))
|
||||||
|
|
||||||
|
(defn process-library-typographies
|
||||||
|
[file file-id file-desc zip]
|
||||||
|
(if (:has-typographies file-desc)
|
||||||
|
(let [add-typography
|
||||||
|
(fn [file [id typography]]
|
||||||
|
(let [typography (d/kebab-keys typography)
|
||||||
|
file (fb/add-library-typography file typography)]
|
||||||
|
(assoc file [:library-mapping id] (:last-id file))))
|
||||||
|
|
||||||
|
path (str (d/name file-id) "/typographies.json")]
|
||||||
|
(->> (uz/get-file zip path)
|
||||||
|
(rx/mapcat (comp json/decode :content))
|
||||||
|
(rx/reduce add-typography file)))
|
||||||
|
|
||||||
|
(rx/of file)))
|
||||||
|
|
||||||
|
(defn process-library-media
|
||||||
|
[file file-id file-desc zip]
|
||||||
|
(rx/of file)
|
||||||
|
(if (:has-media file-desc)
|
||||||
|
(let [add-media
|
||||||
|
(fn [file media]
|
||||||
|
(let [file (fb/add-library-media file (dissoc media :old-id))]
|
||||||
|
(assoc file [:library-mapping (:old-id media)] (:last-id file))))
|
||||||
|
|
||||||
|
path (str (d/name file-id) "/media.json")]
|
||||||
|
|
||||||
|
(->> (uz/get-file zip path)
|
||||||
|
(rx/mapcat (comp json/decode :content))
|
||||||
|
(rx/flat-map
|
||||||
|
(fn [[id media]]
|
||||||
|
(let [file-path (str (d/name file-id) "/media/" (d/name id) "." (dom/mtype->extension (:mtype media)))]
|
||||||
|
(->> (uz/get-file zip file-path "blob")
|
||||||
|
(rx/map (fn [{blob :content}]
|
||||||
|
(let [content (.slice blob 0 (.-size blob) (:mtype media))]
|
||||||
|
{:name (:name media)
|
||||||
|
:file-id (:id file)
|
||||||
|
:content content
|
||||||
|
:is-local false})))
|
||||||
|
(rx/flat-map #(rp/mutation! :upload-file-media-object %))
|
||||||
|
(rx/map (fn [response]
|
||||||
|
(-> media
|
||||||
|
(assoc :old-id id)
|
||||||
|
(assoc :id (:id response)))))))))
|
||||||
|
(rx/reduce add-media file)))
|
||||||
|
|
||||||
|
(rx/of file)))
|
||||||
|
|
||||||
|
(defn process-library-components
|
||||||
|
[file file-id file-desc zip]
|
||||||
|
(rx/of file))
|
||||||
|
|
||||||
|
(defn process-file
|
||||||
|
[file file-id file-desc zip]
|
||||||
|
(->> (process-file-pages file file-id file-desc zip)
|
||||||
|
(rx/flat-map #(process-library-colors % file-id file-desc zip))
|
||||||
|
(rx/flat-map #(process-library-typographies % file-id file-desc zip))
|
||||||
|
(rx/flat-map #(process-library-media % file-id file-desc zip))
|
||||||
|
(rx/flat-map #(process-library-components % file-id file-desc zip))
|
||||||
|
(rx/flat-map send-changes)
|
||||||
|
(rx/ignore)))
|
||||||
|
|
||||||
(defn process-package
|
(defn process-package
|
||||||
[project-id zip-file]
|
[project-id zip-file]
|
||||||
|
@ -203,8 +283,9 @@
|
||||||
(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 file-desc)
|
(let [file-desc (d/kebab-keys file-desc)]
|
||||||
(rx/flat-map #(process-file % file-id file-desc zip-file)))))))
|
(->> (create-file project-id file-desc)
|
||||||
|
(rx/flat-map #(process-file % file-id file-desc zip-file))))))))
|
||||||
|
|
||||||
(defmethod impl/handler :import-file
|
(defmethod impl/handler :import-file
|
||||||
[{:keys [project-id files]}]
|
[{:keys [project-id files]}]
|
||||||
|
|
Loading…
Add table
Reference in a new issue