mirror of
https://github.com/penpot/penpot.git
synced 2025-06-04 04:11:39 +02:00
✨ Fix single set import
This commit is contained in:
parent
982118c942
commit
a20dd3f955
6 changed files with 127 additions and 50 deletions
|
@ -665,20 +665,20 @@
|
|||
["$value" :map]
|
||||
["$type" :string]]]))
|
||||
|
||||
(defn has-legacy-format?
|
||||
(defn get-json-format
|
||||
"Searches through parsed token file and returns:
|
||||
- true when first node satisfies `legacy-node?` predicate
|
||||
- false when first node satisfies `dtcg-node?` predicate
|
||||
- nil if neither combination is found"
|
||||
- `:json-format/legacy` when first node satisfies `legacy-node?` predicate
|
||||
- `:json-format/dtcg` when first node satisfies `dtcg-node?` predicate
|
||||
- `nil` if neither combination is found"
|
||||
([data]
|
||||
(has-legacy-format? data legacy-node? dtcg-node?))
|
||||
(get-json-format data legacy-node? dtcg-node?))
|
||||
([data legacy-node? dtcg-node?]
|
||||
(let [branch? map?
|
||||
children (fn [node] (vals node))
|
||||
check-node (fn [node]
|
||||
(cond
|
||||
(legacy-node? node) true
|
||||
(dtcg-node? node) false
|
||||
(legacy-node? node) :json-format/legacy
|
||||
(dtcg-node? node) :json-format/dtcg
|
||||
:else nil))
|
||||
walk (fn walk [node]
|
||||
(lazy-seq
|
||||
|
@ -690,6 +690,10 @@
|
|||
(filter some?)
|
||||
first))))
|
||||
|
||||
(defn single-set? [data]
|
||||
(and (not (contains? data "$metadata"))
|
||||
(not (contains? data "$themes"))))
|
||||
|
||||
;; DEPRECATED
|
||||
(defn walk-sets-tree-seq
|
||||
"Walk sets tree as a flat list.
|
||||
|
@ -826,6 +830,24 @@
|
|||
|
||||
(declare make-tokens-lib)
|
||||
|
||||
(defn- legacy-nodes->dtcg-nodes [sets-data]
|
||||
(walk/postwalk
|
||||
(fn [node]
|
||||
(cond-> node
|
||||
(and (map? node)
|
||||
(contains? node "value")
|
||||
(sequential? (get node "value")))
|
||||
(update "value"
|
||||
(fn [seq-value]
|
||||
(map #(set/rename-keys % {"type" "$type"}) seq-value)))
|
||||
|
||||
(and (map? node)
|
||||
(and (contains? node "type")
|
||||
(contains? node "value")))
|
||||
(set/rename-keys {"value" "$value"
|
||||
"type" "$type"})))
|
||||
sets-data))
|
||||
|
||||
(defprotocol ITokensLib
|
||||
"A library of tokens, sets and themes."
|
||||
(set-path-exists? [_ path] "if a set at `path` exists")
|
||||
|
@ -844,6 +866,8 @@ Will return a value that matches this schema:
|
|||
(get-active-themes-set-tokens [_] "set of set names that are active in the the active themes")
|
||||
(encode-dtcg [_] "Encodes library to a dtcg compatible json string")
|
||||
(decode-dtcg-json [_ parsed-json] "Decodes parsed json containing tokens and converts to library")
|
||||
(decode-single-set-json [_ set-name tokens] "Decodes parsed json containing single token set and converts to library")
|
||||
(decode-single-set-legacy-json [_ set-name tokens] "Decodes parsed legacy json containing single token set and converts to library")
|
||||
(decode-legacy-json [_ parsed-json] "Decodes parsed legacy json containing tokens and converts to library")
|
||||
(get-all-tokens [_] "all tokens in the lib")
|
||||
(validate [_]))
|
||||
|
@ -1287,6 +1311,17 @@ Will return a value that matches this schema:
|
|||
(assoc-in ["$metadata" "activeThemes"] active-themes-clear)
|
||||
(assoc-in ["$metadata" "activeSets"] active-sets))))
|
||||
|
||||
(decode-single-set-json [this set-name tokens]
|
||||
(assert (map? tokens) "expected a map data structure for `data`")
|
||||
|
||||
(add-set this (make-token-set :name (normalize-set-name set-name)
|
||||
:tokens (flatten-nested-tokens-json tokens ""))))
|
||||
|
||||
|
||||
(decode-single-set-legacy-json [this set-name tokens]
|
||||
(assert (map? tokens) "expected a map data structure for `data`")
|
||||
(decode-single-set-json this set-name (legacy-nodes->dtcg-nodes tokens)))
|
||||
|
||||
(decode-dtcg-json [_ data]
|
||||
(assert (map? data) "expected a map data structure for `data`")
|
||||
|
||||
|
@ -1370,22 +1405,7 @@ Will return a value that matches this schema:
|
|||
(decode-legacy-json [this parsed-legacy-json]
|
||||
(let [other-data (select-keys parsed-legacy-json ["$themes" "$metadata"])
|
||||
sets-data (dissoc parsed-legacy-json "$themes" "$metadata")
|
||||
dtcg-sets-data (walk/postwalk
|
||||
(fn [node]
|
||||
(cond-> node
|
||||
(and (map? node)
|
||||
(contains? node "value")
|
||||
(sequential? (get node "value")))
|
||||
(update "value"
|
||||
(fn [seq-value]
|
||||
(map #(set/rename-keys % {"type" "$type"}) seq-value)))
|
||||
|
||||
(and (map? node)
|
||||
(and (contains? node "type")
|
||||
(contains? node "value")))
|
||||
(set/rename-keys {"value" "$value"
|
||||
"type" "$type"})))
|
||||
sets-data)]
|
||||
dtcg-sets-data (legacy-nodes->dtcg-nodes sets-data)]
|
||||
(decode-dtcg-json this (merge other-data
|
||||
dtcg-sets-data))))
|
||||
(get-all-tokens [this]
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{"color":
|
||||
{"red":
|
||||
{"100":
|
||||
{"value":"red",
|
||||
"type":"color",
|
||||
"description":""}}}}
|
6
common/test/common_tests/types/data/single-set.json
Normal file
6
common/test/common_tests/types/data/single-set.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{"color":
|
||||
{"red":
|
||||
{"100":
|
||||
{"$value":"red",
|
||||
"$type":"color",
|
||||
"$description":""}}}}
|
|
@ -1371,6 +1371,30 @@
|
|||
(t/testing "invalid tokens got discarded"
|
||||
(t/is (nil? (get-set-token "typography" "H1.Bold")))))))
|
||||
|
||||
#?(:clj
|
||||
(t/deftest single-set-legacy-json-decoding
|
||||
(let [json (-> (slurp "test/common_tests/types/data/legacy-single-set.json")
|
||||
(tr/decode-str))
|
||||
lib (ctob/decode-single-set-legacy-json (ctob/ensure-tokens-lib nil) "single_set" json)
|
||||
get-set-token (fn [set-name token-name]
|
||||
(some-> (ctob/get-set lib set-name)
|
||||
(ctob/get-token token-name)))]
|
||||
(t/is (= '("single_set") (ctob/get-ordered-set-names lib)))
|
||||
(t/testing "token added"
|
||||
(t/is (some? (get-set-token "single_set" "color.red.100")))))))
|
||||
|
||||
#?(:clj
|
||||
(t/deftest single-set-dtcg-json-decoding
|
||||
(let [json (-> (slurp "test/common_tests/types/data/single-set.json")
|
||||
(tr/decode-str))
|
||||
lib (ctob/decode-single-set-json (ctob/ensure-tokens-lib nil) "single_set" json)
|
||||
get-set-token (fn [set-name token-name]
|
||||
(some-> (ctob/get-set lib set-name)
|
||||
(ctob/get-token token-name)))]
|
||||
(t/is (= '("single_set") (ctob/get-ordered-set-names lib)))
|
||||
(t/testing "token added"
|
||||
(t/is (some? (get-set-token "single_set" "color.red.100")))))))
|
||||
|
||||
#?(:clj
|
||||
(t/deftest dtcg-encoding-decoding-json
|
||||
(let [json (-> (slurp "test/common_tests/types/data/tokens-multi-set-example.json")
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
[app.util.i18n :refer [tr]]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]
|
||||
|
@ -367,9 +368,10 @@
|
|||
(fn [event]
|
||||
(let [file (-> (dom/get-target event)
|
||||
(dom/get-files)
|
||||
(first))]
|
||||
(first))
|
||||
file-name (str/replace (.-name file) ".json" "")]
|
||||
(->> (wapi/read-file-as-text file)
|
||||
(sd/process-json-stream)
|
||||
(sd/process-json-stream {:file-name file-name})
|
||||
(rx/subs! (fn [lib]
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "import-tokens"})
|
||||
(dt/import-tokens-lib lib)))
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[app.common.schema :as sm]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.tokens.errors :as wte]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
|
@ -249,33 +250,51 @@
|
|||
(= header-2 "Reference Errors:"))
|
||||
errors)))
|
||||
|
||||
(defn process-json-stream [data-stream]
|
||||
(->> data-stream
|
||||
(rx/map (fn [data]
|
||||
(try
|
||||
(t/decode-str data)
|
||||
(catch js/Error e
|
||||
(throw (wte/error-ex-info :error.import/json-parse-error data e))))))
|
||||
(rx/map (fn [json-data]
|
||||
(try
|
||||
(if-not (ctob/has-legacy-format? json-data)
|
||||
(ctob/decode-dtcg-json (ctob/ensure-tokens-lib nil) json-data)
|
||||
(ctob/decode-legacy-json (ctob/ensure-tokens-lib nil) json-data))
|
||||
(catch js/Error e
|
||||
(throw (wte/error-ex-info :error.import/invalid-json-data json-data e))))))
|
||||
(rx/mapcat (fn [tokens-lib]
|
||||
(defn process-json-stream
|
||||
([data-stream]
|
||||
(process-json-stream nil data-stream))
|
||||
([params data-stream]
|
||||
(let [{:keys [file-name]} params]
|
||||
(->> data-stream
|
||||
(rx/map (fn [data]
|
||||
(try
|
||||
(-> (ctob/get-all-tokens tokens-lib)
|
||||
(resolve-tokens-with-errors+)
|
||||
(p/then (fn [_] tokens-lib))
|
||||
(p/catch (fn [sd-error]
|
||||
(let [reference-errors (reference-errors sd-error)
|
||||
err (if reference-errors
|
||||
(wte/error-ex-info :error.import/style-dictionary-reference-errors reference-errors sd-error)
|
||||
(wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error))]
|
||||
(throw err)))))
|
||||
(t/decode-str data)
|
||||
(catch js/Error e
|
||||
(p/rejected (wte/error-ex-info :error.import/style-dictionary-unknown-error "" e))))))))
|
||||
(throw (wte/error-ex-info :error.import/json-parse-error data e))))))
|
||||
(rx/map (fn [json-data]
|
||||
(let [single-set? (ctob/single-set? json-data)
|
||||
json-format (ctob/get-json-format json-data)]
|
||||
(try
|
||||
(cond
|
||||
(and single-set?
|
||||
(= :json-format/legacy json-format))
|
||||
(ctob/decode-single-set-legacy-json (ctob/ensure-tokens-lib (deref refs/tokens-lib)) file-name json-data)
|
||||
|
||||
(and single-set?
|
||||
(= :json-format/dtcg json-format))
|
||||
(ctob/decode-single-set-json (ctob/ensure-tokens-lib (deref refs/tokens-lib)) file-name json-data)
|
||||
|
||||
(= :json-format/legacy json-format)
|
||||
(ctob/decode-legacy-json (ctob/ensure-tokens-lib nil) json-data)
|
||||
|
||||
:else
|
||||
(ctob/decode-dtcg-json (ctob/ensure-tokens-lib nil) json-data))
|
||||
|
||||
(catch js/Error e
|
||||
(throw (wte/error-ex-info :error.import/invalid-json-data json-data e)))))))
|
||||
(rx/mapcat (fn [tokens-lib]
|
||||
(try
|
||||
(-> (ctob/get-all-tokens tokens-lib)
|
||||
(resolve-tokens-with-errors+)
|
||||
(p/then (fn [_] tokens-lib))
|
||||
(p/catch (fn [sd-error]
|
||||
(let [reference-errors (reference-errors sd-error)
|
||||
err (if reference-errors
|
||||
(wte/error-ex-info :error.import/style-dictionary-reference-errors reference-errors sd-error)
|
||||
(wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error))]
|
||||
(throw err)))))
|
||||
(catch js/Error e
|
||||
(p/rejected (wte/error-ex-info :error.import/style-dictionary-unknown-error "" e))))))))))
|
||||
|
||||
;; === Errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue