@atlaskit/eslint-plugin-design-system 8.23.0 → 8.23.2

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 (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/ast-nodes/function-call.js +48 -0
  3. package/dist/cjs/ast-nodes/import.js +49 -0
  4. package/dist/cjs/ast-nodes/index.js +40 -0
  5. package/dist/cjs/ast-nodes/jsx-attribute.js +64 -0
  6. package/dist/cjs/ast-nodes/jsx-element.js +55 -0
  7. package/dist/cjs/ast-nodes/root.js +34 -0
  8. package/dist/cjs/rules/ensure-design-token-usage/error-boundary.js +24 -0
  9. package/dist/cjs/rules/ensure-design-token-usage/index.js +208 -177
  10. package/dist/cjs/rules/use-primitives/index.js +6 -76
  11. package/dist/cjs/rules/use-primitives/transformers/emotion-css/index.js +168 -0
  12. package/dist/cjs/rules/use-primitives/transformers/emotion-css/supported.js +52 -0
  13. package/dist/cjs/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +3 -0
  14. package/dist/es2019/ast-nodes/function-call.js +42 -0
  15. package/dist/es2019/ast-nodes/import.js +42 -0
  16. package/dist/es2019/ast-nodes/index.js +5 -0
  17. package/dist/es2019/ast-nodes/jsx-attribute.js +59 -0
  18. package/dist/es2019/ast-nodes/jsx-element.js +50 -0
  19. package/dist/es2019/ast-nodes/root.js +28 -0
  20. package/dist/es2019/rules/ensure-design-token-usage/error-boundary.js +19 -0
  21. package/dist/es2019/rules/ensure-design-token-usage/index.js +33 -16
  22. package/dist/es2019/rules/use-primitives/index.js +9 -79
  23. package/dist/es2019/rules/use-primitives/transformers/emotion-css/index.js +159 -0
  24. package/dist/es2019/rules/use-primitives/transformers/emotion-css/supported.js +46 -0
  25. package/dist/es2019/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +3 -0
  26. package/dist/esm/ast-nodes/function-call.js +42 -0
  27. package/dist/esm/ast-nodes/import.js +43 -0
  28. package/dist/esm/ast-nodes/index.js +5 -0
  29. package/dist/esm/ast-nodes/jsx-attribute.js +59 -0
  30. package/dist/esm/ast-nodes/jsx-element.js +50 -0
  31. package/dist/esm/ast-nodes/root.js +28 -0
  32. package/dist/esm/rules/ensure-design-token-usage/error-boundary.js +18 -0
  33. package/dist/esm/rules/ensure-design-token-usage/index.js +208 -177
  34. package/dist/esm/rules/use-primitives/index.js +9 -79
  35. package/dist/esm/rules/use-primitives/transformers/emotion-css/index.js +158 -0
  36. package/dist/esm/rules/use-primitives/transformers/emotion-css/supported.js +46 -0
  37. package/dist/esm/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +3 -0
  38. package/dist/types/ast-nodes/function-call.d.ts +21 -0
  39. package/dist/types/ast-nodes/import.d.ts +16 -0
  40. package/dist/types/ast-nodes/index.d.ts +5 -0
  41. package/dist/types/ast-nodes/jsx-attribute.d.ts +26 -0
  42. package/dist/types/ast-nodes/jsx-element.d.ts +21 -0
  43. package/dist/types/ast-nodes/root.d.ts +19 -0
  44. package/dist/types/rules/ensure-design-token-usage/error-boundary.d.ts +11 -0
  45. package/dist/types/rules/ensure-design-token-usage/types.d.ts +1 -0
  46. package/dist/types/rules/use-primitives/transformers/emotion-css/index.d.ts +35 -0
  47. package/dist/types/rules/use-primitives/transformers/emotion-css/supported.d.ts +9 -0
  48. package/dist/types-ts4.5/ast-nodes/function-call.d.ts +21 -0
  49. package/dist/types-ts4.5/ast-nodes/import.d.ts +16 -0
  50. package/dist/types-ts4.5/ast-nodes/index.d.ts +5 -0
  51. package/dist/types-ts4.5/ast-nodes/jsx-attribute.d.ts +26 -0
  52. package/dist/types-ts4.5/ast-nodes/jsx-element.d.ts +21 -0
  53. package/dist/types-ts4.5/ast-nodes/root.d.ts +19 -0
  54. package/dist/types-ts4.5/rules/ensure-design-token-usage/error-boundary.d.ts +11 -0
  55. package/dist/types-ts4.5/rules/ensure-design-token-usage/types.d.ts +1 -0
  56. package/dist/types-ts4.5/rules/use-primitives/transformers/emotion-css/index.d.ts +35 -0
  57. package/dist/types-ts4.5/rules/use-primitives/transformers/emotion-css/supported.d.ts +9 -0
  58. package/package.json +1 -1
@@ -6,13 +6,15 @@ import { createLintRule } from '../utils/create-rule';
6
6
  import { includesHardCodedColor } from '../utils/is-color';
7
7
  import { isDecendantOfGlobalToken, isDecendantOfStyleBlock, isDecendantOfType } from '../utils/is-node';
8
8
  import { lintJSXIdentifierForColor, lintJSXLiteralForColor, lintJSXMemberForColor, lintObjectForColor, lintTemplateIdentifierForColor } from './color';
9
+ import { errorBoundary } from './error-boundary';
9
10
  import ruleMeta from './rule-meta';
10
11
  import { lintObjectForSpacing } from './spacing';
11
12
  import { convertHyphenatedNameToCamelCase, emToPixels, getDomainsForProperty, getFontSizeFromNode, getFontSizeValueInScope, getTokenReplacement, getValueFromShorthand, getValueFromTemplateLiteralRaw, includesTokenString, insertTokensImport, isAuto, isCalc, isTokenValueString, isValidSpacingValue, isZero, processCssNode, splitShorthandValues } from './utils';
12
13
  var defaultConfig = {
13
14
  domains: ['color', 'spacing'],
14
15
  applyImport: true,
15
- shouldEnforceFallbacks: false
16
+ shouldEnforceFallbacks: false,
17
+ failSilently: false
16
18
  };
17
19
  var createWithConfig = function createWithConfig(initialConfig) {
18
20
  return function (context) {
@@ -22,18 +24,27 @@ var createWithConfig = function createWithConfig(initialConfig) {
22
24
  domains: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.domains) || initialConfig.domains,
23
25
  applyImport: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.applyImport) !== undefined ? userConfig.applyImport : initialConfig.applyImport,
24
26
  shouldEnforceFallbacks: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.shouldEnforceFallbacks) !== undefined ? userConfig.shouldEnforceFallbacks : initialConfig.shouldEnforceFallbacks,
25
- exceptions: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.exceptions) || []
27
+ exceptions: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.exceptions) || [],
28
+ failSilently: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.failSilently) || defaultConfig.failSilently
26
29
  };
27
30
  var tokenNode = null;
28
31
  return {
29
32
  ImportDeclaration: function ImportDeclaration(node) {
30
- if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
31
- tokenNode = node;
32
- }
33
+ return errorBoundary(function () {
34
+ if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
35
+ tokenNode = node;
36
+ }
37
+ }, {
38
+ config: config
39
+ });
33
40
  },
34
41
  // For expressions within template literals (e.g. `color: ${red}`) - color only
35
42
  'TemplateLiteral > Identifier': function TemplateLiteralIdentifier(node) {
36
- return lintTemplateIdentifierForColor(node, context, config);
43
+ return errorBoundary(function () {
44
+ return lintTemplateIdentifierForColor(node, context, config);
45
+ }, {
46
+ config: config
47
+ });
37
48
  },
38
49
  // const styles = css({ color: 'red', margin: '4px' }), styled.div({ color: 'red', margin: '4px' })
39
50
  ObjectExpression: function (_ObjectExpression) {
@@ -45,220 +56,240 @@ var createWithConfig = function createWithConfig(initialConfig) {
45
56
  };
46
57
  return ObjectExpression;
47
58
  }(function (parentNode) {
48
- // To force the correct node type
49
- if (!isNodeOfType(parentNode, 'ObjectExpression')) {
50
- return;
51
- }
52
-
53
- // Return for nested objects - these get handled automatically so without returning we'd be doubling up
54
- if (parentNode.parent.type === 'Property') {
55
- return;
56
- }
57
- if (!isDecendantOfStyleBlock(parentNode) && !isDecendantOfType(parentNode, 'JSXExpressionContainer')) {
58
- return;
59
- }
60
- function findObjectStyles(node) {
61
- if (!isNodeOfType(node, 'Property')) {
59
+ return errorBoundary(function () {
60
+ // To force the correct node type
61
+ if (!isNodeOfType(parentNode, 'ObjectExpression')) {
62
62
  return;
63
63
  }
64
- if (isNodeOfType(node.value, 'ObjectExpression')) {
65
- return node.value.properties.forEach(findObjectStyles);
66
- }
67
- if (!isNodeOfType(node.key, 'Identifier') && !isNodeOfType(node.key, 'Literal')) {
64
+
65
+ // Return for nested objects - these get handled automatically so without returning we'd be doubling up
66
+ if (parentNode.parent.type === 'Property') {
68
67
  return;
69
68
  }
70
- var propertyName = isNodeOfType(node.key, 'Identifier') ? node.key.name : String(node.key.value);
71
-
72
- // Returns which domains to lint against based on rule's config and current property
73
- var domains = getDomainsForProperty(propertyName, config.domains);
74
- if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
69
+ if (!isDecendantOfStyleBlock(parentNode) && !isDecendantOfType(parentNode, 'JSXExpressionContainer')) {
75
70
  return;
76
71
  }
77
- if (isNodeOfType(node.value, 'TemplateLiteral')) {
78
- var value = getValueFromTemplateLiteralRaw(node.value, context);
79
- if (Array.isArray(value) && value.some(isCalc)) {
80
- return context.report({
81
- node: node,
82
- messageId: 'noCalcUsage',
83
- data: {
84
- payload: "".concat(propertyName)
85
- }
86
- });
72
+ function findObjectStyles(node) {
73
+ if (!isNodeOfType(node, 'Property')) {
74
+ return;
87
75
  }
88
- if (node.value.expressions.some(isDecendantOfGlobalToken)) {
76
+ if (isNodeOfType(node.value, 'ObjectExpression')) {
77
+ return node.value.properties.forEach(findObjectStyles);
78
+ }
79
+ if (!isNodeOfType(node.key, 'Identifier') && !isNodeOfType(node.key, 'Literal')) {
89
80
  return;
90
81
  }
82
+ var propertyName = isNodeOfType(node.key, 'Identifier') ? node.key.name : String(node.key.value);
83
+
84
+ // Returns which domains to lint against based on rule's config and current property
85
+ var domains = getDomainsForProperty(propertyName, config.domains);
86
+ if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
87
+ return;
88
+ }
89
+ if (isNodeOfType(node.value, 'TemplateLiteral')) {
90
+ var value = getValueFromTemplateLiteralRaw(node.value, context);
91
+ if (Array.isArray(value) && value.some(isCalc)) {
92
+ return context.report({
93
+ node: node,
94
+ messageId: 'noCalcUsage',
95
+ data: {
96
+ payload: "".concat(propertyName)
97
+ }
98
+ });
99
+ }
100
+ if (node.value.expressions.some(isDecendantOfGlobalToken)) {
101
+ return;
102
+ }
103
+ }
104
+ if (domains.includes('color')) {
105
+ return lintObjectForColor(node, context, config);
106
+ }
107
+ if (domains.includes('spacing') || domains.includes('shape') || domains.includes('typography')) {
108
+ /**
109
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
110
+ */
111
+ var fontSize = getFontSizeFromNode(parentNode, context);
112
+ return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
113
+ }
91
114
  }
92
- if (domains.includes('color')) {
93
- return lintObjectForColor(node, context, config);
94
- }
95
- if (domains.includes('spacing') || domains.includes('shape') || domains.includes('typography')) {
96
- /**
97
- * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
98
- */
99
- var fontSize = getFontSizeFromNode(parentNode, context);
100
- return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
101
- }
102
- }
103
- parentNode.properties.forEach(findObjectStyles);
115
+ parentNode.properties.forEach(findObjectStyles);
116
+ }, {
117
+ config: config
118
+ });
104
119
  }),
105
120
  // CSSTemplateLiteral and StyledTemplateLiteral
106
121
  // const cssTemplateLiteral = css`color: red; padding: 12px`;
107
122
  // const styledTemplateLiteral = styled.p`color: red; padding: 8px`;
108
123
  'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"],TaggedTemplateExpression[tag.callee.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyledTaggedTemplateExpressionTagCalleeNameStyled(node) {
109
- // To force the correct node type
110
- if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
111
- return;
112
- }
113
- var processedCssLines = processCssNode(node, context);
114
- if (!processedCssLines) {
115
- // if we can't get a processed css we bail
116
- return;
117
- }
118
- var globalFontSize = getFontSizeValueInScope(processedCssLines);
119
- var textForSource = context.getSourceCode().getText(node.quasi);
120
- var allReplacedValues = [];
121
- var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
122
- var _ref2 = _slicedToArray(_ref, 2),
123
- resolvedCssLine = _ref2[0],
124
- originalCssLine = _ref2[1];
125
- var _resolvedCssLine$spli = resolvedCssLine.split(':'),
126
- _resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
127
- originalProperty = _resolvedCssLine$spli2[0],
128
- resolvedCssValues = _resolvedCssLine$spli2[1];
129
- var _originalCssLine$spli = originalCssLine.split(':'),
130
- _originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
131
- _ = _originalCssLine$spli2[0],
132
- originalCssValues = _originalCssLine$spli2[1];
133
- var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
134
- var isFontFamily = /fontFamily/.test(propertyName);
135
- var replacedValuesPerProperty = [originalProperty];
136
- var domains = getDomainsForProperty(propertyName, config.domains);
137
- if (domains.length === 0 || !resolvedCssValues) {
138
- // in both of these cases no changes should be made to the current property
139
- return currentSource;
124
+ return errorBoundary(function () {
125
+ // To force the correct node type
126
+ if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
127
+ return;
140
128
  }
141
- if (domains.includes('color')) {
142
- if (includesTokenString(resolvedCssValues.trim())) {
143
- return currentSource;
144
- }
145
- if (includesHardCodedColor(resolvedCssValues)) {
146
- context.report({
147
- messageId: 'hardCodedColor',
148
- node: node
149
- });
150
- return currentSource;
151
- }
129
+ var processedCssLines = processCssNode(node, context);
130
+ if (!processedCssLines) {
131
+ // if we can't get a processed css we bail
132
+ return;
152
133
  }
153
- if (domains.includes('spacing') || domains.includes('typography') || domains.includes('shape')) {
154
- if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
155
- // no changes should be made to the current property
134
+ var globalFontSize = getFontSizeValueInScope(processedCssLines);
135
+ var textForSource = context.getSourceCode().getText(node.quasi);
136
+ var allReplacedValues = [];
137
+ var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
138
+ var _ref2 = _slicedToArray(_ref, 2),
139
+ resolvedCssLine = _ref2[0],
140
+ originalCssLine = _ref2[1];
141
+ var _resolvedCssLine$spli = resolvedCssLine.split(':'),
142
+ _resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
143
+ originalProperty = _resolvedCssLine$spli2[0],
144
+ resolvedCssValues = _resolvedCssLine$spli2[1];
145
+ var _originalCssLine$spli = originalCssLine.split(':'),
146
+ _originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
147
+ _ = _originalCssLine$spli2[0],
148
+ originalCssValues = _originalCssLine$spli2[1];
149
+ var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
150
+ var isFontFamily = /fontFamily/.test(propertyName);
151
+ var replacedValuesPerProperty = [originalProperty];
152
+ var domains = getDomainsForProperty(propertyName, config.domains);
153
+ if (domains.length === 0 || !resolvedCssValues) {
154
+ // in both of these cases no changes should be made to the current property
156
155
  return currentSource;
157
156
  }
157
+ if (domains.includes('color')) {
158
+ if (includesTokenString(resolvedCssValues.trim())) {
159
+ return currentSource;
160
+ }
161
+ if (includesHardCodedColor(resolvedCssValues)) {
162
+ context.report({
163
+ messageId: 'hardCodedColor',
164
+ node: node
165
+ });
166
+ return currentSource;
167
+ }
168
+ }
169
+ if (domains.includes('spacing') || domains.includes('typography') || domains.includes('shape')) {
170
+ if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
171
+ // no changes should be made to the current property
172
+ return currentSource;
173
+ }
158
174
 
159
- // gets the values from the associated property, numeric values or NaN
160
- var processedNumericValues = getValueFromShorthand(resolvedCssValues);
161
- var processedValues = splitShorthandValues(resolvedCssValues);
162
- // only splits shorthand values but it does not transform NaNs so tokens are preserved
163
- var originalValues = splitShorthandValues(originalCssValues);
175
+ // gets the values from the associated property, numeric values or NaN
176
+ var processedNumericValues = getValueFromShorthand(resolvedCssValues);
177
+ var processedValues = splitShorthandValues(resolvedCssValues);
178
+ // only splits shorthand values but it does not transform NaNs so tokens are preserved
179
+ var originalValues = splitShorthandValues(originalCssValues);
164
180
 
165
- // reconstructing the string
166
- // should replace what it can and preserve the raw value for everything else
181
+ // reconstructing the string
182
+ // should replace what it can and preserve the raw value for everything else
167
183
 
168
- var replacementValue = processedNumericValues
169
- // put together resolved value and original value on a tuple
170
- .map(function (value, index) {
171
- return [
172
- // if emToPX conversion fails we'll default to original value
173
- emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
174
- }).map(function (_ref3) {
175
- var _ref4 = _slicedToArray(_ref3, 3),
176
- numericOrNanValue = _ref4[0],
177
- pxValue = _ref4[1],
178
- originalValue = _ref4[2];
179
- if (!originalValue) {
180
- return originalValue;
181
- }
182
- if (isCalc(originalValue)) {
184
+ var replacementValue = processedNumericValues
185
+ // put together resolved value and original value on a tuple
186
+ .map(function (value, index) {
187
+ return [
188
+ // if emToPX conversion fails we'll default to original value
189
+ emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
190
+ }).map(function (_ref3) {
191
+ var _ref4 = _slicedToArray(_ref3, 3),
192
+ numericOrNanValue = _ref4[0],
193
+ pxValue = _ref4[1],
194
+ originalValue = _ref4[2];
195
+ if (!originalValue) {
196
+ return originalValue;
197
+ }
198
+ if (isCalc(originalValue)) {
199
+ context.report({
200
+ node: node,
201
+ messageId: 'noCalcUsage',
202
+ data: {
203
+ payload: "".concat(propertyName)
204
+ }
205
+ });
206
+ return originalValue;
207
+ }
208
+ if (isTokenValueString(originalValue)) {
209
+ // if the value is already valid, nothing to report or replace
210
+ return originalValue;
211
+ }
212
+
213
+ // do not replace 0 or auto with tokens
214
+ if (isZero(pxValue) || isAuto(pxValue)) {
215
+ return originalValue;
216
+ }
217
+ if (isNaN(numericOrNanValue) && !isFontFamily) {
218
+ // do not report if we have nothing to replace with
219
+ return originalValue;
220
+ }
221
+
222
+ // value is numeric or fontFamily, and needs replacing we'll report first
183
223
  context.report({
184
224
  node: node,
185
- messageId: 'noCalcUsage',
225
+ messageId: 'noRawSpacingValues',
186
226
  data: {
187
- payload: "".concat(propertyName)
227
+ payload: "".concat(propertyName, ":").concat(numericOrNanValue)
188
228
  }
189
229
  });
190
- return originalValue;
191
- }
192
- if (isTokenValueString(originalValue)) {
193
- // if the value is already valid, nothing to report or replace
194
- return originalValue;
195
- }
196
-
197
- // do not replace 0 or auto with tokens
198
- if (isZero(pxValue) || isAuto(pxValue)) {
199
- return originalValue;
200
- }
201
- if (isNaN(numericOrNanValue) && !isFontFamily) {
202
- // do not report if we have nothing to replace with
203
- return originalValue;
204
- }
205
230
 
206
- // value is numeric or fontFamily, and needs replacing we'll report first
207
- context.report({
208
- node: node,
209
- messageId: 'noRawSpacingValues',
210
- data: {
211
- payload: "".concat(propertyName, ":").concat(numericOrNanValue)
231
+ // from here on we know value is numeric or a font family, so it might or might not have a token equivalent
232
+ var replacementNode = getTokenReplacement(propertyName, numericOrNanValue);
233
+ if (!replacementNode) {
234
+ return originalValue;
212
235
  }
213
- });
236
+ var replacementToken = '${' + replacementNode.toString() + '}';
237
+ replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
238
+ return replacementToken;
239
+ }).join(' ');
240
+ if (replacedValuesPerProperty.length > 1) {
241
+ // first value is the property name, so it will always have at least 1
242
+ allReplacedValues.push(replacedValuesPerProperty);
243
+ }
214
244
 
215
- // from here on we know value is numeric or a font family, so it might or might not have a token equivalent
216
- var replacementNode = getTokenReplacement(propertyName, numericOrNanValue);
217
- if (!replacementNode) {
218
- return originalValue;
245
+ // replace property:val with new property:val
246
+ var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
247
+ "".concat(originalProperty, ": ").concat(replacementValue));
248
+ if (!replacedCssLine) {
249
+ return currentSource;
219
250
  }
220
- var replacementToken = '${' + replacementNode.toString() + '}';
221
- replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
222
- return replacementToken;
223
- }).join(' ');
224
- if (replacedValuesPerProperty.length > 1) {
225
- // first value is the property name, so it will always have at least 1
226
- allReplacedValues.push(replacedValuesPerProperty);
251
+ return replacedCssLine;
227
252
  }
253
+ return currentSource;
254
+ }, textForSource);
255
+ if (completeSource !== textForSource) {
256
+ // means we found some replacement values, we'll give the option to fix them
228
257
 
229
- // replace property:val with new property:val
230
- var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
231
- "".concat(originalProperty, ": ").concat(replacementValue));
232
- if (!replacedCssLine) {
233
- return currentSource;
234
- }
235
- return replacedCssLine;
258
+ context.report({
259
+ node: node,
260
+ messageId: 'autofixesPossible',
261
+ fix: function fix(fixer) {
262
+ return (!tokenNode && config.applyImport ? [insertTokensImport(fixer)] : []).concat([fixer.replaceText(node.quasi, completeSource)]);
263
+ }
264
+ });
236
265
  }
237
- return currentSource;
238
- }, textForSource);
239
- if (completeSource !== textForSource) {
240
- // means we found some replacement values, we'll give the option to fix them
241
-
242
- context.report({
243
- node: node,
244
- messageId: 'autofixesPossible',
245
- fix: function fix(fixer) {
246
- return (!tokenNode && config.applyImport ? [insertTokensImport(fixer)] : []).concat([fixer.replaceText(node.quasi, completeSource)]);
247
- }
248
- });
249
- }
266
+ }, {
267
+ config: config
268
+ });
250
269
  },
251
270
  // For inline JSX styles - literals (e.g. <Test color="red"/>) - color only
252
271
  'JSXAttribute > Literal': function JSXAttributeLiteral(node) {
253
- return lintJSXLiteralForColor(node, context, config);
272
+ return errorBoundary(function () {
273
+ return lintJSXLiteralForColor(node, context, config);
274
+ }, {
275
+ config: config
276
+ });
254
277
  },
255
278
  // For inline JSX styles - members (e.g. <Test color={color.red}/>) - color only
256
279
  'JSXExpressionContainer > MemberExpression': function JSXExpressionContainerMemberExpression(node) {
257
- return lintJSXMemberForColor(node, context, config);
280
+ return errorBoundary(function () {
281
+ return lintJSXMemberForColor(node, context, config);
282
+ }, {
283
+ config: config
284
+ });
258
285
  },
259
286
  // For inline JSX styles - identifiers (e.g. <Test color={red}/>) - color only
260
287
  'JSXExpressionContainer > Identifier': function JSXExpressionContainerIdentifier(node) {
261
- return lintJSXIdentifierForColor(node, context, config);
288
+ return errorBoundary(function () {
289
+ return lintJSXIdentifierForColor(node, context, config);
290
+ }, {
291
+ config: config
292
+ });
262
293
  }
263
294
  };
264
295
  };
@@ -1,8 +1,9 @@
1
- import { getIdentifierInParentScope, isNodeOfType } from 'eslint-codemod-utils';
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
2
  import { createLintRule } from '../utils/create-rule';
3
3
  import { getConfig } from './config';
4
- import { jsxElementToBoxTransformer, styledComponentToPrimitive } from './transformers';
5
- import { containsOnlySupportedAttrs, findValidJsxUsageToTransform, findValidStyledComponentCall, getAttributeValueIdentifier, getJSXAttributeByName, getVariableDefinitionValue, getVariableUsagesCount, isFunctionNamed, isValidCssPropertiesToTransform, isValidTagName } from './utils';
4
+ import { styledComponentToPrimitive } from './transformers';
5
+ import { EmotionCSS } from './transformers/emotion-css';
6
+ import { findValidJsxUsageToTransform, findValidStyledComponentCall, isValidCssPropertiesToTransform } from './utils';
6
7
  var boxDocsUrl = 'https://atlassian.design/components/primitives/box';
7
8
  var rule = createLintRule({
8
9
  meta: {
@@ -53,84 +54,13 @@ var rule = createLintRule({
53
54
  });
54
55
  },
55
56
  // transforms <div css={...}> usages
56
- JSXOpeningElement: function JSXOpeningElement(node) {
57
- if (!config.patterns.includes('compiled-css-function')) {
58
- return false;
59
- }
60
- if (!isNodeOfType(node, 'JSXOpeningElement')) {
61
- return;
62
- }
63
- if (!isNodeOfType(node.name, 'JSXIdentifier')) {
64
- return;
65
- }
66
- if (!isNodeOfType(node.parent, 'JSXElement')) {
67
- return;
68
- }
69
- var suggestBox = shouldSuggestBox(node.parent, context, config);
70
- if (suggestBox) {
71
- context.report({
72
- node: node,
73
- messageId: 'preferPrimitivesBox',
74
- data: {
75
- element: node.name.name
76
- },
77
- suggest: [{
78
- desc: "Convert to Box",
79
- fix: jsxElementToBoxTransformer(node.parent, context)
80
- }]
81
- });
82
- }
57
+ JSXElement: function JSXElement(node) {
58
+ EmotionCSS.lint(node, {
59
+ context: context,
60
+ config: config
61
+ });
83
62
  }
84
63
  };
85
64
  }
86
65
  });
87
- var shouldSuggestBox = function shouldSuggestBox(node, context, config
88
- // scope: Scope.Scope,
89
- ) {
90
- if (!node) {
91
- return false;
92
- }
93
-
94
- // Currently we only support `div`, but possibly more in future
95
- if (!isValidTagName(node)) {
96
- return false;
97
- }
98
-
99
- // Currently we only support elements that contain only a `css` attr, possibly more in future
100
- if (!containsOnlySupportedAttrs(node)) {
101
- return false;
102
- }
103
-
104
- // Get the `css` attr
105
- var cssAttr = getJSXAttributeByName(node.openingElement, 'css');
106
-
107
- // Get the prop value, e.g. `myStyles` in `css={myStyles}`
108
- var cssVariableName = getAttributeValueIdentifier(cssAttr);
109
-
110
- // `cssVariableName` could be undefined if the maker has
111
- // done something like `css={[styles1, styles2]}`, `css={...styles}`, etc
112
- if (!cssVariableName) {
113
- return false;
114
- }
115
-
116
- /**
117
- * Make sure the variable is not used in multiple JSX elements:
118
- * ```
119
- * <div css={paddingStyles}></div>
120
- * <input css={paddingStyles}></input>
121
- * ```
122
- */
123
- if (getVariableUsagesCount(cssVariableName, context) !== 1) {
124
- return false;
125
- }
126
-
127
- // Find where `cssVariableName` is defined. We're looking for `const myStyles = css({...})`
128
- var cssVariableDefinition = getIdentifierInParentScope(context.getScope(), cssVariableName);
129
- var cssVariableValue = getVariableDefinitionValue(cssVariableDefinition);
130
- // Check if `cssVariableValue` is a function called `css()`
131
- if (!cssVariableValue || !isFunctionNamed(cssVariableValue, 'css')) {
132
- return false;
133
- }
134
- return isValidCssPropertiesToTransform(cssVariableValue.node.init, config);
135
- };
136
66
  export default rule;