@kong/design-tokens 1.18.2 → 1.18.3-pr.613.acae02c.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.
- package/dist/stylelint-plugin/index.mjs +2 -1
- package/dist/stylelint-plugin/rules/use-css-token/index.mjs +153 -0
- package/dist/tokens/css/custom-properties.css +1 -1
- package/dist/tokens/js/cjs/index.d.ts +1 -1
- package/dist/tokens/js/cjs/index.js +1 -1
- package/dist/tokens/js/index.d.ts +1 -1
- package/dist/tokens/js/index.mjs +1 -1
- package/dist/tokens/less/variables.less +1 -1
- package/dist/tokens/scss/_map.scss +1 -1
- package/dist/tokens/scss/_variables.scss +1 -1
- package/package.json +16 -16
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import stylelint from 'stylelint'
|
|
2
|
+
import { KONG_TOKEN_PREFIX, RULE_NAME_PREFIX } from '../../utilities/index.mjs'
|
|
3
|
+
|
|
4
|
+
const { ruleMessages, validateOptions, report } = stylelint.utils
|
|
5
|
+
const ruleName = `${RULE_NAME_PREFIX}/use-css-token`
|
|
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)',
|
|
8
|
+
})
|
|
9
|
+
const meta = {
|
|
10
|
+
url: 'https://github.com/Kong/design-tokens/blob/main/stylelint-plugin/README.md',
|
|
11
|
+
fixable: true,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Convert SCSS token ($kui-token) to CSS token (--kui-token)
|
|
15
|
+
const getCssToken = (scssToken) => {
|
|
16
|
+
const tokenName = scssToken.substring(1) // Remove $
|
|
17
|
+
return `--${tokenName}`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Find all occurrences of a token in a value
|
|
21
|
+
const findAllTokenOccurrences = (value, token) => {
|
|
22
|
+
const occurrences = []
|
|
23
|
+
let searchIndex = 0
|
|
24
|
+
while (true) {
|
|
25
|
+
const index = value.indexOf(token, searchIndex)
|
|
26
|
+
if (index === -1) {
|
|
27
|
+
break
|
|
28
|
+
}
|
|
29
|
+
occurrences.push(index)
|
|
30
|
+
searchIndex = index + 1
|
|
31
|
+
}
|
|
32
|
+
return occurrences
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Check if token at given position is properly wrapped in var()
|
|
36
|
+
const isTokenProperlyWrapped = (value, tokenIndex, token, cssToken) => {
|
|
37
|
+
// Calculate exact positions based on enforced format: var(--css-token, $scss-token)
|
|
38
|
+
// Format breakdown: var(-- + token-name + , $ + scss-token + )
|
|
39
|
+
// var(-- = 6 chars, token-name = cssToken.length - 2, , $ = 3 chars
|
|
40
|
+
const charactersBack = cssToken.length + 7 // 6 + (cssToken.length - 2) + 3
|
|
41
|
+
const charactersForward = token.length + 1 // token + )
|
|
42
|
+
|
|
43
|
+
const startIndex = tokenIndex - charactersBack
|
|
44
|
+
const endIndex = tokenIndex + charactersForward
|
|
45
|
+
|
|
46
|
+
// Check bounds
|
|
47
|
+
if (startIndex < 0 || endIndex > value.length) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Extract the substring that should match the pattern
|
|
52
|
+
const substring = value.substring(startIndex, endIndex)
|
|
53
|
+
|
|
54
|
+
// Check if it matches the expected pattern: var(--css-token, $scss-token)
|
|
55
|
+
const expectedPattern = new RegExp(`^var\\(\\s*${cssToken}\\s*,\\s*${token}\\s*\\)$`)
|
|
56
|
+
return expectedPattern.test(substring)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const ruleFunction = () => {
|
|
60
|
+
return (postcssRoot, postcssResult) => {
|
|
61
|
+
const validOptions = validateOptions(postcssResult, ruleName, {})
|
|
62
|
+
|
|
63
|
+
if (!validOptions) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
postcssRoot.walkDecls((decl) => {
|
|
68
|
+
const declValue = decl.value
|
|
69
|
+
|
|
70
|
+
// Extract all SCSS tokens (starting with $kui-)
|
|
71
|
+
const scssTokenRegex = new RegExp(`\\$${KONG_TOKEN_PREFIX}[a-z0-9-]+`, 'g')
|
|
72
|
+
const scssTokens = declValue.match(scssTokenRegex)
|
|
73
|
+
|
|
74
|
+
// If no SCSS tokens are used, skip validation
|
|
75
|
+
if (!scssTokens || scssTokens.length === 0) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Get unique SCSS tokens
|
|
80
|
+
const uniqueScssTokens = Array.from(new Set(scssTokens))
|
|
81
|
+
|
|
82
|
+
// Check if each SCSS token is properly wrapped in var()
|
|
83
|
+
// Pattern: var(--kui-token-name, $kui-token-name)
|
|
84
|
+
const improperlyUsedTokens = []
|
|
85
|
+
|
|
86
|
+
uniqueScssTokens.forEach((scssToken) => {
|
|
87
|
+
const cssToken = getCssToken(scssToken)
|
|
88
|
+
const tokenOccurrences = findAllTokenOccurrences(declValue, scssToken)
|
|
89
|
+
|
|
90
|
+
// Check each occurrence to see if it's properly wrapped
|
|
91
|
+
const hasImproperUsage = tokenOccurrences.some((tokenIndex) => {
|
|
92
|
+
return !isTokenProperlyWrapped(declValue, tokenIndex, scssToken, cssToken)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
if (hasImproperUsage) {
|
|
96
|
+
improperlyUsedTokens.push(scssToken)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
if (improperlyUsedTokens.length > 0) {
|
|
101
|
+
// Create fix function
|
|
102
|
+
const fix = () => {
|
|
103
|
+
let fixedValue = declValue
|
|
104
|
+
const replacements = []
|
|
105
|
+
|
|
106
|
+
// First, identify all positions that need to be replaced
|
|
107
|
+
improperlyUsedTokens.forEach((scssToken) => {
|
|
108
|
+
const cssToken = getCssToken(scssToken)
|
|
109
|
+
const tokenOccurrences = findAllTokenOccurrences(fixedValue, scssToken)
|
|
110
|
+
const properFormat = `var(${cssToken}, ${scssToken})`
|
|
111
|
+
|
|
112
|
+
tokenOccurrences.forEach((index) => {
|
|
113
|
+
// Check if this occurrence is in proper format
|
|
114
|
+
if (!isTokenProperlyWrapped(fixedValue, index, scssToken, cssToken)) {
|
|
115
|
+
// This occurrence needs to be replaced
|
|
116
|
+
replacements.push({
|
|
117
|
+
start: index,
|
|
118
|
+
end: index + scssToken.length,
|
|
119
|
+
replacement: properFormat,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Sort replacements by position (descending) to avoid offset issues
|
|
126
|
+
replacements.sort((a, b) => b.start - a.start)
|
|
127
|
+
|
|
128
|
+
// Apply replacements from end to start
|
|
129
|
+
replacements.forEach(({ start, end, replacement }) => {
|
|
130
|
+
fixedValue = fixedValue.substring(0, start) + replacement + fixedValue.substring(end)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
decl.value = fixedValue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
report({
|
|
137
|
+
message: messages.expected,
|
|
138
|
+
node: decl,
|
|
139
|
+
result: postcssResult,
|
|
140
|
+
ruleName,
|
|
141
|
+
fix,
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
ruleFunction.ruleName = ruleName
|
|
149
|
+
ruleFunction.messages = messages
|
|
150
|
+
ruleFunction.meta = meta
|
|
151
|
+
|
|
152
|
+
export default stylelint.createPlugin(ruleName, ruleFunction)
|
|
153
|
+
|
package/dist/tokens/js/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kong/design-tokens",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.3-pr.613.acae02c.0",
|
|
4
4
|
"description": "Kong UI Design Tokens and style dictionary",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -53,30 +53,30 @@
|
|
|
53
53
|
"url": "https://github.com/Kong/design-tokens/issues"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@commitlint/cli": "^20.
|
|
57
|
-
"@commitlint/config-conventional": "^20.
|
|
56
|
+
"@commitlint/cli": "^20.2.0",
|
|
57
|
+
"@commitlint/config-conventional": "^20.2.0",
|
|
58
58
|
"@digitalroute/cz-conventional-changelog-for-jira": "^8.0.1",
|
|
59
|
-
"@evilmartians/lefthook": "^2.0.
|
|
60
|
-
"@kong/eslint-config-kong-ui": "^1.
|
|
59
|
+
"@evilmartians/lefthook": "^2.0.13",
|
|
60
|
+
"@kong/eslint-config-kong-ui": "^1.6.0",
|
|
61
61
|
"@semantic-release/changelog": "^6.0.3",
|
|
62
62
|
"@semantic-release/git": "^10.0.1",
|
|
63
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
63
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
64
64
|
"chokidar-cli": "^3.0.0",
|
|
65
65
|
"commitizen": "^4.3.1",
|
|
66
66
|
"cz-conventional-changelog": "^3.3.0",
|
|
67
|
-
"eslint": "^9.39.
|
|
67
|
+
"eslint": "^9.39.2",
|
|
68
68
|
"npm-run-all2": "^8.0.4",
|
|
69
|
-
"rimraf": "^6.1.
|
|
70
|
-
"sass": "^1.
|
|
71
|
-
"semantic-release": "^25.0.
|
|
69
|
+
"rimraf": "^6.1.2",
|
|
70
|
+
"sass": "^1.97.1",
|
|
71
|
+
"semantic-release": "^25.0.2",
|
|
72
72
|
"shx": "^0.4.0",
|
|
73
73
|
"style-dictionary": "^4.4.0",
|
|
74
74
|
"typescript": "^5.9.3",
|
|
75
|
-
"vite": "^7.
|
|
75
|
+
"vite": "^7.3.0",
|
|
76
76
|
"vite-plugin-restart": "^2.0.0",
|
|
77
|
-
"vite-plugin-vue-devtools": "^8.0.
|
|
78
|
-
"vue": "^3.5.
|
|
79
|
-
"vue-router": "^4.6.
|
|
77
|
+
"vite-plugin-vue-devtools": "^8.0.5",
|
|
78
|
+
"vue": "^3.5.26",
|
|
79
|
+
"vue-router": "^4.6.4"
|
|
80
80
|
},
|
|
81
81
|
"release": {
|
|
82
82
|
"branches": [
|
|
@@ -126,13 +126,13 @@
|
|
|
126
126
|
"jiraAppend": "]"
|
|
127
127
|
}
|
|
128
128
|
},
|
|
129
|
-
"packageManager": "pnpm@10.
|
|
129
|
+
"packageManager": "pnpm@10.26.2",
|
|
130
130
|
"engines": {
|
|
131
131
|
"node": ">=20.19.5",
|
|
132
132
|
"pnpm": ">=9.14.4 || >=10.1.0"
|
|
133
133
|
},
|
|
134
134
|
"volta": {
|
|
135
|
-
"node": "24.
|
|
135
|
+
"node": "24.12.0"
|
|
136
136
|
},
|
|
137
137
|
"pnpm": {
|
|
138
138
|
"onlyBuiltDependencies": [
|