@atlaskit/eslint-plugin-platform 2.0.2 → 2.1.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/index.js +3 -0
  3. package/dist/cjs/rules/compiled/expand-background-shorthand/index.js +2 -17
  4. package/dist/cjs/rules/compiled/expand-spacing-shorthand/index.js +196 -0
  5. package/dist/cjs/rules/util/compiled-utils.js +21 -0
  6. package/dist/cjs/rules/util/context-compat.js +2 -2
  7. package/dist/es2019/index.js +3 -0
  8. package/dist/es2019/rules/compiled/expand-background-shorthand/index.js +1 -15
  9. package/dist/es2019/rules/compiled/expand-spacing-shorthand/index.js +162 -0
  10. package/dist/es2019/rules/util/compiled-utils.js +15 -0
  11. package/dist/es2019/rules/util/context-compat.js +1 -1
  12. package/dist/esm/index.js +3 -0
  13. package/dist/esm/rules/compiled/expand-background-shorthand/index.js +1 -16
  14. package/dist/esm/rules/compiled/expand-spacing-shorthand/index.js +189 -0
  15. package/dist/esm/rules/util/compiled-utils.js +16 -0
  16. package/dist/esm/rules/util/context-compat.js +1 -1
  17. package/dist/types/index.d.ts +3 -0
  18. package/dist/types/rules/compiled/expand-spacing-shorthand/index.d.ts +3 -0
  19. package/dist/types/rules/util/compiled-utils.d.ts +3 -0
  20. package/dist/types/rules/util/context-compat.d.ts +12 -1
  21. package/dist/types-ts4.5/index.d.ts +3 -0
  22. package/dist/types-ts4.5/rules/compiled/expand-spacing-shorthand/index.d.ts +3 -0
  23. package/dist/types-ts4.5/rules/util/compiled-utils.d.ts +3 -0
  24. package/dist/types-ts4.5/rules/util/context-compat.d.ts +12 -1
  25. package/package.json +1 -1
  26. package/src/index.tsx +3 -0
  27. package/src/rules/compiled/expand-background-shorthand/__tests__/rule.test.ts +1 -1
  28. package/src/rules/compiled/expand-background-shorthand/index.tsx +1 -25
  29. package/src/rules/compiled/expand-spacing-shorthand/README.md +38 -0
  30. package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +344 -0
  31. package/src/rules/compiled/expand-spacing-shorthand/index.ts +150 -0
  32. package/src/rules/util/compiled-utils.ts +27 -0
  33. package/src/rules/util/context-compat.ts +1 -1
  34. package/tsconfig.app.json +0 -1
  35. package/tsconfig.dev.json +0 -1
  36. package/tsconfig.json +0 -1
@@ -0,0 +1,189 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ import { getSourceCode } from '../../util/context-compat';
6
+ import { isCompiledAPI } from '../../util/compiled-utils';
7
+ var spacingPos = ["Top", "Right", "Bottom", "Left"];
8
+ ;
9
+
10
+ // Checks if node is a call expression with identifier 'token'
11
+ var isTokenCallExpression = function isTokenCallExpression(node) {
12
+ if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
13
+ return true;
14
+ }
15
+ return false;
16
+ };
17
+
18
+ // Given a TemplateLiteral node, returns the value of the spacing property as an array of strings
19
+ // e.g. `0 ${token('a')} ${token('b')}` -> ['0', 'token('a')', 'token('b')']
20
+ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, context) {
21
+ var expressions = templateLiteral.expressions;
22
+ var quasis = templateLiteral.quasis;
23
+ var propertyValues = [];
24
+ for (var i = 0; i < expressions.length || i < quasis.length; i++) {
25
+ if (i < quasis.length) {
26
+ var cookedQuasi = quasis[i].value.cooked;
27
+ if (cookedQuasi) {
28
+ var splitQuasi = cookedQuasi.split(" ").filter(function (str) {
29
+ return str.length > 0;
30
+ });
31
+ splitQuasi.forEach(function (str) {
32
+ propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
33
+ });
34
+ }
35
+ }
36
+ if (i < expressions.length) {
37
+ var expr = getSourceCode(context).getText(expressions[i]);
38
+ propertyValues.push(expr);
39
+ }
40
+ }
41
+ return propertyValues;
42
+ };
43
+ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
44
+ if (!propertyValues.some(function (str) {
45
+ return str.includes("token(");
46
+ })) {
47
+ return false;
48
+ }
49
+ if (propertyValues.length < 1 || propertyValues.length > 4) {
50
+ return false;
51
+ }
52
+ if (propertyValues.some(function (str) {
53
+ return str.includes("calc(");
54
+ })) {
55
+ return false;
56
+ }
57
+ return true;
58
+ };
59
+
60
+ // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
61
+ var expandSpacingProperties = function expandSpacingProperties(_ref) {
62
+ var context = _ref.context,
63
+ node = _ref.node,
64
+ propertyValues = _ref.propertyValues,
65
+ fixer = _ref.fixer,
66
+ propertyShorthand = _ref.propertyShorthand;
67
+ var _propertyValues = _slicedToArray(propertyValues, 4),
68
+ top = _propertyValues[0],
69
+ _propertyValues$ = _propertyValues[1],
70
+ right = _propertyValues$ === void 0 ? top : _propertyValues$,
71
+ _propertyValues$2 = _propertyValues[2],
72
+ bottom = _propertyValues$2 === void 0 ? top : _propertyValues$2,
73
+ _propertyValues$3 = _propertyValues[3],
74
+ left = _propertyValues$3 === void 0 ? right : _propertyValues$3;
75
+ var spacing = [top, right, bottom, left];
76
+ var fixes = [];
77
+ var parentNode = node.parent;
78
+ if (parentNode && parentNode.type === 'ObjectExpression') {
79
+ var _iterator = _createForOfIteratorHelper(parentNode.properties),
80
+ _step;
81
+ try {
82
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
83
+ var prop = _step.value;
84
+ if (prop.type !== 'Property') {
85
+ continue;
86
+ }
87
+ if (prop.key.type === 'Identifier' && prop.range && prop.key.name !== "".concat(propertyShorthand)) {
88
+ for (var i = 0; i < spacing.length; i++) {
89
+ if (prop.key.name === "".concat(propertyShorthand).concat(spacingPos[i])) {
90
+ var _prop$range = _slicedToArray(prop.range, 2),
91
+ start = _prop$range[0],
92
+ end = _prop$range[1];
93
+ // Remove the entire line for the duplicate property
94
+ while (getSourceCode(context).text[end] !== "\n") {
95
+ end += 1;
96
+ }
97
+ while (getSourceCode(context).text[start] !== "\n") {
98
+ start -= 1;
99
+ }
100
+ spacing[i] = getSourceCode(context).getText(prop.value);
101
+ fixes.push(fixer.removeRange([start, end]));
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ }
107
+ } catch (err) {
108
+ _iterator.e(err);
109
+ } finally {
110
+ _iterator.f();
111
+ }
112
+ }
113
+ fixes.push(fixer.insertTextAfter(node, "".concat(propertyShorthand, "Top: ").concat(spacing[0], ",\n")));
114
+ fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Right: ").concat(spacing[1], ",\n")));
115
+ fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Bottom: ").concat(spacing[2], ",\n")));
116
+ fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Left: ").concat(spacing[3])));
117
+ fixes.push(fixer.remove(node));
118
+ return fixes;
119
+ };
120
+ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node, propertyShorthand) {
121
+ if (!isCompiledAPI(context, node)) {
122
+ return;
123
+ }
124
+ if (node.value.type === 'TemplateLiteral') {
125
+ // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
126
+ var propertyValues = parseTemplateLiteral(node.value, context);
127
+ if (!checkValidPropertyValues(propertyValues)) {
128
+ return;
129
+ }
130
+ context.report({
131
+ node: node,
132
+ messageId: 'expandSpacingShorthand',
133
+ data: {
134
+ property: propertyShorthand
135
+ },
136
+ fix: function fix(fixer) {
137
+ return expandSpacingProperties({
138
+ context: context,
139
+ node: node,
140
+ propertyValues: propertyValues,
141
+ fixer: fixer,
142
+ propertyShorthand: propertyShorthand
143
+ });
144
+ }
145
+ });
146
+ } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
147
+ // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
148
+ var _propertyValues2 = [getSourceCode(context).getText(node.value)];
149
+ context.report({
150
+ node: node,
151
+ messageId: 'expandSpacingShorthand',
152
+ data: {
153
+ property: propertyShorthand
154
+ },
155
+ fix: function fix(fixer) {
156
+ return expandSpacingProperties({
157
+ context: context,
158
+ node: node,
159
+ propertyValues: _propertyValues2,
160
+ fixer: fixer,
161
+ propertyShorthand: propertyShorthand
162
+ });
163
+ }
164
+ });
165
+ }
166
+ };
167
+ export var expandSpacingShorthand = {
168
+ meta: {
169
+ docs: {
170
+ url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/'
171
+ },
172
+ messages: {
173
+ expandSpacingShorthand: 'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand'
174
+ },
175
+ type: 'problem',
176
+ fixable: 'code'
177
+ },
178
+ create: function create(context) {
179
+ return {
180
+ 'Property[key.name="padding"]': function PropertyKeyNamePadding(node) {
181
+ executeExpandSpacingRule(context, node, 'padding');
182
+ },
183
+ 'Property[key.name="margin"]': function PropertyKeyNameMargin(node) {
184
+ executeExpandSpacingRule(context, node, 'margin');
185
+ }
186
+ };
187
+ }
188
+ };
189
+ export default expandSpacingShorthand;
@@ -0,0 +1,16 @@
1
+ import { getAncestors, getScope } from './context-compat';
2
+ import { getImportSources, isCompiled, isAtlasKitCSS } from '@atlaskit/eslint-utils/is-supported-import';
3
+
4
+ // Checks if the function that holds the property is using a Compiled import package that this rule is targeting
5
+ export var isCompiledAPI = function isCompiledAPI(context, node) {
6
+ var importSources = getImportSources(context);
7
+ var _getScope = getScope(context, node),
8
+ references = _getScope.references;
9
+ var ancestors = getAncestors(context, node);
10
+ if (ancestors.some(function (ancestor) {
11
+ return ancestor.type === 'CallExpression' && ancestor.callee && (isCompiled(ancestor.callee, references, importSources) || isAtlasKitCSS(ancestor.callee, references, importSources));
12
+ })) {
13
+ return true;
14
+ }
15
+ return false;
16
+ };
@@ -9,7 +9,7 @@
9
9
  * `context.getSourceCode()` is deprecated in v8 and removed in v9.
