@atlaskit/eslint-plugin-platform 2.2.0 → 2.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @atlaskit/eslint-plugin-platform
2
2
 
3
+ ## 2.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#103444](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/103444)
8
+ [`5d5006fe81146`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/5d5006fe81146) -
9
+ AFB-822 Refactor ESLint rule and added an extra case for when ESLint rule should throw error but
10
+ not provide a fix
11
+
3
12
  ## 2.2.0
4
13
 
5
14
  ### Minor Changes
@@ -46,31 +46,74 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
46
46
  }
47
47
  return propertyValues;
48
48
  };
49
- var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
49
+
50
+ /**
51
+ * Checks if the parsed property values are valid (i.e. no rule violation will be thrown). Cases are, the property values:
52
+ * 1. Do not contain a token
53
+ * 2. Have length that are not in the range [1, 4]
54
+ * 3. Includes `calc(...)`
55
+ * Then, the rule will return with no error
56
+ * @param propertyValues property values parsed as list of strings
57
+ * @returns boolean
58
+ */
59
+ var isPropertyValueExempted = function isPropertyValueExempted(propertyValues) {
50
60
  if (!propertyValues.some(function (str) {
51
61
  return str.includes('token(');
52
62
  })) {
53
- return false;
63
+ return true;
54
64
  }
55
65
  if (propertyValues.length < 1 || propertyValues.length > 4) {
56
- return false;
66
+ return true;
57
67
  }
58
68
  if (propertyValues.some(function (str) {
59
69
  return str.includes('calc(');
60
70
  })) {
61
- return false;
71
+ return true;
62
72
  }
63
- return true;
73
+ return false;
64
74
  };
65
75
 
66
- // Check that all expressions in TemplateLiteral are token expressions
67
- // If true: create an autofix
68
- // If false: report violation without autofix
69
- var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
76
+ /**
77
+ * Checks if the parsed property values are invalid (i.e. rule violation thrown) and autofix required. Cases are when:
78
+ * 1. All expressions in TemplateLiteral are token expressions
79
+ * 2. Property values must have a format which includes -> e.g. 2, '2(rem|em|px)', auto, initial, inherit, token(...)
80
+ * The rule will return with error and provide a fix
81
+ * @param templateLiteral TemplateLiteral AST Node
82
+ * @param propertyValues property values parsed as list of strings
83
+ * @returns boolean
84
+ */
85
+ var isPropertyValuesInvalidFix = function isPropertyValuesInvalidFix(templateLiteral, propertyValues) {
70
86
  var expressions = templateLiteral.expressions;
71
- return expressions.every(function (expr) {
87
+ if (!expressions.every(function (expr) {
72
88
  return expr.type === 'CallExpression' && isTokenCallExpression(expr);
73
- });
89
+ })) {
90
+ return false;
91
+ }
92
+ var _iterator = _createForOfIteratorHelper(propertyValues),
93
+ _step;
94
+ try {
95
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
96
+ var propValue = _step.value;
97
+ if (propValue === '0') {
98
+ continue;
99
+ }
100
+ if (['auto', 'initial', 'inherit'].includes(propValue.slice(1, -1))) {
101
+ continue;
102
+ }
103
+ if (/^token\(.*\)$/.test(propValue)) {
104
+ continue;
105
+ }
106
+ if (/^['"]\d+(\.\d+)?((rem)|(em)|(px))['"]$/.test(propValue)) {
107
+ continue;
108
+ }
109
+ return false;
110
+ }
111
+ } catch (err) {
112
+ _iterator.e(err);
113
+ } finally {
114
+ _iterator.f();
115
+ }
116
+ return true;
74
117
  };
75
118
 
76
119
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
@@ -92,11 +135,11 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
92
135
  var fixes = [];
93
136
  var parentNode = node.parent;
94
137
  if (parentNode && parentNode.type === 'ObjectExpression') {
95
- var _iterator = _createForOfIteratorHelper(parentNode.properties),
96
- _step;
138
+ var _iterator2 = _createForOfIteratorHelper(parentNode.properties),
139
+ _step2;
97
140
  try {
98
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
99
- var prop = _step.value;
141
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
142
+ var prop = _step2.value;
100
143
  if (prop.type !== 'Property') {
101
144
  continue;
102
145
  }
@@ -121,9 +164,9 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
121
164
  }
122
165
  }
123
166
  } catch (err) {
124
- _iterator.e(err);
167
+ _iterator2.e(err);
125
168
  } finally {
126
- _iterator.f();
169
+ _iterator2.f();
127
170
  }
128
171
  }
129
172
  fixes.push(fixer.insertTextAfter(node, "".concat(propertyShorthand, "Top: ").concat(spacing[0], ",\n")));
@@ -138,8 +181,30 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
138
181
  return;
139
182
  }
140
183
  if (node.value.type === 'TemplateLiteral') {
141
- // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
142
- if (!hasOnlyTokens(node.value)) {
184
+ var propertyValues = parseTemplateLiteral(node.value, context);
185
+ if (isPropertyValueExempted(propertyValues)) {
186
+ // Valid, so no error should be thrown
187
+ return;
188
+ }
189
+ if (isPropertyValuesInvalidFix(node.value, propertyValues)) {
190
+ // Invalid, so error should be thrown and fix provided
191
+ context.report({
192
+ node: node,
193
+ messageId: 'expandSpacingShorthand',
194
+ data: {
195
+ property: propertyShorthand
196
+ },
197
+ fix: function fix(fixer) {
198
+ return expandSpacingProperties({
199
+ context: context,
200
+ node: node,
201
+ propertyValues: propertyValues,
202
+ fixer: fixer,
203
+ propertyShorthand: propertyShorthand
204
+ });
205
+ }
206
+ });
207
+ } else {
143
208
  context.report({
144
209
  node: node,
145
210
  messageId: 'expandSpacingShorthand',
@@ -149,26 +214,6 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
149
214
  });
150
215
  return;
151
216
  }
152
- var propertyValues = parseTemplateLiteral(node.value, context);
153
- if (!checkValidPropertyValues(propertyValues)) {
154
- return;
155
- }
156
- context.report({
157
- node: node,
158
- messageId: 'expandSpacingShorthand',
159
- data: {
160
- property: propertyShorthand
161
- },
162
- fix: function fix(fixer) {
163
- return expandSpacingProperties({
164
- context: context,
165
- node: node,
166
- propertyValues: propertyValues,
167
- fixer: fixer,
168
- propertyShorthand: propertyShorthand
169
- });
170
- }
171
- });
172
217
  } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
173
218
  // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
174
219
  var _propertyValues2 = [(0, _contextCompat.getSourceCode)(context).getText(node.value)];
@@ -35,25 +35,59 @@ const parseTemplateLiteral = (templateLiteral, context) => {
35
35
  }
36
36
  return propertyValues;
37
37
  };
38
- const checkValidPropertyValues = propertyValues => {
38
+
39
+ /**
40
+ * Checks if the parsed property values are valid (i.e. no rule violation will be thrown). Cases are, the property values:
41
+ * 1. Do not contain a token
42
+ * 2. Have length that are not in the range [1, 4]
43
+ * 3. Includes `calc(...)`
44
+ * Then, the rule will return with no error
45
+ * @param propertyValues property values parsed as list of strings
46
+ * @returns boolean
47
+ */
48
+ const isPropertyValueExempted = propertyValues => {
39
49
  if (!propertyValues.some(str => str.includes('token('))) {
40
- return false;
50
+ return true;
41
51
  }
42
52
  if (propertyValues.length < 1 || propertyValues.length > 4) {
43
- return false;
53
+ return true;
44
54
  }
45
55
  if (propertyValues.some(str => str.includes('calc('))) {
46
- return false;
56
+ return true;
47
57
  }
48
- return true;
58
+ return false;
49
59
  };
50
60
 
51
- // Check that all expressions in TemplateLiteral are token expressions
52
- // If true: create an autofix
53
- // If false: report violation without autofix
54
- const hasOnlyTokens = templateLiteral => {
61
+ /**
62
+ * Checks if the parsed property values are invalid (i.e. rule violation thrown) and autofix required. Cases are when:
63
+ * 1. All expressions in TemplateLiteral are token expressions
64
+ * 2. Property values must have a format which includes -> e.g. 2, '2(rem|em|px)', auto, initial, inherit, token(...)
65
+ * The rule will return with error and provide a fix
66
+ * @param templateLiteral TemplateLiteral AST Node
67
+ * @param propertyValues property values parsed as list of strings
68
+ * @returns boolean
69
+ */
70
+ const isPropertyValuesInvalidFix = (templateLiteral, propertyValues) => {
55
71
  const expressions = templateLiteral.expressions;
56
- return expressions.every(expr => expr.type === 'CallExpression' && isTokenCallExpression(expr));
72
+ if (!expressions.every(expr => expr.type === 'CallExpression' && isTokenCallExpression(expr))) {
73
+ return false;
74
+ }
75
+ for (const propValue of propertyValues) {
76
+ if (propValue === '0') {
77
+ continue;
78
+ }
79
+ if (['auto', 'initial', 'inherit'].includes(propValue.slice(1, -1))) {
80
+ continue;
81
+ }
82
+ if (/^token\(.*\)$/.test(propValue)) {
83
+ continue;
84
+ }
85
+ if (/^['"]\d+(\.\d+)?((rem)|(em)|(px))['"]$/.test(propValue)) {
86
+ continue;
87
+ }
88
+ return false;
89
+ }
90
+ return true;
57
91
  };
58
92
 
59
93
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
@@ -104,8 +138,30 @@ const executeExpandSpacingRule = (context, node, propertyShorthand) => {
104
138
  return;
105
139
  }
106
140
  if (node.value.type === 'TemplateLiteral') {
107
- // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
108
- if (!hasOnlyTokens(node.value)) {
141
+ const propertyValues = parseTemplateLiteral(node.value, context);
142
+ if (isPropertyValueExempted(propertyValues)) {
143
+ // Valid, so no error should be thrown
144
+ return;
145
+ }
146
+ if (isPropertyValuesInvalidFix(node.value, propertyValues)) {
147
+ // Invalid, so error should be thrown and fix provided
148
+ context.report({
149
+ node,
150
+ messageId: 'expandSpacingShorthand',
151
+ data: {
152
+ property: propertyShorthand
153
+ },
154
+ fix(fixer) {
155
+ return expandSpacingProperties({
156
+ context,
157
+ node,
158
+ propertyValues,
159
+ fixer,
160
+ propertyShorthand
161
+ });
162
+ }
163
+ });
164
+ } else {
109
165
  context.report({
110
166
  node,
111
167
  messageId: 'expandSpacingShorthand',
@@ -115,26 +171,6 @@ const executeExpandSpacingRule = (context, node, propertyShorthand) => {
115
171
  });
116
172
  return;
117
173
  }
118
- const propertyValues = parseTemplateLiteral(node.value, context);
119
- if (!checkValidPropertyValues(propertyValues)) {
120
- return;
121
- }
122
- context.report({
123
- node,
124
- messageId: 'expandSpacingShorthand',
125
- data: {
126
- property: propertyShorthand
127
- },
128
- fix(fixer) {
129
- return expandSpacingProperties({
130
- context,
131
- node,
132
- propertyValues,
133
- fixer,
134
- propertyShorthand
135
- });
136
- }
137
- });
138
174
  } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
139
175
  // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
140
176
  const propertyValues = [getSourceCode(context).getText(node.value)];
@@ -39,31 +39,74 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
39
39
  }
40
40
  return propertyValues;
41
41
  };
42
- var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
42
+
43
+ /**
44
+ * Checks if the parsed property values are valid (i.e. no rule violation will be thrown). Cases are, the property values:
45
+ * 1. Do not contain a token
46
+ * 2. Have length that are not in the range [1, 4]
47
+ * 3. Includes `calc(...)`
48
+ * Then, the rule will return with no error
49
+ * @param propertyValues property values parsed as list of strings
50
+ * @returns boolean
51
+ */
52
+ var isPropertyValueExempted = function isPropertyValueExempted(propertyValues) {
43
53
  if (!propertyValues.some(function (str) {
44
54
  return str.includes('token(');
45
55
  })) {
46
- return false;
56
+ return true;
47
57
  }
48
58
  if (propertyValues.length < 1 || propertyValues.length > 4) {
49
- return false;
59
+ return true;
50
60
  }
51
61
  if (propertyValues.some(function (str) {
52
62
  return str.includes('calc(');
53
63
  })) {
54
- return false;
64
+ return true;
55
65
  }
56
- return true;
66
+ return false;
57
67
  };
58
68
 
59
- // Check that all expressions in TemplateLiteral are token expressions
60
- // If true: create an autofix
61
- // If false: report violation without autofix
62
- var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
69
+ /**
70
+ * Checks if the parsed property values are invalid (i.e. rule violation thrown) and autofix required. Cases are when:
71
+ * 1. All expressions in TemplateLiteral are token expressions
72
+ * 2. Property values must have a format which includes -> e.g. 2, '2(rem|em|px)', auto, initial, inherit, token(...)
73
+ * The rule will return with error and provide a fix
74
+ * @param templateLiteral TemplateLiteral AST Node
75
+ * @param propertyValues property values parsed as list of strings
76
+ * @returns boolean
77
+ */
78
+ var isPropertyValuesInvalidFix = function isPropertyValuesInvalidFix(templateLiteral, propertyValues) {
63
79
  var expressions = templateLiteral.expressions;
64
- return expressions.every(function (expr) {
80
+ if (!expressions.every(function (expr) {
65
81
  return expr.type === 'CallExpression' && isTokenCallExpression(expr);
66
- });
82
+ })) {
83
+ return false;
84
+ }
85
+ var _iterator = _createForOfIteratorHelper(propertyValues),
86
+ _step;
87
+ try {
88
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
89
+ var propValue = _step.value;
90
+ if (propValue === '0') {
91
+ continue;
92
+ }
93
+ if (['auto', 'initial', 'inherit'].includes(propValue.slice(1, -1))) {
94
+ continue;
95
+ }
96
+ if (/^token\(.*\)$/.test(propValue)) {
97
+ continue;
98
+ }
99
+ if (/^['"]\d+(\.\d+)?((rem)|(em)|(px))['"]$/.test(propValue)) {
100
+ continue;
101
+ }
102
+ return false;
103
+ }
104
+ } catch (err) {
105
+ _iterator.e(err);
106
+ } finally {
107
+ _iterator.f();
108
+ }
109
+ return true;
67
110
  };
68
111
 
69
112
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
@@ -85,11 +128,11 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
85
128
  var fixes = [];
86
129
  var parentNode = node.parent;
87
130
  if (parentNode && parentNode.type === 'ObjectExpression') {
88
- var _iterator = _createForOfIteratorHelper(parentNode.properties),
89
- _step;
131
+ var _iterator2 = _createForOfIteratorHelper(parentNode.properties),
132
+ _step2;
90
133
  try {
91
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
92
- var prop = _step.value;
134
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
135
+ var prop = _step2.value;
93
136
  if (prop.type !== 'Property') {
94
137
  continue;
95
138
  }
@@ -114,9 +157,9 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
114
157
  }
115
158
  }
116
159
  } catch (err) {
117
- _iterator.e(err);
160
+ _iterator2.e(err);
118
161
  } finally {
119
- _iterator.f();
162
+ _iterator2.f();
120
163
  }
121
164
  }
122
165
  fixes.push(fixer.insertTextAfter(node, "".concat(propertyShorthand, "Top: ").concat(spacing[0], ",\n")));
@@ -131,8 +174,30 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
131
174
  return;
132
175
  }
133
176
  if (node.value.type === 'TemplateLiteral') {
134
- // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
135
- if (!hasOnlyTokens(node.value)) {
177
+ var propertyValues = parseTemplateLiteral(node.value, context);
178
+ if (isPropertyValueExempted(propertyValues)) {
179
+ // Valid, so no error should be thrown
180
+ return;
181
+ }
182
+ if (isPropertyValuesInvalidFix(node.value, propertyValues)) {
183
+ // Invalid, so error should be thrown and fix provided
184
+ context.report({
185
+ node: node,
186
+ messageId: 'expandSpacingShorthand',
187
+ data: {
188
+ property: propertyShorthand
189
+ },
190
+ fix: function fix(fixer) {
191
+ return expandSpacingProperties({
192
+ context: context,
193
+ node: node,
194
+ propertyValues: propertyValues,
195
+ fixer: fixer,
196
+ propertyShorthand: propertyShorthand
197
+ });
198
+ }
199
+ });
200
+ } else {
136
201
  context.report({
137
202
  node: node,
138
203
  messageId: 'expandSpacingShorthand',
@@ -142,26 +207,6 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
142
207
  });
143
208
  return;
144
209
  }
145
- var propertyValues = parseTemplateLiteral(node.value, context);
146
- if (!checkValidPropertyValues(propertyValues)) {
147
- return;
148
- }
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: propertyValues,
160
- fixer: fixer,
161
- propertyShorthand: propertyShorthand
162
- });
163
- }
164
- });
165
210
  } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
