@kong/design-tokens 1.18.3-pr.613.51bd0cb.0 → 1.18.3-pr.613.857d684.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { KONG_TOKEN_PREFIX, RULE_NAME_PREFIX } from '../../utilities/index.mjs'
4
4
  const { ruleMessages, validateOptions, report } = stylelint.utils
5
5
  const ruleName = `${RULE_NAME_PREFIX}/use-css-token`
6
6
  const messages = ruleMessages(ruleName, {
7
- expected: 'SCSS tokens must be used as fallback values in CSS custom properties. Use format: var(--kui-design-token, $kui-design-token)',
7
+ expected: 'SCSS tokens must be used as fallback values in CSS custom properties. Use format: var(--kui-design-token, $kui-design-token) with exactly one space before the comma and no other spaces.',
8
8
  })
9
9
  const meta = {
10
10
  url: 'https://github.com/Kong/design-tokens/blob/main/stylelint-plugin/README.md',
@@ -17,11 +17,6 @@ const getCssToken = (scssToken) => {
17
17
  return `--${tokenName}`
18
18
  }
19
19
 
20
- // Create regex pattern to match var(--token, $token) format
21
- const createProperUsagePattern = (cssToken, scssToken) => {
22
- return new RegExp(`var\\(\\s*${cssToken}\\s*,\\s*${scssToken}\\s*\\)`)
23
- }
24
-
25
20
  // Find all occurrences of a token in a value
26
21
  const findAllTokenOccurrences = (value, token) => {
27
22
  const occurrences = []
@@ -38,11 +33,26 @@ const findAllTokenOccurrences = (value, token) => {
38
33
  }
39
34
 
40
35
  // Check if token at given position is properly wrapped in var()
41
- const isTokenProperlyWrapped = (value, tokenIndex, token, pattern) => {
42
- const windowStart = Math.max(0, tokenIndex - 100)
43
- const windowEnd = Math.min(value.length, tokenIndex + token.length + 100)
44
- const context = value.substring(windowStart, windowEnd)
45
- return pattern.test(context)
36
+ // Enforces exact format: var(--token, $token) with exactly one space before comma
37
+ const isTokenProperlyWrapped = (value, tokenIndex, token, cssToken) => {
38
+ // Use regex to find all var(--token, $token) patterns
39
+ // Escape special regex characters in tokens (though they should only have letters/digits/hyphens)
40
+ const pattern = new RegExp(`var\\(${cssToken}, ${token}\\)`, 'g')
41
+
42
+ // Find all matches
43
+ let match
44
+ while ((match = pattern.exec(value)) !== null) {
45
+ const matchStart = match.index
46
+ const matchEnd = matchStart + match[0].length
47
+
48
+ // Check if our token at tokenIndex is inside this match
49
+ const tokenEndIndex = tokenIndex + token.length
50
+ if (tokenIndex >= matchStart && tokenEndIndex <= matchEnd) {
51
+ return true
52
+ }
53
+ }
54
+
55
+ return false
46
56
  }
47
57
 
48
58
  const ruleFunction = () => {
@@ -74,12 +84,11 @@ const ruleFunction = () => {
74
84
 
75
85
  uniqueScssTokens.forEach((scssToken) => {
76
86
  const cssToken = getCssToken(scssToken)
77
- const properUsagePattern = createProperUsagePattern(cssToken, scssToken)
78
87
  const tokenOccurrences = findAllTokenOccurrences(declValue, scssToken)
79
88
 
80
89
  // Check each occurrence to see if it's properly wrapped
81
90
  const hasImproperUsage = tokenOccurrences.some((tokenIndex) => {
82
- return !isTokenProperlyWrapped(declValue, tokenIndex, scssToken, properUsagePattern)
91
+ return !isTokenProperlyWrapped(declValue, tokenIndex, scssToken, cssToken)
83
92
  })
84
93
 
85
94
  if (hasImproperUsage) {
@@ -96,19 +105,53 @@ const ruleFunction = () => {
96
105
  // First, identify all positions that need to be replaced
97
106
  improperlyUsedTokens.forEach((scssToken) => {
98
107
  const cssToken = getCssToken(scssToken)
99
- const properUsagePattern = createProperUsagePattern(cssToken, scssToken)
100
108
  const tokenOccurrences = findAllTokenOccurrences(fixedValue, scssToken)
101
109
  const properFormat = `var(${cssToken}, ${scssToken})`
102
110
 
103
- tokenOccurrences.forEach((index) => {
111
+ tokenOccurrences.forEach((tokenIndex) => {
104
112
  // Check if this occurrence is in proper format
105
- if (!isTokenProperlyWrapped(fixedValue, index, scssToken, properUsagePattern)) {
106
- // This occurrence needs to be replaced
107
- replacements.push({
108
- start: index,
109
- end: index + scssToken.length,
110
- replacement: properFormat,
111
- })
113
+ if (!isTokenProperlyWrapped(fixedValue, tokenIndex, scssToken, cssToken)) {
114
+ // Find the var() expression containing this token to replace the whole thing
115
+ const beforeToken = fixedValue.substring(0, tokenIndex)
116
+ const varStartIndex = beforeToken.lastIndexOf('var(')
117
+
118
+ if (varStartIndex === -1) {
119
+ // No var( found, just replace the token with proper format
120
+ replacements.push({
121
+ start: tokenIndex,
122
+ end: tokenIndex + scssToken.length,
123
+ replacement: properFormat,
124
+ })
125
+ return
126
+ }
127
+
128
+ // Find the matching closing parenthesis
129
+ let parenCount = 0
130
+ let searchIndex = varStartIndex
131
+ let varEndIndex = -1
132
+
133
+ while (searchIndex < fixedValue.length) {
134
+ const char = fixedValue[searchIndex]
135
+ if (char === '(') {
136
+ parenCount++
137
+ } else if (char === ')') {
138
+ parenCount--
139
+ if (parenCount === 0) {
140
+ varEndIndex = searchIndex
141
+ break
142
+ }
143
+ }
144
+ searchIndex++
145
+ }
146
+
147
+ if (varEndIndex !== -1) {
148
+ // Replace the entire var() expression
149
+ replacements.push({
150
+ start: varStartIndex,
151
+ end: varEndIndex + 1,
152
+ replacement: properFormat,
153
+ })
154
+ }
112
155
  }
113
156
  })
114
157
  })
@@ -116,8 +159,18 @@ const ruleFunction = () => {
116
159
  // Sort replacements by position (descending) to avoid offset issues
117
160
  replacements.sort((a, b) => b.start - a.start)
118
161
 
162
+ // Remove duplicates (same start position)
163
+ const uniqueReplacements = []
164
+ const seenStarts = new Set()
165
+ replacements.forEach((replacement) => {
166
+ if (!seenStarts.has(replacement.start)) {
167
+ seenStarts.add(replacement.start)
168
+ uniqueReplacements.push(replacement)
169
+ }
170
+ })
171
+
119
172
  // Apply replacements from end to start
120
- replacements.forEach(({ start, end, replacement }) => {
173
+ uniqueReplacements.forEach(({ start, end, replacement }) => {
121
174
  fixedValue = fixedValue.substring(0, start) + replacement + fixedValue.substring(end)
122
175
  })
123
176
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Mon, 05 Jan 2026 17:14:15 GMT
3
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  *
5
5
  * Kong Design Tokens
6
6
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Mon, 05 Jan 2026 17:14:14 GMT
3
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  *
5
5
  * Kong Design Tokens
6
6
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Mon, 05 Jan 2026 17:14:14 GMT
3
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  *
5
5
  * Kong Design Tokens
6
6
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Mon, 05 Jan 2026 17:14:14 GMT
3
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  *
5
5
  * Kong Design Tokens
6
6
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Mon, 05 Jan 2026 17:14:14 GMT
3
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  *
5
5
  * Kong Design Tokens
6
6
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly, this file was auto-generated.
3
- // Generated on Mon, 05 Jan 2026 17:14:15 GMT
3
+ // Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  //
5
5
  // Kong Design Tokens
6
6
  // GitHub: https://github.com/Kong/design-tokens
@@ -1,7 +1,7 @@
1
1
 
2
2
  /**
3
3
  * Do not edit directly, this file was auto-generated.
4
- * Generated on Mon, 05 Jan 2026 17:14:15 GMT
4
+ * Generated on Mon, 05 Jan 2026 20:33:50 GMT
5
5
  *
6
6
  * Kong Design Tokens
7
7
  * GitHub: https://github.com/Kong/design-tokens
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly, this file was auto-generated.
3
- // Generated on Mon, 05 Jan 2026 17:14:15 GMT
3
+ // Generated on Mon, 05 Jan 2026 20:33:50 GMT
4
4
  //
5
5
  // Kong Design Tokens
6
6
  // GitHub: https://github.com/Kong/design-tokens
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kong/design-tokens",
3
- "version": "1.18.3-pr.613.51bd0cb.0",
3
+ "version": "1.18.3-pr.613.857d684.0",
4
4
  "description": "Kong UI Design Tokens and style dictionary",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -53,8 +53,8 @@
53
53
  "url": "https://github.com/Kong/design-tokens/issues"
54
54
  },
55
55
  "devDependencies": {
56
- "@commitlint/cli": "^20.2.0",
57
- "@commitlint/config-conventional": "^20.2.0",
56
+ "@commitlint/cli": "^20.3.0",
57
+ "@commitlint/config-conventional": "^20.3.0",
58
58
  "@digitalroute/cz-conventional-changelog-for-jira": "^8.0.1",
59
59
  "@evilmartians/lefthook": "^2.0.13",
60
60
  "@kong/eslint-config-kong-ui": "^1.6.0",
@@ -126,7 +126,7 @@
126
126
  "jiraAppend": "]"
127
127
  }
128
128
  },
129
- "packageManager": "pnpm@10.26.2",
129
+ "packageManager": "pnpm@10.27.0",
130
130
  "engines": {
131
131
  "node": ">=20.19.5",
132
132
  "pnpm": ">=9.14.4 || >=10.1.0"