mirror of
https://github.com/penpot/penpot.git
synced 2025-05-17 12:16:10 +02:00
🐛 Fix json encoding on zip encoding decoding
This commit is contained in:
parent
1f53e48032
commit
2643dae0a7
4 changed files with 120 additions and 72 deletions
|
@ -5,12 +5,11 @@
|
||||||
;; Copyright (c) KALEIDOS INC
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
(ns app.common.json
|
(ns app.common.json
|
||||||
(:refer-clojure :exclude [read])
|
(:refer-clojure :exclude [read clj->js js->clj])
|
||||||
(:require
|
(:require
|
||||||
#?(:clj [clojure.data.json :as j])
|
#?(:clj [clojure.data.json :as j])
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(defn read
|
(defn read
|
||||||
[reader & {:as opts}]
|
[reader & {:as opts}]
|
||||||
|
@ -21,34 +20,6 @@
|
||||||
[writer data & {:as opts}]
|
[writer data & {:as opts}]
|
||||||
(j/write data writer opts)))
|
(j/write data writer opts)))
|
||||||
|
|
||||||
#?(:cljs
|
|
||||||
(defn map->obj
|
|
||||||
"A simplified version of clj->js with focus on performance"
|
|
||||||
[x & {:keys [key-fn]}]
|
|
||||||
(cond
|
|
||||||
(nil? x)
|
|
||||||
nil
|
|
||||||
|
|
||||||
(keyword? x)
|
|
||||||
(name x)
|
|
||||||
|
|
||||||
(map? x)
|
|
||||||
(reduce-kv (fn [m k v]
|
|
||||||
(let [k (if (keyword? k) (name k) k)]
|
|
||||||
(unchecked-set m (key-fn k) (map->obj v key-fn))
|
|
||||||
m))
|
|
||||||
#js {}
|
|
||||||
x)
|
|
||||||
|
|
||||||
(coll? x)
|
|
||||||
(reduce (fn [arr v]
|
|
||||||
(.push arr v)
|
|
||||||
arr)
|
|
||||||
(array)
|
|
||||||
x)
|
|
||||||
|
|
||||||
:else x)))
|
|
||||||
|
|
||||||
(defn read-kebab-key
|
(defn read-kebab-key
|
||||||
[k]
|
[k]
|
||||||
(if (and (string? k) (not (str/includes? k "/")))
|
(if (and (string? k) (not (str/includes? k "/")))
|
||||||
|
@ -61,12 +32,76 @@
|
||||||
(str/camel k)
|
(str/camel k)
|
||||||
(str k)))
|
(str k)))
|
||||||
|
|
||||||
#?(:clj
|
#?(:cljs
|
||||||
(defn encode
|
(defn ->js
|
||||||
[data & {:as opts}]
|
[x & {:keys [key-fn]
|
||||||
(j/write-str data opts)))
|
:or {key-fn write-camel-key} :as opts}]
|
||||||
|
(let [f (fn this-fn [x]
|
||||||
|
(cond
|
||||||
|
(nil? x)
|
||||||
|
nil
|
||||||
|
|
||||||
#?(:clj
|
(satisfies? cljs.core/IEncodeJS x)
|
||||||
(defn decode
|
(cljs.core/-clj->js x)
|
||||||
|
|
||||||
|
(or (keyword? x)
|
||||||
|
(symbol? x))
|
||||||
|
(name x)
|
||||||
|
|
||||||
|
(number? x)
|
||||||
|
x
|
||||||
|
|
||||||
|
(boolean? x)
|
||||||
|
x
|
||||||
|
|
||||||
|
(map? x)
|
||||||
|
(reduce-kv (fn [m k v]
|
||||||
|
(let [k (key-fn k)]
|
||||||
|
(unchecked-set m k (this-fn v))
|
||||||
|
m))
|
||||||
|
#js {}
|
||||||
|
x)
|
||||||
|
|
||||||
|
(coll? x)
|
||||||
|
(reduce (fn [arr v]
|
||||||
|
(.push arr (this-fn v))
|
||||||
|
arr)
|
||||||
|
(array)
|
||||||
|
x)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(str x)))]
|
||||||
|
(f x))))
|
||||||
|
|
||||||
|
|
||||||
|
#?(:cljs
|
||||||
|
(defn ->clj
|
||||||
|
[o & {:keys [key-fn val-fn] :or {key-fn read-kebab-key val-fn identity}}]
|
||||||
|
(let [f (fn this-fn [x]
|
||||||
|
(let [x (val-fn x)]
|
||||||
|
(cond
|
||||||
|
(array? x)
|
||||||
|
(persistent!
|
||||||
|
(.reduce ^js/Array x
|
||||||
|
#(conj! %1 (this-fn %2))
|
||||||
|
(transient [])))
|
||||||
|
|
||||||
|
(identical? (type x) js/Object)
|
||||||
|
(persistent!
|
||||||
|
(.reduce ^js/Array (js-keys x)
|
||||||
|
#(assoc! %1 (key-fn %2) (this-fn (unchecked-get x %2)))
|
||||||
|
(transient {})))
|
||||||
|
|
||||||
|
:else
|
||||||
|
x)))]
|
||||||
|
(f o))))
|
||||||
|
|
||||||
|
(defn encode
|
||||||
[data & {:as opts}]
|
[data & {:as opts}]
|
||||||
(j/read-str data opts)))
|
#?(:clj (j/write-str data opts)
|
||||||
|
:cljs (.stringify js/JSON (->js data opts))))
|
||||||
|
|
||||||
|
(defn decode
|
||||||
|
[data & {:as opts}]
|
||||||
|
#?(:clj (j/read-str data opts)
|
||||||
|
:cljs (->clj (.parse js/JSON data) opts)))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.worker.export
|
(ns app.worker.export
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.json :as json]
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
[app.common.text :as ct]
|
[app.common.text :as ct]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
|
@ -16,7 +17,6 @@
|
||||||
[app.main.render :as r]
|
[app.main.render :as r]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.json :as json]
|
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[app.util.zip :as uz]
|
[app.util.zip :as uz]
|
||||||
[app.worker.impl :as impl]
|
[app.worker.impl :as impl]
|
||||||
|
|
|
@ -9,18 +9,21 @@
|
||||||
(:require
|
(:require
|
||||||
["jszip" :as zip]
|
["jszip" :as zip]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.exceptions :as ex]
|
||||||
[app.common.files.builder :as fb]
|
[app.common.files.builder :as fb]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes.path :as gpa]
|
[app.common.geom.shapes.path :as gpa]
|
||||||
|
[app.common.json :as json]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
[app.common.pprint :as pp]
|
[app.common.pprint :as pp]
|
||||||
|
[app.common.schema :as sm]
|
||||||
[app.common.text :as ct]
|
[app.common.text :as ct]
|
||||||
|
[app.common.time :as tm]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.json :as json]
|
|
||||||
[app.util.sse :as sse]
|
[app.util.sse :as sse]
|
||||||
[app.util.webapi :as wapi]
|
[app.util.webapi :as wapi]
|
||||||
[app.util.zip :as uz]
|
[app.util.zip :as uz]
|
||||||
|
@ -37,6 +40,29 @@
|
||||||
|
|
||||||
(def conjv (fnil conj []))
|
(def conjv (fnil conj []))
|
||||||
|
|
||||||
|
(def ^:private iso-date-rx
|
||||||
|
"Incomplete ISO regex for detect datetime-like values on strings"
|
||||||
|
#"^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d.*")
|
||||||
|
|
||||||
|
(defn read-json-key
|
||||||
|
[m]
|
||||||
|
(or (sm/parse-uuid m)
|
||||||
|
(json/read-kebab-key m)))
|
||||||
|
|
||||||
|
(defn read-json-val
|
||||||
|
[m]
|
||||||
|
(cond
|
||||||
|
(and (string? m)
|
||||||
|
(re-matches sm/uuid-rx m))
|
||||||
|
(uuid/uuid m)
|
||||||
|
|
||||||
|
(and (string? m)
|
||||||
|
(re-matches iso-date-rx m))
|
||||||
|
(or (ex/ignoring (tm/parse-instant m)) m)
|
||||||
|
|
||||||
|
:else
|
||||||
|
m))
|
||||||
|
|
||||||
(defn get-file
|
(defn get-file
|
||||||
"Resolves the file inside the context given its id and the data"
|
"Resolves the file inside the context given its id and the data"
|
||||||
([context type]
|
([context type]
|
||||||
|
@ -62,22 +88,22 @@
|
||||||
|
|
||||||
parse-svg? (and (not= type :media) (str/ends-with? path "svg"))
|
parse-svg? (and (not= type :media) (str/ends-with? path "svg"))
|
||||||
parse-json? (and (not= type :media) (str/ends-with? path "json"))
|
parse-json? (and (not= type :media) (str/ends-with? path "json"))
|
||||||
no-parse? (or (= type :media)
|
|
||||||
(not (or parse-svg? parse-json?)))
|
|
||||||
|
|
||||||
file-type (if (or parse-svg? parse-json?) "text" "blob")]
|
file-type (if (or parse-svg? parse-json?) "text" "blob")]
|
||||||
|
|
||||||
(log/debug :action "parsing" :path path)
|
(log/debug :action "parsing" :path path)
|
||||||
|
|
||||||
(cond->> (uz/get-file (:zip context) path file-type)
|
(let [stream (->> (uz/get-file (:zip context) path file-type)
|
||||||
|
(rx/map :content))]
|
||||||
|
|
||||||
|
(cond
|
||||||
parse-svg?
|
parse-svg?
|
||||||
(rx/map (comp tubax/xml->clj :content))
|
(rx/map tubax/xml->clj stream)
|
||||||
|
|
||||||
parse-json?
|
parse-json?
|
||||||
(rx/map (comp json/decode :content))
|
(rx/map #(json/decode % :key-fn read-json-key :val-fn read-json-val) stream)
|
||||||
|
|
||||||
no-parse?
|
:else
|
||||||
(rx/map :content)))))
|
stream)))))
|
||||||
|
|
||||||
(defn progress!
|
(defn progress!
|
||||||
([context type]
|
([context type]
|
||||||
|
@ -569,7 +595,7 @@
|
||||||
(update :id resolve))]
|
(update :id resolve))]
|
||||||
(fb/add-library-color file color)))]
|
(fb/add-library-color file color)))]
|
||||||
(->> (get-file context :colors-list)
|
(->> (get-file context :colors-list)
|
||||||
(rx/merge-map (comp d/kebab-keys parser/string->uuid))
|
(rx/merge-map identity)
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [[id color]]
|
(fn [[id color]]
|
||||||
(let [color (assoc color :id id)
|
(let [color (assoc color :id id)
|
||||||
|
@ -599,7 +625,7 @@
|
||||||
(if (:has-typographies context)
|
(if (:has-typographies context)
|
||||||
(let [resolve (:resolve context)]
|
(let [resolve (:resolve context)]
|
||||||
(->> (get-file context :typographies)
|
(->> (get-file context :typographies)
|
||||||
(rx/merge-map (comp d/kebab-keys parser/string->uuid))
|
(rx/merge-map identity)
|
||||||
(rx/map (fn [[id typography]]
|
(rx/map (fn [[id typography]]
|
||||||
(-> typography
|
(-> typography
|
||||||
(d/kebab-keys)
|
(d/kebab-keys)
|
||||||
|
@ -613,7 +639,7 @@
|
||||||
(if (:has-media context)
|
(if (:has-media context)
|
||||||
(let [resolve (:resolve context)]
|
(let [resolve (:resolve context)]
|
||||||
(->> (get-file context :media-list)
|
(->> (get-file context :media-list)
|
||||||
(rx/merge-map (comp d/kebab-keys parser/string->uuid))
|
(rx/merge-map identity)
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
(fn [[id media]]
|
(fn [[id media]]
|
||||||
(let [media (-> media
|
(let [media (-> media
|
||||||
|
@ -725,7 +751,6 @@
|
||||||
(rx/filter (fn [data] (= "application/zip" (:type data))))
|
(rx/filter (fn [data] (= "application/zip" (:type data))))
|
||||||
(rx/merge-map #(zip/loadAsync (:body %)))
|
(rx/merge-map #(zip/loadAsync (:body %)))
|
||||||
(rx/merge-map #(get-file {:zip %} :manifest))
|
(rx/merge-map #(get-file {:zip %} :manifest))
|
||||||
(rx/map (comp d/kebab-keys parser/string->uuid))
|
|
||||||
(rx/map
|
(rx/map
|
||||||
(fn [data]
|
(fn [data]
|
||||||
;; Checks if the file is exported with components v2 and the current team only
|
;; Checks if the file is exported with components v2 and the current team only
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.files.repair :as cfr]
|
[app.common.files.repair :as cfr]
|
||||||
[app.common.files.validate :as cfv]
|
[app.common.files.validate :as cfv]
|
||||||
|
[app.common.json :as json]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uri :as u]
|
[app.common.uri :as u]
|
||||||
|
@ -97,26 +97,14 @@
|
||||||
(effect-fn input)
|
(effect-fn input)
|
||||||
(rf result input)))))
|
(rf result input)))))
|
||||||
|
|
||||||
(defn prettify
|
|
||||||
"Prepare x for cleaner output when logged."
|
|
||||||
[x]
|
|
||||||
(cond
|
|
||||||
(map? x) (d/mapm #(prettify %2) x)
|
|
||||||
(vector? x) (mapv prettify x)
|
|
||||||
(seq? x) (map prettify x)
|
|
||||||
(set? x) (into #{} (map prettify) x)
|
|
||||||
(number? x) (mth/precision x 4)
|
|
||||||
(uuid? x) (str/concat "#uuid " x)
|
|
||||||
:else x))
|
|
||||||
|
|
||||||
(defn ^:export logjs
|
(defn ^:export logjs
|
||||||
([str] (tap (partial logjs str)))
|
([str] (tap (partial logjs str)))
|
||||||
([str val]
|
([str val]
|
||||||
(js/console.log str (clj->js (prettify val) :keyword-fn (fn [v] (str/concat v))))
|
(js/console.log str (json/->js val))
|
||||||
val))
|
val))
|
||||||
|
|
||||||
(when (exists? js/window)
|
(when (exists? js/window)
|
||||||
(set! (.-dbg ^js js/window) clj->js)
|
(set! (.-dbg ^js js/window) json/->js)
|
||||||
(set! (.-pp ^js js/window) pprint))
|
(set! (.-pp ^js js/window) pprint))
|
||||||
|
|
||||||
(defonce widget-style "
|
(defonce widget-style "
|
||||||
|
@ -479,7 +467,7 @@
|
||||||
(let [result (map (fn [row]
|
(let [result (map (fn [row]
|
||||||
(update row :id str))
|
(update row :id str))
|
||||||
result)]
|
result)]
|
||||||
(js/console.table (clj->js result))))
|
(js/console.table (json/->js result))))
|
||||||
(fn [cause]
|
(fn [cause]
|
||||||
(js/console.log "EE:" cause))))
|
(js/console.log "EE:" cause))))
|
||||||
nil))
|
nil))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue