@atlaskit/eslint-plugin-platform 2.1.0 → 2.1.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,13 @@
1
1
  # @atlaskit/eslint-plugin-platform
2
2
 
3
+ ## 2.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#101753](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/101753)
8
+ [`ab8a4d93399e8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/ab8a4d93399e8) -
9
+ AFB-822 Turn of expand-spacing-shorthand rule until all of Jira and Platform rollout is complete
10
+
3
11
  ## 2.1.0
4
12
 
5
13
  ### Minor Changes
package/dist/cjs/index.js CHANGED
@@ -72,7 +72,7 @@ var commonConfig = {
72
72
  // Compiled: rules that are not included via `@compiled/recommended
73
73
  '@atlaskit/platform/expand-border-shorthand': 'error',
74
74
  '@atlaskit/platform/expand-background-shorthand': 'error',
75
- '@atlaskit/platform/expand-spacing-shorthand': 'warn',
75
+ '@atlaskit/platform/expand-spacing-shorthand': 'off',
76
76
  '@compiled/jsx-pragma': ['error', {
77
77
  importSources: ['@atlaskit/css'],
78
78
  onlyRunIfImportingCompiled: true,
@@ -11,9 +11,7 @@ var _compiledUtils = require("../../util/compiled-utils");
11
11
  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; } } }; }
12
12
  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; } }
13
13
  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; }
14
- var spacingPos = ["Top", "Right", "Bottom", "Left"];
15
- ;
16
-
14
+ var spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
17
15
  // Checks if node is a call expression with identifier 'token'
18
16
  var isTokenCallExpression = function isTokenCallExpression(node) {
19
17
  if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
@@ -32,8 +30,8 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
32
30
  if (i < quasis.length) {
33
31
  var cookedQuasi = quasis[i].value.cooked;
34
32
  if (cookedQuasi) {
35
- var splitQuasi = cookedQuasi.split(" ").filter(function (str) {
36
- return str.length > 0;
33
+ var splitQuasi = cookedQuasi.split(' ').filter(function (str) {
34
+ return str.trim().length > 0;
37
35
  });
38
36
  splitQuasi.forEach(function (str) {
39
37
  propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
@@ -49,7 +47,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
49
47
  };
50
48
  var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
51
49
  if (!propertyValues.some(function (str) {
52
- return str.includes("token(");
50
+ return str.includes('token(');
53
51
  })) {
54
52
  return false;
55
53
  }
@@ -57,13 +55,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
57
55
  return false;
58
56
  }
59
57
  if (propertyValues.some(function (str) {
60
- return str.includes("calc(");
58
+ return str.includes('calc(');
61
59
  })) {
62
60
  return false;
63
61
  }
64
62
  return true;
65
63
  };
66
64
 
65
+ // Check that all expressions in TemplateLiteral are token expressions
66
+ // If true: create an autofix
67
+ // If false: report violation without autofix
68
+ var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
69
+ var expressions = templateLiteral.expressions;
70
+ return expressions.every(function (expr) {
71
+ return expr.type === 'CallExpression' && isTokenCallExpression(expr);
72
+ });
73
+ };
74
+
67
75
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
68
76
  var expandSpacingProperties = function expandSpacingProperties(_ref) {
69
77
  var context = _ref.context,
@@ -98,10 +106,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
98
106
  start = _prop$range[0],
99
107
  end = _prop$range[1];
100
108
  // Remove the entire line for the duplicate property
101
- while ((0, _contextCompat.getSourceCode)(context).text[end] !== "\n") {
109
+ while ((0, _contextCompat.getSourceCode)(context).text[end] !== '\n') {
102
110
  end += 1;
103
111
  }
104
- while ((0, _contextCompat.getSourceCode)(context).text[start] !== "\n") {
112
+ while ((0, _contextCompat.getSourceCode)(context).text[start] !== '\n') {
105
113
  start -= 1;
106
114
  }
107
115
  spacing[i] = (0, _contextCompat.getSourceCode)(context).getText(prop.value);
@@ -130,6 +138,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
130
138
  }
131
139
  if (node.value.type === 'TemplateLiteral') {
132
140
  // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
141
+ if (!hasOnlyTokens(node.value)) {
142
+ context.report({
143
+ node: node,
144
+ messageId: 'expandSpacingShorthand',
145
+ data: {
146
+ property: propertyShorthand
147
+ }
148
+ });
149
+ return;
150
+ }
133
151
  var propertyValues = parseTemplateLiteral(node.value, context);
134
152
  if (!checkValidPropertyValues(propertyValues)) {
135
153
  return;
@@ -64,7 +64,7 @@ const commonConfig = {
64
64
  // Compiled: rules that are not included via `@compiled/recommended
65
65
  '@atlaskit/platform/expand-border-shorthand': 'error',
66
66
  '@atlaskit/platform/expand-background-shorthand': 'error',
67
- '@atlaskit/platform/expand-spacing-shorthand': 'warn',
67
+ '@atlaskit/platform/expand-spacing-shorthand': 'off',
68
68
  '@compiled/jsx-pragma': ['error', {
69
69
  importSources: ['@atlaskit/css'],
70
70
  onlyRunIfImportingCompiled: true,
@@ -1,8 +1,6 @@
1
1
  import { getSourceCode } from '../../util/context-compat';
2
2
  import { isCompiledAPI } from '../../util/compiled-utils';
3
- const spacingPos = ["Top", "Right", "Bottom", "Left"];
4
- ;
5
-
3
+ const spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
6
4
  // Checks if node is a call expression with identifier 'token'
7
5
  const isTokenCallExpression = node => {
8
6
  if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
@@ -21,7 +19,7 @@ const parseTemplateLiteral = (templateLiteral, context) => {
21
19
  if (i < quasis.length) {
22
20
  const cookedQuasi = quasis[i].value.cooked;
23
21
  if (cookedQuasi) {
24
- const splitQuasi = cookedQuasi.split(" ").filter(str => str.length > 0);
22
+ const splitQuasi = cookedQuasi.split(' ').filter(str => str.trim().length > 0);
25
23
  splitQuasi.forEach(str => {
26
24
  propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
27
25
  });
@@ -35,18 +33,26 @@ const parseTemplateLiteral = (templateLiteral, context) => {
35
33
  return propertyValues;
36
34
  };
37
35
  const checkValidPropertyValues = propertyValues => {
38
- if (!propertyValues.some(str => str.includes("token("))) {
36
+ if (!propertyValues.some(str => str.includes('token('))) {
39
37
  return false;
40
38
  }
41
39
  if (propertyValues.length < 1 || propertyValues.length > 4) {
42
40
  return false;
43
41
  }
44
- if (propertyValues.some(str => str.includes("calc("))) {
42
+ if (propertyValues.some(str => str.includes('calc('))) {
45
43
  return false;
46
44
  }
47
45
  return true;
48
46
  };
49
47
 
48
+ // Check that all expressions in TemplateLiteral are token expressions
49
+ // If true: create an autofix
50
+ // If false: report violation without autofix
51
+ const hasOnlyTokens = templateLiteral => {
52
+ const expressions = templateLiteral.expressions;
53
+ return expressions.every(expr => expr.type === 'CallExpression' && isTokenCallExpression(expr));
54
+ };
55
+
50
56
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
51
57
  const expandSpacingProperties = ({
52
58
  context,
@@ -69,10 +75,10 @@ const expandSpacingProperties = ({
69
75
  if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
70
76
  let [start, end] = prop.range;
71
77
  // Remove the entire line for the duplicate property
72
- while (getSourceCode(context).text[end] !== "\n") {
78
+ while (getSourceCode(context).text[end] !== '\n') {
73
79
  end += 1;
74
80
  }
75
- while (getSourceCode(context).text[start] !== "\n") {
81
+ while (getSourceCode(context).text[start] !== '\n') {
76
82
  start -= 1;
77
83
  }
78
84
  spacing[i] = getSourceCode(context).getText(prop.value);
@@ -96,6 +102,16 @@ const executeExpandSpacingRule = (context, node, propertyShorthand) => {
96
102
  }
97
103
  if (node.value.type === 'TemplateLiteral') {
98
104
  // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
105
+ if (!hasOnlyTokens(node.value)) {
106
+ context.report({
107
+ node,
108
+ messageId: 'expandSpacingShorthand',
109
+ data: {
110
+ property: propertyShorthand
111
+ }
112
+ });
113
+ return;
114
+ }
99
115
  const propertyValues = parseTemplateLiteral(node.value, context);
100
116
  if (!checkValidPropertyValues(propertyValues)) {
101
117
  return;
package/dist/esm/index.js CHANGED
@@ -67,7 +67,7 @@ var commonConfig = {
67
67
  // Compiled: rules that are not included via `@compiled/recommended
68
68
  '@atlaskit/platform/expand-border-shorthand': 'error',
69
69
  '@atlaskit/platform/expand-background-shorthand': 'error',
70
- '@atlaskit/platform/expand-spacing-shorthand': 'warn',
70
+ '@atlaskit/platform/expand-spacing-shorthand': 'off',
71
71
  '@compiled/jsx-pragma': ['error', {
72
72
  importSources: ['@atlaskit/css'],
73
73
  onlyRunIfImportingCompiled: true,
@@ -4,9 +4,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
4
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
5
  import { getSourceCode } from '../../util/context-compat';
6
6
  import { isCompiledAPI } from '../../util/compiled-utils';
7
- var spacingPos = ["Top", "Right", "Bottom", "Left"];
8
- ;
9
-
7
+ var spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
10
8
  // Checks if node is a call expression with identifier 'token'
11
9
  var isTokenCallExpression = function isTokenCallExpression(node) {
12
10
  if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
@@ -25,8 +23,8 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
25
23
  if (i < quasis.length) {
26
24
  var cookedQuasi = quasis[i].value.cooked;
27
25
  if (cookedQuasi) {
28
- var splitQuasi = cookedQuasi.split(" ").filter(function (str) {
29
- return str.length > 0;
26
+ var splitQuasi = cookedQuasi.split(' ').filter(function (str) {
27
+ return str.trim().length > 0;
30
28
  });
31
29
  splitQuasi.forEach(function (str) {
32
30
  propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
@@ -42,7 +40,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
42
40
  };
43
41
  var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
44
42
  if (!propertyValues.some(function (str) {
45
- return str.includes("token(");
43
+ return str.includes('token(');
46
44
  })) {
47
45
  return false;
48
46
  }
@@ -50,13 +48,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
50
48
  return false;
51
49
  }
52
50
  if (propertyValues.some(function (str) {
53
- return str.includes("calc(");
51
+ return str.includes('calc(');
54
52
  })) {
55
53
  return false;
56
54
  }
57
55
  return true;
58
56
  };
59
57
 
58
+ // Check that all expressions in TemplateLiteral are token expressions
59
+ // If true: create an autofix
60
+ // If false: report violation without autofix
61
+ var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
62
+ var expressions = templateLiteral.expressions;
63
+ return expressions.every(function (expr) {
64
+ return expr.type === 'CallExpression' && isTokenCallExpression(expr);
65
+ });
66
+ };
67
+
60
68
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
61
69
  var expandSpacingProperties = function expandSpacingProperties(_ref) {
62
70
  var context = _ref.context,
@@ -91,10 +99,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
91
99
  start = _prop$range[0],
92
100
  end = _prop$range[1];
93
101
  // Remove the entire line for the duplicate property
94
- while (getSourceCode(context).text[end] !== "\n") {
102
+ while (getSourceCode(context).text[end] !== '\n') {
95
103
  end += 1;
96
104
  }
97
- while (getSourceCode(context).text[start] !== "\n") {
105
+ while (getSourceCode(context).text[start] !== '\n') {
98
106
  start -= 1;
99
107
  }
100
108
  spacing[i] = getSourceCode(context).getText(prop.value);
@@ -123,6 +131,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
123
131
  }
124
132
  if (node.value.type === 'TemplateLiteral') {
125
133
  // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
134
+ if (!hasOnlyTokens(node.value)) {
135
+ context.report({
136
+ node: node,
137
+ messageId: 'expandSpacingShorthand',
138
+ data: {
139
+ property: propertyShorthand
140
+ }
141
+ });
142
+ return;
143
+ }
126
144
  var propertyValues = parseTemplateLiteral(node.value, context);
127
145
  if (!checkValidPropertyValues(propertyValues)) {
128
146
  return;
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.1.0",
4
+ "version": "2.1.1",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
7
7
  "team": "Build Infra",
package/src/index.tsx CHANGED
@@ -66,7 +66,7 @@ const commonConfig = {
66
66
  // Compiled: rules that are not included via `@compiled/recommended
67
67
  '@atlaskit/platform/expand-border-shorthand': 'error',
68
68
  '@atlaskit/platform/expand-background-shorthand': 'error',
69
- '@atlaskit/platform/expand-spacing-shorthand': 'warn',
69
+ '@atlaskit/platform/expand-spacing-shorthand': 'off',
70
70
  '@compiled/jsx-pragma': [
71
71
  'error',
72
72
  {
@@ -2,15 +2,8 @@ import { outdent } from 'outdent';
2
2
  import { tester } from '../../../../__tests__/utils/_tester';
3
3
  import { expandSpacingShorthand } from '../index';
4
4
 
5
- const included_compiled_libraries = [
6
- '@compiled/react',
7
- '@atlaskit/css'
8
- ];
9
- const exempt_libraries = [
10
- '@atlaskit/primitives',
11
- '@emotion',
12
- 'styled-components',
13
- ];
5
+ const included_compiled_libraries = ['@compiled/react', '@atlaskit/css'];
6
+ const exempt_libraries = ['@emotion/react', 'styled-components'];
14
7
 
15
8
  const validTestCases = (property: string) => {
16
9
  return [
@@ -18,9 +11,14 @@ const validTestCases = (property: string) => {
18
11
  name: `${property}: do not have to handle non-compiled packages (${imp})`,
19
12
  code: outdent`
20
13
  import {css} from '${imp}';
14
+ import {xcss} from '@atlaskit/primitives';
15
+
21
16
  const styles = css({
22
17
  ${property}: token('space.200'),
23
18
  });
19
+ const styles2 = xcss({
20
+ ${property}: token('space.200'),
21
+ });
24
22
  `,
25
23
  })),
26
24
  {
@@ -254,6 +252,26 @@ const invalidTestCases = (property: string) => {
254
252
  `,
255
253
  errors: [{ messageId: 'expandSpacingShorthand' }],
256
254
  },
255
+ // Template literal containing expressions that is not token should only throw error with no autofix
256
+ {
257
+ name: `${property}: property value template string where it contains an expression that is not a token`,
258
+ code: outdent`
259
+ import {css} from '@compiled/react';
260
+ const styles = css({
261
+ ${property}: \`\${token('space.100', '8px')} \${gridSize * 2}px\`,
262
+ });
263
+ const styles2 = css({
264
+ padding: \`\${DROPDOWN_HEADER_VERTICAL_PADDING} \${token('space.075','6px')}
265
+ \${DROPDOWN_HEADER_VERTICAL_PADDING} \${token('space.200', '16px')}\`,
266
+ });
267
+ const styles3 = css({
268
+ ${property}: \`\${token('space.050', '4px')} \${token('space.150', '12px')} \${token('space.150', '12px')}
269
+ \${({ isSummaryView }: EditFormContentWrapperProps) =>
270
+ isSummaryView ? token('space.0', '0') : token('space.150', '12px')}\`,
271
+ });
272
+ `,
273
+ errors: Array.from(Array(3), () => ({ messageId: 'expandSpacingShorthand' })),
274
+ },
257
275
  // Miscellaneous
258
276
  {
259
277
  name: `${property}: new property should not be created if existing property already exists`,
@@ -329,16 +347,54 @@ const invalidTestCases = (property: string) => {
329
347
  `,
330
348
  errors: Array.from(Array(3), () => ({ messageId: 'expandSpacingShorthand' })),
331
349
  },
350
+ {
351
+ name: `${property}: property value includes newline and tab`,
352
+ code: outdent`
353
+ import {css} from '@compiled/react';
354
+ const styles = css({
355
+ ${property}: \`\${token('space.100')} \${token('space.200')}
356
+ \${token('space.300')} \${token('space.400')}\`,
357
+ });
358
+ `,
359
+ output: outdent`
360
+ import {css} from '@compiled/react';
361
+ const styles = css({
362
+ ${property}Top: token('space.100'),
363
+ ${property}Right: token('space.200'),
364
+ ${property}Bottom: token('space.300'),
365
+ ${property}Left: token('space.400'),
366
+ });
367
+ `,
368
+ errors: [{ messageId: 'expandSpacingShorthand' }],
369
+ },
370
+ // TODO (AFB-1022): Resolve this failing test
371
+ // {
372
+ // name: `${property}: styled components with prop input`,
373
+ // code: outdent`
374
+ // import { styled } from '@compiled/react';
375
+ // const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
376
+ // '& button': ({ isDisabled }) => ({
377
+ // ${property}: \`\${token('space.075', '6px')} \${token('space.200', '16px')}\`,
378
+ // }),
379
+ // });
380
+ // `,
381
+ // output: outdent`
382
+ // import { styled } from '@compiled/react';
383
+ // const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
384
+ // '& button': ({ isDisabled }) => ({
385
+ // ${property}Top: token('space.075', '6px'),
386
+ // ${property}Right: token('space.200', '16px'),
387
+ // ${property}Bottom: token('space.075', '6px'),
388
+ // ${property}Left: token('space.200', '16px'),
389
+ // }),
390
+ // });
391
+ // `,
392
+ // errors: [{ messageId: 'expandSpacingShorthand' }],
393
+ // },
332
394
  ];
333
395
  };
334
396
 
335
397
  tester.run('expand-spacing-shorthand', expandSpacingShorthand, {
336
- valid: [
337
- ...validTestCases('padding'),
338
- ...validTestCases('margin'),
339
- ],
340
- invalid: [
341
- ...invalidTestCases('padding'),
342
- ...invalidTestCases('margin'),
343
- ],
398
+ valid: [...validTestCases('padding'), ...validTestCases('margin')],
399
+ invalid: [...invalidTestCases('padding'), ...invalidTestCases('margin')],
344
400
  });
@@ -3,15 +3,15 @@ import type { Property, Node, TemplateLiteral, CallExpression } from 'estree';
3
3
  import { getSourceCode } from '../../util/context-compat';
4
4
  import { isCompiledAPI } from '../../util/compiled-utils';
5
5
 
6
- const spacingPos = ["Top", "Right", "Bottom", "Left"] as const;
6
+ const spacingPos = ['Top', 'Right', 'Bottom', 'Left'] as const;
7
7
 
8
8
  interface ExpandSpacingPropertiesType {
9
- context: Rule.RuleContext,
10
- node: Property & { parent?: Node },
11
- propertyValues: string[],
12
- fixer: Rule.RuleFixer,
13
- propertyShorthand: string,
14
- };
9
+ context: Rule.RuleContext;
10
+ node: Property & { parent?: Node };
11
+ propertyValues: string[];
12
+ fixer: Rule.RuleFixer;
13
+ propertyShorthand: string;
14
+ }
15
15
 
16
16
  // Checks if node is a call expression with identifier 'token'
17
17
  const isTokenCallExpression = (node: CallExpression) => {
@@ -29,11 +29,11 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
29
29
 
30
30
  let propertyValues: string[] = [];
31
31
  for (let i = 0; i < expressions.length || i < quasis.length; i++) {
32
- if (i < quasis.length) {
32
+ if (i < quasis.length) {
33
33
  const cookedQuasi = quasis[i].value.cooked;
34
34
  if (cookedQuasi) {
35
- const splitQuasi = cookedQuasi.split(" ").filter(str => str.length > 0);
36
- splitQuasi.forEach(str => {
35
+ const splitQuasi = cookedQuasi.split(' ').filter((str) => str.trim().length > 0);
36
+ splitQuasi.forEach((str) => {
37
37
  propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
38
38
  });
39
39
  }
@@ -47,14 +47,34 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
47
47
  };
48
48
 
49
49
  const checkValidPropertyValues = (propertyValues: string[]) => {
50
- if (!propertyValues.some(str => str.includes("token("))) { return false; }
51
- if (propertyValues.length < 1 || propertyValues.length > 4) { return false; }
52
- if (propertyValues.some(str => str.includes("calc("))) { return false; }
50
+ if (!propertyValues.some((str) => str.includes('token('))) {
51
+ return false;
52
+ }
53
+ if (propertyValues.length < 1 || propertyValues.length > 4) {
54
+ return false;
55
+ }
56
+ if (propertyValues.some((str) => str.includes('calc('))) {
57
+ return false;
58
+ }
53
59
  return true;
54
- }
60
+ };
61
+
62
+ // Check that all expressions in TemplateLiteral are token expressions
63
+ // If true: create an autofix
64
+ // If false: report violation without autofix
65
+ const hasOnlyTokens = (templateLiteral: TemplateLiteral) => {
66
+ const expressions = templateLiteral.expressions;
67
+ return expressions.every((expr) => expr.type === 'CallExpression' && isTokenCallExpression(expr));
68
+ };
55
69
 
56
70
  // To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
57
- const expandSpacingProperties = ({ context, node, propertyValues, fixer, propertyShorthand }: ExpandSpacingPropertiesType) => {
71
+ const expandSpacingProperties = ({
72
+ context,
73
+ node,
74
+ propertyValues,
75
+ fixer,
76
+ propertyShorthand,
77
+ }: ExpandSpacingPropertiesType) => {
58
78
  const [top, right = top, bottom = top, left = right] = propertyValues;
59
79
  const spacing: string[] = [top, right, bottom, left];
60
80
 
@@ -63,16 +83,22 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
63
83
  const parentNode = node.parent;
64
84
  if (parentNode && parentNode.type === 'ObjectExpression') {
65
85
  for (var prop of parentNode.properties) {
66
- if (prop.type !== 'Property') { continue; }
67
- if (prop.key.type === 'Identifier' && prop.range && prop.key.name !== `${propertyShorthand}`) {
86
+ if (prop.type !== 'Property') {
87
+ continue;
88
+ }
89
+ if (
90
+ prop.key.type === 'Identifier' &&
91
+ prop.range &&
92
+ prop.key.name !== `${propertyShorthand}`
93
+ ) {
68
94
  for (let i = 0; i < spacing.length; i++) {
69
95
  if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
70
96
  let [start, end] = prop.range;
71
97
  // Remove the entire line for the duplicate property
72
- while (getSourceCode(context).text[end] !== "\n") {
98
+ while (getSourceCode(context).text[end] !== '\n') {
73
99
  end += 1;
74
100
  }
75
- while (getSourceCode(context).text[start] !== "\n") {
101
+ while (getSourceCode(context).text[start] !== '\n') {
76
102
  start -= 1;
77
103
  }
78
104
  spacing[i] = getSourceCode(context).getText(prop.value);
@@ -83,7 +109,7 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
83
109
  }
84
110
  }
85
111
  }
86
-
112
+
87
113
  fixes.push(fixer.insertTextAfter(node, `${propertyShorthand}Top: ${spacing[0]},\n`));
88
114
  fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Right: ${spacing[1]},\n`));
89
115
  fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Bottom: ${spacing[2]},\n`));
@@ -92,12 +118,30 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
92
118
  return fixes;
93
119
  };
94
120
 
95
- const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, propertyShorthand: string) => {
96
- if (!isCompiledAPI(context, node)) { return; }
121
+ const executeExpandSpacingRule = (
122
+ context: Rule.RuleContext,
123
+ node: Property,
124
+ propertyShorthand: string,
125
+ ) => {
126
+ if (!isCompiledAPI(context, node)) {
127
+ return;
128
+ }
97
129
  if (node.value.type === 'TemplateLiteral') {
98
130
  // Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
131
+ if (!hasOnlyTokens(node.value)) {
132
+ context.report({
133
+ node,
134
+ messageId: 'expandSpacingShorthand',
135
+ data: {
136
+ property: propertyShorthand,
137
+ },
138
+ });
139
+ return;
140
+ }
99
141
  const propertyValues = parseTemplateLiteral(node.value, context);
100
- if (!checkValidPropertyValues(propertyValues)) { return; }
142
+ if (!checkValidPropertyValues(propertyValues)) {
143
+ return;
144
+ }
101
145
  context.report({
102
146
  node,
103
147
  messageId: 'expandSpacingShorthand',
@@ -105,12 +149,12 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
105
149
  property: propertyShorthand,
106
150
  },
107
151
  fix(fixer) {
108
- return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
152
+ return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
109
153
  },
110
154
  });
111
155
  } else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
112
156
  // Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
113
- const propertyValues = [ getSourceCode(context).getText(node.value) ];
157
+ const propertyValues = [getSourceCode(context).getText(node.value)];
114
158
  context.report({
115
159
  node,
116
160
  messageId: 'expandSpacingShorthand',
@@ -118,11 +162,11 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
118
162
  property: propertyShorthand,
119
163
  },
120
164
  fix(fixer) {
121
- return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
165
+ return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
122
166
  },
123
167
  });
124
168
  }
125
- }
169
+ };
126
170
 
127
171
  export const expandSpacingShorthand: Rule.RuleModule = {
128
172
  meta: {
@@ -130,7 +174,8 @@ export const expandSpacingShorthand: Rule.RuleModule = {
130
174
  url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/',
131
175
  },
132
176
  messages: {
133
- expandSpacingShorthand: 'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand',
177
+ expandSpacingShorthand:
178
+ 'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand',
134
179
  },
135
180
  type: 'problem',
136
181
  fixable: 'code',
@@ -147,4 +192,4 @@ export const expandSpacingShorthand: Rule.RuleModule = {
147
192
  },
148
193
  };
149
194
 
150
- export default expandSpacingShorthand;
195
+ export default expandSpacingShorthand;