0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-11 07:11:32 -05:00

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
: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))

View file

@ -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]

View file

@ -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")

View file

@ -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`."

View file

@ -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

View file

@ -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