166
211
  // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
167
212
  var _propertyValues2 = [getSourceCode(context).getText(node.value)];
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.2.0",
4
+ "version": "2.2.1",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
7
7
  "team": "Build Infra",
@@ -272,6 +272,36 @@ const invalidTestCases = (property: string) => {
272
272
  `,
273
273
  errors: Array.from(Array(3), () => ({ messageId: 'expandSpacingShorthand' })),
274
274
  },
275
+ // Strings that are not valid property values should not be autofixed (e.g. !important)
276
+ {
277
+ name: `${property}: Don't autofix if not able to handle all the string values, e.g !important`,
278
+ code: outdent`
279
+ import {css} from '@compiled/react';
280
+ const styles = css({
281
+ ${property}: \`0 \${token('space.200', '16px')} !important\`,
282
+ });
283
+ `,
284
+ errors: [{ messageId: 'expandSpacingShorthand' }],
285
+ },
286
+ {
287
+ name: `${property}: Autofix if able to handle all string values`,
288
+ code: outdent`
289
+ import {css} from '@compiled/react';
290
+ const styles = css({
291
+ ${property}: \`0 auto \${token('space.300', '24px')}\`,
292
+ });
293
+ `,
294
+ output: outdent`
295
+ import {css} from '@compiled/react';
296
+ const styles = css({
297
+ ${property}Top: 0,
298
+ ${property}Right: 'auto',
299
+ ${property}Bottom: token('space.300', '24px'),
300
+ ${property}Left: 'auto',
301
+ });
302
+ `,
303
+ errors: [{ messageId: 'expandSpacingShorthand' }],
304
+ },
275
305
  // Miscellaneous
