@atlaskit/eslint-plugin-design-system 4.11.2 → 4.12.1

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/constellation/index/examples.mdx +309 -1
  3. package/constellation/index/usage.mdx +41 -1
  4. package/dist/cjs/index.js +5 -4
  5. package/dist/cjs/rules/ensure-design-token-usage-spacing/index.js +277 -0
  6. package/dist/cjs/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/utils.js +5 -3
  7. package/dist/cjs/rules/no-unsafe-design-token-usage/index.js +29 -3
  8. package/dist/cjs/rules/utils/is-node.js +1 -1
  9. package/dist/cjs/version.json +1 -1
  10. package/dist/es2019/index.js +4 -3
  11. package/dist/es2019/rules/ensure-design-token-usage-spacing/index.js +227 -0
  12. package/dist/es2019/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/utils.js +5 -3
  13. package/dist/es2019/rules/no-unsafe-design-token-usage/index.js +22 -3
  14. package/dist/es2019/rules/utils/is-node.js +1 -1
  15. package/dist/es2019/version.json +1 -1
  16. package/dist/esm/index.js +4 -3
  17. package/dist/esm/rules/ensure-design-token-usage-spacing/index.js +262 -0
  18. package/dist/esm/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/utils.js +5 -3
  19. package/dist/esm/rules/no-unsafe-design-token-usage/index.js +28 -3
  20. package/dist/esm/rules/utils/is-node.js +1 -1
  21. package/dist/esm/version.json +1 -1
  22. package/dist/types/index.d.ts +3 -2
  23. package/dist/types/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/index.d.ts +0 -0
  24. package/dist/types/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/utils.d.ts +0 -0
  25. package/dist/types/rules/utils/is-node.d.ts +2 -2
  26. package/dist/types-ts4.0/index.d.ts +3 -2
  27. package/dist/types-ts4.0/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/index.d.ts +0 -0
  28. package/dist/types-ts4.0/rules/{no-raw-spacing-values → ensure-design-token-usage-spacing}/utils.d.ts +0 -0
  29. package/dist/types-ts4.0/rules/utils/is-node.d.ts +2 -2
  30. package/package.json +2 -3
  31. package/constellation/index/props.mdx +0 -0
  32. package/dist/cjs/rules/no-raw-spacing-values/index.js +0 -180
  33. package/dist/es2019/rules/no-raw-spacing-values/index.js +0 -144
  34. package/dist/esm/rules/no-raw-spacing-values/index.js +0 -168
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 4.12.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e86c57a4a60`](https://bitbucket.org/atlassian/atlassian-frontend/commits/e86c57a4a60) - Improves the `no-raw-spacing-values` rule to include an autofixer. Spacing values that can be resolved to a token will be.
8
+
9
+ ## 4.12.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`109c705cd9c`](https://bitbucket.org/atlassian/atlassian-frontend/commits/109c705cd9c) - [ux] Adds a new case to the no-unsafe-design-token-usage rule to lint against uses of 'experimental' tokens and automatically replace them with their replacement (either a token or a fallback) via a fixer.
14
+
3
15
  ## 4.11.2
4
16
 
5
17
  ### Patch Changes
@@ -2,4 +2,312 @@
2
2
  order: 0
3
3
  ---
4
4
 
5
- examples
5
+ ## ensure-design-token-usage
6
+
7
+ Ensures that the codebase uses the global `token` function, rather than hard-coded values. This ruleset is great for codebases that are starting to adopt tokens and those that have already adopted tokens. This ruleset also prevents new contributors from accidentally adding hard-coded color values.
8
+
9
+ 👎 Example of **incorrect** code for this rule:
10
+
11
+ ```jsx
12
+ css({
13
+ color: 'red',
14
+ ^^^
15
+ });
16
+ ```
17
+
18
+ ```jsx
19
+ css({
20
+ boxShadow: '0px 1px 1px #161A1D32',
21
+ ^^^^^^^^^
22
+ })
23
+ ```
24
+
25
+ ```jsx
26
+ import { e100 } from '@atlaskit/theme/elevation';
27
+
28
+ css`
29
+ ${e100};
30
+ ^^^^
31
+ `;
32
+ ```
33
+
34
+ ```jsx
35
+ import { B100 } from '@atlaskit/theme/colors';
36
+
37
+ css({
38
+ color: B100,
39
+ ^^^^
40
+ });
41
+ ```
42
+
43
+ 👍 Example of **correct** code for this rule:
44
+
45
+ ```jsx
46
+ import { token } from '@atlaskit/tokens';
47
+
48
+ css({
49
+ boxShadow: token('elevation.shadow.card'),
50
+ });
51
+ ```
52
+
53
+ ```jsx
54
+ import { token } from '@atlaskit/tokens';
55
+
56
+ css`
57
+ color: ${token('color.text.highemphasis')};
58
+ `;
59
+ ```
60
+
61
+ ## no-deprecated-design-token-usage
62
+
63
+ Will catch deprecated token usage and autofix a replacement.
64
+
65
+ It's recommended to set this rule to "warn" on error to allow for new and old tokens to exist side-by-side for the duration of the deprecation period and avoid big-bang migrations.
66
+
67
+ Once the deprecation period is over for a token, it will be moved into `deleted` state, at which point the counterpart of this rule `eslint-plugin-design-system/no-unsafe-design-token-usage` will begin to throw errors.
68
+
69
+ Run `eslint --fix` will automatically apply replacement tokens.
70
+
71
+ 👎 Example of **incorrect** code for this rule:
72
+
73
+ ```jsx
74
+ import { token } from '@atlaskit/tokens';
75
+
76
+ css({
77
+ color: token('i.am.deprecated'), // 👎
78
+ });
79
+ ```
80
+
81
+ ```jsx
82
+ css({
83
+ color: token('i.am.a.token'), // 👍
84
+ });
85
+ ```
86
+
87
+ ## no-unsafe-design-token-usage
88
+
89
+ Ensures usages of the `token` function are done correctly, so that current token names are being used, and the resulting `var(--some-token)` statements aren't being used. This ruleset is great for codebases that have already adopted tokens.
90
+
91
+ 👎 Example of **incorrect** code for this rule:
92
+
93
+ ```jsx
94
+ const textColor = 'red';
95
+
96
+ css({
97
+ color: textColor,
98
+ ^^^^^^^^^
99
+ });
100
+ ```
101
+
102
+ ```jsx
103
+ css({
104
+ boxShadow: '0px 1px 1px var(--ds-accent-subtleBlue)',
105
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
106
+ })
107
+ ```
108
+
109
+ 👍 Example of **correct** code for this rule:
110
+
111
+ ```jsx
112
+ import { token } from '@atlaskit/tokens';
113
+
114
+ css({
115
+ boxShadow: token('elevation.shadow.card'),
116
+ });
117
+ ```
118
+
119
+ ```jsx
120
+ import { token } from '@atlaskit/tokens';
121
+
122
+ css`
123
+ color: ${(token('color.text.highemphasis'), N20)};
124
+ `;
125
+ ```
126
+
127
+ ## icon-label
128
+
129
+ Enforces accessible usage of icon labels when composed with other Design System components.
130
+
131
+ 👎 Example of **incorrect** code for this rule:
132
+
133
+ ```jsx
134
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
135
+
136
+ <ActivityIcon>
137
+ ^^^^^^^^^^^^^^ missing `label` prop
138
+ ```
139
+
140
+ ```jsx
141
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
142
+
143
+ <Button iconLeft={<ActivityIcon label="">} />
144
+ ^^^^^ label should be defined
145
+ ```
146
+
147
+ ```jsx
148
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
149
+
150
+ <ButtonItem iconBefore={<ActivityIcon label="">}>
151
+ ^^^^^ label should not be defined
152
+ My activity
153
+ </ButtonItem>
154
+ ```
155
+
156
+ 👍 Example of **correct** code for this rule:
157
+
158
+ ```jsx
159
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
160
+
161
+ <ActivityIcon label="Activity">
162
+ ```
163
+
164
+ ```jsx
165
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
166
+
167
+ <Button iconLeft={<ActivityIcon label="Activity">} />
168
+ ```
169
+
170
+ ```jsx
171
+ import ActivityIcon from '@atlaskit/icon/glyph/activity'
172
+
173
+ <ButtonItem iconBefore={<ActivityIcon label="">}>
174
+ My activity
175
+ </ButtonItem>
176
+ ```
177
+
178
+ ## no-banned-imports
179
+
180
+ Prevents usage of private or experimental Atlassian Design System packages.
181
+
182
+ 👎 Example of **incorrect** code for this rule:
183
+
184
+ ```ts
185
+ import noop from '@atlaskit/ds-lib/noop';
186
+ ^^^^^^^^^^^^^^^^^^^^^
187
+ ```
188
+
189
+ ```ts
190
+ import { Text } from '@atlaskit/ds-explorations';
191
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
192
+ ```
193
+
194
+ ## no-deprecated-api-usage
195
+
196
+ Ensures usage of current Atlassian Design System API usage.
197
+
198
+ 👎 Example of **incorrect** code for this rule:
199
+
200
+ ```jsx
201
+ import { ButtonItem } from '@atlaskit/menu';
202
+
203
+ const Element = () => (
204
+ <ButtonItem cssFn={cssFn()} />
205
+ ^^^^
206
+ );
207
+ ```
208
+
209
+ ```jsx
210
+ import Drawer from '@atlaskit/drawer';
211
+
212
+ const Element = () => (
213
+ <Drawer overrides={overrides} />
214
+ ^^^^
215
+ );
216
+ ```
217
+
218
+ 👍 Example of **correct** code for this rule:
219
+
220
+ ```jsx
221
+ import { SomeElement } from 'some-other-library';
222
+
223
+ const Element = () => <SomeElement cssFn={cssFn()} />;
224
+ ```
225
+
226
+ ```jsx
227
+ import { ButtonItem } from '@atlaskit/menu';
228
+
229
+ const Element = () => <ButtonItem />;
230
+ ```
231
+
232
+ ```jsx
233
+ import Drawer from '@atlaskit/drawer';
234
+
235
+ const Element = () => <Drawer />;
236
+ ```
237
+
238
+ ## no-deprecated-imports
239
+
240
+ Ensures usage of current Atlassian Design System dependencies.
241
+
242
+ 👎 Example of **incorrect** code for this rule:
243
+
244
+ ```ts
245
+ import Item from '@atlaskit/item';
246
+ ^^^^^^^^^^^^^^
247
+ ```
248
+
249
+ ```ts
250
+ import GlobalNav from '@atlaskit/global-navigation';
251
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
252
+ ```
253
+
254
+ 👍 Example of **correct** code for this rule:
255
+
256
+ ```ts
257
+ import Modal from '@atlaskit/modal-dialog';
258
+ ```
259
+
260
+ ```ts
261
+ import { ButtonItem } from '@atlaskit/menu';
262
+ ```
263
+
264
+ ## use-visually-hidden
265
+
266
+ This rule makes Design System consumers aware of the existing solutions.
267
+
268
+ 👎 Example of **incorrect** code for this rule:
269
+
270
+ ```jsx
271
+ import { css } from '@emotion/core';
272
+
273
+ const visuallyHiddenStyles = css({
274
+ width: '1px',
275
+ height: '1px',
276
+ padding: '0',
277
+ position: 'absolute',
278
+ border: '0',
279
+ clip: 'rect(1px, 1px, 1px, 1px)',
280
+ overflow: 'hidden',
281
+ whiteSpace: 'nowrap',
282
+ });
283
+ ^^^^
284
+ ```
285
+
286
+ ```jsx
287
+ import styled from '@emotion/styled';
288
+
289
+ const VisuallyHidden = styled.span`
290
+ width: 1px;
291
+ height: 1px;
292
+ padding: 0;
293
+ position: absolute;
294
+ border: 0;
295
+ clip: rect(1px, 1px, 1px, 1px);
296
+ overflow: hidden;
297
+ whiteSpace: nowrap;
298
+ `;
299
+ ^^^^
300
+ ```
301
+
302
+ ```jsx
303
+ import { visuallyHidden } from '@atlaskit/theme/constants';
304
+
305
+ const VisuallyHidden = styled.span`${visuallyHidden()}`;
306
+ ^^^^^^^^^^^^^^
307
+ ```
308
+
309
+ 👍 Example of **correct** code for this rule:
310
+
311
+ ```jsx
312
+ import VisuallyHidden from '@atlaskit/visually-hidden';
313
+ ```
@@ -2,4 +2,44 @@
2
2
  order: 2
3
3
  ---
4
4
 
5
- usage
5
+ This plugin contains rules that should be used with the Atlassian Design System.
6
+ Where possible, these rules come with auto fixers.
7
+
8
+ You can read more about configuring eslint in their [documentation](https://eslint.org/docs/user-guide/configuring).
9
+
10
+ ## Configuration
11
+
12
+ Add the plugin to your `.eslintrc.js` file.
13
+
14
+ ```diff
15
+ module.exports = {
16
+ plugins: [
17
+ + '@atlaskit/design-system',
18
+ ],
19
+ };
20
+ ```
21
+
22
+ Extend the configuration file.
23
+
24
+ ```diff
25
+ module.exports = {
26
+ extends: [
27
+ + 'plugin:@atlaskit/design-system/recommended',
28
+ ],
29
+ };
30
+ ```
31
+
32
+ Enable any desired rules. The rules shown below are strongly recommended.
33
+
34
+ ```diff
35
+ module.exports = {
36
+ rules: {
37
+ + '@atlaskit/design-system/ensure-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
38
+ + '@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
39
+ + '@atlaskit/design-system/no-unsafe-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
40
+ + '@atlaskit/design-system/use-visually-hidden': 'error',
41
+ + '@atlaskit/design-system/no-deprecated-imports': 'error',
42
+ + '@atlaskit/design-system/no-deprecated-apis': 'error'
43
+ }
44
+ };
45
+ ```
package/dist/cjs/index.js CHANGED
@@ -9,6 +9,8 @@ exports.rules = exports.configs = void 0;
9
9
 
10
10
  var _ensureDesignTokenUsage = _interopRequireDefault(require("./rules/ensure-design-token-usage"));
11
11
 
12
+ var _ensureDesignTokenUsageSpacing = _interopRequireDefault(require("./rules/ensure-design-token-usage-spacing"));
13
+
12
14
  var _iconLabel = _interopRequireDefault(require("./rules/icon-label"));
13
15
 
14
16
  var _noBannedImports = _interopRequireDefault(require("./rules/no-banned-imports"));
@@ -19,8 +21,6 @@ var _noDeprecatedDesignTokenUsage = _interopRequireDefault(require("./rules/no-d
19
21
 
20
22
  var _noDeprecatedImports = _interopRequireDefault(require("./rules/no-deprecated-imports"));
21
23
 
22
- var _noRawSpacingValues = _interopRequireDefault(require("./rules/no-raw-spacing-values"));
23
-
24
24
  var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./rules/no-unsafe-design-token-usage"));
25
25
 
26
26
  var _useVisuallyHidden = _interopRequireDefault(require("./rules/use-visually-hidden"));
@@ -34,7 +34,7 @@ var rules = {
34
34
  'no-banned-imports': _noBannedImports.default,
35
35
  'no-unsafe-design-token-usage': _noUnsafeDesignTokenUsage.default,
36
36
  'use-visually-hidden': _useVisuallyHidden.default,
37
- 'no-raw-spacing-values': _noRawSpacingValues.default
37
+ 'ensure-design-token-usage-spacing': _ensureDesignTokenUsageSpacing.default
38
38
  };
39
39
  exports.rules = rules;
40
40
  var configs = {
@@ -57,7 +57,8 @@ var configs = {
57
57
  '@atlaskit/design-system/use-visually-hidden': 'error',
58
58
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
59
59
  '@atlaskit/design-system/no-banned-imports': 'error',
60
- '@atlaskit/design-system/no-raw-spacing-values': 'error'
60
+ '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
61
+ '@atlaskit/design-system/ensure-design-token-usage-spacing': 'error'
61
62
  }
62
63
  }
63
64
  };
@@ -0,0 +1,277 @@
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
15
+
16
+ var _spacingRaw = _interopRequireDefault(require("@atlaskit/tokens/spacing-raw"));
17
+
18
+ var _isNode = require("../utils/is-node");
19
+
20
+ var _utils = require("./utils");
21
+
22
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
23
+
24
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
25
+
26
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
27
+
28
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
29
+
30
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
31
+
32
+ var spacingValueToToken = Object.fromEntries(_spacingRaw.default.map(function (token) {
33
+ return [token.value, token.name];
34
+ }));
35
+ /**
36
+ * @example
37
+ * ```
38
+ * '8px' => token('spacing.scale.100', '8px')
39
+ * ```
40
+ */
41
+
42
+ function pixelValueToSpacingTokenNode(pixelValueString) {
43
+ var _spacingValueToToken$;
44
+
45
+ return (0, _eslintCodemodUtils.callExpression)({
46
+ callee: (0, _eslintCodemodUtils.identifier)({
47
+ name: 'token'
48
+ }),
49
+ arguments: [(0, _eslintCodemodUtils.literal)({
50
+ value: "'".concat((_spacingValueToToken$ = spacingValueToToken[pixelValueString]) !== null && _spacingValueToToken$ !== void 0 ? _spacingValueToToken$ : '', "'")
51
+ }), (0, _eslintCodemodUtils.literal)("'".concat(pixelValueString, "'"))],
52
+ optional: false
53
+ });
54
+ }
55
+
56
+ var rule = {
57
+ meta: {
58
+ type: 'problem',
59
+ fixable: 'code',
60
+ docs: {
61
+ description: 'Rule ensures all spacing CSS properties apply a matching spacing token',
62
+ recommended: true
63
+ },
64
+ messages: {
65
+ noMarginProperties: 'The use of margin is considered a dangerous as it breaks the component model. Prefer the application of `gap` via CSS Flexbox or Grid to achieve the same result and control the layout from the parent.',
66
+ noRawSpacingValues: 'The use of spacing primitives or tokens is preferred over the direct application of spacing properties.\n\n@meta <<{{payload}}>>'
67
+ }
68
+ },
69
+ create: function create(context) {
70
+ return {
71
+ // CSSObjectExpression
72
+ // const styles = css({ color: 'red', margin: '4px' })
73
+ 'CallExpression[callee.name=css] > ObjectExpression': function CallExpressionCalleeNameCssObjectExpression(parentNode) {
74
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(parentNode, 'ObjectExpression')) {
75
+ return;
76
+ }
77
+ /**
78
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
79
+ */
80
+
81
+
82
+ var fontSizeNode = parentNode.properties.find(function (node) {
83
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'Property')) {
84
+ return;
85
+ }
86
+
87
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.key, 'Identifier')) {
88
+ return;
89
+ }
90
+
91
+ return node.key.name === 'fontSize';
92
+ });
93
+ var fontSizeValue = (0, _utils.getValue)( // @ts-ignore
94
+ (0, _eslintCodemodUtils.isNodeOfType)(fontSizeNode, 'Property') && fontSizeNode.value, context);
95
+ var fontSize = Array.isArray(fontSizeValue) ? fontSizeValue[0] : fontSizeValue;
96
+ parentNode.properties.forEach(function (node) {
97
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'Property')) {
98
+ return;
99
+ }
100
+
101
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.key, 'Identifier')) {
102
+ return;
103
+ }
104
+
105
+ if (!(0, _utils.isSpacingProperty)(node.key.name)) {
106
+ return;
107
+ }
108
+
109
+ if ((0, _isNode.isDecendantOfGlobalToken)(node.value)) {
110
+ return;
111
+ }
112
+
113
+ if (node.value.type === 'Literal' && !(0, _utils.isValidSpacingValue)(node.value.value, fontSize)) {
114
+ context.report({
115
+ node: node,
116
+ messageId: 'noRawSpacingValues',
117
+ data: {
118
+ payload: "NaN:".concat(node.value.value)
119
+ }
120
+ });
121
+ return;
122
+ }
123
+
124
+ var value = (0, _utils.getValue)(node.value, context); // value is either NaN or it can't be resolved eg, em, 100% etc...
125
+
126
+ if (!(value && (0, _utils.isValidSpacingValue)(value, fontSize))) {
127
+ return context.report({
128
+ node: node,
129
+ messageId: 'noRawSpacingValues',
130
+ data: {
131
+ payload: "NaN:".concat(value)
132
+ }
133
+ });
134
+ }
135
+
136
+ var values = Array.isArray(value) ? value : [value]; // value is a single value so we can apply a more robust approach to our fix
137
+
138
+ if (values.length === 1) {
139
+ var _values = (0, _slicedToArray2.default)(values, 1),
140
+ _value = _values[0];
141
+
142
+ var pixelValue = (0, _utils.emToPixels)(_value, fontSize);
143
+ return context.report({
144
+ node: node,
145
+ messageId: 'noRawSpacingValues',
146
+ data: {
147
+ payload: "".concat(node.key.name, ":").concat(pixelValue)
148
+ },
149
+ fix: function fix(fixer) {
150
+ var _node$loc;
151
+
152
+ if (!/padding|margin|gap/.test(node.key.name)) {
153
+ return null;
154
+ }
155
+
156
+ var pixelValueString = "".concat(pixelValue, "px");
157
+ var tokenName = spacingValueToToken[pixelValueString];
158
+
159
+ if (!tokenName) {
160
+ return null;
161
+ }
162
+
163
+ return [fixer.insertTextBefore(node, "// TODO Delete this comment after verifying spacing token -> previous value `".concat((0, _eslintCodemodUtils.node)(node.value), "`\n").concat(' '.padStart(((_node$loc = node.loc) === null || _node$loc === void 0 ? void 0 : _node$loc.start.column) || 0))), fixer.replaceText(node, (0, _eslintCodemodUtils.property)(_objectSpread(_objectSpread({}, node), {}, {
164
+ value: pixelValueToSpacingTokenNode(pixelValueString)
165
+ })).toString())];
166
+ }
167
+ });
168
+ }
169
+ /**
170
+ * Compound values are hard to deal with / replace because we need to find/replace strings inside an
171
+ * estree node.
172
+ *
173
+ * @example
174
+ * { padding: '8px 0px' } // two values we don't try and apply the fixer
175
+ */
176
+
177
+
178
+ values.forEach(function (val, index) {
179
+ var pixelValue = (0, _utils.emToPixels)(val, fontSize);
180
+ context.report({
181
+ node: node,
182
+ messageId: 'noRawSpacingValues',
183
+ data: {
184
+ payload: "".concat(node.key.name, ":").concat(pixelValue)
185
+ },
186
+ fix: index === 0 ? function (fixer) {
187
+ var allResolvableValues = values.every(function (value) {
188
+ return !Number.isNaN((0, _utils.emToPixels)(value, fontSize));
189
+ });
190
+
191
+ if (!allResolvableValues) {
192
+ return null;
193
+ }
194
+
195
+ return fixer.replaceText(node.value, "`".concat(values.map(function (value) {
196
+ var pixelValue = (0, _utils.emToPixels)(value, fontSize);
197
+ var pixelValueString = "".concat(pixelValue, "px");
198
+ return "${".concat(pixelValueToSpacingTokenNode(pixelValueString), "}");
199
+ }).join(' '), "`"));
200
+ } : undefined
201
+ });
202
+ });
203
+ });
204
+ },
205
+ // CSSTemplateLiteral and StyledTemplateLiteral
206
+ // const cssTemplateLiteral = css`color: red; padding: 12px`;
207
+ // const styledTemplateLiteral = styled.p`color: red; padding: 8px`;
208
+ 'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyled(node) {
209
+ if (node.type !== 'TaggedTemplateExpression') {
210
+ return;
211
+ }
212
+
213
+ var combinedString = node.quasi.quasis.map(function (q, i) {
214
+ return "".concat(q.value.raw).concat(node.quasi.expressions[i] ? (0, _utils.getValue)(node.quasi.expressions[i], context) : '');
215
+ }).join('');
216
+ /**
217
+ * Attempts to remove all non-essential words & characters from a style block.
218
+ * Including selectors and queries
219
+ * Adapted from ensure-design-token-usage
220
+ */
221
+
222
+ var cssProperties = combinedString.split('\n').filter(function (line) {
223
+ return !line.trim().startsWith('@');
224
+ }).join('\n').replace(/\n/g, '').split(/;|{|}/).map(function (el) {
225
+ return el.trim() || '';
226
+ });
227
+ cssProperties.forEach(function (style) {
228
+ var _style$split = style.split(':'),
229
+ _style$split2 = (0, _slicedToArray2.default)(_style$split, 2),
230
+ rawProperty = _style$split2[0],
231
+ value = _style$split2[1];
232
+
233
+ var property = (0, _utils.convertHyphenatedNameToCamelCase)(rawProperty);
234
+
235
+ if (!(0, _utils.isSpacingProperty)(property)) {
236
+ return;
237
+ }
238
+
239
+ if (!(0, _utils.isValidSpacingValue)(value)) {
240
+ return context.report({
241
+ node: node,
242
+ messageId: 'noRawSpacingValues',
243
+ data: {
244
+ payload: "NaN:".concat(value)
245
+ }
246
+ });
247
+ }
248
+
249
+ var values = (0, _utils.getValueFromShorthand)(value);
250
+
251
+ var _iterator = _createForOfIteratorHelper(values),
252
+ _step;
253
+
254
+ try {
255
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
256
+ var val = _step.value;
257
+ // could be array of values e.g. padding: 8px 12px 3px
258
+ context.report({
259
+ node: node,
260
+ messageId: 'noRawSpacingValues',
261
+ data: {
262
+ payload: "".concat(property, ":").concat(val)
263
+ }
264
+ });
265
+ }
266
+ } catch (err) {
267
+ _iterator.e(err);
268
+ } finally {
269
+ _iterator.f();
270
+ }
271
+ });
272
+ }
273
+ };
274
+ }
275
+ };
276
+ var _default = rule;
277
+ exports.default = _default;