@atlaskit/eslint-plugin-design-system 3.2.0 → 4.0.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/CHANGELOG.md +33 -0
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/rules/ensure-design-token-usage/index.js +4 -115
- package/dist/cjs/rules/no-unsafe-design-token-usage/index.js +162 -0
- package/dist/cjs/rules/{ensure-design-token-usage/utils → utils}/is-color.js +0 -0
- package/dist/cjs/rules/{ensure-design-token-usage/utils → utils}/is-elevation.js +0 -0
- package/dist/cjs/rules/{ensure-design-token-usage/utils → utils}/is-node.js +0 -0
- package/dist/cjs/rules/{ensure-design-token-usage/utils → utils}/is-token.js +0 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/index.js +2 -0
- package/dist/es2019/rules/ensure-design-token-usage/index.js +4 -129
- package/dist/es2019/rules/no-unsafe-design-token-usage/index.js +166 -0
- package/dist/es2019/rules/{ensure-design-token-usage/utils → utils}/is-color.js +0 -0
- package/dist/es2019/rules/{ensure-design-token-usage/utils → utils}/is-elevation.js +0 -0
- package/dist/es2019/rules/{ensure-design-token-usage/utils → utils}/is-node.js +0 -0
- package/dist/es2019/rules/{ensure-design-token-usage/utils → utils}/is-token.js +0 -0
- package/dist/es2019/version.json +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/rules/ensure-design-token-usage/index.js +4 -110
- package/dist/esm/rules/no-unsafe-design-token-usage/index.js +148 -0
- package/dist/esm/rules/{ensure-design-token-usage/utils → utils}/is-color.js +0 -0
- package/dist/esm/rules/{ensure-design-token-usage/utils → utils}/is-elevation.js +0 -0
- package/dist/esm/rules/{ensure-design-token-usage/utils → utils}/is-node.js +0 -0
- package/dist/esm/rules/{ensure-design-token-usage/utils → utils}/is-token.js +0 -0
- package/dist/esm/version.json +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/rules/no-unsafe-design-token-usage/index.d.ts +3 -0
- package/dist/types/rules/{ensure-design-token-usage/utils → utils}/is-color.d.ts +0 -0
- package/dist/types/rules/{ensure-design-token-usage/utils → utils}/is-elevation.d.ts +0 -0
- package/dist/types/rules/{ensure-design-token-usage/utils → utils}/is-node.d.ts +0 -0
- package/dist/types/rules/{ensure-design-token-usage/utils → utils}/is-token.d.ts +0 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-design-system
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`a2f953f3814`](https://bitbucket.org/atlassian/atlassian-frontend/commits/a2f953f3814) - Previously the `ensure-design-token-usage` eslint rule contained all checks relating to token use. This has now been split up into two separate rules:
|
|
8
|
+
|
|
9
|
+
`ensure-design-token-usage` now covers:
|
|
10
|
+
|
|
11
|
+
- `legacyElevation` — warns about old usages of the elevation mixins or styles, which instead should use the `card` or `overlay` tokens.
|
|
12
|
+
- `hardCodedColor` — warns about use of hard-coded colors such as `color: colors.B100`, which instead should be wrapped in a `token()` call. This covers the majority of cases in existing codebases when first adopting tokens.
|
|
13
|
+
|
|
14
|
+
`no-unsafe-design-token-usage` (new) covers the remaining rules:
|
|
15
|
+
|
|
16
|
+
- `directTokenUsage` — warns against using the CSS Custom Property name that is output in the browser by the `token()` call.
|
|
17
|
+
Eg. directly using `var(--ds-accent-subtleBlue)` is bad.
|
|
18
|
+
- `staticToken` — warns when tokens aren't used inline. Inlining the token usages helps with static analysis, which unlocks future improvements.
|
|
19
|
+
Eg. pulling the token out into a const like `css={ color: token(primaryButtonText) }` is bad.
|
|
20
|
+
- `invalidToken` — warns when using a token that doesn't exist (not one that's been renamed, see the next point).
|
|
21
|
+
- `tokenRenamed` — warns when using a token that's been renamed in a subsequent release.
|
|
22
|
+
- `tokenFallbackEnforced` — warns if a fallback for the token call is not provided.
|
|
23
|
+
Eg. call with the fallback like this `token('color.background.disabled', N10)` instead of `token('color.background.disabled')`.
|
|
24
|
+
- `tokenFallbackRestricted` — the opposite of `tokenFallbackEnforced`.
|
|
25
|
+
Eg. do not pass in a fallback like this `token('color.background.disabled', N10)` and instead only include the token `token('color.background.disabled')`.
|
|
26
|
+
|
|
27
|
+
Upgrading — some instances of `\\eslint-disable` may need to be changed to the new rule. If you have failing lint rules after only bumping this package then switch those ignores to use `no-unsafe-design-token-usage` instead.
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- [`f460cc7c411`](https://bitbucket.org/atlassian/atlassian-frontend/commits/f460cc7c411) - Builds for this package now pass through a tokens babel plugin, removing runtime invocations of the tokens() function and improving bundle size.
|
|
32
|
+
- [`26719f5b7b0`](https://bitbucket.org/atlassian/atlassian-frontend/commits/26719f5b7b0) - Update @atlaskit tokens dependency from a devDependency to a regular dependency
|
|
33
|
+
- [`a66711cd58c`](https://bitbucket.org/atlassian/atlassian-frontend/commits/a66711cd58c) - Remove `@atlaskit/tokens` from peer dependency.
|
|
34
|
+
- Updated dependencies
|
|
35
|
+
|
|
3
36
|
## 3.2.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -11,8 +11,11 @@ var _ensureDesignTokenUsage = _interopRequireDefault(require("./rules/ensure-des
|
|
|
11
11
|
|
|
12
12
|
var _noDeprecatedImports = _interopRequireDefault(require("./rules/no-deprecated-imports"));
|
|
13
13
|
|
|
14
|
+
var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./rules/no-unsafe-design-token-usage"));
|
|
15
|
+
|
|
14
16
|
var rules = {
|
|
15
17
|
'ensure-design-token-usage': _ensureDesignTokenUsage.default,
|
|
18
|
+
'no-unsafe-design-token-usage': _noUnsafeDesignTokenUsage.default,
|
|
16
19
|
'no-deprecated-imports': _noDeprecatedImports.default
|
|
17
20
|
};
|
|
18
21
|
exports.rules = rules;
|
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
3
|
Object.defineProperty(exports, "__esModule", {
|
|
6
4
|
value: true
|
|
7
5
|
});
|
|
8
6
|
exports.default = void 0;
|
|
9
7
|
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
var _tokenNames = _interopRequireDefault(require("@atlaskit/tokens/token-names"));
|
|
13
|
-
|
|
14
|
-
var _isColor = require("./utils/is-color");
|
|
15
|
-
|
|
16
|
-
var _isElevation = require("./utils/is-elevation");
|
|
8
|
+
var _isColor = require("../utils/is-color");
|
|
17
9
|
|
|
18
|
-
var
|
|
10
|
+
var _isElevation = require("../utils/is-elevation");
|
|
19
11
|
|
|
20
|
-
var
|
|
12
|
+
var _isNode = require("../utils/is-node");
|
|
21
13
|
|
|
22
14
|
var defaultConfig = {
|
|
23
15
|
shouldEnforceFallbacks: false
|
|
@@ -58,13 +50,7 @@ var rule = {
|
|
|
58
50
|
type: 'problem',
|
|
59
51
|
messages: {
|
|
60
52
|
legacyElevation: "Elevations can be sourced from the global theme using the token function made of both a background and shadow. Use \"card\" for card elevations, and \"overlay\" for anything else that should appear elevated.\n\n{{example}}\n",
|
|
61
|
-
|
|
62
|
-
hardCodedColor: "Colors can be sourced from the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('color.background.blanket');\n```\n",
|
|
63
|
-
staticToken: "Token string should be inlined directly into the function call.\n\n```\ntoken('color.background.blanket');\n```\n",
|
|
64
|
-
invalidToken: 'The token "{{name}}" does not exist.',
|
|
65
|
-
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
66
|
-
tokenFallbackEnforced: "Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.\n\n```\ntoken('color.background.blanket', N500A);\n```\n ",
|
|
67
|
-
tokenFallbackRestricted: "Token function must not use a fallback.\n\n```\ntoken('color.background.blanket');\n```\n "
|
|
53
|
+
hardCodedColor: "Colors can be sourced from the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('color.background.blanket');\n```\n"
|
|
68
54
|
}
|
|
69
55
|
},
|
|
70
56
|
create: function create(context) {
|
|
@@ -134,25 +120,12 @@ var rule = {
|
|
|
134
120
|
var value = node.quasi.quasis.map(function (q) {
|
|
135
121
|
return q.value.raw;
|
|
136
122
|
}).join('');
|
|
137
|
-
var tokenKey = (0, _isToken.isToken)(value, _tokenNames.default);
|
|
138
|
-
|
|
139
|
-
if (tokenKey) {
|
|
140
|
-
context.report({
|
|
141
|
-
messageId: 'directTokenUsage',
|
|
142
|
-
node: node,
|
|
143
|
-
data: {
|
|
144
|
-
tokenKey: tokenKey
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
123
|
/**
|
|
150
124
|
* Attempts to remove all non-essential words & characters from a style block.
|
|
151
125
|
* Including selectors, queries and property names, leaving only values
|
|
152
126
|
* This is necessary to avoid cases where a property might have a color in its name ie. "white-space"
|
|
153
127
|
*/
|
|
154
128
|
|
|
155
|
-
|
|
156
129
|
var cssProperties = value.replace(/\n/g, '').split(/;|{|}/).filter(function (el) {
|
|
157
130
|
return !el.match(/\.|\@|\(|\)/);
|
|
158
131
|
}).map(function (el) {
|
|
@@ -181,23 +154,6 @@ var rule = {
|
|
|
181
154
|
return;
|
|
182
155
|
}
|
|
183
156
|
|
|
184
|
-
var tokenKey = (0, _isToken.isToken)(node.value, _tokenNames.default);
|
|
185
|
-
var isCSSVar = node.value.startsWith('var(');
|
|
186
|
-
|
|
187
|
-
if (tokenKey) {
|
|
188
|
-
context.report({
|
|
189
|
-
messageId: 'directTokenUsage',
|
|
190
|
-
node: node,
|
|
191
|
-
data: {
|
|
192
|
-
tokenKey: tokenKey
|
|
193
|
-
},
|
|
194
|
-
fix: function fix(fixer) {
|
|
195
|
-
return isCSSVar ? fixer.replaceText(node, "token('".concat(tokenKey, "')")) : null;
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
157
|
if ((0, _isColor.isHardCodedColor)(node.value) || (0, _isColor.includesHardCodedColor)(node.value)) {
|
|
202
158
|
context.report({
|
|
203
159
|
messageId: 'hardCodedColor',
|
|
@@ -226,73 +182,6 @@ var rule = {
|
|
|
226
182
|
suggest: getTokenSuggestion(node, "".concat(node.callee.name, "()"), config)
|
|
227
183
|
});
|
|
228
184
|
},
|
|
229
|
-
'CallExpression[callee.name="token"]': function CallExpressionCalleeNameToken(node) {
|
|
230
|
-
if (node.type !== 'CallExpression') {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
235
|
-
context.report({
|
|
236
|
-
messageId: 'tokenFallbackEnforced',
|
|
237
|
-
node: node
|
|
238
|
-
});
|
|
239
|
-
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
240
|
-
if (node.arguments[0].type === 'Literal') {
|
|
241
|
-
var value = node.arguments[0].value;
|
|
242
|
-
context.report({
|
|
243
|
-
messageId: 'tokenFallbackRestricted',
|
|
244
|
-
node: node.arguments[1],
|
|
245
|
-
fix: function fix(fixer) {
|
|
246
|
-
return fixer.replaceText(node, "token('".concat(value, "')"));
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
} else {
|
|
250
|
-
context.report({
|
|
251
|
-
messageId: 'tokenFallbackRestricted',
|
|
252
|
-
node: node.arguments[1]
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
258
|
-
context.report({
|
|
259
|
-
messageId: 'staticToken',
|
|
260
|
-
node: node
|
|
261
|
-
});
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
var tokenKey = node.arguments[0].value;
|
|
266
|
-
|
|
267
|
-
if (!tokenKey) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (typeof tokenKey === 'string' && tokenKey in _renameMapping.default) {
|
|
272
|
-
context.report({
|
|
273
|
-
messageId: 'tokenRenamed',
|
|
274
|
-
node: node,
|
|
275
|
-
data: {
|
|
276
|
-
name: tokenKey
|
|
277
|
-
},
|
|
278
|
-
fix: function fix(fixer) {
|
|
279
|
-
return fixer.replaceText(node.arguments[0], "'".concat(_renameMapping.default[tokenKey], "'"));
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !_tokenNames.default[tokenKey]) {
|
|
286
|
-
context.report({
|
|
287
|
-
messageId: 'invalidToken',
|
|
288
|
-
node: node,
|
|
289
|
-
data: {
|
|
290
|
-
name: tokenKey.toString()
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
},
|
|
296
185
|
JSXAttribute: function JSXAttribute(node) {
|
|
297
186
|
if (!node.value) {
|
|
298
187
|
return;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var _renameMapping = _interopRequireDefault(require("@atlaskit/tokens/rename-mapping"));
|
|
11
|
+
|
|
12
|
+
var _tokenNames = _interopRequireDefault(require("@atlaskit/tokens/token-names"));
|
|
13
|
+
|
|
14
|
+
var _isNode = require("../utils/is-node");
|
|
15
|
+
|
|
16
|
+
var _isToken = require("../utils/is-token");
|
|
17
|
+
|
|
18
|
+
var defaultConfig = {
|
|
19
|
+
shouldEnforceFallbacks: false
|
|
20
|
+
};
|
|
21
|
+
var rule = {
|
|
22
|
+
meta: {
|
|
23
|
+
docs: {
|
|
24
|
+
recommended: true
|
|
25
|
+
},
|
|
26
|
+
fixable: 'code',
|
|
27
|
+
type: 'problem',
|
|
28
|
+
messages: {
|
|
29
|
+
directTokenUsage: "Access the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('{{tokenKey}}');\n```\n",
|
|
30
|
+
staticToken: "Token string should be inlined directly into the function call.\n\n```\ntoken('color.background.blanket');\n```\n",
|
|
31
|
+
invalidToken: 'The token "{{name}}" does not exist.',
|
|
32
|
+
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
33
|
+
tokenFallbackEnforced: "Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.\n\n```\ntoken('color.background.blanket', N500A);\n```\n ",
|
|
34
|
+
tokenFallbackRestricted: "Token function must not use a fallback.\n\n```\ntoken('color.background.blanket');\n```\n "
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
create: function create(context) {
|
|
38
|
+
var config = context.options[0] || defaultConfig;
|
|
39
|
+
return {
|
|
40
|
+
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyled(node) {
|
|
41
|
+
if (node.type !== 'TaggedTemplateExpression') {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var value = node.quasi.quasis.map(function (q) {
|
|
46
|
+
return q.value.raw;
|
|
47
|
+
}).join('');
|
|
48
|
+
var tokenKey = (0, _isToken.isToken)(value, _tokenNames.default);
|
|
49
|
+
|
|
50
|
+
if (tokenKey) {
|
|
51
|
+
context.report({
|
|
52
|
+
messageId: 'directTokenUsage',
|
|
53
|
+
node: node,
|
|
54
|
+
data: {
|
|
55
|
+
tokenKey: tokenKey
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
'ObjectExpression > Property > Literal': function ObjectExpressionPropertyLiteral(node) {
|
|
62
|
+
if (node.type !== 'Literal') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (typeof node.value !== 'string') {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!(0, _isNode.isDecendantOfStyleBlock)(node) && !(0, _isNode.isDecendantOfStyleJsxAttribute)(node)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
var tokenKey = (0, _isToken.isToken)(node.value, _tokenNames.default);
|
|
75
|
+
var isCSSVar = node.value.startsWith('var(');
|
|
76
|
+
|
|
77
|
+
if (tokenKey) {
|
|
78
|
+
context.report({
|
|
79
|
+
messageId: 'directTokenUsage',
|
|
80
|
+
node: node,
|
|
81
|
+
data: {
|
|
82
|
+
tokenKey: tokenKey
|
|
83
|
+
},
|
|
84
|
+
fix: function fix(fixer) {
|
|
85
|
+
return isCSSVar ? fixer.replaceText(node, "token('".concat(tokenKey, "')")) : null;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
'CallExpression[callee.name="token"]': function CallExpressionCalleeNameToken(node) {
|
|
92
|
+
if (node.type !== 'CallExpression') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
97
|
+
context.report({
|
|
98
|
+
messageId: 'tokenFallbackEnforced',
|
|
99
|
+
node: node
|
|
100
|
+
});
|
|
101
|
+
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
102
|
+
if (node.arguments[0].type === 'Literal') {
|
|
103
|
+
var value = node.arguments[0].value;
|
|
104
|
+
context.report({
|
|
105
|
+
messageId: 'tokenFallbackRestricted',
|
|
106
|
+
node: node.arguments[1],
|
|
107
|
+
fix: function fix(fixer) {
|
|
108
|
+
return fixer.replaceText(node, "token('".concat(value, "')"));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
context.report({
|
|
113
|
+
messageId: 'tokenFallbackRestricted',
|
|
114
|
+
node: node.arguments[1]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
120
|
+
context.report({
|
|
121
|
+
messageId: 'staticToken',
|
|
122
|
+
node: node
|
|
123
|
+
});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
var tokenKey = node.arguments[0].value;
|
|
128
|
+
|
|
129
|
+
if (!tokenKey) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (typeof tokenKey === 'string' && tokenKey in _renameMapping.default) {
|
|
134
|
+
context.report({
|
|
135
|
+
messageId: 'tokenRenamed',
|
|
136
|
+
node: node,
|
|
137
|
+
data: {
|
|
138
|
+
name: tokenKey
|
|
139
|
+
},
|
|
140
|
+
fix: function fix(fixer) {
|
|
141
|
+
return fixer.replaceText(node.arguments[0], "'".concat(_renameMapping.default[tokenKey], "'"));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !_tokenNames.default[tokenKey]) {
|
|
148
|
+
context.report({
|
|
149
|
+
messageId: 'invalidToken',
|
|
150
|
+
node: node,
|
|
151
|
+
data: {
|
|
152
|
+
name: tokenKey.toString()
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var _default = rule;
|
|
162
|
+
exports.default = _default;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/cjs/version.json
CHANGED
package/dist/es2019/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import ensureTokenUsage from './rules/ensure-design-token-usage';
|
|
2
2
|
import noDeprecatedImports from './rules/no-deprecated-imports';
|
|
3
|
+
import noUnsafeUsage from './rules/no-unsafe-design-token-usage';
|
|
3
4
|
export const rules = {
|
|
4
5
|
'ensure-design-token-usage': ensureTokenUsage,
|
|
6
|
+
'no-unsafe-design-token-usage': noUnsafeUsage,
|
|
5
7
|
'no-deprecated-imports': noDeprecatedImports
|
|
6
8
|
};
|
|
7
9
|
export const configs = {
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { isLegacyElevation } from './utils/is-elevation';
|
|
5
|
-
import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute, isDecendantOfType } from './utils/is-node';
|
|
6
|
-
import { isToken } from './utils/is-token';
|
|
1
|
+
import { includesHardCodedColor, isHardCodedColor, isLegacyColor, isLegacyNamedColor } from '../utils/is-color';
|
|
2
|
+
import { isLegacyElevation } from '../utils/is-elevation';
|
|
3
|
+
import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute, isDecendantOfType } from '../utils/is-node';
|
|
7
4
|
const defaultConfig = {
|
|
8
5
|
shouldEnforceFallbacks: false
|
|
9
6
|
};
|
|
@@ -36,14 +33,6 @@ const rule = {
|
|
|
36
33
|
legacyElevation: `Elevations can be sourced from the global theme using the token function made of both a background and shadow. Use "card" for card elevations, and "overlay" for anything else that should appear elevated.
|
|
37
34
|
|
|
38
35
|
{{example}}
|
|
39
|
-
`,
|
|
40
|
-
directTokenUsage: `Access the global theme using the token function.
|
|
41
|
-
|
|
42
|
-
\`\`\`
|
|
43
|
-
import { token } from '@atlaskit/tokens';
|
|
44
|
-
|
|
45
|
-
token('{{tokenKey}}');
|
|
46
|
-
\`\`\`
|
|
47
36
|
`,
|
|
48
37
|
hardCodedColor: `Colors can be sourced from the global theme using the token function.
|
|
49
38
|
|
|
@@ -52,27 +41,7 @@ import { token } from '@atlaskit/tokens';
|
|
|
52
41
|
|
|
53
42
|
token('color.background.blanket');
|
|
54
43
|
\`\`\`
|
|
55
|
-
|
|
56
|
-
staticToken: `Token string should be inlined directly into the function call.
|
|
57
|
-
|
|
58
|
-
\`\`\`
|
|
59
|
-
token('color.background.blanket');
|
|
60
|
-
\`\`\`
|
|
61
|
-
`,
|
|
62
|
-
invalidToken: 'The token "{{name}}" does not exist.',
|
|
63
|
-
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
64
|
-
tokenFallbackEnforced: `Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.
|
|
65
|
-
|
|
66
|
-
\`\`\`
|
|
67
|
-
token('color.background.blanket', N500A);
|
|
68
|
-
\`\`\`
|
|
69
|
-
`,
|
|
70
|
-
tokenFallbackRestricted: `Token function must not use a fallback.
|
|
71
|
-
|
|
72
|
-
\`\`\`
|
|
73
|
-
token('color.background.blanket');
|
|
74
|
-
\`\`\`
|
|
75
|
-
`
|
|
44
|
+
`
|
|
76
45
|
}
|
|
77
46
|
},
|
|
78
47
|
|
|
@@ -151,25 +120,12 @@ ${' '.repeat(getNodeColumn(node) - 2)}box-shadow: \${token('${elevation.shadow}'
|
|
|
151
120
|
}
|
|
152
121
|
|
|
153
122
|
const value = node.quasi.quasis.map(q => q.value.raw).join('');
|
|
154
|
-
const tokenKey = isToken(value, tokens);
|
|
155
|
-
|
|
156
|
-
if (tokenKey) {
|
|
157
|
-
context.report({
|
|
158
|
-
messageId: 'directTokenUsage',
|
|
159
|
-
node,
|
|
160
|
-
data: {
|
|
161
|
-
tokenKey
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
123
|
/**
|
|
167
124
|
* Attempts to remove all non-essential words & characters from a style block.
|
|
168
125
|
* Including selectors, queries and property names, leaving only values
|
|
169
126
|
* This is necessary to avoid cases where a property might have a color in its name ie. "white-space"
|
|
170
127
|
*/
|
|
171
128
|
|
|
172
|
-
|
|
173
129
|
const cssProperties = value.replace(/\n/g, '').split(/;|{|}/).filter(el => !el.match(/\.|\@|\(|\)/)).map(el => el.trim().split(':').pop() || '');
|
|
174
130
|
cssProperties.forEach(property => {
|
|
175
131
|
if (includesHardCodedColor(property)) {
|
|
@@ -194,21 +150,6 @@ ${' '.repeat(getNodeColumn(node) - 2)}box-shadow: \${token('${elevation.shadow}'
|
|
|
194
150
|
return;
|
|
195
151
|
}
|
|
196
152
|
|
|
197
|
-
const tokenKey = isToken(node.value, tokens);
|
|
198
|
-
const isCSSVar = node.value.startsWith('var(');
|
|
199
|
-
|
|
200
|
-
if (tokenKey) {
|
|
201
|
-
context.report({
|
|
202
|
-
messageId: 'directTokenUsage',
|
|
203
|
-
node,
|
|
204
|
-
data: {
|
|
205
|
-
tokenKey
|
|
206
|
-
},
|
|
207
|
-
fix: fixer => isCSSVar ? fixer.replaceText(node, `token('${tokenKey}')`) : null
|
|
208
|
-
});
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
153
|
if (isHardCodedColor(node.value) || includesHardCodedColor(node.value)) {
|
|
213
154
|
context.report({
|
|
214
155
|
messageId: 'hardCodedColor',
|
|
@@ -239,72 +180,6 @@ ${' '.repeat(getNodeColumn(node) - 2)}box-shadow: \${token('${elevation.shadow}'
|
|
|
239
180
|
});
|
|
240
181
|
},
|
|
241
182
|
|
|
242
|
-
'CallExpression[callee.name="token"]': node => {
|
|
243
|
-
if (node.type !== 'CallExpression') {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
248
|
-
context.report({
|
|
249
|
-
messageId: 'tokenFallbackEnforced',
|
|
250
|
-
node
|
|
251
|
-
});
|
|
252
|
-
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
253
|
-
if (node.arguments[0].type === 'Literal') {
|
|
254
|
-
const {
|
|
255
|
-
value
|
|
256
|
-
} = node.arguments[0];
|
|
257
|
-
context.report({
|
|
258
|
-
messageId: 'tokenFallbackRestricted',
|
|
259
|
-
node: node.arguments[1],
|
|
260
|
-
fix: fixer => fixer.replaceText(node, `token('${value}')`)
|
|
261
|
-
});
|
|
262
|
-
} else {
|
|
263
|
-
context.report({
|
|
264
|
-
messageId: 'tokenFallbackRestricted',
|
|
265
|
-
node: node.arguments[1]
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
271
|
-
context.report({
|
|
272
|
-
messageId: 'staticToken',
|
|
273
|
-
node
|
|
274
|
-
});
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const tokenKey = node.arguments[0].value;
|
|
279
|
-
|
|
280
|
-
if (!tokenKey) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (typeof tokenKey === 'string' && tokenKey in renameMapping) {
|
|
285
|
-
context.report({
|
|
286
|
-
messageId: 'tokenRenamed',
|
|
287
|
-
node,
|
|
288
|
-
data: {
|
|
289
|
-
name: tokenKey
|
|
290
|
-
},
|
|
291
|
-
fix: fixer => fixer.replaceText(node.arguments[0], `'${renameMapping[tokenKey]}'`)
|
|
292
|
-
});
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !tokens[tokenKey]) {
|
|
297
|
-
context.report({
|
|
298
|
-
messageId: 'invalidToken',
|
|
299
|
-
node,
|
|
300
|
-
data: {
|
|
301
|
-
name: tokenKey.toString()
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
|
|
308
183
|
JSXAttribute(node) {
|
|
309
184
|
if (!node.value) {
|
|
310
185
|
return;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import renameMapping from '@atlaskit/tokens/rename-mapping';
|
|
2
|
+
import tokens from '@atlaskit/tokens/token-names';
|
|
3
|
+
import { isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute } from '../utils/is-node';
|
|
4
|
+
import { isToken } from '../utils/is-token';
|
|
5
|
+
const defaultConfig = {
|
|
6
|
+
shouldEnforceFallbacks: false
|
|
7
|
+
};
|
|
8
|
+
const rule = {
|
|
9
|
+
meta: {
|
|
10
|
+
docs: {
|
|
11
|
+
recommended: true
|
|
12
|
+
},
|
|
13
|
+
fixable: 'code',
|
|
14
|
+
type: 'problem',
|
|
15
|
+
messages: {
|
|
16
|
+
directTokenUsage: `Access the global theme using the token function.
|
|
17
|
+
|
|
18
|
+
\`\`\`
|
|
19
|
+
import { token } from '@atlaskit/tokens';
|
|
20
|
+
|
|
21
|
+
token('{{tokenKey}}');
|
|
22
|
+
\`\`\`
|
|
23
|
+
`,
|
|
24
|
+
staticToken: `Token string should be inlined directly into the function call.
|
|
25
|
+
|
|
26
|
+
\`\`\`
|
|
27
|
+
token('color.background.blanket');
|
|
28
|
+
\`\`\`
|
|
29
|
+
`,
|
|
30
|
+
invalidToken: 'The token "{{name}}" does not exist.',
|
|
31
|
+
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
32
|
+
tokenFallbackEnforced: `Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.
|
|
33
|
+
|
|
34
|
+
\`\`\`
|
|
35
|
+
token('color.background.blanket', N500A);
|
|
36
|
+
\`\`\`
|
|
37
|
+
`,
|
|
38
|
+
tokenFallbackRestricted: `Token function must not use a fallback.
|
|
39
|
+
|
|
40
|
+
\`\`\`
|
|
41
|
+
token('color.background.blanket');
|
|
42
|
+
\`\`\`
|
|
43
|
+
`
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
create(context) {
|
|
48
|
+
const config = context.options[0] || defaultConfig;
|
|
49
|
+
return {
|
|
50
|
+
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': node => {
|
|
51
|
+
if (node.type !== 'TaggedTemplateExpression') {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const value = node.quasi.quasis.map(q => q.value.raw).join('');
|
|
56
|
+
const tokenKey = isToken(value, tokens);
|
|
57
|
+
|
|
58
|
+
if (tokenKey) {
|
|
59
|
+
context.report({
|
|
60
|
+
messageId: 'directTokenUsage',
|
|
61
|
+
node,
|
|
62
|
+
data: {
|
|
63
|
+
tokenKey
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
'ObjectExpression > Property > Literal': node => {
|
|
70
|
+
if (node.type !== 'Literal') {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (typeof node.value !== 'string') {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!isDecendantOfStyleBlock(node) && !isDecendantOfStyleJsxAttribute(node)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const tokenKey = isToken(node.value, tokens);
|
|
83
|
+
const isCSSVar = node.value.startsWith('var(');
|
|
84
|
+
|
|
85
|
+
if (tokenKey) {
|
|
86
|
+
context.report({
|
|
87
|
+
messageId: 'directTokenUsage',
|
|
88
|
+
node,
|
|
89
|
+
data: {
|
|
90
|
+
tokenKey
|
|
91
|
+
},
|
|
92
|
+
fix: fixer => isCSSVar ? fixer.replaceText(node, `token('${tokenKey}')`) : null
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
'CallExpression[callee.name="token"]': node => {
|
|
98
|
+
if (node.type !== 'CallExpression') {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
103
|
+
context.report({
|
|
104
|
+
messageId: 'tokenFallbackEnforced',
|
|
105
|
+
node
|
|
106
|
+
});
|
|
107
|
+
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
108
|
+
if (node.arguments[0].type === 'Literal') {
|
|
109
|
+
const {
|
|
110
|
+
value
|
|
111
|
+
} = node.arguments[0];
|
|
112
|
+
context.report({
|
|
113
|
+
messageId: 'tokenFallbackRestricted',
|
|
114
|
+
node: node.arguments[1],
|
|
115
|
+
fix: fixer => fixer.replaceText(node, `token('${value}')`)
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
context.report({
|
|
119
|
+
messageId: 'tokenFallbackRestricted',
|
|
120
|
+
node: node.arguments[1]
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
126
|
+
context.report({
|
|
127
|
+
messageId: 'staticToken',
|
|
128
|
+
node
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const tokenKey = node.arguments[0].value;
|
|
134
|
+
|
|
135
|
+
if (!tokenKey) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (typeof tokenKey === 'string' && tokenKey in renameMapping) {
|
|
140
|
+
context.report({
|
|
141
|
+
messageId: 'tokenRenamed',
|
|
142
|
+
node,
|
|
143
|
+
data: {
|
|
144
|
+
name: tokenKey
|
|
145
|
+
},
|
|
146
|
+
fix: fixer => fixer.replaceText(node.arguments[0], `'${renameMapping[tokenKey]}'`)
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !tokens[tokenKey]) {
|
|
152
|
+
context.report({
|
|
153
|
+
messageId: 'invalidToken',
|
|
154
|
+
node,
|
|
155
|
+
data: {
|
|
156
|
+
name: tokenKey.toString()
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
};
|
|
166
|
+
export default rule;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/es2019/version.json
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import ensureTokenUsage from './rules/ensure-design-token-usage';
|
|
2
2
|
import noDeprecatedImports from './rules/no-deprecated-imports';
|
|
3
|
+
import noUnsafeUsage from './rules/no-unsafe-design-token-usage';
|
|
3
4
|
export var rules = {
|
|
4
5
|
'ensure-design-token-usage': ensureTokenUsage,
|
|
6
|
+
'no-unsafe-design-token-usage': noUnsafeUsage,
|
|
5
7
|
'no-deprecated-imports': noDeprecatedImports
|
|
6
8
|
};
|
|
7
9
|
export var configs = {
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { isLegacyElevation } from './utils/is-elevation';
|
|
5
|
-
import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute, isDecendantOfType } from './utils/is-node';
|
|
6
|
-
import { isToken } from './utils/is-token';
|
|
1
|
+
import { includesHardCodedColor, isHardCodedColor, isLegacyColor, isLegacyNamedColor } from '../utils/is-color';
|
|
2
|
+
import { isLegacyElevation } from '../utils/is-elevation';
|
|
3
|
+
import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute, isDecendantOfType } from '../utils/is-node';
|
|
7
4
|
var defaultConfig = {
|
|
8
5
|
shouldEnforceFallbacks: false
|
|
9
6
|
};
|
|
@@ -43,13 +40,7 @@ var rule = {
|
|
|
43
40
|
type: 'problem',
|
|
44
41
|
messages: {
|
|
45
42
|
legacyElevation: "Elevations can be sourced from the global theme using the token function made of both a background and shadow. Use \"card\" for card elevations, and \"overlay\" for anything else that should appear elevated.\n\n{{example}}\n",
|
|
46
|
-
|
|
47
|
-
hardCodedColor: "Colors can be sourced from the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('color.background.blanket');\n```\n",
|
|
48
|
-
staticToken: "Token string should be inlined directly into the function call.\n\n```\ntoken('color.background.blanket');\n```\n",
|
|
49
|
-
invalidToken: 'The token "{{name}}" does not exist.',
|
|
50
|
-
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
51
|
-
tokenFallbackEnforced: "Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.\n\n```\ntoken('color.background.blanket', N500A);\n```\n ",
|
|
52
|
-
tokenFallbackRestricted: "Token function must not use a fallback.\n\n```\ntoken('color.background.blanket');\n```\n "
|
|
43
|
+
hardCodedColor: "Colors can be sourced from the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('color.background.blanket');\n```\n"
|
|
53
44
|
}
|
|
54
45
|
},
|
|
55
46
|
create: function create(context) {
|
|
@@ -119,25 +110,12 @@ var rule = {
|
|
|
119
110
|
var value = node.quasi.quasis.map(function (q) {
|
|
120
111
|
return q.value.raw;
|
|
121
112
|
}).join('');
|
|
122
|
-
var tokenKey = isToken(value, tokens);
|
|
123
|
-
|
|
124
|
-
if (tokenKey) {
|
|
125
|
-
context.report({
|
|
126
|
-
messageId: 'directTokenUsage',
|
|
127
|
-
node: node,
|
|
128
|
-
data: {
|
|
129
|
-
tokenKey: tokenKey
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
113
|
/**
|
|
135
114
|
* Attempts to remove all non-essential words & characters from a style block.
|
|
136
115
|
* Including selectors, queries and property names, leaving only values
|
|
137
116
|
* This is necessary to avoid cases where a property might have a color in its name ie. "white-space"
|
|
138
117
|
*/
|
|
139
118
|
|
|
140
|
-
|
|
141
119
|
var cssProperties = value.replace(/\n/g, '').split(/;|{|}/).filter(function (el) {
|
|
142
120
|
return !el.match(/\.|\@|\(|\)/);
|
|
143
121
|
}).map(function (el) {
|
|
@@ -166,23 +144,6 @@ var rule = {
|
|
|
166
144
|
return;
|
|
167
145
|
}
|
|
168
146
|
|
|
169
|
-
var tokenKey = isToken(node.value, tokens);
|
|
170
|
-
var isCSSVar = node.value.startsWith('var(');
|
|
171
|
-
|
|
172
|
-
if (tokenKey) {
|
|
173
|
-
context.report({
|
|
174
|
-
messageId: 'directTokenUsage',
|
|
175
|
-
node: node,
|
|
176
|
-
data: {
|
|
177
|
-
tokenKey: tokenKey
|
|
178
|
-
},
|
|
179
|
-
fix: function fix(fixer) {
|
|
180
|
-
return isCSSVar ? fixer.replaceText(node, "token('".concat(tokenKey, "')")) : null;
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
147
|
if (isHardCodedColor(node.value) || includesHardCodedColor(node.value)) {
|
|
187
148
|
context.report({
|
|
188
149
|
messageId: 'hardCodedColor',
|
|
@@ -211,73 +172,6 @@ var rule = {
|
|
|
211
172
|
suggest: getTokenSuggestion(node, "".concat(node.callee.name, "()"), config)
|
|
212
173
|
});
|
|
213
174
|
},
|
|
214
|
-
'CallExpression[callee.name="token"]': function CallExpressionCalleeNameToken(node) {
|
|
215
|
-
if (node.type !== 'CallExpression') {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
220
|
-
context.report({
|
|
221
|
-
messageId: 'tokenFallbackEnforced',
|
|
222
|
-
node: node
|
|
223
|
-
});
|
|
224
|
-
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
225
|
-
if (node.arguments[0].type === 'Literal') {
|
|
226
|
-
var value = node.arguments[0].value;
|
|
227
|
-
context.report({
|
|
228
|
-
messageId: 'tokenFallbackRestricted',
|
|
229
|
-
node: node.arguments[1],
|
|
230
|
-
fix: function fix(fixer) {
|
|
231
|
-
return fixer.replaceText(node, "token('".concat(value, "')"));
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
} else {
|
|
235
|
-
context.report({
|
|
236
|
-
messageId: 'tokenFallbackRestricted',
|
|
237
|
-
node: node.arguments[1]
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
243
|
-
context.report({
|
|
244
|
-
messageId: 'staticToken',
|
|
245
|
-
node: node
|
|
246
|
-
});
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
var tokenKey = node.arguments[0].value;
|
|
251
|
-
|
|
252
|
-
if (!tokenKey) {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (typeof tokenKey === 'string' && tokenKey in renameMapping) {
|
|
257
|
-
context.report({
|
|
258
|
-
messageId: 'tokenRenamed',
|
|
259
|
-
node: node,
|
|
260
|
-
data: {
|
|
261
|
-
name: tokenKey
|
|
262
|
-
},
|
|
263
|
-
fix: function fix(fixer) {
|
|
264
|
-
return fixer.replaceText(node.arguments[0], "'".concat(renameMapping[tokenKey], "'"));
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !tokens[tokenKey]) {
|
|
271
|
-
context.report({
|
|
272
|
-
messageId: 'invalidToken',
|
|
273
|
-
node: node,
|
|
274
|
-
data: {
|
|
275
|
-
name: tokenKey.toString()
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
175
|
JSXAttribute: function JSXAttribute(node) {
|
|
282
176
|
if (!node.value) {
|
|
283
177
|
return;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import renameMapping from '@atlaskit/tokens/rename-mapping';
|
|
2
|
+
import tokens from '@atlaskit/tokens/token-names';
|
|
3
|
+
import { isDecendantOfStyleBlock, isDecendantOfStyleJsxAttribute } from '../utils/is-node';
|
|
4
|
+
import { isToken } from '../utils/is-token';
|
|
5
|
+
var defaultConfig = {
|
|
6
|
+
shouldEnforceFallbacks: false
|
|
7
|
+
};
|
|
8
|
+
var rule = {
|
|
9
|
+
meta: {
|
|
10
|
+
docs: {
|
|
11
|
+
recommended: true
|
|
12
|
+
},
|
|
13
|
+
fixable: 'code',
|
|
14
|
+
type: 'problem',
|
|
15
|
+
messages: {
|
|
16
|
+
directTokenUsage: "Access the global theme using the token function.\n\n```\nimport { token } from '@atlaskit/tokens';\n\ntoken('{{tokenKey}}');\n```\n",
|
|
17
|
+
staticToken: "Token string should be inlined directly into the function call.\n\n```\ntoken('color.background.blanket');\n```\n",
|
|
18
|
+
invalidToken: 'The token "{{name}}" does not exist.',
|
|
19
|
+
tokenRenamed: 'The token "{{name}}" has been renamed.',
|
|
20
|
+
tokenFallbackEnforced: "Token function requires a fallback, preferably something that best matches the light/default theme in case tokens aren't present.\n\n```\ntoken('color.background.blanket', N500A);\n```\n ",
|
|
21
|
+
tokenFallbackRestricted: "Token function must not use a fallback.\n\n```\ntoken('color.background.blanket');\n```\n "
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
create: function create(context) {
|
|
25
|
+
var config = context.options[0] || defaultConfig;
|
|
26
|
+
return {
|
|
27
|
+
'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyled(node) {
|
|
28
|
+
if (node.type !== 'TaggedTemplateExpression') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var value = node.quasi.quasis.map(function (q) {
|
|
33
|
+
return q.value.raw;
|
|
34
|
+
}).join('');
|
|
35
|
+
var tokenKey = isToken(value, tokens);
|
|
36
|
+
|
|
37
|
+
if (tokenKey) {
|
|
38
|
+
context.report({
|
|
39
|
+
messageId: 'directTokenUsage',
|
|
40
|
+
node: node,
|
|
41
|
+
data: {
|
|
42
|
+
tokenKey: tokenKey
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
'ObjectExpression > Property > Literal': function ObjectExpressionPropertyLiteral(node) {
|
|
49
|
+
if (node.type !== 'Literal') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof node.value !== 'string') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!isDecendantOfStyleBlock(node) && !isDecendantOfStyleJsxAttribute(node)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var tokenKey = isToken(node.value, tokens);
|
|
62
|
+
var isCSSVar = node.value.startsWith('var(');
|
|
63
|
+
|
|
64
|
+
if (tokenKey) {
|
|
65
|
+
context.report({
|
|
66
|
+
messageId: 'directTokenUsage',
|
|
67
|
+
node: node,
|
|
68
|
+
data: {
|
|
69
|
+
tokenKey: tokenKey
|
|
70
|
+
},
|
|
71
|
+
fix: function fix(fixer) {
|
|
72
|
+
return isCSSVar ? fixer.replaceText(node, "token('".concat(tokenKey, "')")) : null;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
'CallExpression[callee.name="token"]': function CallExpressionCalleeNameToken(node) {
|
|
79
|
+
if (node.type !== 'CallExpression') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (node.arguments.length < 2 && config.shouldEnforceFallbacks === true) {
|
|
84
|
+
context.report({
|
|
85
|
+
messageId: 'tokenFallbackEnforced',
|
|
86
|
+
node: node
|
|
87
|
+
});
|
|
88
|
+
} else if (node.arguments.length > 1 && config.shouldEnforceFallbacks === false) {
|
|
89
|
+
if (node.arguments[0].type === 'Literal') {
|
|
90
|
+
var value = node.arguments[0].value;
|
|
91
|
+
context.report({
|
|
92
|
+
messageId: 'tokenFallbackRestricted',
|
|
93
|
+
node: node.arguments[1],
|
|
94
|
+
fix: function fix(fixer) {
|
|
95
|
+
return fixer.replaceText(node, "token('".concat(value, "')"));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
context.report({
|
|
100
|
+
messageId: 'tokenFallbackRestricted',
|
|
101
|
+
node: node.arguments[1]
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (node.arguments[0] && node.arguments[0].type !== 'Literal') {
|
|
107
|
+
context.report({
|
|
108
|
+
messageId: 'staticToken',
|
|
109
|
+
node: node
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
var tokenKey = node.arguments[0].value;
|
|
115
|
+
|
|
116
|
+
if (!tokenKey) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (typeof tokenKey === 'string' && tokenKey in renameMapping) {
|
|
121
|
+
context.report({
|
|
122
|
+
messageId: 'tokenRenamed',
|
|
123
|
+
node: node,
|
|
124
|
+
data: {
|
|
125
|
+
name: tokenKey
|
|
126
|
+
},
|
|
127
|
+
fix: function fix(fixer) {
|
|
128
|
+
return fixer.replaceText(node.arguments[0], "'".concat(renameMapping[tokenKey], "'"));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (typeof tokenKey !== 'string' || typeof tokenKey === 'string' && !tokens[tokenKey]) {
|
|
135
|
+
context.report({
|
|
136
|
+
messageId: 'invalidToken',
|
|
137
|
+
node: node,
|
|
138
|
+
data: {
|
|
139
|
+
name: tokenKey.toString()
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
export default rule;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/esm/version.json
CHANGED
package/dist/types/index.d.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-design-system",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"author": "Atlassian Pty Ltd",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -20,19 +20,16 @@
|
|
|
20
20
|
".": "./src/index.tsx"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"@atlaskit/tokens": "^0.4.0",
|
|
23
24
|
"@babel/runtime": "^7.0.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@atlaskit/tokens": "*",
|
|
27
27
|
"@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
|
|
28
28
|
"eslint": "^7.7.0",
|
|
29
29
|
"ts-node": "^10.0.0",
|
|
30
30
|
"tsconfig-paths": "^3.9.0",
|
|
31
31
|
"typescript": "3.9.6"
|
|
32
32
|
},
|
|
33
|
-
"peerDependencies": {
|
|
34
|
-
"@atlaskit/tokens": "*"
|
|
35
|
-
},
|
|
36
33
|
"techstack": {
|
|
37
34
|
"@atlassian/frontend": {
|
|
38
35
|
"import-structure": "atlassian-conventions",
|
|
@@ -40,7 +37,10 @@
|
|
|
40
37
|
},
|
|
41
38
|
"@repo/internal": {
|
|
42
39
|
"design-system": "v1",
|
|
43
|
-
"deprecation": "no-deprecated-imports"
|
|
40
|
+
"deprecation": "no-deprecated-imports",
|
|
41
|
+
"styling": [
|
|
42
|
+
"emotion"
|
|
43
|
+
]
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.1"
|