276
306
  {
277
307
  name: `${property}: new property should not be created if existing property already exists`,
@@ -383,7 +413,7 @@ const invalidTestCases = (property: string) => {
383
413
  `,
384
414
  errors: Array.from(Array(2), () => ({ messageId: 'expandSpacingShorthand' })),
385
415
  },
386
- // TODO (AFB-1022): Resolve this failing test
416
+ // // TODO (AFB-1022): Resolve this failing test
387
417
  // {
388
418
  // name: `${property}: styled components with prop input`,
389
419
  // code: outdent`
@@ -49,26 +49,52 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
49
49
  return propertyValues;
50
50
  };
51
51
 
52
- const checkValidPropertyValues = (propertyValues: string[]) => {
52
+ /**
53
+ * Checks if the parsed property values are valid (i.e. no rule violation will be thrown). Cases are, the property values:
54
+ * 1. Do not contain a token
55
+ * 2. Have length that are not in the range [1, 4]
56
+ * 3. Includes `calc(...)`
57
+ * Then, the rule will return with no error
58
+ * @param propertyValues property values parsed as list of strings
59
+ * @returns boolean
60
+ */
61
+ const isPropertyValueExempted = (propertyValues: string[]) => {
53
62
  if (!propertyValues.some((str) => str.includes('token('))) {
54
- return false;
63
+ return true;
55
64
  }
56
65
  if (propertyValues.length < 1 || propertyValues.length > 4) {
57
- return false;
66
+ return true;
58
67
  }
59
68
  if (propertyValues.some((str) => str.includes('calc('))) {
60
- return false;
69
+ return true;
61
70
  }
62
- return true;
71
+ return false;
63
72
  };
64
73
 
65
- // Check that all expressions in TemplateLiteral are token expressions
66
- // If true: create an autofix
67
- // If false: report violation without autofix
68
- const hasOnlyTokens = (templateLiteral: TemplateLiteral) => {
74
+ /**
75
+ * Checks if the parsed property values are invalid (i.e. rule violation thrown) and autofix required. Cases are when:
76
+ * 1. All expressions in TemplateLiteral are token expressions
77
+ * 2. Property values must have a format which includes -> e.g. 2, '2(rem|em|px)', auto, initial, inherit, token(...)
78
+ * The rule will return with error and provide a fix
79
+ * @param templateLiteral TemplateLiteral AST Node
80
+ * @param propertyValues property values parsed as list of strings
81
+ * @returns boolean
82
+ */
83
+ const isPropertyValuesInvalidFix = (templateLiteral: TemplateLiteral, propertyValues: string[]) => {
69
84
  const expressions = templateLiteral.expressions;
70
- return expressions.every((expr) => expr.type === 'CallExpression' && isTokenCallExpression(expr));
71
- };
85
+ if (!expressions.every((expr) => expr.type === 'CallExpression' && isTokenCallExpression(expr))) {
86
+ return false;
87
+ }
88
+
89
+ for (const propValue of propertyValues) {
90
+ if (propValue === '0') { continue; }
91
+ if (['auto', 'initial', 'inherit'].includes(propValue.slice(1, -1))) { continue; }
92
+ if ((/^token\(.*\)$/).test(propValue)) { continue; }
93
+ if ((/^['"]\d+(\.\d+)?((rem)|(em)|(px))['"]$/).test(propValue)) { continue; }
94
+ return false;
95
+ }
96
+ return true;
97
+ }
72
98
 
73
99
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
74
100
  const expandSpacingProperties = ({
@@ -130,8 +156,24 @@ const executeExpandSpacingRule = (
130
156
  return;
131
157
  }
132
158
  if (node.value.type === 'TemplateLiteral') {
133
- // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
134
- if (!hasOnlyTokens(node.value)) {
159
+ const propertyValues = parseTemplateLiteral(node.value, context);
160
+ if (isPropertyValueExempted(propertyValues)) {
161
+ // Valid, so no error should be thrown
162
+ return;
163
+ }
164
+ if (isPropertyValuesInvalidFix(node.value, propertyValues)) {
165
+ // Invalid, so error should be thrown and fix provided
166
+ context.report({
167
+ node,
168
+ messageId: 'expandSpacingShorthand',
169
+ data: {
170
+ property: propertyShorthand,
171
+ },
172
+ fix(fixer) {
173
+ return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
174
+ },
175
+ });
176
+ } else {
135
177
  context.report({
136
178
  node,
137
179
  messageId: 'expandSpacingShorthand',
@@ -141,20 +183,6 @@ const executeExpandSpacingRule = (
141
183
  });
142
184
  return;
143
185
  }
144
- const propertyValues = parseTemplateLiteral(node.value, context);
145
- if (!checkValidPropertyValues(propertyValues)) {
146
- return;
147
- }
148
- context.report({
149
- node,
150
- messageId: 'expandSpacingShorthand',
151
- data: {
152
- property: propertyShorthand,
153
- },
154
- fix(fixer) {
155
- return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
156
- },
157
- });
158
186
  } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
159
187
  // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
160
188
  const propertyValues = [getSourceCode(context).getText(node.value)];