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.
This commit is contained in:
Florian Schroedl 2024-08-07 15:14:32 +02:00
parent d8621974c2
commit 252797183c
6 changed files with 82 additions and 73 deletions

View file

@ -47,10 +47,12 @@
:string :string
:typography}) :typography})
(def token-name-ref :string)
(sm/register! ::token (sm/register! ::token
[:map {:title "Token"} [:map {:title "Token"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name token-name-ref]
[:type [::sm/one-of token-types]] [:type [::sm/one-of token-types]]
[:value :any] [:value :any]
[:description {:optional true} :string] [:description {:optional true} :string]
@ -58,48 +60,48 @@
(sm/register! ::border-radius (sm/register! ::border-radius
[:map [:map
[:rx {:optional true} ::sm/uuid] [:rx {:optional true} token-name-ref]
[:ry {:optional true} ::sm/uuid] [:ry {:optional true} token-name-ref]
[:r1 {:optional true} ::sm/uuid] [:r1 {:optional true} token-name-ref]
[:r2 {:optional true} ::sm/uuid] [:r2 {:optional true} token-name-ref]
[:r3 {:optional true} ::sm/uuid] [:r3 {:optional true} token-name-ref]
[:r4 {:optional true} ::sm/uuid]]) [:r4 {:optional true} token-name-ref]])
(def border-radius-keys (schema-keys ::border-radius)) (def border-radius-keys (schema-keys ::border-radius))
(sm/register! ::stroke-width (sm/register! ::stroke-width
[:map [:map
[:stroke-width {:optional true} ::sm/uuid]]) [:stroke-width {:optional true} token-name-ref]])
(def stroke-width-keys (schema-keys ::stroke-width)) (def stroke-width-keys (schema-keys ::stroke-width))
(sm/register! ::sizing (sm/register! ::sizing
[:map [:map
[:width {:optional true} ::sm/uuid] [:width {:optional true} token-name-ref]
[:height {:optional true} ::sm/uuid] [:height {:optional true} token-name-ref]
[:layout-item-min-w {:optional true} ::sm/uuid] [:layout-item-min-w {:optional true} token-name-ref]
[:layout-item-max-w {:optional true} ::sm/uuid] [:layout-item-max-w {:optional true} token-name-ref]
[:layout-item-min-h {:optional true} ::sm/uuid] [:layout-item-min-h {:optional true} token-name-ref]
[:layout-item-max-h {:optional true} ::sm/uuid]]) [:layout-item-max-h {:optional true} token-name-ref]])
(def sizing-keys (schema-keys ::sizing)) (def sizing-keys (schema-keys ::sizing))
(sm/register! ::opacity (sm/register! ::opacity
[:map [:map
[:opacity {:optional true} ::sm/uuid]]) [:opacity {:optional true} token-name-ref]])
(def opacity-keys (schema-keys ::opacity)) (def opacity-keys (schema-keys ::opacity))
(sm/register! ::spacing (sm/register! ::spacing
[:map [:map
[:row-gap {:optional true} ::sm/uuid] [:row-gap {:optional true} token-name-ref]
[:column-gap {:optional true} ::sm/uuid] [:column-gap {:optional true} token-name-ref]
[:p1 {:optional true} ::sm/uuid] [:p1 {:optional true} token-name-ref]
[:p2 {:optional true} ::sm/uuid] [:p2 {:optional true} token-name-ref]
[:p3 {:optional true} ::sm/uuid] [:p3 {:optional true} token-name-ref]
[:p4 {:optional true} ::sm/uuid] [:p4 {:optional true} token-name-ref]
[:x {:optional true} ::sm/uuid] [:x {:optional true} token-name-ref]
[:y {:optional true} ::sm/uuid]]) [:y {:optional true} token-name-ref]])
(def spacing-keys (schema-keys ::spacing)) (def spacing-keys (schema-keys ::spacing))
@ -113,7 +115,7 @@
(sm/register! ::rotation (sm/register! ::rotation
[:map [:map
[:rotation {:optional true} ::sm/uuid]]) [:rotation {:optional true} token-name-ref]])
(def rotation-keys (schema-keys ::rotation)) (def rotation-keys (schema-keys ::rotation))

View file

@ -38,7 +38,7 @@
(let [undo-id (js/Symbol) (let [undo-id (js/Symbol)
resolved-value (-> (get sd-tokens (:id token)) resolved-value (-> (get sd-tokens (:id token))
(wtt/resolve-token-value)) (wtt/resolve-token-value))
tokenized-attributes (wtt/attributes-map attributes (:id token))] tokenized-attributes (wtt/attributes-map attributes token)]
(rx/of (rx/of
(dwu/start-undo-transaction undo-id) (dwu/start-undo-transaction undo-id)
(dwsh/update-shapes shape-ids (fn [shape] (dwsh/update-shapes shape-ids (fn [shape]
@ -58,7 +58,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/of (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 (dwsh/update-shapes
shape-ids shape-ids
(fn [shape] (fn [shape]

View file

@ -86,18 +86,19 @@
[tokens & {:keys [debug?] :as config}] [tokens & {:keys [debug?] :as config}]
(p/let [sd-tokens (-> (wtt/token-names-tree tokens) (p/let [sd-tokens (-> (wtt/token-names-tree tokens)
(resolve-sd-tokens+ config))] (resolve-sd-tokens+ config))]
(let [resolved-tokens (reduce (let [tokens-by-name (wtt/token-names-map tokens)
resolved-tokens (reduce
(fn [acc ^js cur] (fn [acc ^js cur]
(let [value (.-value cur) (let [value (.-value cur)
resolved-value (d/parse-double (.-value cur)) resolved-value (d/parse-double (.-value cur))
original-value (-> cur .-original .-value) original-value (-> cur .-original .-value)
id (uuid (.-uuid (.-id cur))) id (.-name cur)
missing-reference? (and (not resolved-value) missing-reference? (and (not resolved-value)
(re-find #"\{" value) (re-find #"\{" value)
(= value original-value))] (= value original-value))]
(cond-> (assoc-in acc [id :resolved-value] resolved-value) (cond-> (assoc-in acc [id :resolved-value] resolved-value)
missing-reference? (update-in [id :errors] (fnil conj #{}) :style-dictionary/missing-reference)))) missing-reference? (update-in [id :errors] (fnil conj #{}) :style-dictionary/missing-reference))))
tokens sd-tokens)] tokens-by-name sd-tokens)]
(when debug? (when debug?
(js/console.log "Resolved tokens" resolved-tokens)) (js/console.log "Resolved tokens" resolved-tokens))
resolved-tokens))) resolved-tokens)))
@ -157,6 +158,7 @@
(-> (->
(clj->js {"a" {:name "a" :value "5"} (clj->js {"a" {:name "a" :value "5"}
"b" {:name "b" :value "{a} * 2"}}) "b" {:name "b" :value "{a} * 2"}})
(#(resolve-sd-tokens+ % {:debug? true}))) (#(resolve-sd-tokens+ % {:debug? true})))
(let [example (-> (shadow.resource/inline "./data/example-tokens-set.json") (let [example (-> (shadow.resource/inline "./data/example-tokens-set.json")

View file

@ -4,6 +4,9 @@
[clojure.set :as set] [clojure.set :as set]
[cuerdas.core :as str])) [cuerdas.core :as str]))
(defn token-identifier [{:keys [name] :as _token}]
name)
(defn resolve-token-value [{:keys [value resolved-value] :as _token}] (defn resolve-token-value [{:keys [value resolved-value] :as _token}]
(or (or
resolved-value resolved-value
@ -11,17 +14,17 @@
(defn attributes-map (defn attributes-map
"Creats an attributes map using collection of `attributes` for `id`." "Creats an attributes map using collection of `attributes` for `id`."
[attributes id] [attributes token]
(->> (map (fn [attr] {attr id}) attributes) (->> (map (fn [attr] [attr (token-identifier token)]) attributes)
(into {}))) (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`." "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)] (let [attr? (set attributes)]
(->> (remove (fn [[k v]] (->> (remove (fn [[k v]]
(and (attr? k) (and (attr? k)
(= v token-id))) (= v (token-identifier token))))
applied-tokens) applied-tokens)
(into {})))) (into {}))))
@ -29,7 +32,7 @@
"Test if `token` is applied to a `shape` on single `token-attribute`." "Test if `token` is applied to a `shape` on single `token-attribute`."
[token shape token-attribute] [token shape token-attribute]
(when-let [id (get-in shape [:applied-tokens token-attribute])] (when-let [id (get-in shape [:applied-tokens token-attribute])]
(= (:id token) id))) (= (token-identifier token) id)))
(defn token-applied? (defn token-applied?
"Test if `token` is applied to a `shape` with at least one of the one of the given `token-attributes`." "Test if `token` is applied to a `shape` with at least one of the one of the given `token-attributes`."

View file

@ -15,8 +15,8 @@
(defn apply-token-to-shape [file shape-label token-label attributes] (defn apply-token-to-shape [file shape-label token-label attributes]
(let [first-page-id (get-in file [:data :pages 0]) (let [first-page-id (get-in file [:data :pages 0])
shape-id (thi/id shape-label) shape-id (thi/id shape-label)
token-id (thi/id token-label) token (get-token file token-label)
applied-attributes (wtt/attributes-map attributes token-id)] applied-attributes (wtt/attributes-map attributes token)]
(update-in file [:data (update-in file [:data
:pages-index first-page-id :pages-index first-page-id
:objects shape-id :objects shape-id

View file

@ -10,66 +10,68 @@
[cljs.test :as t :include-macros true])) [cljs.test :as t :include-macros true]))
(t/deftest remove-attributes-for-token-id (t/deftest remove-attributes-for-token-id
(t/testing "removes attributes matching the `token-id`, keeps other attributes" (t/testing "removes attributes matching the `token`, keeps other attributes"
(t/is (= {:ry :b} (t/is (= {:ry "b"}
(wtt/remove-attributes-for-token-id (wtt/remove-attributes-for-token #{:rx :ry} {:name "a"} {:rx "a" :ry "b"})))))
#{:rx :ry} :a {:rx :a :ry :b})))))
(t/deftest token-applied-test (t/deftest token-applied-test
(t/testing "matches passed token with `:token-attributes`" (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/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/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/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/deftest token-applied-attributes
(t/is (= #{:x} (wtt/token-applied-attributes {:id :a} (t/is (= #{:x} (wtt/token-applied-attributes {:name "a"}
{:applied-tokens {:x :a :y :b}} {:applied-tokens {:x "a" :y "b"}}
#{:x :missing})))) #{:x :missing}))))
(t/deftest shapes-ids-by-applied-attributes (t/deftest shapes-ids-by-applied-attributes
(t/testing "Returns set of matched attributes that fit the applied token" (t/testing "Returns set of matched attributes that fit the applied token"
(let [attributes #{:x :y :z} (let [attributes #{:x :y :z}
shape-applied-x {:id :shape-applied-x shape-applied-x {:id "shape-applied-x"
:applied-tokens {:x 1}} :applied-tokens {:x "1"}}
shape-applied-y {:id :shape-applied-y shape-applied-y {:id "shape-applied-y"
:applied-tokens {:y 1}} :applied-tokens {:y "1"}}
shape-applied-x-y {:id :shape-applied-x-y shape-applied-x-y {:id "shape-applied-x-y"
:applied-tokens {:x 1 :y 1}} :applied-tokens {:x "1" :y "1"}}
shape-applied-none {:id :shape-applied-none shape-applied-none {:id "shape-applied-none"
:applied-tokens {}} :applied-tokens {}}
shape-applied-all {:id :shape-applied-all shape-applied-all {:id "shape-applied-all"
:applied-tokens {:x 1 :y 1 :z 1}} :applied-tokens {:x "1" :y "1" :z "1"}}
ids-set (fn [& xs] (into #{} (map :id xs))) shape-ids (fn [& xs] (into #{} (map :id xs)))
shapes [shape-applied-x shapes [shape-applied-x
shape-applied-y shape-applied-y
shape-applied-x-y shape-applied-x-y
shape-applied-all shape-applied-all
shape-applied-none] shape-applied-none]
expected (wtt/shapes-ids-by-applied-attributes {:id 1} shapes attributes)] expected (wtt/shapes-ids-by-applied-attributes {:name "1"} shapes attributes)]
(t/is (= (:x expected) (ids-set shape-applied-x (t/is (= (:x expected) (shape-ids shape-applied-x
shape-applied-x-y shape-applied-x-y
shape-applied-all))) shape-applied-all)))
(t/is (= (:y expected) (ids-set shape-applied-y (t/is (= (:y expected) (shape-ids shape-applied-y
shape-applied-x-y shape-applied-x-y
shape-applied-all))) shape-applied-all)))
(t/is (= (:z expected) (ids-set shape-applied-all))) (t/is (= (:z expected) (shape-ids shape-applied-all)))
(t/is (true? (wtt/shapes-applied-all? expected (ids-set shape-applied-all) attributes))) (t/is (true? (wtt/shapes-applied-all? expected (shape-ids shape-applied-all) attributes)))
(t/is (false? (wtt/shapes-applied-all? expected (apply ids-set shapes) 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/deftest tokens-applied-test
(t/testing "is true when single shape matches the token and attributes" (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}} (t/is (true? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}}
{:applied-tokens {:x :b}}] {:applied-tokens {:x "b"}}]
#{:x})))) #{:x}))))
(t/testing "is false when no shape matches the token or attributes" (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}} (t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "b"}}
{:applied-tokens {:x :b}}] {:applied-tokens {:x "b"}}]
#{:x}))) #{:x})))
(t/is (nil? (wtt/shapes-token-applied? {:id :a} [{:applied-tokens {:x :a}} (t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}}
{:applied-tokens {:x :a}}] {:applied-tokens {:x "a"}}]
#{:y}))))) #{:y})))))
(t/deftest name->path-test (t/deftest name->path-test