🎉 Rename token group (#8275)

* 🎉 Rename token group

* 📎 Add to CHANGES
This commit is contained in:
Xaviju
2026-03-19 22:54:21 +01:00
committed by GitHub
parent 8e7e6ffc2f
commit f8913c755d
22 changed files with 687 additions and 59 deletions

View File

@@ -147,6 +147,27 @@
#(and (some? tokens-tree)
(not (ctob/token-name-path-exists? % tokens-tree)))]])
(defn make-node-token-name-schema
"Dynamically generates a schema to check a token node name, adding translated error messages
and two additional validations:
- Min and max length.
- Checks if other token with a path derived from the name already exists at `tokens-tree`.
e.g. it's not allowed to create a token `foo.bar` if a token `foo` already exists."
[active-tokens tokens-tree node]
[:and
[:string {:min 1 :max 255 :error/fn #(str (:value %) (tr "workspace.tokens.token-name-length-validation-error"))}]
(-> cto/schema:token-node-name
(sm/update-properties assoc :error/fn #(str (:value %) (tr "workspace.tokens.token-name-validation-error"))))
[:fn {:error/fn #(tr "workspace.tokens.token-name-duplication-validation-error" (:value %))}
(fn [name]
(let [current-path (:path node)
current-name (:name node)
new-tokens (ctob/update-tokens-group active-tokens current-path current-name name)]
(and (some? new-tokens)
(some (fn [[token-name _]]
(not (ctob/token-name-path-exists? token-name tokens-tree)))
new-tokens))))]])
(def schema:token-description
[:string {:max 2048 :error/fn #(tr "errors.field-max-length" 2048)}])
@@ -165,6 +186,11 @@
(when (and name value)
(not (cto/token-value-self-reference? name value))))]])
(defn make-node-token-schema
[active-tokens tokens-tree node]
[:map
[:name (make-node-token-name-schema active-tokens tokens-tree node)]])
(defn convert-dtcg-token
"Convert token attributes as they come from a decoded json, with DTCG types, to internal types.
Eg. From this:

View File

@@ -136,6 +136,9 @@
(def token-name-validation-regex
#"^[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*$")
(def token-node-name-validation-regex
#"^[a-zA-Z0-9_-][a-zA-Z0-9$_-]*(\.[a-zA-Z0-9$_-]+)*$")
(def schema:token-name
"A token name can contains letters, numbers, underscores the character $ and dots, but
not start with $ or end with a dot. The $ character does not have any special meaning,
@@ -153,6 +156,14 @@
:gen/gen sg/text}
token-ref-validation-regex])
(def schema:token-node-name
"A token node name can contains letters, numbers, underscores and the character $, but
not start with $ or a dot, or end with a dot. The $ character does not have any special meaning,
but dots separate token groups (e.g. color.primary.background)."
[:re {:title "TokenNodeName"
:gen/gen sg/text}
token-node-name-validation-regex])
(def schema:token-type
[::sm/one-of {:decode/json (fn [type]
(if (string? type)

View File

@@ -153,6 +153,18 @@
tokens)]
(group-by :type tokens')))
(defn rename-path
"Renames a node or token path segment with a new name.
If token is provided, it renames a token path, otherwise it renames a node path."
([node new-name]
(rename-path node nil new-name))
([node token new-name]
(let [element (if token (:name token) (:path node))
split-path (cpn/split-path element :separator ".")
updated-split-element-name (assoc split-path (:depth node) new-name)
new-element-path (cpn/join-path updated-split-element-name :separator "." :with-spaces? false)]
new-element-path)))
;; === Token Set
(defprotocol ITokenSet
@@ -1490,6 +1502,30 @@ Will return a value that matches this schema:
(seq)
(boolean)))))
(defn update-tokens-group
"Updates the active tokens path when renaming a group node.
- Filters tokens whose path matches the current path prefix
- Replaces the token name with the new name
- Updates the :path value in the token object
active-tokens: map of token-name to token-object for all active tokens in the set
current-path: the path of the group being renamed, e.g. \"foo.bar\"
current-name: the current name of the group being renamed, e.g. \"bar\"
new-name: the new name for the group being renamed, e.g. \"baz\""
[active-tokens current-path current-name new-name]
(let [path-prefix (str/replace current-path current-name "")]
(mapv (fn [[token-path token-obj]]
(if (str/starts-with? token-path path-prefix)
(let [new-token-path (str/replace token-path current-name new-name)
new-token-obj (-> token-obj
(assoc :name new-token-path)
(cond-> (:path token-obj)
(assoc :path (str/replace (:path token-obj) current-name new-name))))]
[new-token-path new-token-obj])
[token-path token-obj]))
active-tokens)))
;; === Import / Export from JSON format
;; Supported formats: