From 252797183c6737399170ea020bc70b216611a9bd Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 7 Aug 2024 15:14:32 +0200 Subject: [PATCH 01/24] Use :name as the token identifier [*] [*] Using uuid as the token identiefier for :applied-tokens is not correct as we want to merge all sets together by their name, to get the final values. --- common/src/app/common/types/token.cljc | 50 +++++++------ .../app/main/ui/workspace/tokens/changes.cljs | 4 +- .../ui/workspace/tokens/style_dictionary.cljs | 8 +- .../app/main/ui/workspace/tokens/token.cljs | 15 ++-- frontend/test/token_tests/helpers/tokens.cljs | 4 +- frontend/test/token_tests/token_test.cljs | 74 ++++++++++--------- 6 files changed, 82 insertions(+), 73 deletions(-) diff --git a/common/src/app/common/types/token.cljc b/common/src/app/common/types/token.cljc index 2e8a4e2cc..104948105 100644 --- a/common/src/app/common/types/token.cljc +++ b/common/src/app/common/types/token.cljc @@ -47,10 +47,12 @@ :string :typography}) +(def token-name-ref :string) + (sm/register! ::token [:map {:title "Token"} [:id ::sm/uuid] - [:name :string] + [:name token-name-ref] [:type [::sm/one-of token-types]] [:value :any] [:description {:optional true} :string] @@ -58,48 +60,48 @@ (sm/register! ::border-radius [:map - [:rx {:optional true} ::sm/uuid] - [:ry {:optional true} ::sm/uuid] - [:r1 {:optional true} ::sm/uuid] - [:r2 {:optional true} ::sm/uuid] - [:r3 {:optional true} ::sm/uuid] - [:r4 {:optional true} ::sm/uuid]]) + [:rx {:optional true} token-name-ref] + [:ry {:optional true} token-name-ref] + [:r1 {:optional true} token-name-ref] + [:r2 {:optional true} token-name-ref] + [:r3 {:optional true} token-name-ref] + [:r4 {:optional true} token-name-ref]]) (def border-radius-keys (schema-keys ::border-radius)) (sm/register! ::stroke-width [:map - [:stroke-width {:optional true} ::sm/uuid]]) + [:stroke-width {:optional true} token-name-ref]]) (def stroke-width-keys (schema-keys ::stroke-width)) (sm/register! ::sizing [:map - [:width {:optional true} ::sm/uuid] - [:height {:optional true} ::sm/uuid] - [:layout-item-min-w {:optional true} ::sm/uuid] - [:layout-item-max-w {:optional true} ::sm/uuid] - [:layout-item-min-h {:optional true} ::sm/uuid] - [:layout-item-max-h {:optional true} ::sm/uuid]]) + [:width {:optional true} token-name-ref] + [:height {:optional true} token-name-ref] + [:layout-item-min-w {:optional true} token-name-ref] + [:layout-item-max-w {:optional true} token-name-ref] + [:layout-item-min-h {:optional true} token-name-ref] + [:layout-item-max-h {:optional true} token-name-ref]]) (def sizing-keys (schema-keys ::sizing)) (sm/register! ::opacity [:map - [:opacity {:optional true} ::sm/uuid]]) + [:opacity {:optional true} token-name-ref]]) (def opacity-keys (schema-keys ::opacity)) (sm/register! ::spacing [:map - [:row-gap {:optional true} ::sm/uuid] - [:column-gap {:optional true} ::sm/uuid] - [:p1 {:optional true} ::sm/uuid] - [:p2 {:optional true} ::sm/uuid] - [:p3 {:optional true} ::sm/uuid] - [:p4 {:optional true} ::sm/uuid] - [:x {:optional true} ::sm/uuid] - [:y {:optional true} ::sm/uuid]]) + [:row-gap {:optional true} token-name-ref] + [:column-gap {:optional true} token-name-ref] + [:p1 {:optional true} token-name-ref] + [:p2 {:optional true} token-name-ref] + [:p3 {:optional true} token-name-ref] + [:p4 {:optional true} token-name-ref] + [:x {:optional true} token-name-ref] + [:y {:optional true} token-name-ref]]) (def spacing-keys (schema-keys ::spacing)) @@ -113,7 +115,7 @@ (sm/register! ::rotation [:map - [:rotation {:optional true} ::sm/uuid]]) + [:rotation {:optional true} token-name-ref]]) (def rotation-keys (schema-keys ::rotation)) diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index af53ee46c..e6e311ad0 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -38,7 +38,7 @@ (let [undo-id (js/Symbol) resolved-value (-> (get sd-tokens (:id token)) (wtt/resolve-token-value)) - tokenized-attributes (wtt/attributes-map attributes (:id token))] + tokenized-attributes (wtt/attributes-map attributes token)] (rx/of (dwu/start-undo-transaction undo-id) (dwsh/update-shapes shape-ids (fn [shape] @@ -58,7 +58,7 @@ ptk/WatchEvent (watch [_ _ _] (rx/of - (let [remove-token #(when % (wtt/remove-attributes-for-token-id attributes (:id token) %))] + (let [remove-token #(when % (wtt/remove-attributes-for-token attributes token %))] (dwsh/update-shapes shape-ids (fn [shape] diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 738cdbc1e..7d16ffd0e 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -86,18 +86,19 @@ [tokens & {:keys [debug?] :as config}] (p/let [sd-tokens (-> (wtt/token-names-tree tokens) (resolve-sd-tokens+ config))] - (let [resolved-tokens (reduce + (let [tokens-by-name (wtt/token-names-map tokens) + resolved-tokens (reduce (fn [acc ^js cur] (let [value (.-value cur) resolved-value (d/parse-double (.-value cur)) original-value (-> cur .-original .-value) - id (uuid (.-uuid (.-id cur))) + id (.-name cur) missing-reference? (and (not resolved-value) (re-find #"\{" value) (= value original-value))] (cond-> (assoc-in acc [id :resolved-value] resolved-value) missing-reference? (update-in [id :errors] (fnil conj #{}) :style-dictionary/missing-reference)))) - tokens sd-tokens)] + tokens-by-name sd-tokens)] (when debug? (js/console.log "Resolved tokens" resolved-tokens)) resolved-tokens))) @@ -157,6 +158,7 @@ (-> (clj->js {"a" {:name "a" :value "5"} "b" {:name "b" :value "{a} * 2"}}) + (#(resolve-sd-tokens+ % {:debug? true}))) (let [example (-> (shadow.resource/inline "./data/example-tokens-set.json") diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index b0d12d220..647dab736 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -4,6 +4,9 @@ [clojure.set :as set] [cuerdas.core :as str])) +(defn token-identifier [{:keys [name] :as _token}] + name) + (defn resolve-token-value [{:keys [value resolved-value] :as _token}] (or resolved-value @@ -11,17 +14,17 @@ (defn attributes-map "Creats an attributes map using collection of `attributes` for `id`." - [attributes id] - (->> (map (fn [attr] {attr id}) attributes) + [attributes token] + (->> (map (fn [attr] [attr (token-identifier token)]) attributes) (into {}))) -(defn remove-attributes-for-token-id +(defn remove-attributes-for-token "Removes applied tokens with `token-id` for the given `attributes` set from `applied-tokens`." - [attributes token-id applied-tokens] + [attributes token applied-tokens] (let [attr? (set attributes)] (->> (remove (fn [[k v]] (and (attr? k) - (= v token-id))) + (= v (token-identifier token)))) applied-tokens) (into {})))) @@ -29,7 +32,7 @@ "Test if `token` is applied to a `shape` on single `token-attribute`." [token shape token-attribute] (when-let [id (get-in shape [:applied-tokens token-attribute])] - (= (:id token) id))) + (= (token-identifier token) id))) (defn token-applied? "Test if `token` is applied to a `shape` with at least one of the one of the given `token-attributes`." diff --git a/frontend/test/token_tests/helpers/tokens.cljs b/frontend/test/token_tests/helpers/tokens.cljs index 716dd0755..87db316fb 100644 --- a/frontend/test/token_tests/helpers/tokens.cljs +++ b/frontend/test/token_tests/helpers/tokens.cljs @@ -15,8 +15,8 @@ (defn apply-token-to-shape [file shape-label token-label attributes] (let [first-page-id (get-in file [:data :pages 0]) shape-id (thi/id shape-label) - token-id (thi/id token-label) - applied-attributes (wtt/attributes-map attributes token-id)] + token (get-token file token-label) + applied-attributes (wtt/attributes-map attributes token)] (update-in file [:data :pages-index first-page-id :objects shape-id diff --git a/frontend/test/token_tests/token_test.cljs b/frontend/test/token_tests/token_test.cljs index bcf86fcc9..4ad17cf5b 100644 --- a/frontend/test/token_tests/token_test.cljs +++ b/frontend/test/token_tests/token_test.cljs @@ -10,66 +10,68 @@ [cljs.test :as t :include-macros true])) (t/deftest remove-attributes-for-token-id - (t/testing "removes attributes matching the `token-id`, keeps other attributes" - (t/is (= {:ry :b} - (wtt/remove-attributes-for-token-id - #{:rx :ry} :a {:rx :a :ry :b}))))) + (t/testing "removes attributes matching the `token`, keeps other attributes" + (t/is (= {:ry "b"} + (wtt/remove-attributes-for-token #{:rx :ry} {:name "a"} {:rx "a" :ry "b"}))))) (t/deftest token-applied-test (t/testing "matches passed token with `:token-attributes`" - (t/is (true? (wtt/token-applied? {:id :a} {:applied-tokens {:x :a}} #{:x})))) + (t/is (true? (wtt/token-applied? {:name "a"} {:applied-tokens {:x "a"}} #{:x})))) (t/testing "doesn't match empty token" - (t/is (nil? (wtt/token-applied? {} {:applied-tokens {:x :a}} #{:x})))) + (t/is (nil? (wtt/token-applied? {} {:applied-tokens {:x "a"}} #{:x})))) (t/testing "does't match passed token `:id`" - (t/is (nil? (wtt/token-applied? {:id :b} {:applied-tokens {:x :a}} #{:x})))) + (t/is (nil? (wtt/token-applied? {:name "b"} {:applied-tokens {:x "a"}} #{:x})))) (t/testing "doesn't match passed `:token-attributes`" - (t/is (nil? (wtt/token-applied? {:id :a} {:applied-tokens {:x :a}} #{:y}))))) + (t/is (nil? (wtt/token-applied? {:name "a"} {:applied-tokens {:x "a"}} #{:y}))))) (t/deftest token-applied-attributes - (t/is (= #{:x} (wtt/token-applied-attributes {:id :a} - {:applied-tokens {:x :a :y :b}} + (t/is (= #{:x} (wtt/token-applied-attributes {:name "a"} + {:applied-tokens {:x "a" :y "b"}} #{:x :missing})))) (t/deftest shapes-ids-by-applied-attributes (t/testing "Returns set of matched attributes that fit the applied token" (let [attributes #{:x :y :z} - shape-applied-x {:id :shape-applied-x - :applied-tokens {:x 1}} - shape-applied-y {:id :shape-applied-y - :applied-tokens {:y 1}} - shape-applied-x-y {:id :shape-applied-x-y - :applied-tokens {:x 1 :y 1}} - shape-applied-none {:id :shape-applied-none + shape-applied-x {:id "shape-applied-x" + :applied-tokens {:x "1"}} + shape-applied-y {:id "shape-applied-y" + :applied-tokens {:y "1"}} + shape-applied-x-y {:id "shape-applied-x-y" + :applied-tokens {:x "1" :y "1"}} + shape-applied-none {:id "shape-applied-none" :applied-tokens {}} - shape-applied-all {:id :shape-applied-all - :applied-tokens {:x 1 :y 1 :z 1}} - ids-set (fn [& xs] (into #{} (map :id xs))) + shape-applied-all {:id "shape-applied-all" + :applied-tokens {:x "1" :y "1" :z "1"}} + shape-ids (fn [& xs] (into #{} (map :id xs))) shapes [shape-applied-x shape-applied-y shape-applied-x-y shape-applied-all shape-applied-none] - expected (wtt/shapes-ids-by-applied-attributes {:id 1} shapes attributes)] - (t/is (= (:x expected) (ids-set shape-applied-x - shape-applied-x-y - shape-applied-all))) - (t/is (= (:y expected) (ids-set shape-applied-y - shape-applied-x-y - shape-applied-all))) - (t/is (= (:z expected) (ids-set shape-applied-all))) - (t/is (true? (wtt/shapes-applied-all? expected (ids-set shape-applied-all) attributes))) - (t/is (false? (wtt/shapes-applied-all? expected (apply ids-set shapes) attributes)))))) + expected (wtt/shapes-ids-by-applied-attributes {:name "1"} shapes attributes)] + (t/is (= (:x expected) (shape-ids shape-applied-x + shape-applied-x-y + shape-applied-all))) + (t/is (= (:y expected) (shape-ids shape-applied-y + shape-applied-x-y + shape-applied-all))) + (t/is (= (:z expected) (shape-ids shape-applied-all))) + (t/is (true? (wtt/shapes-applied-all? expected (shape-ids shape-applied-all) attributes))) + (t/is (false? (wtt/shapes-applied-all? expected (apply shape-ids shapes) attributes))) + (shape-ids shape-applied-x + shape-applied-x-y + shape-applied-all)))) (t/deftest tokens-applied-test (t/testing "is true when single shape matches the token and attributes" - (t/is (true? (wtt/shapes-token-applied? {:id :a} [{:applied-tokens {:x :a}} - {:applied-tokens {:x :b}}] + (t/is (true? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}} + {:applied-tokens {:x "b"}}] #{:x})))) (t/testing "is false when no shape matches the token or attributes" - (t/is (nil? (wtt/shapes-token-applied? {:id :a} [{:applied-tokens {:x :b}} - {:applied-tokens {:x :b}}] + (t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "b"}} + {:applied-tokens {:x "b"}}] #{:x}))) - (t/is (nil? (wtt/shapes-token-applied? {:id :a} [{:applied-tokens {:x :a}} - {:applied-tokens {:x :a}}] + (t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}} + {:applied-tokens {:x "a"}}] #{:y}))))) (t/deftest name->path-test From 980238e27b34d4690ac9c2e149093606d16ea6eb Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 09:22:32 +0200 Subject: [PATCH 02/24] Move find-token-references to token namespace --- .../app/main/ui/workspace/tokens/form.cljs | 2 +- .../ui/workspace/tokens/style_dictionary.cljs | 7 ------- .../app/main/ui/workspace/tokens/token.cljs | 7 +++++++ .../token_tests/style_dictionary_test.cljs | 20 ------------------- frontend/test/token_tests/token_test.cljs | 10 ++++++++++ 5 files changed, 18 insertions(+), 28 deletions(-) delete mode 100644 frontend/test/token_tests/style_dictionary_test.cljs diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 5094f29ef..400e2b6cc 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -92,7 +92,7 @@ Token names should only contain letters and digits separated by . characters.")} ;; When creating a new token we dont have a token name yet, ;; so we use a temporary token name that hopefully doesn't clash with any of the users token names. token-name (if (str/empty? name-value) "__TOKEN_STUDIO_SYSTEM.TEMP" name-value) - token-references (sd/find-token-references input) + token-references (wtt/find-token-references input) direct-self-reference? (get token-references token-name)] (cond empty-input? (p/rejected nil) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 7d16ffd0e..83231fc30 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -23,13 +23,6 @@ ;; Functions ------------------------------------------------------------------- -(defn find-token-references - "Finds token reference values in `value-string` and returns a set with all contained namespaces." - [value-string] - (some->> (re-seq #"\{([^}]*)\}" value-string) - (map second) - (into #{}))) - (defn tokens->style-dictionary+ "Resolves references and math expressions using StyleDictionary. Returns a promise with the resolved dictionary." diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 647dab736..557d3dad0 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -4,6 +4,13 @@ [clojure.set :as set] [cuerdas.core :as str])) +(defn find-token-references + "Finds token reference values in `value-string` and returns a set with all contained namespaces." + [value-string] + (some->> (re-seq #"\{([^}]*)\}" value-string) + (map second) + (into #{}))) + (defn token-identifier [{:keys [name] :as _token}] name) diff --git a/frontend/test/token_tests/style_dictionary_test.cljs b/frontend/test/token_tests/style_dictionary_test.cljs deleted file mode 100644 index ff03ba16c..000000000 --- a/frontend/test/token_tests/style_dictionary_test.cljs +++ /dev/null @@ -1,20 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) KALEIDOS INC - -(ns token-tests.style-dictionary-test - (:require - [app.main.ui.workspace.tokens.style-dictionary :as wtsd] - [cljs.test :as t :include-macros true])) - -(t/deftest test-find-token-references - ;; Return references - (t/is (= #{"foo" "bar"} (wtsd/find-token-references "{foo} + {bar}"))) - ;; Ignore non reference text - (t/is (= #{"foo.bar.baz"} (wtsd/find-token-references "{foo.bar.baz} + something"))) - ;; No references found - (t/is (nil? (wtsd/find-token-references "1 + 2"))) - ;; Edge-case: Ignore unmatched closing parens - (t/is (= #{"foo" "bar"} (wtsd/find-token-references "{foo}} + {bar}")))) diff --git a/frontend/test/token_tests/token_test.cljs b/frontend/test/token_tests/token_test.cljs index 4ad17cf5b..d9f2732b9 100644 --- a/frontend/test/token_tests/token_test.cljs +++ b/frontend/test/token_tests/token_test.cljs @@ -9,6 +9,16 @@ [app.main.ui.workspace.tokens.token :as wtt] [cljs.test :as t :include-macros true])) +(t/deftest find-token-references + ;; Return references + (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo} + {bar}"))) + ;; Ignore non reference text + (t/is (= #{"foo.bar.baz"} (wtt/find-token-references "{foo.bar.baz} + something"))) + ;; No references found + (t/is (nil? (wtt/find-token-references "1 + 2"))) + ;; Edge-case: Ignore unmatched closing parens + (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo}} + {bar}")))) + (t/deftest remove-attributes-for-token-id (t/testing "removes attributes matching the `token`, keeps other attributes" (t/is (= {:ry "b"} From 2e8e33d7019696733faba8c02138ceed86cc4b57 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 09:40:26 +0200 Subject: [PATCH 03/24] Add token value parsing function --- .../app/main/ui/workspace/tokens/token.cljs | 8 ++++++ frontend/test/token_tests/token_test.cljs | 27 +++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 557d3dad0..92591f14a 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -4,6 +4,14 @@ [clojure.set :as set] [cuerdas.core :as str])) +(def parseable-token-value-regexp + #"^\s*(-?[0-9]+\.?[0-9]*)\s*$") + +(defn parse-token-value [value] + (when-let [double-str (-> (re-find parseable-token-value-regexp value) + (last))] + (d/parse-double double-str))) + (defn find-token-references "Finds token reference values in `value-string` and returns a set with all contained namespaces." [value-string] diff --git a/frontend/test/token_tests/token_test.cljs b/frontend/test/token_tests/token_test.cljs index d9f2732b9..77cb674ae 100644 --- a/frontend/test/token_tests/token_test.cljs +++ b/frontend/test/token_tests/token_test.cljs @@ -9,15 +9,26 @@ [app.main.ui.workspace.tokens.token :as wtt] [cljs.test :as t :include-macros true])) +(t/deftest test-parse-token-value + (t/testing "parses double from a token value" + (t/is (= 100.1 (wtt/parse-token-value "100.1"))) + (t/is (= -9 (wtt/parse-token-value "-9"))) + (t/testing "trims white-space" + (t/is (= -1.3 (wtt/parse-token-value " -1.3 ")))) + (t/testing "returns nil for any invalid characters" + (t/is (nil? (wtt/parse-token-value " -1.3a ")))) + (t/testing "doesnt accept invalid double" + (t/is (nil? (wtt/parse-token-value ".3")))))) + (t/deftest find-token-references - ;; Return references - (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo} + {bar}"))) - ;; Ignore non reference text - (t/is (= #{"foo.bar.baz"} (wtt/find-token-references "{foo.bar.baz} + something"))) - ;; No references found - (t/is (nil? (wtt/find-token-references "1 + 2"))) - ;; Edge-case: Ignore unmatched closing parens - (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo}} + {bar}")))) + (t/testing "finds references inside curly braces in a string" + (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo} + {bar}"))) + (t/testing "ignores extra text" + (t/is (= #{"foo.bar.baz"} (wtt/find-token-references "{foo.bar.baz} + something")))) + (t/testing "ignores string without references" + (t/is (nil? (wtt/find-token-references "1 + 2")))) + (t/testing "handles edge-case for extra curly braces" + (t/is (= #{"foo" "bar"} (wtt/find-token-references "{foo}} + {bar}")))))) (t/deftest remove-attributes-for-token-id (t/testing "removes attributes matching the `token`, keeps other attributes" From 37f23855e873f30ad1f404254f14d73eec876ca3 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 09:52:51 +0200 Subject: [PATCH 04/24] Fix re-find only accepting string values throw --- frontend/src/app/main/ui/workspace/tokens/token.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 92591f14a..8d967151b 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -8,9 +8,10 @@ #"^\s*(-?[0-9]+\.?[0-9]*)\s*$") (defn parse-token-value [value] - (when-let [double-str (-> (re-find parseable-token-value-regexp value) - (last))] - (d/parse-double double-str))) + (when (string? value) + (when-let [double-str (-> (re-find parseable-token-value-regexp value) + (last))] + (d/parse-double double-str)))) (defn find-token-references "Finds token reference values in `value-string` and returns a set with all contained namespaces." From 0684d893e06561e0c1ef754a61595b493a1af662 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:06:49 +0200 Subject: [PATCH 05/24] Return resolved & parsed token names map --- .../app/main/ui/workspace/tokens/changes.cljs | 5 ++-- .../ui/workspace/tokens/style_dictionary.cljs | 30 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index e6e311ad0..45ff044df 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -34,10 +34,9 @@ (watch [_ state _] (->> (rx/from (sd/resolve-tokens+ (get-in state [:workspace-data :tokens]))) (rx/mapcat - (fn [sd-tokens] + (fn [resolved-tokens] (let [undo-id (js/Symbol) - resolved-value (-> (get sd-tokens (:id token)) - (wtt/resolve-token-value)) + resolved-value (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value]) tokenized-attributes (wtt/attributes-map attributes token)] (rx/of (dwu/start-undo-transaction undo-id) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 83231fc30..1ab85db96 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -79,19 +79,16 @@ [tokens & {:keys [debug?] :as config}] (p/let [sd-tokens (-> (wtt/token-names-tree tokens) (resolve-sd-tokens+ config))] - (let [tokens-by-name (wtt/token-names-map tokens) - resolved-tokens (reduce + (let [resolved-tokens (reduce (fn [acc ^js cur] - (let [value (.-value cur) - resolved-value (d/parse-double (.-value cur)) - original-value (-> cur .-original .-value) - id (.-name cur) - missing-reference? (and (not resolved-value) - (re-find #"\{" value) - (= value original-value))] - (cond-> (assoc-in acc [id :resolved-value] resolved-value) - missing-reference? (update-in [id :errors] (fnil conj #{}) :style-dictionary/missing-reference)))) - tokens-by-name sd-tokens)] + (let [id (uuid (.-uuid (.-id cur))) + origin-token (get tokens id) + resolved-value (wtt/parse-token-value (.-value cur)) + resolved-token (if (not resolved-value) + (assoc origin-token :errors [:style-dictionary/missing-reference]) + (assoc origin-token :resolved-value resolved-value))] + (assoc acc (wtt/token-identifier resolved-token) resolved-token))) + {} sd-tokens)] (when debug? (js/console.log "Resolved tokens" resolved-tokens)) resolved-tokens))) @@ -142,11 +139,18 @@ (comment (defonce !output (atom nil)) + (-> @refs/workspace-tokens + (resolve-tokens+ {:debug? false}) + (.then js/console.log)) + (-> (resolve-workspace-tokens+ {:debug? true}) (p/then #(reset! !output %))) + @!output + (->> @refs/workspace-tokens - (resolve-tokens+)) + (resolve-tokens+) + (#(doto % js/console.log))) (-> (clj->js {"a" {:name "a" :value "5"} From 31674db11df16dd2a496d0e25817ffca6d4b42eb Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:07:24 +0200 Subject: [PATCH 06/24] Skip parsing on numbers --- frontend/src/app/main/ui/workspace/tokens/token.cljs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index 8d967151b..a64129537 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -8,10 +8,11 @@ #"^\s*(-?[0-9]+\.?[0-9]*)\s*$") (defn parse-token-value [value] - (when (string? value) - (when-let [double-str (-> (re-find parseable-token-value-regexp value) - (last))] - (d/parse-double double-str)))) + (cond + (number? value) value + (string? value) (when-let [double-str (-> (re-find parseable-token-value-regexp value) + (last))] + (d/parse-double double-str)))) (defn find-token-references "Finds token reference values in `value-string` and returns a set with all contained namespaces." From d98e9826649e91c1e57c473f72d800f2d6642fad Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:07:32 +0200 Subject: [PATCH 07/24] Cleanup --- frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 1ab85db96..fd0fe6d36 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -2,7 +2,6 @@ (:require ["@tokens-studio/sd-transforms" :as sd-transforms] ["style-dictionary$default" :as sd] - [app.common.data :as d] [app.main.refs :as refs] [app.main.ui.workspace.tokens.token :as wtt] [cuerdas.core :as str] From e27e2d357ceb68c18c5122120da3e14e5fa43e5a Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:09:12 +0200 Subject: [PATCH 08/24] Add simple applying test --- .../token_tests/logic/token_actions_test.cljs | 58 ++++--------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/frontend/test/token_tests/logic/token_actions_test.cljs b/frontend/test/token_tests/logic/token_actions_test.cljs index beef09847..7e0f87e7c 100644 --- a/frontend/test/token_tests/logic/token_actions_test.cljs +++ b/frontend/test/token_tests/logic/token_actions_test.cljs @@ -5,6 +5,8 @@ [app.common.test-helpers.files :as cthf] [app.common.test-helpers.shapes :as cths] [app.main.ui.workspace.tokens.changes :as wtch] + [app.main.ui.workspace.tokens.token :as wtt] + [cljs.pprint :as pprint] [cljs.test :as t :include-macros true] [frontend-tests.helpers.pages :as thp] [frontend-tests.helpers.state :as ths] @@ -31,65 +33,29 @@ :type :border-radius}))) (t/deftest test-apply-token - (t/testing "applying a token twice with the same attributes will override the previous applied token" - (t/async - done - (let [file (setup-file) - store (ths/setup-store file) - rect-1 (cths/get-shape file :rect-1) - events [(wtch/apply-token {:shape-ids [(:id rect-1)] - :attributes #{:rx :ry} - :token (toht/get-token file :token-1) - :on-update-shape wtch/update-shape-radius-all}) - (wtch/apply-token {:shape-ids [(:id rect-1)] - :attributes #{:rx :ry} - :token (toht/get-token file :token-2) - :on-update-shape wtch/update-shape-radius-all})]] - (tohs/run-store-async - store done events - (fn [new-state] - (let [file' (ths/get-file-from-store new-state) - token-2' (toht/get-token file' :token-2) - rect-1' (cths/get-shape file' :rect-1)] - (t/is (some? (:applied-tokens rect-1'))) - (t/is (= (:rx (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:ry (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:rx rect-1') 24)) - (t/is (= (:ry rect-1') 24))))))))) - -(t/deftest test-apply-token-overwrite - (t/testing "removes old token attributes and applies only single attribute" + (t/testing "applies token to shape and updates shape attributes to resolved value" (t/async done (let [file (setup-file) store (ths/setup-store file) rect-1 (cths/get-shape file :rect-1) - events [;; Apply `:token-1` to all border radius attributes - (wtch/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4} - :token (toht/get-token file :token-1) - :shape-ids [(:id rect-1)] - :on-update-shape wtch/update-shape-radius-all}) - ;; Apply single `:r1` attribute to same shape - ;; while removing other attributes from the border-radius set - ;; but keep `:r4` for testing purposes - (wtch/apply-token {:attributes #{:r1} - :attributes-to-remove #{:rx :ry :r1 :r2 :r3} + events [(wtch/apply-token {:shape-ids [(:id rect-1)] + :attributes #{:rx :ry} :token (toht/get-token file :token-2) - :shape-ids [(:id rect-1)] :on-update-shape wtch/update-shape-radius-all})]] (tohs/run-store-async store done events (fn [new-state] (let [file' (ths/get-file-from-store new-state) - token-1' (toht/get-token file' :token-1) token-2' (toht/get-token file' :token-2) rect-1' (cths/get-shape file' :rect-1)] - (t/testing "other border-radius attributes got removed" - (t/is (nil? (:rx (:applied-tokens rect-1'))))) - (t/testing "r1 got applied with :token-2" - (t/is (= (:r1 (:applied-tokens rect-1')) (:id token-2')))) - (t/testing "while :r4 was kept" - (t/is (= (:r4 (:applied-tokens rect-1')) (:id token-1')))))))))));))))))))))) + (t/testing "shape `:applied-tokens` got updated" + (t/is (some? (:applied-tokens rect-1'))) + (t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2'))) + (t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2')))) + (t/testing "shape radius got update to the resolved token value." + (t/is (= (:rx rect-1') 24)) + (t/is (= (:ry rect-1') 24)))))))))) (t/deftest test-apply-border-radius (t/testing "applies radius token and updates the shapes radius" From a073520d0e7ee5d75ccf5904ac5de902c8916eba Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:22:40 +0200 Subject: [PATCH 09/24] Restore tests to work with new identifier --- .../token_tests/logic/token_actions_test.cljs | 185 +++++++++++------- 1 file changed, 114 insertions(+), 71 deletions(-) diff --git a/frontend/test/token_tests/logic/token_actions_test.cljs b/frontend/test/token_tests/logic/token_actions_test.cljs index 7e0f87e7c..17c16bece 100644 --- a/frontend/test/token_tests/logic/token_actions_test.cljs +++ b/frontend/test/token_tests/logic/token_actions_test.cljs @@ -6,7 +6,6 @@ [app.common.test-helpers.shapes :as cths] [app.main.ui.workspace.tokens.changes :as wtch] [app.main.ui.workspace.tokens.token :as wtt] - [cljs.pprint :as pprint] [cljs.test :as t :include-macros true] [frontend-tests.helpers.pages :as thp] [frontend-tests.helpers.state :as ths] @@ -57,63 +56,77 @@ (t/is (= (:rx rect-1') 24)) (t/is (= (:ry rect-1') 24)))))))))) -(t/deftest test-apply-border-radius - (t/testing "applies radius token and updates the shapes radius" +(t/deftest test-apply-multiple-tokens + (t/testing "applying a token twice with the same attributes will override the previously applied tokens values" (t/async - done - (let [file (setup-file) - store (ths/setup-store file) - rect-1 (cths/get-shape file :rect-1) - events [(wtch/apply-token {:shape-ids [(:id rect-1)] - :attributes #{:rx :ry} - :token (toht/get-token file :token-2) - :on-update-shape wtch/update-shape-radius-all})]] - (tohs/run-store-async - store done events - (fn [new-state] - (let [file' (ths/get-file-from-store new-state) - token-2' (toht/get-token file' :token-2) - rect-1' (cths/get-shape file' :rect-1)] - (t/is (some? (:applied-tokens rect-1'))) - (t/is (= (:rx (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:ry (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:rx rect-1') 24)) - (t/is (= (:ry rect-1') 24))))))))) + done + (let [file (setup-file) + store (ths/setup-store file) + rect-1 (cths/get-shape file :rect-1) + events [(wtch/apply-token {:shape-ids [(:id rect-1)] + :attributes #{:rx :ry} + :token (toht/get-token file :token-1) + :on-update-shape wtch/update-shape-radius-all}) + (wtch/apply-token {:shape-ids [(:id rect-1)] + :attributes #{:rx :ry} + :token (toht/get-token file :token-2) + :on-update-shape wtch/update-shape-radius-all})]] + (tohs/run-store-async + store done events + (fn [new-state] + (let [file' (ths/get-file-from-store new-state) + token-2' (toht/get-token file' :token-2) + rect-1' (cths/get-shape file' :rect-1)] + (t/testing "shape `:applied-tokens` got updated" + (t/is (some? (:applied-tokens rect-1'))) + (t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2'))) + (t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2')))) + (t/testing "shape radius got update to the resolved token value." + (t/is (= (:rx rect-1') 24)) + (t/is (= (:ry rect-1') 24)))))))))) + +(t/deftest test-apply-token-overwrite + (t/testing "removes old token attributes and applies only single attribute" + (t/async + done + (let [file (setup-file) + store (ths/setup-store file) + rect-1 (cths/get-shape file :rect-1) + events [;; Apply `:token-1` to all border radius attributes + (wtch/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4} + :token (toht/get-token file :token-1) + :shape-ids [(:id rect-1)] + :on-update-shape wtch/update-shape-radius-all}) + ;; Apply single `:r1` attribute to same shape + ;; while removing other attributes from the border-radius set + ;; but keep `:r4` for testing purposes + (wtch/apply-token {:attributes #{:r1} + :attributes-to-remove #{:rx :ry :r1 :r2 :r3} + :token (toht/get-token file :token-2) + :shape-ids [(:id rect-1)] + :on-update-shape wtch/update-shape-radius-all})]] + (tohs/run-store-async + store done events + (fn [new-state] + (let [file' (ths/get-file-from-store new-state) + token-1' (toht/get-token file' :token-1) + token-2' (toht/get-token file' :token-2) + rect-1' (cths/get-shape file' :rect-1)] + (t/testing "other border-radius attributes got removed" + (t/is (nil? (:rx (:applied-tokens rect-1'))))) + (t/testing "r1 got applied with :token-2" + (t/is (= (:r1 (:applied-tokens rect-1')) (wtt/token-identifier token-2')))) + (t/testing "while :r4 was kept" + (t/is (= (:r4 (:applied-tokens rect-1')) (wtt/token-identifier token-1')))))))))));))))))))))) (t/deftest test-apply-dimensions (t/testing "applies dimensions token and updates the shapes width and height" - (t/async - done - (let [file (-> (setup-file) - (toht/add-token :token-target {:value "100" - :name "dimensions.sm" - :type :dimensions})) - store (ths/setup-store file) - rect-1 (cths/get-shape file :rect-1) - events [(wtch/apply-token {:shape-ids [(:id rect-1)] - :attributes #{:width :height} - :token (toht/get-token file :token-target) - :on-update-shape wtch/update-shape-dimensions})]] - (tohs/run-store-async - store done events - (fn [new-state] - (let [file' (ths/get-file-from-store new-state) - token-target' (toht/get-token file' :token-target) - rect-1' (cths/get-shape file' :rect-1)] - (t/is (some? (:applied-tokens rect-1'))) - (t/is (= (:width (:applied-tokens rect-1')) (:id token-target'))) - (t/is (= (:height (:applied-tokens rect-1')) (:id token-target'))) - (t/is (= (:width rect-1') 100)) - (t/is (= (:height rect-1') 100))))))))) - -(t/deftest test-apply-sizing - (t/testing "applies sizing token and updates the shapes width and height" (t/async done (let [file (-> (setup-file) (toht/add-token :token-target {:value "100" - :name "sizing.sm" - :type :sizing})) + :name "dimensions.sm" + :type :dimensions})) store (ths/setup-store file) rect-1 (cths/get-shape file :rect-1) events [(wtch/apply-token {:shape-ids [(:id rect-1)] @@ -126,11 +139,41 @@ (let [file' (ths/get-file-from-store new-state) token-target' (toht/get-token file' :token-target) rect-1' (cths/get-shape file' :rect-1)] - (t/is (some? (:applied-tokens rect-1'))) - (t/is (= (:width (:applied-tokens rect-1')) (:id token-target'))) - (t/is (= (:height (:applied-tokens rect-1')) (:id token-target'))) - (t/is (= (:width rect-1') 100)) - (t/is (= (:height rect-1') 100))))))))) + (t/testing "shape `:applied-tokens` got updated" + (t/is (some? (:applied-tokens rect-1'))) + (t/is (= (:width (:applied-tokens rect-1')) (wtt/token-identifier token-target'))) + (t/is (= (:height (:applied-tokens rect-1')) (wtt/token-identifier token-target')))) + (t/testing "shapes width and height got updated" + (t/is (= (:width rect-1') 100)) + (t/is (= (:height rect-1') 100)))))))))) + +;; (t/deftest test-apply-sizing +;; (t/testing "applies sizing token and updates the shapes width and height" +;; (t/async +;; done +;; (let [file (-> (setup-file) +;; (toht/add-token :token-target {:value "100" +;; :name "sizing.sm" +;; :type :sizing})) +;; store (ths/setup-store file) +;; rect-1 (cths/get-shape file :rect-1) +;; events [(wtch/apply-token {:shape-ids [(:id rect-1)] +;; :attributes #{:width :height} +;; :token (toht/get-token file :token-target) +;; :on-update-shape wtch/update-shape-dimensions})]] +;; (tohs/run-store-async +;; store done events +;; (fn [new-state] +;; (let [file' (ths/get-file-from-store new-state) +;; token-target' (toht/get-token file' :token-target) +;; rect-1' (cths/get-shape file' :rect-1)] +;; (t/testing "shape `:applied-tokens` got updated" +;; (t/is (some? (:applied-tokens rect-1'))) +;; (t/is (= (:width (:applied-tokens rect-1')) (wtt/token-identifier token-target'))) +;; (t/is (= (:height (:applied-tokens rect-1')) (wtt/token-identifier token-target')))) +;; (t/testing "shapes width and height got updated" +;; (t/is (= (:width rect-1') 100)) +;; (t/is (= (:height rect-1') 100)))))))))) (t/deftest test-apply-opacity (t/testing "applies opacity token and updates the shapes opacity" @@ -173,13 +216,13 @@ token-opacity-percent (toht/get-token file' :opacity-percent) token-opacity-invalid (toht/get-token file' :opacity-invalid)] (t/testing "float value got translated to float and applied to opacity" - (t/is (= (:opacity (:applied-tokens rect-1')) (:id token-opacity-float))) + (t/is (= (:opacity (:applied-tokens rect-1')) (wtt/token-identifier token-opacity-float))) (t/is (= (:opacity rect-1') 0.3))) (t/testing "percentage value got translated to float and applied to opacity" - (t/is (= (:opacity (:applied-tokens rect-2')) (:id token-opacity-percent))) + (t/is (= (:opacity (:applied-tokens rect-2')) (wtt/token-identifier token-opacity-percent))) (t/is (= (:opacity rect-2') 0.4))) (t/testing "invalid opacity value got applied but did not change shape" - (t/is (= (:opacity (:applied-tokens rect-3')) (:id token-opacity-invalid))) + (t/is (= (:opacity (:applied-tokens rect-3')) (wtt/token-identifier token-opacity-invalid))) (t/is (nil? (:opacity rect-3'))))))))))) (t/deftest test-apply-rotation @@ -203,7 +246,7 @@ token-target' (toht/get-token file' :token-target) rect-1' (cths/get-shape file' :rect-1)] (t/is (some? (:applied-tokens rect-1'))) - (t/is (= (:rotation (:applied-tokens rect-1')) (:id token-target'))) + (t/is (= (:rotation (:applied-tokens rect-1')) (wtt/token-identifier token-target'))) (t/is (= (:rotation rect-1') 120))))))))) (t/deftest test-apply-stroke-width @@ -233,10 +276,10 @@ rect-with-stroke' (cths/get-shape file' :rect-1) rect-without-stroke' (cths/get-shape file' :rect-2)] (t/testing "token got applied to rect with stroke and shape stroke got updated" - (t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (:id token-target'))) + (t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (wtt/token-identifier token-target'))) (t/is (= (get-in rect-with-stroke' [:strokes 0 :stroke-width]) 10))) (t/testing "token got applied to rect without stroke but shape didnt get updated" - (t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (:id token-target'))) + (t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (wtt/token-identifier token-target'))) (t/is (empty? (:strokes rect-without-stroke'))))))))))) (t/deftest test-toggle-token-none @@ -260,10 +303,10 @@ rect-2' (cths/get-shape file' :rect-2)] (t/is (some? (:applied-tokens rect-1'))) (t/is (some? (:applied-tokens rect-2'))) - (t/is (= (:rx (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:rx (:applied-tokens rect-2')) (:id token-2'))) - (t/is (= (:ry (:applied-tokens rect-1')) (:id token-2'))) - (t/is (= (:ry (:applied-tokens rect-2')) (:id token-2'))) + (t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2'))) + (t/is (= (:rx (:applied-tokens rect-2')) (wtt/token-identifier token-2'))) + (t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2'))) + (t/is (= (:ry (:applied-tokens rect-2')) (wtt/token-identifier token-2'))) (t/is (= (:rx rect-1') 24)) (t/is (= (:rx rect-2') 24))))))))) @@ -327,10 +370,10 @@ rect-with-other-token-2' (cths/get-shape file' :rect-3)] (t/testing "token got applied to all shapes" - (t/is (= (:rx (:applied-tokens rect-with-other-token-1')) (:id target-token))) - (t/is (= (:rx (:applied-tokens rect-without-token')) (:id target-token))) - (t/is (= (:rx (:applied-tokens rect-with-other-token-2')) (:id target-token))) + (t/is (= (:rx (:applied-tokens rect-with-other-token-1')) (wtt/token-identifier target-token))) + (t/is (= (:rx (:applied-tokens rect-without-token')) (wtt/token-identifier target-token))) + (t/is (= (:rx (:applied-tokens rect-with-other-token-2')) (wtt/token-identifier target-token))) - (t/is (= (:ry (:applied-tokens rect-with-other-token-1')) (:id target-token))) - (t/is (= (:ry (:applied-tokens rect-without-token')) (:id target-token))) - (t/is (= (:ry (:applied-tokens rect-with-other-token-2')) (:id target-token))))))))))) + (t/is (= (:ry (:applied-tokens rect-with-other-token-1')) (wtt/token-identifier target-token))) + (t/is (= (:ry (:applied-tokens rect-without-token')) (wtt/token-identifier target-token))) + (t/is (= (:ry (:applied-tokens rect-with-other-token-2')) (wtt/token-identifier target-token))))))))))) From 2d67a92d6485b9f003e05a43e2bd47bc8afd1184 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 11:39:58 +0200 Subject: [PATCH 10/24] Fix getter --- frontend/src/app/main/ui/workspace/tokens/form.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 400e2b6cc..452190628 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -104,7 +104,7 @@ Token names should only contain letters and digits separated by . characters.")} (-> (sd/resolve-tokens+ new-tokens #_ {:debug? true}) (p/then (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-id)] + (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)] (cond resolved-value (p/resolved resolved-token) (sd/missing-reference-error? errors) (p/rejected :error/token-missing-reference) From 8b8b909fb7255bc2ecee445a5e6dbf94293c16f9 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 15:12:28 +0200 Subject: [PATCH 11/24] Parse values with unit --- .../ui/workspace/tokens/style_dictionary.cljs | 16 ++++++++------ .../app/main/ui/workspace/tokens/token.cljs | 11 +++++----- frontend/test/token_tests/token_test.cljs | 21 ++++++++++++------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index fd0fe6d36..81881d810 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -6,8 +6,7 @@ [app.main.ui.workspace.tokens.token :as wtt] [cuerdas.core :as str] [promesa.core :as p] - [rumext.v2 :as mf] - [shadow.resource])) + [rumext.v2 :as mf])) (def StyleDictionary "The global StyleDictionary instance used as an external library for now, @@ -82,10 +81,12 @@ (fn [acc ^js cur] (let [id (uuid (.-uuid (.-id cur))) origin-token (get tokens id) - resolved-value (wtt/parse-token-value (.-value cur)) - resolved-token (if (not resolved-value) + parsed-value (wtt/parse-token-value (.-value cur)) + resolved-token (if (not parsed-value) (assoc origin-token :errors [:style-dictionary/missing-reference]) - (assoc origin-token :resolved-value resolved-value))] + (assoc origin-token + :resolved-value (:value parsed-value) + :resolved-unit (:unit parsed-value)))] (assoc acc (wtt/token-identifier resolved-token) resolved-token))) {} sd-tokens)] (when debug? @@ -157,9 +158,12 @@ (#(resolve-sd-tokens+ % {:debug? true}))) + (defonce output (atom nil)) + (require '[shadow.resource]) (let [example (-> (shadow.resource/inline "./data/example-tokens-set.json") (js/JSON.parse) .-core)] - (resolve-sd-tokens+ example {:debug? true})) + (.then (resolve-sd-tokens+ example {:debug? true}) + #(reset! output %))) nil) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index a64129537..aabfdf412 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -5,14 +5,15 @@ [cuerdas.core :as str])) (def parseable-token-value-regexp - #"^\s*(-?[0-9]+\.?[0-9]*)\s*$") + #"^\s*(-?[0-9]+\.?[0-9]*)(px|%)?\s*$") (defn parse-token-value [value] (cond - (number? value) value - (string? value) (when-let [double-str (-> (re-find parseable-token-value-regexp value) - (last))] - (d/parse-double double-str)))) + (number? value) {:value value} + (string? value) (when-let [[_ value unit] (re-find parseable-token-value-regexp value)] + (when-let [parsed-value (d/parse-double value)] + {:value parsed-value + :unit unit})))) (defn find-token-references "Finds token reference values in `value-string` and returns a set with all contained namespaces." diff --git a/frontend/test/token_tests/token_test.cljs b/frontend/test/token_tests/token_test.cljs index 77cb674ae..4b38c889c 100644 --- a/frontend/test/token_tests/token_test.cljs +++ b/frontend/test/token_tests/token_test.cljs @@ -11,14 +11,19 @@ (t/deftest test-parse-token-value (t/testing "parses double from a token value" - (t/is (= 100.1 (wtt/parse-token-value "100.1"))) - (t/is (= -9 (wtt/parse-token-value "-9"))) - (t/testing "trims white-space" - (t/is (= -1.3 (wtt/parse-token-value " -1.3 ")))) - (t/testing "returns nil for any invalid characters" - (t/is (nil? (wtt/parse-token-value " -1.3a ")))) - (t/testing "doesnt accept invalid double" - (t/is (nil? (wtt/parse-token-value ".3")))))) + (t/is (= {:value 100.1 :unit nil} (wtt/parse-token-value "100.1"))) + (t/is (= {:value -9 :unit nil} (wtt/parse-token-value "-9")))) + (t/testing "trims white-space" + (t/is (= {:value -1.3 :unit nil} (wtt/parse-token-value " -1.3 ")))) + (t/testing "parses unit: px" + (t/is (= {:value 70.3 :unit "px"} (wtt/parse-token-value " 70.3px ")))) + (t/testing "parses unit: %" + (t/is (= {:value -10 :unit "%"} (wtt/parse-token-value "-10%")))) + (t/testing "parses unit: px") + (t/testing "returns nil for any invalid characters" + (t/is (nil? (wtt/parse-token-value " -1.3a ")))) + (t/testing "doesnt accept invalid double" + (t/is (nil? (wtt/parse-token-value ".3"))))) (t/deftest find-token-references (t/testing "finds references inside curly braces in a string" From e992bf0aa6bf4f61ac30b7f8e4d6cd9f99e5f29d Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 8 Aug 2024 15:13:04 +0200 Subject: [PATCH 12/24] Fix sizing test --- .../token_tests/logic/token_actions_test.cljs | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/frontend/test/token_tests/logic/token_actions_test.cljs b/frontend/test/token_tests/logic/token_actions_test.cljs index 17c16bece..e0d3fac38 100644 --- a/frontend/test/token_tests/logic/token_actions_test.cljs +++ b/frontend/test/token_tests/logic/token_actions_test.cljs @@ -147,33 +147,33 @@ (t/is (= (:width rect-1') 100)) (t/is (= (:height rect-1') 100)))))))))) -;; (t/deftest test-apply-sizing -;; (t/testing "applies sizing token and updates the shapes width and height" -;; (t/async -;; done -;; (let [file (-> (setup-file) -;; (toht/add-token :token-target {:value "100" -;; :name "sizing.sm" -;; :type :sizing})) -;; store (ths/setup-store file) -;; rect-1 (cths/get-shape file :rect-1) -;; events [(wtch/apply-token {:shape-ids [(:id rect-1)] -;; :attributes #{:width :height} -;; :token (toht/get-token file :token-target) -;; :on-update-shape wtch/update-shape-dimensions})]] -;; (tohs/run-store-async -;; store done events -;; (fn [new-state] -;; (let [file' (ths/get-file-from-store new-state) -;; token-target' (toht/get-token file' :token-target) -;; rect-1' (cths/get-shape file' :rect-1)] -;; (t/testing "shape `:applied-tokens` got updated" -;; (t/is (some? (:applied-tokens rect-1'))) -;; (t/is (= (:width (:applied-tokens rect-1')) (wtt/token-identifier token-target'))) -;; (t/is (= (:height (:applied-tokens rect-1')) (wtt/token-identifier token-target')))) -;; (t/testing "shapes width and height got updated" -;; (t/is (= (:width rect-1') 100)) -;; (t/is (= (:height rect-1') 100)))))))))) +(t/deftest test-apply-sizing + (t/testing "applies sizing token and updates the shapes width and height" + (t/async + done + (let [file (-> (setup-file) + (toht/add-token :token-target {:value "100" + :name "sizing.sm" + :type :sizing})) + store (ths/setup-store file) + rect-1 (cths/get-shape file :rect-1) + events [(wtch/apply-token {:shape-ids [(:id rect-1)] + :attributes #{:width :height} + :token (toht/get-token file :token-target) + :on-update-shape wtch/update-shape-dimensions})]] + (tohs/run-store-async + store done events + (fn [new-state] + (let [file' (ths/get-file-from-store new-state) + token-target' (toht/get-token file' :token-target) + rect-1' (cths/get-shape file' :rect-1)] + (t/testing "shape `:applied-tokens` got updated" + (t/is (some? (:applied-tokens rect-1'))) + (t/is (= (:width (:applied-tokens rect-1')) (wtt/token-identifier token-target'))) + (t/is (= (:height (:applied-tokens rect-1')) (wtt/token-identifier token-target')))) + (t/testing "shapes width and height got updated" + (t/is (= (:width rect-1') 100)) + (t/is (= (:height rect-1') 100)))))))))) (t/deftest test-apply-opacity (t/testing "applies opacity token and updates the shapes opacity" From 5552295d61fe43ed59f5f0f79ef9b8e2db13fb85 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 9 Aug 2024 17:37:36 +0200 Subject: [PATCH 13/24] Add docstring --- frontend/src/app/main/ui/workspace/tokens/token.cljs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/token.cljs b/frontend/src/app/main/ui/workspace/tokens/token.cljs index aabfdf412..9c0efd356 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token.cljs @@ -5,9 +5,14 @@ [cuerdas.core :as str])) (def parseable-token-value-regexp + "Regexp that can be used to parse a number value out of resolved token value. + This regexp also trims whitespace around the value." #"^\s*(-?[0-9]+\.?[0-9]*)(px|%)?\s*$") -(defn parse-token-value [value] +(defn parse-token-value + "Parses a resolved value and separates the unit from the value. + Returns a map of {:value `number` :unit `string`}." + [value] (cond (number? value) {:value value} (string? value) (when-let [[_ value unit] (re-find parseable-token-value-regexp value)] From 9ff4567955766a9fcf34ac993c78f65823f3f882 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 9 Aug 2024 18:03:20 +0200 Subject: [PATCH 14/24] Remove unused function --- frontend/src/app/main/data/tokens.cljs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/frontend/src/app/main/data/tokens.cljs b/frontend/src/app/main/data/tokens.cljs index 84c83ef0a..3cce3bbc8 100644 --- a/frontend/src/app/main/data/tokens.cljs +++ b/frontend/src/app/main/data/tokens.cljs @@ -80,17 +80,6 @@ (apply-token-to-shape props) shape)) -(defn update-token-from-attributes - [{:keys [token-id shape-id attributes]}] - (ptk/reify ::update-token-from-attributes - ptk/WatchEvent - (watch [_ state _] - (let [shape (get-shape-from-state shape-id state) - applied-tokens (apply-token-id-to-attributes {:shape shape - :token-id token-id - :attributes attributes})] - (rx/of (update-shape shape-id {:applied-tokens applied-tokens})))))) - (defn get-token-data-from-token-id [id] (let [workspace-data (deref refs/workspace-data)] From 51a27c07ec28d4f244a2ee66c95af37e4e217bb8 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 9 Aug 2024 18:03:47 +0200 Subject: [PATCH 15/24] Use token identifier --- frontend/src/app/main/data/tokens.cljs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/main/data/tokens.cljs b/frontend/src/app/main/data/tokens.cljs index 3cce3bbc8..a27c7f30c 100644 --- a/frontend/src/app/main/data/tokens.cljs +++ b/frontend/src/app/main/data/tokens.cljs @@ -16,6 +16,7 @@ [app.main.data.workspace.shapes :as dwsh] [app.main.refs :as refs] [app.main.ui.workspace.tokens.common :refer [workspace-shapes]] + [app.main.ui.workspace.tokens.token :as wtt] [beicon.v2.core :as rx] [clojure.data :as data] [cuerdas.core :as str] @@ -55,22 +56,22 @@ (first))] shape)) -(defn token-from-attributes [token-id attributes] - (->> (map (fn [attr] [attr token-id]) attributes) +(defn token-from-attributes [token attributes] + (->> (map (fn [attr] [attr (wtt/token-identifier token)]) attributes) (into {}))) (defn unapply-token-id [shape attributes] (update shape :applied-tokens d/without-keys attributes)) -(defn apply-token-id-to-attributes [{:keys [shape token-id attributes]}] - (let [token (token-from-attributes token-id attributes)] +(defn apply-token-to-attributes [{:keys [shape token attributes]}] + (let [token (token-from-attributes token attributes)] (toggle-or-apply-token shape token))) (defn apply-token-to-shape [{:keys [shape token attributes] :as _props}] - (let [applied-tokens (apply-token-id-to-attributes {:shape shape - :token-id (:id token) - :attributes attributes})] + (let [applied-tokens (apply-token-to-attributes {:shape shape + :token token + :attributes attributes})] (update shape :applied-tokens #(merge % applied-tokens)))) (defn maybe-apply-token-to-shape From 726b0a26713d5200592df78ce6d10907f44afd31 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Fri, 9 Aug 2024 18:04:33 +0200 Subject: [PATCH 16/24] Fix :applied-tokens not being updated --- .../app/main/ui/workspace/sidebar/options/menus/measures.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs index 05efc28a4..e786b1141 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs @@ -300,7 +300,7 @@ (update-fn shape) shape)) {:reg-objects? true - :attrs [:rx :ry :r1 :r2 :r3 :r4]}))) + :attrs [:rx :ry :r1 :r2 :r3 :r4 :applied-tokens]}))) on-switch-to-radius-1 (mf/use-fn From cf9ef2ae6038734557fe1a3c4ff8d4eb703afae7 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 14 Aug 2024 15:33:24 +0200 Subject: [PATCH 17/24] Remove unused function --- frontend/src/app/main/ui/workspace/tokens/changes.cljs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index 45ff044df..fa3efb718 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -148,15 +148,6 @@ (rx/of (dwsl/update-layout layout-shape-ids layout-attributes)))))) -(defn update-layout-spacing-column [value shape-ids] - (ptk/reify ::update-layout-spacing-column - ptk/WatchEvent - (watch [_ _ _] - (rx/concat - (for [shape-id shape-ids] - (let [layout-update {:layout-gap {:column-gap value :row-gap value}}] - (dwsl/update-layout [shape-id] layout-update))))))) - (defn update-shape-position [value shape-ids attributes] (ptk/reify ::update-shape-position ptk/WatchEvent From 1ba2acea7c2e296b95f2bbe7d867c5fc52a5b67d Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 14 Aug 2024 16:39:43 +0200 Subject: [PATCH 18/24] Fix crash for applying spacing layout token --- .../options/menus/layout_container.cljs | 25 +++++++++++++------ .../app/main/ui/workspace/tokens/changes.cljs | 3 +++ .../ui/workspace/tokens/context_menu.cljs | 11 ++++---- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index b2f71ae23..294185fe6 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -29,6 +29,8 @@ [app.main.ui.icons :as i] [app.main.ui.workspace.tokens.core :as wtc] [app.main.ui.workspace.tokens.editable-select :refer [editable-select]] + [app.main.ui.workspace.tokens.token :as wtt] + [app.main.ui.workspace.tokens.changes :as wtch] [app.main.ui.workspace.tokens.token-types :as wtty] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] @@ -985,18 +987,25 @@ (mf/use-fn (mf/deps ids) (fn [type prop value] - (let [token-value (wtc/maybe-resolve-token-value value) - val (or token-value (mth/finite value 0))] + (let [token-identifier (wtt/token-identifier value) + val (or token-identifier (mth/finite value 0)) + on-update-shape wtch/update-layout-padding] (cond (and (= type :simple) (= prop :p1)) - (st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val} - :applied-tokens {:padding-p1 (if token-value (:id value) nil) - :padding-p3 (if token-value (:id value) nil)}})) + (if token-identifier + (st/emit! (wtch/apply-token {:shape-ids ids + :attributes #{:p1 :p3} + :token value + :on-update-shape on-update-shape})) + (st/emit! (on-update-shape value ids #{:p1 :p3}))) (and (= type :simple) (= prop :p2)) - (st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val} - :applied-tokens {:padding-p2 (if token-value (:id value) nil) - :padding-p4 (if token-value (:id value) nil)}})) + (if token-identifier + (st/emit! (wtch/apply-token {:shape-ids ids + :attributes #{:p2 :p4} + :token value + :on-update-shape on-update-shape})) + (st/emit! (on-update-shape value ids #{:p2 :p4}))) (some? prop) (st/emit! (dwsl/update-layout ids {:layout-padding {prop val}})))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index fa3efb718..95243ee51 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -136,6 +136,9 @@ (zipmap (repeat value)))] {:layout-gap layout-gap})) +(defn update-layout-padding [value shape-ids attrs] + (dwsl/update-layout shape-ids {:layout-padding (zipmap attrs (repeat value))})) + (defn update-layout-spacing [value shape-ids attributes] (ptk/reify ::update-layout-spacing ptk/WatchEvent diff --git a/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs b/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs index 615f758d4..57e6311d1 100644 --- a/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/context_menu.cljs @@ -81,8 +81,7 @@ (concat [all-action] single-actions))) (defn spacing-attribute-actions [{:keys [token selected-shapes] :as context-data}] - (let [on-update-shape (fn [resolved-value shape-ids attrs] - (dwsl/update-layout shape-ids {:layout-padding (zipmap attrs (repeat resolved-value))})) + (let [on-update-shape-padding wtch/update-layout-padding padding-attrs {:p1 "Top" :p2 "Right" :p3 "Bottom" @@ -105,7 +104,7 @@ :shape-ids shape-ids}] (if all-selected? (st/emit! (wtch/unapply-token props)) - (st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape))))))} + (st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape-padding))))))} {:title "Horizontal" :selected? horizontal-padding-selected? :action (fn [] @@ -116,7 +115,7 @@ horizontal-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attributes)) :else (wtch/apply-token (assoc props :attributes horizontal-attributes - :on-update-shape on-update-shape)))] + :on-update-shape on-update-shape-padding)))] (st/emit! event)))} {:title "Vertical" :selected? vertical-padding-selected? @@ -128,7 +127,7 @@ vertical-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes)) :else (wtch/apply-token (assoc props :attributes vertical-attributes - :on-update-shape on-update-shape)))] + :on-update-shape on-update-shape-padding)))] (st/emit! event)))}] single-padding-items (->> padding-attrs (map (fn [[attr title]] @@ -149,7 +148,7 @@ all-selected? (-> (assoc props :attributes-to-remove all-padding-attrs) (wtch/apply-token)) selected? (wtch/unapply-token props) - :else (-> (assoc props :on-update-shape on-update-shape) + :else (-> (assoc props :on-update-shape on-update-shape-padding) (wtch/apply-token)))] (st/emit! event))})))) gap-items (all-or-sepearate-actions {:attribute-labels {:column-gap "Column Gap" From ecf4fb8bd055fc0be230f85f4ded8da1a53cda96 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Wed, 14 Aug 2024 16:52:46 +0200 Subject: [PATCH 19/24] Fix popover position --- frontend/src/app/main/ui/workspace/tokens/editable_select.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/workspace/tokens/editable_select.scss b/frontend/src/app/main/ui/workspace/tokens/editable_select.scss index c0905cb8d..c404919ec 100644 --- a/frontend/src/app/main/ui/workspace/tokens/editable_select.scss +++ b/frontend/src/app/main/ui/workspace/tokens/editable_select.scss @@ -14,6 +14,7 @@ width: 100%; padding: $s-8; border-radius: $br-8; + position: relative; cursor: pointer; background: transparent; From 6be2ca8491a4ea402d543360a2fab89fd8e4e922 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 15 Aug 2024 09:21:18 +0200 Subject: [PATCH 20/24] Fix resolved value not showing up when editing token --- frontend/src/app/main/ui/workspace/tokens/form.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 452190628..20e1b3dc4 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -177,7 +177,7 @@ Token names should only contain letters and digits separated by . characters.")} ;; Value value-ref (mf/use-var (:value token)) - token-resolve-result (mf/use-state (get-in tokens [(:id token) :resolved-value])) + token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) set-resolve-value (mf/use-callback (fn [token-or-err] (let [v (cond From c6d13af071d82ea401c7d73c5ced00f58d1c0e31 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 15 Aug 2024 09:21:49 +0200 Subject: [PATCH 21/24] Fix validation not working while editing [*] [*] We've passed the resolved tokens to the validation, but the validation needs the original tokens set. --- .../src/app/main/ui/workspace/tokens/form.cljs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index 20e1b3dc4..5e3351940 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -8,14 +8,15 @@ (:require-macros [app.main.style :as stl]) (:require ["lodash.debounce" :as debounce] - [app.main.ui.workspace.tokens.update :as wtu] [app.common.data :as d] [app.main.data.modal :as modal] [app.main.data.tokens :as dt] + [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.workspace.tokens.common :as tokens.common] [app.main.ui.workspace.tokens.style-dictionary :as sd] [app.main.ui.workspace.tokens.token :as wtt] + [app.main.ui.workspace.tokens.update :as wtu] [app.util.dom :as dom] [cuerdas.core :as str] [malli.core :as m] @@ -141,14 +142,15 @@ Token names should only contain letters and digits separated by . characters.")} (mf/defc form {::mf/wrap-props false} [{:keys [token token-type] :as _args}] - (let [tokens (sd/use-resolved-workspace-tokens) + (let [tokens (mf/deref refs/workspace-tokens) + resolved-tokens (sd/use-resolved-tokens tokens) token-path (mf/use-memo (mf/deps (:name token)) #(wtt/token-name->path (:name token))) tokens-tree (mf/use-memo - (mf/deps token-path tokens) + (mf/deps token-path resolved-tokens) (fn [] - (-> (wtt/token-names-tree tokens) + (-> (wtt/token-names-tree resolved-tokens) ;; Allow setting editing token to it's own path (d/dissoc-in token-path)))) @@ -219,7 +221,7 @@ Token names should only contain letters and digits separated by . characters.")} (not valid-description-field?)) on-submit (mf/use-callback - (mf/deps validate-name validate-descripion token tokens) + (mf/deps validate-name validate-descripion token resolved-tokens) (fn [e] (dom/prevent-default e) ;; We have to re-validate the current form values before submitting @@ -236,7 +238,7 @@ Token names should only contain letters and digits separated by . characters.")} (validate-token-value+ {:input final-value :name-value final-name :token token - :tokens tokens})]) + :tokens resolved-tokens})]) (p/finally (fn [result err] ;; The result should be a vector of all resolved validations ;; We do not handle the error case as it will be handled by the components validations From e4e488a9eee087befc68aaede1060d381b239af3 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 15 Aug 2024 10:03:25 +0200 Subject: [PATCH 22/24] Adds style-dictionary test --- .../token_tests/style_dictionary_test.cljs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 frontend/test/token_tests/style_dictionary_test.cljs diff --git a/frontend/test/token_tests/style_dictionary_test.cljs b/frontend/test/token_tests/style_dictionary_test.cljs new file mode 100644 index 000000000..f15870a60 --- /dev/null +++ b/frontend/test/token_tests/style_dictionary_test.cljs @@ -0,0 +1,37 @@ +(ns token-tests.style-dictionary-test + (:require + [app.main.ui.workspace.tokens.style-dictionary :as sd] + [cljs.test :as t :include-macros true] + [promesa.core :as p])) + +(def border-radius-token + {:id #uuid "8c868278-7c8d-431b-bbc9-7d8f15c8edb9" + :value "12" + :name "borderRadius.sm" + :type :border-radius}) + +(def reference-border-radius-token + {:id #uuid "b9448d78-fd5b-4e3d-aa32-445904063f5b" + :value "{borderRadius.sm} * 2" + :name "borderRadius.md-with-dashes" + :type :border-radius}) + +(def tokens {(:id border-radius-token) border-radius-token + (:id reference-border-radius-token) reference-border-radius-token}) + +(t/deftest resolve-tokens-test + (t/async + done + (t/testing "resolves tokens using style-dictionary" + (-> (sd/resolve-tokens+ tokens) + (p/finally (fn [resolved-tokens] + (let [expected-tokens {"borderRadius.sm" + (assoc border-radius-token + :resolved-value 12 + :resolved-unit nil) + "borderRadius.md-with-dashes" + (assoc reference-border-radius-token + :resolved-value 24 + :resolved-unit nil)}] + (t/is (= expected-tokens resolved-tokens)) + (done)))))))) From 4bd3b14adbe6c1b98cbbd4fa177c9c8887305851 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 15 Aug 2024 10:07:12 +0200 Subject: [PATCH 23/24] Add unit to tests --- frontend/test/token_tests/style_dictionary_test.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/test/token_tests/style_dictionary_test.cljs b/frontend/test/token_tests/style_dictionary_test.cljs index f15870a60..cc96abe1b 100644 --- a/frontend/test/token_tests/style_dictionary_test.cljs +++ b/frontend/test/token_tests/style_dictionary_test.cljs @@ -6,7 +6,7 @@ (def border-radius-token {:id #uuid "8c868278-7c8d-431b-bbc9-7d8f15c8edb9" - :value "12" + :value "12px" :name "borderRadius.sm" :type :border-radius}) @@ -28,10 +28,10 @@ (let [expected-tokens {"borderRadius.sm" (assoc border-radius-token :resolved-value 12 - :resolved-unit nil) + :resolved-unit "px") "borderRadius.md-with-dashes" (assoc reference-border-radius-token :resolved-value 24 - :resolved-unit nil)}] + :resolved-unit "px")}] (t/is (= expected-tokens resolved-tokens)) (done)))))))) From 43e064a768b3fea692120c13574f3585f08d9e79 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 15 Aug 2024 10:12:45 +0200 Subject: [PATCH 24/24] Update doc string --- .../src/app/main/ui/workspace/tokens/style_dictionary.cljs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 81881d810..3ce334a02 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -9,9 +9,8 @@ [rumext.v2 :as mf])) (def StyleDictionary - "The global StyleDictionary instance used as an external library for now, - as the package would need webpack to be bundled, - because shadow-cljs doesn't support some of the more modern bundler features." + "Initiates the global StyleDictionary instance with transforms + from tokens-studio used to parse and resolved token values." (do (sd-transforms/registerTransforms sd) (.registerFormat sd #js {:name "custom/json"