From ba87ea1a4462ce1376bb798ec0ac9b234f22c563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 18 Feb 2026 10:40:08 +0100 Subject: [PATCH] :wrench: Add tokenscript flag and more validations to token values --- common/src/app/common/data.cljc | 15 ++++++ common/src/app/common/files/tokens.cljc | 53 ++++++++++++++++--- common/src/app/common/types/token.cljc | 9 ++++ frontend/src/app/main/data/tokenscript.cljs | 6 +++ .../data/workspace/tokens/import_export.cljs | 24 +++++---- .../data/workspace/tokens/propagation.cljs | 14 +++-- .../main/ui/workspace/tokens/management.cljs | 3 +- .../forms/controls/color_input.cljs | 12 +++-- .../forms/controls/fonts_combobox.cljs | 35 ++++++------ .../management/forms/controls/input.cljs | 5 +- .../tokens/management/forms/generic_form.cljs | 12 ++--- .../tokens/management/forms/shadow.cljs | 2 +- .../tokens/management/forms/typography.cljs | 2 +- .../tokens/management/forms/validators.cljs | 18 +++++-- .../tokens/management/token_pill.cljs | 3 +- frontend/src/app/plugins/tokens.cljs | 29 +++++----- 16 files changed, 170 insertions(+), 72 deletions(-) diff --git a/common/src/app/common/data.cljc b/common/src/app/common/data.cljc index e89f7c91da..4cb6cedc60 100644 --- a/common/src/app/common/data.cljc +++ b/common/src/app/common/data.cljc @@ -760,6 +760,21 @@ default v)))) +(defn percent? + [v] + (str/numeric? (str/rtrim v "%"))) + +(defn parse-percent + ([v] + (parse-percent v nil)) + ([v default] + (if (str/ends-with? v "%") + (let [v (impl-parse-double (str/trim v "%"))] + (if (or (nil? v) (nan? v)) + default + (/ v 100))) + (parse-double v default)))) + (defn parse-uuid [v] (try diff --git a/common/src/app/common/files/tokens.cljc b/common/src/app/common/files/tokens.cljc index 2da869cccf..e8f1208058 100644 --- a/common/src/app/common/files/tokens.cljc +++ b/common/src/app/common/files/tokens.cljc @@ -31,18 +31,56 @@ (def schema:token-value-generic [::sm/text {:error/fn token-value-empty-fn}]) +(def schema:token-value-numeric + [:and + [::sm/text {:error/fn token-value-empty-fn}] + [:fn {:error/fn #(tr "workspace.tokens.invalid-value" (:value %))} + (fn [value] + (if (str/numeric? value) + (let [n (d/parse-double value)] + (some? n)) + true))]]) ;; Leave references or formulas to be checked by the resolver + +(def schema:token-value-percent + [:and + [::sm/text {:error/fn token-value-empty-fn}] + [:fn {:error/fn #(tr "workspace.tokens.value-with-percent" (:value %))} + (fn [value] + (if (d/percent? value) + (let [v (d/parse-percent value)] + (some? v)) + true))]]) ;; Leave references or formulas to be checked by the resolver + (def schema:token-value-composite-ref [::sm/text {:error/fn token-value-empty-fn}]) +(def schema:token-value-opacity + [:and + [::sm/text {:error/fn token-value-empty-fn}] + [:fn {:error/fn #(tr "workspace.tokens.opacity-range")} + (fn [opacity] + (if (str/numeric? opacity) + (let [n (d/parse-percent opacity)] + (and (some? n) (<= 0 n 1))) + true))]]) ;; Leave references or formulas to be checked by the resolver + (def schema:token-value-font-family - [:vector ::sm/text]) + [:or + [:vector ::sm/text] + cto/schema:token-ref]) + +(def schema:token-value-font-weight + [:or + [:fn {:error/fn #(tr "workspace.tokens.invalid-font-weight-token-value")} + cto/valid-font-weight-variant] + ::sm/text]) ;; Leave references or formulas to be checked by the resolver (def schema:token-value-typography-map [:map [:font-family {:optional true} schema:token-value-font-family] - [:font-weight {:optional true} schema:token-value-generic] - [:font-size {:optional true} schema:token-value-generic] - [:line-height {:optional true} schema:token-value-generic] + [:font-size {:optional true} schema:token-value-numeric] + [:font-weight {:optional true} schema:token-value-font-weight] + [:line-height {:optional true} schema:token-value-percent] [:letter-spacing {:optional true} schema:token-value-generic] [:paragraph-spacing {:optional true} schema:token-value-generic] [:text-decoration {:optional true} schema:token-value-generic] @@ -84,7 +122,10 @@ [token-type] [:multi {:dispatch (constantly token-type) :title "Token Value"} + [:opacity schema:token-value-opacity] [:font-family schema:token-value-font-family] + [:font-size schema:token-value-numeric] + [:font-weight schema:token-value-font-weight] [:typography schema:token-value-typography] [:shadow schema:token-value-shadow] [::m/default schema:token-value-generic]]) @@ -169,7 +210,7 @@ [tokens-lib set-id] [:and [:string {:min 1 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}] - [:fn {:error/fn #(tr "errors.token-set-already-exists" (:value %))} + [:fn {:error/fn #(tr "errors.token-set-already-exists")} (fn [name] (or (nil? tokens-lib) (let [set (ctob/get-set-by-name tokens-lib name)] @@ -196,7 +237,7 @@ [tokens-lib name theme-id] [:and [:string {:min 0 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}] - [:fn {:error/fn #(tr "errors.token-theme-already-exists" (:value %))} + [:fn {:error/fn #(tr "errors.token-theme-already-exists")} (fn [group] (or (nil? tokens-lib) (let [theme (ctob/get-theme-by-name tokens-lib group name)] diff --git a/common/src/app/common/types/token.cljc b/common/src/app/common/types/token.cljc index 5f307ed223..e3e541da33 100644 --- a/common/src/app/common/types/token.cljc +++ b/common/src/app/common/types/token.cljc @@ -143,6 +143,15 @@ :gen/gen sg/text} token-name-validation-regex]) +(def token-ref-validation-regex + #"^\{[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*\}$") + +(def schema:token-ref + "A token reference is a token name enclosed in {}." + [:re {:title "TokenRef" + :gen/gen sg/text} + token-ref-validation-regex]) + (def schema:token-type [::sm/one-of {:decode/json (fn [type] (if (string? type) diff --git a/frontend/src/app/main/data/tokenscript.cljs b/frontend/src/app/main/data/tokenscript.cljs index 83a09d35e8..22e07efc66 100644 --- a/frontend/src/app/main/data/tokenscript.cljs +++ b/frontend/src/app/main/data/tokenscript.cljs @@ -69,6 +69,10 @@ (and (number-with-unit-symbol? v) (= (.-unit v) "rem"))) +(defn percent-number-with-unit? [v] + (and (number-with-unit-symbol? v) + (= (.-unit v) "%"))) + (defn rem->px [^js v] (* (.-value v) 16)) @@ -87,10 +91,12 @@ (defn tokenscript-symbols->penpot-unit [^js v] (cond + (nil? v) nil (structured-token? v) (structured-token->penpot-map v) (list-symbol? v) (structured-token->penpot-map v) (color-symbol? v) (.-value (.to v "hex")) (rem-number-with-unit? v) (rem->px v) + (percent-number-with-unit? v) (/ (.-value v) 100) :else (.-value v))) ;; Processors ------------------------------------------------------------------ diff --git a/frontend/src/app/main/data/workspace/tokens/import_export.cljs b/frontend/src/app/main/data/workspace/tokens/import_export.cljs index 7370da7921..32ba61fd70 100644 --- a/frontend/src/app/main/data/workspace/tokens/import_export.cljs +++ b/frontend/src/app/main/data/workspace/tokens/import_export.cljs @@ -8,10 +8,11 @@ (:require [app.common.json :as json] [app.common.path-names :as cpn] - [app.common.types.tokens-lib :as ctob] + [app.config :as cf] [app.main.data.notifications :as ntf] [app.main.data.style-dictionary :as sd] + [app.main.data.tokenscript :as ts] [app.main.data.workspace.tokens.errors :as wte] [app.main.store :as st] [app.util.i18n :refer [tr]] @@ -74,15 +75,18 @@ (when unknown-tokens (st/emit! (show-unknown-types-warning unknown-tokens))) (try - (->> (ctob/get-all-tokens-map tokens-lib) - (sd/resolve-tokens-with-verbose-errors) - (rx/map (fn [_] - tokens-lib)) - (rx/catch (fn [sd-error] - (let [reference-errors (extract-reference-errors sd-error)] - (if reference-errors - (rx/of tokens-lib) - (throw (wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error))))))) + (let [tokens-tree (ctob/get-all-tokens-map tokens-lib) + resolved-tokens (if (contains? cf/flags :tokenscript) + (rx/of (ts/resolve-tokens tokens-tree)) + (sd/resolve-tokens-with-verbose-errors tokens-tree))] + (->> resolved-tokens + (rx/map (fn [_] + tokens-lib)) + (rx/catch (fn [sd-error] + (let [reference-errors (extract-reference-errors sd-error)] + (if reference-errors + (rx/of tokens-lib) + (throw (wte/error-ex-info :error.import/style-dictionary-unknown-error sd-error sd-error)))))))) (catch js/Error e (throw (wte/error-ex-info :error.import/style-dictionary-unknown-error "" e))))) diff --git a/frontend/src/app/main/data/workspace/tokens/propagation.cljs b/frontend/src/app/main/data/workspace/tokens/propagation.cljs index 7ba5c3970c..97e54a8f0b 100644 --- a/frontend/src/app/main/data/workspace/tokens/propagation.cljs +++ b/frontend/src/app/main/data/workspace/tokens/propagation.cljs @@ -6,13 +6,16 @@ (ns app.main.data.workspace.tokens.propagation (:require + [app.common.data :as d] [app.common.files.helpers :as cfh] [app.common.logging :as l] [app.common.time :as ct] [app.common.types.token :as ctt] [app.common.types.tokens-lib :as ctob] + [app.config :as cf] [app.main.data.helpers :as dsh] [app.main.data.style-dictionary :as sd] + [app.main.data.tokenscript :as ts] [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.thumbnails :as dwt] [app.main.data.workspace.tokens.application :as dwta] @@ -210,10 +213,13 @@ (ptk/reify ::propagate-workspace-tokens ptk/WatchEvent (watch [_ state _] - (when-let [tokens-lib (-> (dsh/lookup-file-data state) - (get :tokens-lib))] - (->> (ctob/get-tokens-in-active-sets tokens-lib) - (sd/resolve-tokens) + (when-let [tokens-tree (-> (dsh/lookup-file-data state) + (get :tokens-lib) + (ctob/get-tokens-in-active-sets))] + (->> (if (contains? cf/flags :tokenscript) + (rx/of (-> (ts/resolve-tokens tokens-tree) + (d/update-vals #(update % :resolved-value ts/tokenscript-symbols->penpot-unit)))) + (sd/resolve-tokens tokens-tree)) (rx/mapcat (fn [sd-tokens] (let [undo-id (js/Symbol)] (rx/concat diff --git a/frontend/src/app/main/ui/workspace/tokens/management.cljs b/frontend/src/app/main/ui/workspace/tokens/management.cljs index 1f124b7b8b..0ff4deafa4 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management.cljs @@ -143,8 +143,7 @@ (let [token-ids (set tokens-in-path-ids) remaining-tokens (filter (fn [token] (not (contains? token-ids (:id token)))) - selected-token-set-tokens) - _ (prn "Remaining tokens:" remaining-tokens)] + selected-token-set-tokens)] (seq remaining-tokens)))) delete-token diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/color_input.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/color_input.cljs index b87bb0d675..c9c2f0aaf0 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/color_input.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/color_input.cljs @@ -13,8 +13,10 @@ [app.common.types.color :as cl] [app.common.types.token :as cto] [app.common.types.tokens-lib :as ctob] + [app.config :as cf] [app.main.data.style-dictionary :as sd] [app.main.data.tinycolor :as tinycolor] + [app.main.data.tokenscript :as ts] [app.main.data.workspace.tokens.format :as dwtf] [app.main.refs :as refs] [app.main.ui.ds.controls.input :as ds] @@ -70,11 +72,15 @@ (dissoc (:name prev-token)) (update (:name token) #(ctob/make-token (merge % prev-token token))))] - (->> tokens - (sd/resolve-tokens-interactive) + (->> (if (contains? cf/flags :tokenscript) + (rx/of (ts/resolve-tokens tokens)) + (sd/resolve-tokens-interactive tokens)) (rx/mapcat (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))] + (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token)) + resolved-value (if (contains? cf/flags :tokenscript) + (ts/tokenscript-symbols->penpot-unit resolved-value) + resolved-value)] (if resolved-value (rx/of {:value resolved-value}) (rx/of {:error (first errors)})))))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/fonts_combobox.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/fonts_combobox.cljs index df76d47113..057419dc9c 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/fonts_combobox.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/fonts_combobox.cljs @@ -10,7 +10,9 @@ [app.common.data :as d] [app.common.types.token :as cto] [app.common.types.tokens-lib :as ctob] + [app.config :as cf] [app.main.data.style-dictionary :as sd] + [app.main.data.tokenscript :as ts] [app.main.fonts :as fonts] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.controls.input :refer [input*]] @@ -49,28 +51,30 @@ ;; validate data within the form state. (defn- resolve-value - [tokens prev-token token-name value] - (let [valid-token-name? - (and (string? token-name) - (re-matches cto/token-name-validation-regex token-name)) + [tokens prev-token _token-name value] + (let [tmp-value (cto/split-font-family value) + tmp-name "__PENPOT__FONT_FAMILY__PLACEHOLDER__" + ;; Create a temporary font-family token to validate the value token - {:value (cto/split-font-family value) - :name (if (or (not valid-token-name?) (str/blank? token-name)) - "__PENPOT__TOKEN__NAME__PLACEHOLDER__" - token-name)} + {:name tmp-name + :type :font-family + :value (if (= (:type prev-token) :typography) + (assoc (:value prev-token) :font-family tmp-value) + tmp-value)} tokens - (-> tokens - ;; Remove previous token when renaming a token - (dissoc (:name prev-token)) - (update (:name token) #(ctob/make-token (merge % prev-token token))))] + (update tokens (:name token) #(ctob/make-token (merge % prev-token token)))] - (->> tokens - (sd/resolve-tokens-interactive) + (->> (if (contains? cf/flags :tokenscript) + (rx/of (ts/resolve-tokens tokens)) + (sd/resolve-tokens-interactive tokens)) (rx/mapcat (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))] + (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token)) + resolved-value (if (contains? cf/flags :tokenscript) + (ts/tokenscript-symbols->penpot-unit resolved-value) + resolved-value)] (if resolved-value (rx/of {:value resolved-value}) (rx/of {:error (first errors)})))))))) @@ -176,7 +180,6 @@ (let [message (tr "workspace.tokens.resolved-value" value)] (swap! form update :extra-errors dissoc input-name) (reset! hint* {:message message :type "hint"})))))))] - (fn [] (rx/dispose! subs)))) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/input.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/input.cljs index 6b177aa243..6ab3f2786b 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/input.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/input.cljs @@ -175,7 +175,10 @@ (sd/resolve-tokens-interactive) (rx/mapcat (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))] + (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token)) + resolved-value (if (contains? cf/flags :tokenscript) + (ts/tokenscript-symbols->penpot-unit resolved-value) + resolved-value)] (if resolved-value (rx/of {:value resolved-value}) (rx/of {:error (first errors)})))))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs index b0f36ec06c..f5541f8a40 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/generic_form.cljs @@ -36,9 +36,9 @@ [rumext.v2 :as mf])) (defn get-value-for-validator - [active-tab value value-subfield form-type] + [active-tab value value-subfield value-type] - (case form-type + (case value-type :indexed (if (= active-tab :reference) (:reference value) @@ -62,7 +62,7 @@ make-schema input-component initial - type + value-type value-subfield input-value-placeholder] :as props}] @@ -178,13 +178,13 @@ on-submit (mf/use-fn - (mf/deps validate-token token tokens token-type value-subfield type active-tab on-remap-token on-rename-token is-create) + (mf/deps validate-token token tokens token-type value-subfield value-type active-tab on-remap-token on-rename-token is-create) (fn [form _event] (let [name (get-in @form [:clean-data :name]) path (str (d/name token-type) "." name) description (get-in @form [:clean-data :description]) value (get-in @form [:clean-data :value]) - value-for-validation (get-value-for-validator active-tab value value-subfield type)] + value-for-validation (get-value-for-validator active-tab value value-subfield value-type)] (->> (validate-token {:token-value value-for-validation :token-name name :token-description description @@ -245,7 +245,7 @@ :auto-focus true}]] [:div {:class (stl/css :input-row)} - (case type + (case value-type :indexed [:> input-component {:token token diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/shadow.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/shadow.cljs index 9bf6fa32a2..722683d54a 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/shadow.cljs @@ -365,7 +365,7 @@ :token-type token-type :initial initial :make-schema make-schema - :type :indexed + :value-type :indexed :value-subfield :shadow :input-component tabs-wrapper* :validator validate-shadow-token})] diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/typography.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/typography.cljs index 37a7fda7ca..cb926f72fd 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/typography.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/typography.cljs @@ -300,6 +300,6 @@ :make-schema make-schema :token token :validator validate-typography-token - :type :composite + :value-type :composite :input-component tabs-wrapper*})] [:> generic/form* props])) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/validators.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/validators.cljs index ab04acbd64..4fb9be3e4f 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/validators.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/validators.cljs @@ -4,7 +4,9 @@ [app.common.schema :as sm] [app.common.types.token :as cto] [app.common.types.tokens-lib :as ctob] + [app.config :as cf] [app.main.data.style-dictionary :as sd] + [app.main.data.tokenscript :as ts] [app.main.data.workspace.tokens.errors :as wte] [beicon.v2.core :as rx] [cuerdas.core :as str])) @@ -36,14 +38,20 @@ :always (update (:name token) #(ctob/make-token (merge % prev-token token))))] - (->> tokens' - (sd/resolve-tokens-interactive) + + (->> (if (contains? cf/flags :tokenscript) + (rx/of (ts/resolve-tokens tokens')) + (sd/resolve-tokens-interactive tokens')) (rx/mapcat (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))] + (let [resolved-token (cond-> (get resolved-tokens (:name token)) + (contains? cf/flags :tokenscript) + (update :resolved-value ts/tokenscript-symbols->penpot-unit))] (cond - resolved-value (rx/of resolved-token) - :else (rx/throw {:errors (or (seq errors) + (:resolved-value resolved-token) + (rx/of resolved-token) + + :else (rx/throw {:errors (or (seq (:errors resolved-token)) [(wte/get-error-code :error/unknown-error)])})))))))) (defn- validate-token-with [token validators] diff --git a/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs index 94ac737ed8..c76651c151 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/token_pill.cljs @@ -176,9 +176,10 @@ (mf/defc token-pill* {::mf/wrap [mf/memo]} [{:keys [on-click token on-context-menu selected-shapes is-selected-inside-layout active-theme-tokens]}] - (let [{:keys [name value errors type]} token + (let [{:keys [name value type]} token resolved-token (get active-theme-tokens (:name token)) + errors (:errors resolved-token) has-selected? (pos? (count selected-shapes)) is-reference? (cfo/is-reference? token) diff --git a/frontend/src/app/plugins/tokens.cljs b/frontend/src/app/plugins/tokens.cljs index f22c1fa128..d7de0689a7 100644 --- a/frontend/src/app/plugins/tokens.cljs +++ b/frontend/src/app/plugins/tokens.cljs @@ -12,14 +12,12 @@ [app.common.types.token :as cto] [app.common.types.tokens-lib :as ctob] [app.common.uuid :as uuid] - [app.main.data.style-dictionary :as sd] [app.main.data.tokenscript :as ts] [app.main.data.workspace.tokens.application :as dwta] [app.main.data.workspace.tokens.library-edit :as dwtl] [app.main.store :as st] [app.plugins.utils :as u] [app.util.object :as obj] - [beicon.v2.core :as rx] [clojure.datafy :refer [datafy]])) ;; === Token @@ -260,20 +258,19 @@ :decode/options {:key-fn identity} :fn (fn [attrs] (let [tokens-lib (u/locate-tokens-lib file-id) - tokens-tree (ctob/get-tokens-in-active-sets tokens-lib) - token (ctob/make-token attrs)] - (->> (assoc tokens-tree (:name token) token) - (sd/resolve-tokens-interactive) - (rx/subs! - (fn [resolved-tokens] - (let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens (:name token))] - (if resolved-value - (st/emit! (dwtl/create-token id token)) - (u/display-not-valid :addToken (str errors))))))) - ;; TODO: as the addToken function is synchronous, we must return the newly created - ;; token even if the validator will throw it away if the resolution fails. - ;; This will be solved with the TokenScript resolver, that is syncronous. - (token-proxy plugin-id file-id id (:id token))))} + token (ctob/make-token attrs) + tokens-tree (-> (ctob/get-tokens-in-active-sets tokens-lib) + (assoc (:name token) token)) + resolved-tokens (ts/resolve-tokens tokens-tree) + + {:keys [errors resolved-value] :as resolved-token} + (get resolved-tokens (:name token))] + + (if resolved-value + (do (st/emit! (dwtl/create-token id token)) + (token-proxy plugin-id file-id id (:id token))) + (do (u/display-not-valid :addToken (str errors)) + nil))))} :duplicate (fn []