From d9f98008f4542e2f221128104c962caf101f3b1e Mon Sep 17 00:00:00 2001 From: Andrey Fedorov Date: Tue, 13 May 2025 11:52:43 +0200 Subject: [PATCH] :sparkles: Add unknown token type reporting --- common/src/app/common/types/tokens_lib.cljc | 21 +++++ .../src/app/main/data/style_dictionary.cljs | 83 ++++++++++++------- frontend/translations/en.po | 6 ++ 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index ffed9c3949..77f979dadf 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -826,6 +826,27 @@ (map-indexed (fn [index item] (assoc item :index index)))))) +(defn get-tokens-of-unknown-type + "Recursively search the tokens for unknown types" + [tokens token-path dctg?] + (let [type-key (if dctg? "$type" "type")] + (reduce-kv + (fn [unknown-tokens k v] + (let [child-path (if (empty? token-path) + (name k) + (str token-path "." k))] + (if (and (map? v) + (not (contains? v type-key))) + (let [nested-unknown-tokens (get-tokens-of-unknown-type v child-path dctg?)] + (merge unknown-tokens nested-unknown-tokens)) + (let [token-type-str (get v type-key) + token-type (cto/dtcg-token-type->token-type token-type-str)] + (if (and (not (some? token-type)) (some? token-type-str)) + (assoc unknown-tokens child-path token-type-str) + unknown-tokens))))) + {} + tokens))) + (defn flatten-nested-tokens-json "Recursively flatten the dtcg token structure, joining keys with '.'." [tokens token-path] diff --git a/frontend/src/app/main/data/style_dictionary.cljs b/frontend/src/app/main/data/style_dictionary.cljs index 493f50616c..13d9ec0dee 100644 --- a/frontend/src/app/main/data/style_dictionary.cljs +++ b/frontend/src/app/main/data/style_dictionary.cljs @@ -13,9 +13,12 @@ [app.common.schema :as sm] [app.common.transit :as t] [app.common.types.tokens-lib :as ctob] + [app.main.data.notifications :as ntf] [app.main.data.tinycolor :as tinycolor] [app.main.data.workspace.tokens.errors :as wte] [app.main.data.workspace.tokens.warnings :as wtw] + [app.main.store :as st] + [app.util.i18n :refer [tr]] [app.util.time :as dt] [beicon.v2.core :as rx] [cuerdas.core :as str] @@ -81,21 +84,20 @@ (let [parsed-value (cft/parse-token-value value) out-of-scope (not (<= 0 (:value parsed-value) 1)) references (seq (ctob/find-token-value-references value))] - (cond - (and parsed-value (not out-of-scope)) - parsed-value + (cond (and parsed-value (not out-of-scope)) + parsed-value - references - {:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)] - :references references} + references + {:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)] + :references references} - (and (not has-references?) out-of-scope) - {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-opacity value)]} + (and (not has-references?) out-of-scope) + {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-opacity value)]} - (and has-references? out-of-scope parsed-value) - (assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value-opacity value)]) + (and has-references? out-of-scope parsed-value) + (assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value-opacity value)]) - :else {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]}))) + :else {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]}))) (defn- parse-sd-token-stroke-width-value @@ -167,11 +169,13 @@ (parse-sd-token-numeric-value value)) output-token (cond (:errors parsed-token-value) (merge origin-token parsed-token-value) + (:warnings parsed-token-value) (assoc origin-token :resolved-value (:value parsed-token-value) :warnings (:warnings parsed-token-value) :unit (:unit parsed-token-value)) + :else (assoc origin-token :resolved-value (:value parsed-token-value) @@ -280,6 +284,19 @@ (when name-error? (wte/error-ex-info :error.import/invalid-token-name (:value schema-error) err)))) +(defn- group-by-value [m] + (reduce (fn [acc [k v]] + (update acc v conj k)) {} m)) + +(defn- tokens-of-unknown-type-warning [unknown-tokens] + (let [type->tokens (group-by-value unknown-tokens)] + (ntf/show {:content (tr "workspace.token.unknown-token-type") + :detail (->> (for [[token-type tokens] type->tokens] + (tr "workspace.token.unknown-token-type-section" token-type (count tokens))) + (str/join "\n")) + :type :toast + :level :info}))) + (defn process-json-stream ([data-stream] (process-json-stream nil data-stream)) @@ -293,28 +310,36 @@ (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)) - (decode-single-set-legacy-json (ctob/ensure-tokens-lib nil) file-name json-data) + json-format (ctob/get-json-format json-data) + unknown-tokens (ctob/get-tokens-of-unknown-type + json-data + "" + (= json-format :json-format/dtcg))] + {:tokens-lib + (try + (cond + (and single-set? + (= :json-format/legacy json-format)) + (decode-single-set-legacy-json (ctob/ensure-tokens-lib nil) file-name json-data) - (and single-set? - (= :json-format/dtcg json-format)) - (decode-single-set-json (ctob/ensure-tokens-lib nil) file-name json-data) + (and single-set? + (= :json-format/dtcg json-format)) + (decode-single-set-json (ctob/ensure-tokens-lib nil) file-name json-data) - (= :json-format/legacy json-format) - (ctob/decode-legacy-json (ctob/ensure-tokens-lib nil) 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)) + :else + (ctob/decode-dtcg-json (ctob/ensure-tokens-lib nil) json-data)) - (catch js/Error e - (let [err (or (name-error e) - (wte/error-ex-info :error.import/invalid-json-data json-data e))] - (throw err))))))) - (rx/mapcat (fn [tokens-lib] + (catch js/Error e + (let [err (or (name-error e) + (wte/error-ex-info :error.import/invalid-json-data json-data e))] + (throw err)))) + :unknown-tokens unknown-tokens}))) + (rx/mapcat (fn [{:keys [tokens-lib unknown-tokens]}] + (when unknown-tokens + (st/emit! (tokens-of-unknown-type-warning unknown-tokens))) (try (-> (ctob/get-all-tokens tokens-lib) (resolve-tokens-with-errors+) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 831b96e5ac..e87aafc9a3 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -7433,3 +7433,9 @@ msgstr "The following files have errors:" msgid "dashboard.import.import-error.message2" msgstr "Files with errors will not be uploaded." + +msgid "workspace.token.unknown-token-type" +msgstr "Skipped tokens" + +msgid "workspace.token.unknown-token-type-section" +msgstr "Type '%s' is not supported (%s)\n"