10
10
  * @param context - The ESLint rule context
11
11
  */
12
- var getSourceCode = function getSourceCode(context) {
12
+ export var getSourceCode = function getSourceCode(context) {
13
13
  var _context$sourceCode;
14
14
  return (_context$sourceCode = context.sourceCode) !== null && _context$sourceCode !== void 0 ? _context$sourceCode : context.getSourceCode();
15
15
  };
@@ -10,6 +10,7 @@ export declare const rules: {
10
10
  'ensure-valid-bin-values': import("eslint").Rule.RuleModule;
11
11
  'expand-border-shorthand': import("eslint").Rule.RuleModule;
12
12
  'expand-background-shorthand': import("eslint").Rule.RuleModule;
13
+ 'expand-spacing-shorthand': import("eslint").Rule.RuleModule;
13
14
  'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
14
15
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
15
16
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
@@ -48,6 +49,7 @@ export declare const configs: {
48
49
  '@atlaskit/platform/no-module-level-eval-nav4': string;
49
50
  '@atlaskit/platform/expand-border-shorthand': string;
50
51
  '@atlaskit/platform/expand-background-shorthand': string;
52
+ '@atlaskit/platform/expand-spacing-shorthand': string;
51
53
  '@compiled/jsx-pragma': (string | {
52
54
  importSources: string[];
53
55
  onlyRunIfImportingCompiled: boolean;
@@ -66,6 +68,7 @@ export declare const configs: {
66
68
  '@atlaskit/platform/no-module-level-eval-nav4': string;
67
69
  '@atlaskit/platform/expand-border-shorthand': string;
68
70
  '@atlaskit/platform/expand-background-shorthand': string;
71
+ '@atlaskit/platform/expand-spacing-shorthand': string;
69
72
  '@compiled/jsx-pragma': (string | {
70
73
  importSources: string[];
71
74
  onlyRunIfImportingCompiled: boolean;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const expandSpacingShorthand: Rule.RuleModule;
3
+ export default expandSpacingShorthand;
@@ -0,0 +1,3 @@
1
+ import type { Node } from 'estree';
2
+ import type { Rule } from 'eslint';
3
+ export declare const isCompiledAPI: (context: Rule.RuleContext, node: Node) => boolean;
@@ -1,5 +1,16 @@
1
- import type { Rule, Scope } from 'eslint';
1
+ import type { Rule, Scope, SourceCode } from 'eslint';
2
2
  import type { Node } from 'estree';
3
+ /**
4
+ * TODO: Consider whether this should be replaced by ESLint's compat library.
5
+ * Either way, this should be removed once we no longer need to support ESLint versions less than 8.40.
6
+ */
7
+ /**
8
+ * A compatibility layer to support older versions of ESLint.
9
+ * `context.sourceCode` is the preferred way to access SourceCode, as
10
+ * `context.getSourceCode()` is deprecated in v8 and removed in v9.
11
+ * @param context - The ESLint rule context
12
+ */
13
+ export declare const getSourceCode: (context: Rule.RuleContext) => SourceCode;
3
14
  /**
4
15
  * A compatibility layer to support older versions of ESLint.
5
16
  * `context.sourceCode.getScope()` is the preferred way to access Scope, as
@@ -10,6 +10,7 @@ export declare const rules: {
10
10
  'ensure-valid-bin-values': import("eslint").Rule.RuleModule;
11
11
  'expand-border-shorthand': import("eslint").Rule.RuleModule;
12
12
  'expand-background-shorthand': import("eslint").Rule.RuleModule;
13
+ 'expand-spacing-shorthand': import("eslint").Rule.RuleModule;
13
14
  'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
14
15
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
15
16
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
@@ -48,6 +49,7 @@ export declare const configs: {
48
49
  '@atlaskit/platform/no-module-level-eval-nav4': string;
49
50
  '@atlaskit/platform/expand-border-shorthand': string;
50
51
  '@atlaskit/platform/expand-background-shorthand': string;
52
+ '@atlaskit/platform/expand-spacing-shorthand': string;
51
53
  '@compiled/jsx-pragma': (string | {
52
54
  importSources: string[];
53
55
  onlyRunIfImportingCompiled: boolean;
@@ -66,6 +68,7 @@ export declare const configs: {
66
68
  '@atlaskit/platform/no-module-level-eval-nav4': string;
67
69
  '@atlaskit/platform/expand-border-shorthand': string;
68
70
  '@atlaskit/platform/expand-background-shorthand': string;
71
+ '@atlaskit/platform/expand-spacing-shorthand': string;
69
72
  '@compiled/jsx-pragma': (string | {
70
73
  importSources: string[];
71
74
  onlyRunIfImportingCompiled: boolean;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const expandSpacingShorthand: Rule.RuleModule;
3
+ export default expandSpacingShorthand;
@@ -0,0 +1,3 @@
1
+ import type { Node } from 'estree';
2
+ import type { Rule } from 'eslint';
3
+ export declare const isCompiledAPI: (context: Rule.RuleContext, node: Node) => boolean;
@@ -1,5 +1,16 @@
1
- import type { Rule, Scope } from 'eslint';
1
+ import type { Rule, Scope, SourceCode } from 'eslint';
2
2
  import type { Node } from 'estree';
3
+ /**
4
+ * TODO: Consider whether this should be replaced by ESLint's compat library.
5
+ * Either way, this should be removed once we no longer need to support ESLint versions less than 8.40.
6
+ */
7
+ /**
8
+ * A compatibility layer to support older versions of ESLint.
9
+ * `context.sourceCode` is the preferred way to access SourceCode, as
10
+ * `context.getSourceCode()` is deprecated in v8 and removed in v9.
11
+ * @param context - The ESLint rule context
12
+ */
13
+ export declare const getSourceCode: (context: Rule.RuleContext) => SourceCode;
3
14
  /**
4
15
  * A compatibility layer to support older versions of ESLint.
5
16
  * `context.sourceCode.getScope()` is the preferred way to access Scope, as
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-platform",
3
3
  "description": "The essential plugin for use with Atlassian frontend platform tools",
4
- "version": "2.0.2",
4
+ "version": "2.1.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
7
7
  "team": "Build Infra",
package/src/index.tsx CHANGED
@@ -25,6 +25,7 @@ import noAlias from './rules/feature-gating/no-alias';
25
25
  import useEntrypointsInExamples from './rules/use-entrypoints-in-examples';
26
26
  import useRecommendedUtils from './rules/feature-gating/use-recommended-utils';
27
27
  import expandBackgroundShorthand from './rules/compiled/expand-background-shorthand';
28
+ import expandSpacingShorthand from './rules/compiled/expand-spacing-shorthand';
28
29
 
29
30
  export const rules = {
30
31
  'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
@@ -37,6 +38,7 @@ export const rules = {
37
38
  'ensure-valid-bin-values': ensureValidBinValues,
38
39
  'expand-border-shorthand': expandBorderShorthand,
39
40
  'expand-background-shorthand': expandBackgroundShorthand,
41
+ 'expand-spacing-shorthand': expandSpacingShorthand,
40
42
  'no-duplicate-dependencies': noDuplicateDependencies,
41
43
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
42
44
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
@@ -64,6 +66,7 @@ const commonConfig = {
64
66
  // Compiled: rules that are not included via `@compiled/recommended
65
67
  '@atlaskit/platform/expand-border-shorthand': 'error',
66
68
  '@atlaskit/platform/expand-background-shorthand': 'error',
69
+ '@atlaskit/platform/expand-spacing-shorthand': 'warn',
67
70
  '@compiled/jsx-pragma': [
68
71
  'error',
69
72
  {
@@ -13,7 +13,7 @@ const exempt_packages_calls_and_imports = [
13
13
  ['css', 'styled-components'],
14
14
  ['xcss', '@atlaskit/primitives'],
15
15
  ];
16
- tester.run('expand-border-shorthand', expandBackgroundShorthand, {
16
+ tester.run('expand-background-shorthand', expandBackgroundShorthand, {
17
17
  valid: [
18
18
  ...exempt_packages_calls_and_imports.map(([pkg, imp]) => ({
19
19
  name: `do not have to handle non-Compiled packages (${pkg}, ${imp})`,
@@ -1,30 +1,6 @@
1
1
  import type { Rule } from 'eslint';
2
2
  import type { Property, Node } from 'estree';
3
- import {
4
- getImportSources,
5
- isCompiled,
6
- isAtlasKitCSS,
7
- } from '@atlaskit/eslint-utils/is-supported-import';
8
- import { getAncestors, getScope } from '../../util/context-compat';
9
-
10
- // Checks if the function that holds the border property is using an import package that this rule is targeting
11
- const isCompiledAPI = (context: Rule.RuleContext, node: Node): boolean => {
12
- const importSources = getImportSources(context);
13
- const { references } = getScope(context, node);
14
- const ancestors = getAncestors(context, node);
15
- if (
16
- ancestors.some(
17
- (ancestor) =>
18
- ancestor.type === 'CallExpression' &&
19
- ancestor.callee &&
20
- (isCompiled(ancestor.callee, references, importSources) ||
21
- isAtlasKitCSS(ancestor.callee, references, importSources)),
22
- )
23
- ) {
24
- return true;
25
- }
26
- return false;
27
- };
3
+ import { isCompiledAPI } from '../../util/compiled-utils';
28
4
 
29
5
  // Checks if node is a call expression with identifier 'token'
30
6
  const isTokenCallExpression = (node: Node) => {
@@ -0,0 +1,38 @@
1
+ # `expand-spacing-shorthand`
2
+
3
+ This ESLint rule enforces the expansion of the CSS `padding` and `margin` shorthand properties into
4
+ its longhand equivalent `{spacing}Top`, `{spacing}Right`, `{spacing}Bottom`, `{spacing}Left`, where
5
+ the property's value is either an Atlassian Design System token or a template literal which contains
6
+ a token, and the function call originates from `@compiled/react` or `@atlaskit/css`.
7
+
8
+ ## Rule details
9
+
10
+ 👎 Examples of **incorrect** code for this rule:
11
+
12
+ ```js
13
+ const styles = css({
14
+ padding: token('space.200'),
15
+ });
16
+
17
+ const styles = css({
18
+ margin: `${token('space.100')} 0 2px`,
19
+ });
20
+ ```
21
+
22
+ 👍 Examples of **correct** code for this rule:
23
+
24
+ ```js
25
+ const styles = css({
26
+ paddingTop: token('space.200'),
27
+ paddingRight: token('space.200'),
28
+ paddingBottom: token('space.200'),
29
+ paddingLeft: token('space.200'),
30
+ });
31
+
32
+ const styles = css({
33
+ marginTop: token('space.100'),
34
+ marginRight: 0,
35
+ marginBottom: '2px',
36
+ marginLeft: 0,
37
+ });
38
+ ```